diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 400349f15..000000000 --- a/.clang-format +++ /dev/null @@ -1,75 +0,0 @@ ---- -BasedOnStyle: LLVM -BreakBeforeBraces: Stroustrup -IndentWidth: 4 -TabWidth: 4 -AlignAfterOpenBracket: AlwaysBreak -AlignConsecutiveMacros: 'true' -AlignConsecutiveAssignments: 'false' -AlignConsecutiveDeclarations: 'false' -AlignEscapedNewlines: Right -AlignOperands: 'true' -AlignTrailingComments: 'true' -AllowAllArgumentsOnNextLine: 'false' -AllowAllConstructorInitializersOnNextLine: 'false' -AllowAllParametersOfDeclarationOnNextLine: 'false' -AllowShortBlocksOnASingleLine: 'true' -AllowShortCaseLabelsOnASingleLine: 'false' -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: Never -AlwaysBreakAfterReturnType: None -BinPackArguments: 'false' -BinPackParameters: 'false' -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeTernaryOperators: 'true' -BreakConstructorInitializers: BeforeComma -BreakInheritanceList: BeforeComma -CompactNamespaces: 'false' -ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' -ConstructorInitializerIndentWidth: '4' -ContinuationIndentWidth: '4' -Cpp11BracedListStyle: 'false' -FixNamespaceComments: 'true' -IncludeBlocks: Regroup -IndentCaseLabels: 'true' -IndentPPDirectives: None -IndentWrappedFunctionNames: 'false' -KeepEmptyLinesAtTheStartOfBlocks: 'false' -MaxEmptyLinesToKeep: '1' -NamespaceIndentation: None -PointerAlignment: Left -ReflowComments: 'true' -SortIncludes: 'true' -SortUsingDeclarations: 'true' -SpaceAfterCStyleCast: 'false' -SpaceAfterLogicalNot: 'true' -SpaceAfterTemplateKeyword: 'true' -SpaceBeforeAssignmentOperators: 'true' -SpaceBeforeCpp11BracedList: 'true' -SpaceBeforeCtorInitializerColon: 'true' -SpaceBeforeInheritanceColon: 'true' -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: 'true' -SpaceInEmptyParentheses: 'false' -SpacesBeforeTrailingComments: '3' -SpacesInAngles: 'false' -SpacesInCStyleCastParentheses: 'false' -SpacesInContainerLiterals: 'true' -SpacesInParentheses: 'false' -SpacesInSquareBrackets: 'false' -UseTab: 'Always' - ---- -Language: Cpp -Standard: Cpp03 -ColumnLimit: '240' ---- -Language: ObjC -ColumnLimit: '240' ---- -Language: Java -ColumnLimit: '240' ---- -Language: CSharp -ColumnLimit: '240' -... diff --git a/.clangd b/.clangd deleted file mode 100644 index cd9c5e1db..000000000 --- a/.clangd +++ /dev/null @@ -1,9 +0,0 @@ -CompileFlags: - Add: - - "-std=c++17" - - "-I../ext" - - "-I../ext/prometheus-cpp-lite-1.0/core/include" - - "-I../ext/prometheus-cpp-lite-1.0/simpleapi/include" - - "-I./ext" - - "-I./ext/prometheus-cpp-lite-1.0/core/include" - - "-I./ext/prometheus-cpp-lite-1.0/simpleapi/include" diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 4acef401c..000000000 --- a/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -.git/ -workspace/ diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dbe5330ba..000000000 --- a/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -ext/bin/tap-windows-ndis6/x64/zttap300.inf eol=crlf -ext/bin/tap-windows-ndis6/x64.old/zttap300.inf eol=crlf -ext/bin/tap-windows-ndis6/x86/zttap300.inf eol=crlf -windows/TapDriver6/zttap300.inf eol=crlf diff --git a/.github/ISSUE_TEMPLATE/bugs-and-issues.md b/.github/ISSUE_TEMPLATE/bugs-and-issues.md deleted file mode 100644 index 92e6978c2..000000000 --- a/.github/ISSUE_TEMPLATE/bugs-and-issues.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Bugs and Issues -about: Create a report to help us improve -title: '' -labels: NEEDS TRIAGE -assignees: '' - ---- - -# Before filing a Bug Report - -_Using these will ensure you get quicker support, and make this space available for code-related issues. Thank you!_ - -- [Docs Site](https://docs.zerotier.com/zerotier/troubleshooting) => Troubleshooting, quickstarts, and more advanced topics. -- [Discuss Forum](https://discuss.zerotier.com/) => Our discussion forum for users and support to mutually resolve issues & suggest ideas. -- [Reddit](https://www.reddit.com/r/zerotier/) => Our subreddit, which we monitor regularly and is fairly active. -- [Knowledge Base](https://zerotier.atlassian.net/wiki/spaces/SD/overview) => Older wiki. - -If you are having a connection issue, it's much easier to diagnose through the discussion forum or the ticket system. - - -# If you still want to file a Bug Report - -## Please let us know - -- What you expect to be happening. -- What is actually happening? -- Any steps to reproduce the error. -- Any relevant console output or screenshots. -- What operating system and ZeroTier version. Please try the latest ZeroTier release. - diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 5a1e094c3..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: "[Feature Request] " -labels: suggestion -assignees: '' - ---- - -If there is something you'd like to have added to ZeroTier, to go to https://discuss.zerotier.com/c/feature-requests/ instead. Issues there can be voted on and discussed in-depth. - - -Thank you! diff --git a/.github/ISSUE_TEMPLATE/game-connection-issue.md b/.github/ISSUE_TEMPLATE/game-connection-issue.md deleted file mode 100644 index d7b3a9b2d..000000000 --- a/.github/ISSUE_TEMPLATE/game-connection-issue.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -name: Game Connection Issue -about: Game issues are better served by forum posts -title: Please go to our Discuss or Reddit for game-related issues. Thanks! -labels: wontfix -assignees: '' - ---- - -Are you having trouble connecting to a game on your virtual network after installing ZeroTier? - -- [ ] Yes -- [ ] No - -If you answered yes, then it is very likely that your question would be better answered on our [Community Forums](https://discuss.zerotier.com) or [Reddit](https://www.reddit.com/r/zerotier/) community; we monitor both regularly. We also have extensive documentation on our [Knowledge Base](https://zerotier.atlassian.net/wiki/spaces/SD/overview). Thank you! diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index fee6dd338..000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,126 +0,0 @@ -on: - pull_request: - push: - workflow_dispatch: - -jobs: - build_ubuntu: - runs-on: ubuntu-latest - steps: - - name: gitconfig - run: | - git config --global core.autocrlf input - # git config --global core.eol lf - - name: checkout - uses: actions/checkout@v4 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - targets: x86_64-unknown-linux-gnu - components: rustfmt, clippy - - - name: Set up cargo cache - uses: Swatinem/rust-cache@v2 - continue-on-error: false - with: - key: ${{ runner.os }}-cargo-${{ hashFiles('rustybits//Cargo.lock') }} - shared-key: ${{ runner.os }}-cargo- - workspaces: | - rustybits/ - - - name: make - run: make - - name: selftest - run: | - make selftest - ./zerotier-selftest - - name: 'Tar files' # keeps permissions (execute) - run: tar -cvf zerotier-one.tar zerotier-one - - name: Archive production artifacts - uses: actions/upload-artifact@v4 - with: - name: zerotier-one-ubuntu-x64 - path: zerotier-one.tar - retention-days: 7 - - build_macos: - runs-on: macos-latest - steps: - - name: gitconfig - run: | - git config --global core.autocrlf input - # git config --global core.eol lf - - name: checkout - uses: actions/checkout@v4 - - name: Install Rust aarch64 - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - target: aarch64-apple-darwin - components: rustfmt, clippy - - name: Install Rust x86_64 - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - target: x86_64-apple-darwin - components: rustfmt, clippy - - name: Set up cargo cache - uses: Swatinem/rust-cache@v2 - continue-on-error: false - with: - key: ${{ runner.os }}-cargo-${{ hashFiles('rustybits//Cargo.lock') }} - shared-key: ${{ runner.os }}-cargo- - workspaces: | - rustybits/ - - name: make - run: make - - name: selftest - run: | - make selftest - ./zerotier-selftest - - name: 'Tar files' # keeps permissions (execute) - run: tar -cvf zerotier-one.tar zerotier-one - - name: Archive production artifacts - uses: actions/upload-artifact@v4 - with: - name: zerotier-one-mac - path: zerotier-one.tar - retention-days: 7 - - - build_windows: - runs-on: windows-latest - steps: - - name: gitconfig - run: | - git config --global core.autocrlf true - # git config --global core.eol lf - - name: checkout - uses: actions/checkout@v4 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - target: aarch64-apple-darwin - components: rustfmt, clippy - - name: Set up cargo cache - uses: Swatinem/rust-cache@v2 - continue-on-error: false - with: - key: ${{ runner.os }}-cargo-${{ hashFiles('rustybits//Cargo.lock') }} - shared-key: ${{ runner.os }}-cargo- - workspaces: | - rustybits/ - - - name: setup msbuild - uses: microsoft/setup-msbuild@v2 - - name: msbuild - run: | - msbuild windows\ZeroTierOne.sln /m /p:Configuration=Release /property:Platform=x64 /t:ZeroTierOne - - name: Archive production artifacts - uses: actions/upload-artifact@v4 - with: - name: zerotier-one-windows - path: windows/Build - retention-days: 7 diff --git a/.github/workflows/validate-linux.sh b/.github/workflows/validate-linux.sh deleted file mode 100755 index a661f6f6c..000000000 --- a/.github/workflows/validate-linux.sh +++ /dev/null @@ -1,497 +0,0 @@ -#!/bin/bash - -# This test script joins Earth and pokes some stuff - -TEST_NETWORK=8056c2e21c000001 -RUN_LENGTH=30 -TEST_FINISHED=false -ZTO_VER=$(git describe --tags $(git rev-list --tags --max-count=1)) -ZTO_COMMIT=$(git rev-parse HEAD) -ZTO_COMMIT_SHORT=$(git rev-parse --short HEAD) -TEST_DIR_PREFIX="$ZTO_VER-$ZTO_COMMIT_SHORT-test-results" - -TEST_OK=0 -TEST_FAIL=1 - -echo "Performing test on: $ZTO_VER-$ZTO_COMMIT_SHORT" -TEST_FILEPATH_PREFIX="$TEST_DIR_PREFIX/$ZTO_COMMIT_SHORT" -mkdir $TEST_DIR_PREFIX - -# How long we will wait for ZT to come online before considering it a failure -MAX_WAIT_SECS=30 - -ZT_PORT_NODE_1=9996 -ZT_PORT_NODE_2=9997 - -################################################################################ -# Multi-node connectivity and performance test # -################################################################################ - -test() { - - echo -e "\nPerforming pre-flight checks" - - check_exit_on_invalid_identity - - echo -e "\nRunning test for $RUN_LENGTH seconds" - - export NS1="ip netns exec ns1" - export NS2="ip netns exec ns2" - - export ZT1="$NS1 ./zerotier-cli -p9996 -D$(pwd)/node1" - # Specify custom port on one node to ensure that feature works - export ZT2="$NS2 ./zerotier-cli -p9997 -D$(pwd)/node2" - - echo -e "\nSetting up network namespaces..." - echo "Setting up ns1" - - ip netns add ns1 - $NS1 ip link set dev lo up - ip link add veth0 type veth peer name veth1 - ip link set veth1 netns ns1 - ip addr add 192.168.0.1/24 dev veth0 - ip link set dev veth0 up - - $NS1 ip addr add 192.168.0.2/24 dev veth1 - $NS1 ip link set dev veth1 up - - # Add default route - $NS1 ip route add default via 192.168.0.1 - - iptables -t nat -A POSTROUTING -s 192.168.0.0/255.255.255.0 \ - -o eth0 -j MASQUERADE - iptables -A FORWARD -i eth0 -o veth0 -j ACCEPT - iptables -A FORWARD -o eth0 -i veth0 -j ACCEPT - - echo "Setting up ns2" - ip netns add ns2 - $NS2 ip link set dev lo up - ip link add veth2 type veth peer name veth3 - ip link set veth3 netns ns2 - ip addr add 192.168.1.1/24 dev veth2 - ip link set dev veth2 up - - $NS2 ip addr add 192.168.1.2/24 dev veth3 - $NS2 ip link set dev veth3 up - $NS2 ip route add default via 192.168.1.1 - - iptables -t nat -A POSTROUTING -s 192.168.1.0/255.255.255.0 \ - -o eth0 -j MASQUERADE - iptables -A FORWARD -i eth0 -o veth2 -j ACCEPT - iptables -A FORWARD -o eth0 -i veth2 -j ACCEPT - - # Allow forwarding - sysctl -w net.ipv4.ip_forward=1 - - ################################################################################ - # Memory Leak Check # - ################################################################################ - - export FILENAME_MEMORY_LOG="$TEST_FILEPATH_PREFIX-memory.log" - - echo -e "\nStarting a ZeroTier instance in each namespace..." - - export time_test_start=$(date +%s) - - # Spam the CLI as ZeroTier is starting - spam_cli 100 - - echo "Starting memory leak check" - $NS1 sudo valgrind --demangle=yes --exit-on-first-error=yes \ - --error-exitcode=1 \ - --xml=yes \ - --xml-file=$FILENAME_MEMORY_LOG \ - --leak-check=full \ - ./zerotier-one node1 -p$ZT_PORT_NODE_1 -U >>node_1.log 2>&1 & - - # Second instance, not run in memory profiler - # Don't set up internet access until _after_ zerotier is running - # This has been a source of stuckness in the past. - $NS2 ip addr del 192.168.1.2/24 dev veth3 - $NS2 sudo ./zerotier-one node2 -U -p$ZT_PORT_NODE_2 >>node_2.log 2>&1 & - - sleep 10; # New HTTP control plane is a bit sluggish, so we delay here - - check_bind_to_correct_ports $ZT_PORT_NODE_1 - check_bind_to_correct_ports $ZT_PORT_NODE_2 - - $NS2 ip addr add 192.168.1.2/24 dev veth3 - $NS2 ip route add default via 192.168.1.1 - - echo -e "\nPing from host to namespaces" - - ping -c 3 192.168.0.1 - ping -c 3 192.168.1.1 - - echo -e "\nPing from namespace to host" - - $NS1 ping -c 3 192.168.0.1 - $NS1 ping -c 3 192.168.0.1 - $NS2 ping -c 3 192.168.0.2 - $NS2 ping -c 3 192.168.0.2 - - echo -e "\nPing from ns1 to ns2" - - $NS1 ping -c 3 192.168.0.1 - - echo -e "\nPing from ns2 to ns1" - - $NS2 ping -c 3 192.168.0.1 - - ################################################################################ - # Online Check # - ################################################################################ - - echo "Waiting for ZeroTier to come online before attempting test..." - node1_online=false - node2_online=false - both_instances_online=false - time_zt_node1_start=$(date +%s) - time_zt_node2_start=$(date +%s) - - for ((s = 0; s <= $MAX_WAIT_SECS; s++)); do - node1_online="$($ZT1 -j info | jq '.online' 2>/dev/null)" - node2_online="$($ZT2 -j info | jq '.online' 2>/dev/null)" - echo "Checking for online status: try #$s, node1:$node1_online, node2:$node2_online" - if [[ "$node2_online" == "true" && "$node1_online" == "true" ]]; then - export both_instances_online=true - export time_to_both_nodes_online=$(date +%s) - break - fi - sleep 1 - done - - echo -e "\n\nContents of ZeroTier home paths:" - - ls -lga node1 - tree node1 - ls -lga node2 - tree node2 - - echo -e "\n\nRunning ZeroTier processes:" - echo -e "\nNode 1:\n" - $NS1 ps aux | grep zerotier-one - echo -e "\nNode 2:\n" - $NS2 ps aux | grep zerotier-one - - echo -e "\n\nStatus of each instance:" - - echo -e "\n\nNode 1:\n" - $ZT1 status - echo -e "\n\nNode 2:\n" - $ZT2 status - - if [[ "$both_instances_online" != "true" ]]; then - exit_test_and_generate_report $TEST_FAIL "one or more nodes failed to come online" - fi - - echo -e "\nJoining networks" - - $ZT1 join $TEST_NETWORK - $ZT2 join $TEST_NETWORK - - sleep 10 - - node1_ip4=$($ZT1 get $TEST_NETWORK ip4) - node2_ip4=$($ZT2 get $TEST_NETWORK ip4) - - echo "node1_ip4=$node1_ip4" - echo "node2_ip4=$node2_ip4" - - echo -e "\nPinging each node" - - PING12_FILENAME="$TEST_FILEPATH_PREFIX-ping-1-to-2.txt" - PING21_FILENAME="$TEST_FILEPATH_PREFIX-ping-2-to-1.txt" - - $NS1 ping -c 16 $node2_ip4 >$PING12_FILENAME - $NS2 ping -c 16 $node1_ip4 >$PING21_FILENAME - - ping_loss_percent_1_to_2=$(cat $PING12_FILENAME | - grep "packet loss" | awk '{print $6}' | sed 's/%//') - ping_loss_percent_2_to_1=$(cat $PING21_FILENAME | - grep "packet loss" | awk '{print $6}' | sed 's/%//') - - # Normalize loss value - export ping_loss_percent_1_to_2=$(echo "scale=2; $ping_loss_percent_1_to_2/100.0" | bc) - export ping_loss_percent_2_to_1=$(echo "scale=2; $ping_loss_percent_2_to_1/100.0" | bc) - - ################################################################################ - # CLI Check # - ################################################################################ - - echo "Testing basic CLI functionality..." - - spam_cli 10 - - $ZT1 join $TEST_NETWORK - - $ZT1 -h - $ZT1 -v - $ZT1 status - $ZT1 info - $ZT1 listnetworks - $ZT1 peers - $ZT1 listpeers - - $ZT1 -j status - $ZT1 -j info - $ZT1 -j listnetworks - $ZT1 -j peers - $ZT1 -j listpeers - - $ZT1 dump - - $ZT1 get $TEST_NETWORK allowDNS - $ZT1 get $TEST_NETWORK allowDefault - $ZT1 get $TEST_NETWORK allowGlobal - $ZT1 get $TEST_NETWORK allowManaged - $ZT1 get $TEST_NETWORK bridge - $ZT1 get $TEST_NETWORK broadcastEnabled - $ZT1 get $TEST_NETWORK dhcp - $ZT1 get $TEST_NETWORK id - $ZT1 get $TEST_NETWORK mac - $ZT1 get $TEST_NETWORK mtu - $ZT1 get $TEST_NETWORK name - $ZT1 get $TEST_NETWORK netconfRevision - $ZT1 get $TEST_NETWORK nwid - $ZT1 get $TEST_NETWORK portDeviceName - $ZT1 get $TEST_NETWORK portError - $ZT1 get $TEST_NETWORK status - $ZT1 get $TEST_NETWORK type - - # Test an invalid command - $ZT1 get $TEST_NETWORK derpderp - - # TODO: Validate JSON - - # Performance Test - - export FILENAME_PERF_JSON="$TEST_FILEPATH_PREFIX-iperf.json" - - echo -e "\nBeginning performance test:" - - echo -e "\nStarting server:" - - echo "$NS1 iperf3 -s &" - sleep 1 - - echo -e "\nStarting client:" - sleep 1 - - echo "$NS2 iperf3 --json -c $node1_ip4 > $FILENAME_PERF_JSON" - - cat $FILENAME_PERF_JSON - - # Let ZeroTier idle long enough for various timers - - echo -e "\nIdling ZeroTier for $RUN_LENGTH seconds..." - sleep $RUN_LENGTH - - echo -e "\nLeaving networks" - - $ZT1 leave $TEST_NETWORK - $ZT2 leave $TEST_NETWORK - - sleep 5 - - exit_test_and_generate_report $TEST_OK "completed test" -} - -################################################################################ -# Generate report # -################################################################################ - -exit_test_and_generate_report() { - - echo -e "\nStopping memory check..." - sudo pkill -15 -f valgrind - sleep 10 - - time_test_end=$(date +%s) - - echo "Exiting test with reason: $2 ($1)" - - # Collect ZeroTier dump files - - echo -e "\nCollecting ZeroTier dump files" - - node1_id=$($ZT1 -j status | jq -r .address) - node2_id=$($ZT2 -j status | jq -r .address) - - $ZT1 dump - mv zerotier_dump.txt "$TEST_FILEPATH_PREFIX-node-dump-$node1_id.txt" - - $ZT2 dump - mv zerotier_dump.txt "$TEST_FILEPATH_PREFIX-node-dump-$node2_id.txt" - - # Copy ZeroTier stdout/stderr logs - - cp node_1.log "$TEST_FILEPATH_PREFIX-node-log-$node1_id.txt" - cp node_2.log "$TEST_FILEPATH_PREFIX-node-log-$node2_id.txt" - - # Generate report - - cat $FILENAME_MEMORY_LOG - - DEFINITELY_LOST=$(xmlstarlet sel -t -v '/valgrindoutput/error/xwhat' \ - $FILENAME_MEMORY_LOG | grep "definitely" | awk '{print $1;}') - POSSIBLY_LOST=$(xmlstarlet sel -t -v '/valgrindoutput/error/xwhat' \ - $FILENAME_MEMORY_LOG | grep "possibly" | awk '{print $1;}') - - # Generate coverage report artifact and summary - - FILENAME_COVERAGE_JSON="$TEST_FILEPATH_PREFIX-coverage.json" - FILENAME_COVERAGE_HTML="$TEST_FILEPATH_PREFIX-coverage.html" - - echo -e "\nGenerating coverage test report..." - - gcovr -r . --exclude ext --json-summary $FILENAME_COVERAGE_JSON \ - --html >$FILENAME_COVERAGE_HTML - - cat $FILENAME_COVERAGE_JSON - - COVERAGE_LINE_COVERED=$(cat $FILENAME_COVERAGE_JSON | jq .line_covered) - COVERAGE_LINE_TOTAL=$(cat $FILENAME_COVERAGE_JSON | jq .line_total) - COVERAGE_LINE_PERCENT=$(cat $FILENAME_COVERAGE_JSON | jq .line_percent) - - COVERAGE_LINE_COVERED="${COVERAGE_LINE_COVERED:-0}" - COVERAGE_LINE_TOTAL="${COVERAGE_LINE_TOTAL:-0}" - COVERAGE_LINE_PERCENT="${COVERAGE_LINE_PERCENT:-0}" - - # Default values - - DEFINITELY_LOST="${DEFINITELY_LOST:-0}" - POSSIBLY_LOST="${POSSIBLY_LOST:-0}" - ping_loss_percent_1_to_2="${ping_loss_percent_1_to_2:-100.0}" - ping_loss_percent_2_to_1="${ping_loss_percent_2_to_1:-100.0}" - time_to_both_nodes_online="${time_to_both_nodes_online:--1}" - - # Summarize and emit json for trend reporting - - FILENAME_SUMMARY="$TEST_FILEPATH_PREFIX-summary.json" - - time_length_test=$((time_test_end - time_test_start)) - if [[ $time_to_both_nodes_online != -1 ]]; - then - time_to_both_nodes_online=$((time_to_both_nodes_online - time_test_start)) - fi - #time_length_zt_join=$((time_zt_join_end-time_zt_join_start)) - #time_length_zt_leave=$((time_zt_leave_end-time_zt_leave_start)) - #time_length_zt_can_still_ping=$((time_zt_can_still_ping-time_zt_leave_start)) - - summary=$( - cat <$FILENAME_SUMMARY - cat $FILENAME_SUMMARY - - exit 0 -} - -################################################################################ -# CLI Check # -################################################################################ - -spam_cli() { - echo "Spamming CLI..." - # Rapidly spam the CLI with joins/leaves - - MAX_TRIES="${1:-10}" - - for ((s = 0; s <= MAX_TRIES; s++)); do - $ZT1 status - $ZT2 status - sleep 0.1 - done - - SPAM_TRIES=128 - - for ((s = 0; s <= SPAM_TRIES; s++)); do - $ZT1 join $TEST_NETWORK - done - - for ((s = 0; s <= SPAM_TRIES; s++)); do - $ZT1 leave $TEST_NETWORK - done - - for ((s = 0; s <= SPAM_TRIES; s++)); do - $ZT1 leave $TEST_NETWORK - $ZT1 join $TEST_NETWORK - done -} - -################################################################################ -# Check for proper exit on load of invalid identity # -################################################################################ - -check_exit_on_invalid_identity() { - echo "Checking ZeroTier exits on invalid identity..." - mkdir -p $(pwd)/exit_test - ZT1="sudo ./zerotier-one -p9999 $(pwd)/exit_test" - echo "asdfasdfasdfasdf" > $(pwd)/exit_test/identity.secret - echo "asdfasdfasdfasdf" > $(pwd)/exit_test/authtoken.secret - - echo "Launch ZeroTier with an invalid identity" - $ZT1 & - my_pid=$! - - echo "Waiting 5 seconds" - sleep 5 - - # check if process is running - kill -0 $my_pid - if [ $? -eq 0 ]; then - exit_test_and_generate_report $TEST_FAIL "Exit test FAILED: Process still running after being fed an invalid identity" - fi -} - -################################################################################ -# Check that we're binding to the primary port for TCP/TCP6/UDP # -################################################################################ - -check_bind_to_correct_ports() { - PORT_NUMBER=$1 - echo "Checking bound ports:" - sudo netstat -anp | grep "$PORT_NUMBER" | grep "zerotier" - if [[ $(sudo netstat -anp | grep "$PORT_NUMBER" | grep "zerotier" | grep "tcp") ]]; - then - : - else - exit_test_and_generate_report $TEST_FAIL "ZeroTier did not bind to tcp/$1" - fi - if [[ $(sudo netstat -anp | grep "$PORT_NUMBER" | grep "zerotier" | grep "tcp6") ]]; - then - : - else - exit_test_and_generate_report $TEST_FAIL "ZeroTier did not bind to tcp6/$1" - fi - if [[ $(sudo netstat -anp | grep "$PORT_NUMBER" | grep "zerotier" | grep "udp") ]]; - then - : - else - exit_test_and_generate_report $TEST_FAIL "ZeroTier did not bind to udp/$1" - fi -} - -test "$@" diff --git a/.github/workflows/validate-report.sh b/.github/workflows/validate-report.sh deleted file mode 100755 index 3ae4e1a16..000000000 --- a/.github/workflows/validate-report.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -################################################################################ -# Set exit code depending on tool reports # -################################################################################ - -DEFINITELY_LOST=$(cat *test-results/*summary.json | jq .num_definite_bytes_lost) -EXIT_CODE=$(cat *test-results/*summary.json | jq .exit_code) -EXIT_REASON=$(cat *test-results/*summary.json | jq .exit_reason) - -cat *test-results/*summary.json - -echo -e "\nBytes of memory definitely lost: $DEFINITELY_LOST" - -if [[ "$DEFINITELY_LOST" -gt 0 ]]; then - exit 1 -fi - -# Catch-all for other non-zero exit codes - -if [[ "$EXIT_CODE" -gt 0 ]]; then - echo "Test failed: $EXIT_REASON" - exit 1 -fi \ No newline at end of file diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml deleted file mode 100644 index bbc107660..000000000 --- a/.github/workflows/validate.yml +++ /dev/null @@ -1,57 +0,0 @@ -on: - pull_request: - push: - workflow_dispatch: - -jobs: - build_ubuntu: - runs-on: ubuntu-latest - steps: - - name: gitconfig - run: | - git config --global core.autocrlf input - - - name: checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: x86_64-unknown-linux-gnu - override: true - components: rustfmt, clippy - - - name: Set up cargo cache - uses: Swatinem/rust-cache@v2 - continue-on-error: false - with: - key: ${{ runner.os }}-cargo-${{ hashFiles('zeroidc//Cargo.lock') }} - shared-key: ${{ runner.os }}-cargo- - workspaces: | - zeroidc/ - - - name: validate-1m-linux - env: - CC: 'gcc' - CXX: 'g++' - BRANCH: ${{ github.ref_name }} - run: | - sudo apt update && sudo apt install -y valgrind xmlstarlet gcovr iperf3 tree - make one ZT_COVERAGE=1 ZT_TRACE=1 - sudo chmod +x ./.github/workflows/validate-linux.sh - sudo ./.github/workflows/validate-linux.sh - - - name: Archive test results - uses: actions/upload-artifact@v4 - with: - name: ${{github.sha}}-test-results - path: "*test-results*" - - - name: final-report - run: | - sudo chmod +x ./.github/workflows/validate-report.sh - sudo ./.github/workflows/validate-report.sh - diff --git a/.gitignore b/.gitignore index 04a7d1eac..9c87a061e 100755 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,10 @@ # Main binaries created in *nix builds -/zerotier-one -/zerotier-idtool -/zerotier-cli -/zerotier-selftest -/zerotier -/nltest - -# IDE stuff -/.idea -/.nova -/compile_commands.json +/zerotier-* # OS-created garbage files from various platforms .DS_Store .Apple* Thumbs.db -@eaDir -._* # Windows build droppings /windows/ZeroTierOne.sdf @@ -33,19 +21,10 @@ Thumbs.db /windows/Release /windows/WebUIWrapper/bin /windows/WebUIWrapper/obj -/windows/lib /ext/installfiles/windows/ZeroTier One-SetupFiles +/ext/installfiles/windows/Prerequisites /ext/installfiles/windows/*-cache /ZeroTier One.msi -*.vcxproj.backup -/windows/TapDriver6/Win7Debug -/windows/TapDriver6/win7Release -/windows/*.db -/windows/*.opendb -enc_temp_folder -/windows/copyutil/bin -/windows/copyutil/obj -.vs/ # *nix/Mac build droppings /build-* @@ -54,19 +33,18 @@ enc_temp_folder /examples/docker/test-*.env /world/mkworld /world/*.c25519 -zt1-src.tar.gz -/MacEthernetTapAgent # Miscellaneous temporaries, build files, etc. *.log *.opensdf *.user *.cache +*.obj *.tlog *.pid *.pkg *.o -/*.a +*.a *.dylib *.so *.so.* @@ -78,13 +56,16 @@ zt1-src.tar.gz *.tmp .depend node_modules -zt1_update_* -debian/files -debian/zerotier-one -debian/zerotier-one*.debhelper -debian/*.log -debian/zerotier-one.substvars -root-watcher/config.json +cluster-geo/cluster-geo/config.js +cluster-geo/cluster-geo/cache.* +tests/http/zerotier-one +tests/http/big-test-hosts +netcon/httpstub + +# MacGap wrapper build files +/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/* +/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/xcuserdata/* +/ext/mac-ui-macgap1-wrapper/src/build # Java/Android/JNI build droppings java/obj/ @@ -98,46 +79,5 @@ java/build_win32/ windows/WinUI/obj/ windows/WinUI/bin/ windows/ZeroTierOne/Debug/ -/ext/installfiles/windows/chocolatey/zerotier-one/*.nupkg - -# Miscellaneous mac/Xcode droppings -.DS_Store -.Trashes -*.swp -*~.nib -DerivedData/ -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 -*.xccheckout -xcuserdata/ -.vscode -__pycache__ -*~ -attic/world/*.c25519 -attic/world/mkworld -workspace/ -workspace2/ -zeroidc/target/ -tcp-proxy/target - -#snapcraft specifics -/parts/ -/stage/ -/prime/ - -*.snap - -.snapcraft -__pycache__ -*.pyc -*_source.tar.bz2 -snap/.snapcraft -tcp-proxy/tcp-proxy -rustybits/target -ext/installfiles/windows/*.back*.aip +/doc/*.1 +/doc/*.8 diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 000000000..6b21f572e --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,77 @@ +## Primary Authors + + * ZeroTier protocol design and core network virtualization engine, ZeroTier One service, React web UI, packaging for most platforms, kitchen sink...
+ Adam Ierymenko / adam.ierymenko@zerotier.com + + * Java JNI Interface to enable Android application development, and Android app itself (code for that is elsewhere)
+ Grant Limberg / glimberg@gmail.com + + * Network Containers for Linux, iOS, Android
+ Joseph Henry / joseph.henry@zerotier.com + +## Third Party Contributors + + * A number of fixes and improvements to the new controller, other stuff.
+ Kees Bos / https://github.com/keesbos/ + + * Debugging and testing, OpenWRT support fixes.
+ Moritz Warning / moritzwarning@web.de + + * Debian GNU/Linux packaging, manual pages, and license compliance edits.
+ Ben Finney + + * Several others made smaller contributions, which GitHub tracks here:
+ https://github.com/zerotier/ZeroTierOne/graphs/contributors/ + +## Third-Party Code + + * LZ4 compression algorithm by Yann Collet + + * Files: ext/lz4/* + * Home page: http://code.google.com/p/lz4/ + * License grant: BSD attribution + + * http-parser by Joyent, Inc. (many authors) + + * Files: ext/http-parser/* + * Home page: https://github.com/joyent/http-parser/ + * License grant: MIT/Expat + + * json-parser by James McLaughlin + + * Files: ext/json-parser/* + * Home page: https://github.com/udp/json-parser/ + * License grant: BSD attribution + + * TunTapOSX by Mattias Nissler + + * Files: ext/tap-mac/tuntap/* + * Home page: http://tuntaposx.sourceforge.net/ + * License grant: BSD attribution no-endorsement + + * tap-windows and tap-windows6 by the OpenVPN project + + * Files: windows/TapDriver6/* + * Home page: + https://github.com/OpenVPN/tap-windows/ + https://github.com/OpenVPN/tap-windows6/ + * License grant: GNU GPL v2 + + * Salsa20 stream cipher, Curve25519 elliptic curve cipher, Ed25519 + digital signature algorithm, and Poly1305 MAC algorithm, all by + Daniel J. Bernstein + + * Files: + node/Salsa20.hpp + node/C25519.hpp + node/Poly1305.hpp + * Home page: http://cr.yp.to/ + * License grant: public domain + + * MiniUPNPC by Thomas Bernard + + * Files: + ext/libnatpmp/* + ext/miniupnpc/* + * Home page: http://miniupnp.free.fr/ + * License grant: BSD attribution no-endorsement diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index fff7808e1..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# CMake build script for libzerotiercore.a - -cmake_minimum_required (VERSION 2.8) -project (zerotiercore) - -set (PROJ_DIR ${PROJECT_SOURCE_DIR}) -set (ZT_DEFS -std=c++11) - -file(GLOB core_src_glob ${PROJ_DIR}/node/*.cpp) -add_library(zerotiercore STATIC ${core_src_glob}) - -target_compile_options(zerotiercore PRIVATE ${ZT_DEFS}) diff --git a/COPYING b/COPYING index 7f0801e20..23d42dfa1 100644 --- a/COPYING +++ b/COPYING @@ -1,8 +1,13 @@ ZeroTier One, an endpoint server for the ZeroTier virtual network layer. -Copyright © 2011–2019 ZeroTier, Inc. +Copyright © 2011–2016 ZeroTier, Inc. -ZeroTier is released under the terms of the BUSL version 1.1. See the -file LICENSE.txt for details. +ZeroTier One is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +See the file ‘LICENSE.GPL-3’ for the text of the GNU GPL version 3. +If that file is not present, see . .. Local variables: diff --git a/Dockerfile.ci b/Dockerfile.ci deleted file mode 100644 index 9ff3b011a..000000000 --- a/Dockerfile.ci +++ /dev/null @@ -1,28 +0,0 @@ -# vim: ft=dockerfile - -FROM ubuntu:21.04 as stage - -RUN apt-get update -qq && apt-get -qq install make clang -COPY . . -RUN /usr/bin/make -RUN echo $PWD -RUN cp zerotier-one /usr/sbin - -FROM ubuntu:21.04 - -COPY --from=stage /zerotier-one /usr/sbin -RUN ln -sf /usr/sbin/zerotier-one /usr/sbin/zerotier-idtool -RUN ln -sf /usr/sbin/zerotier-one /usr/sbin/zerotier-cli - -RUN echo "${VERSION}" > /etc/zerotier-version -RUN rm -rf /var/lib/zerotier-one - - -RUN apt-get -qq update -RUN apt-get -qq install iproute2 net-tools fping 2ping iputils-ping iputils-arping - -COPY entrypoint.sh.release /entrypoint.sh -RUN chmod 755 /entrypoint.sh - -CMD [] -ENTRYPOINT ["/entrypoint.sh"] diff --git a/Dockerfile.release b/Dockerfile.release deleted file mode 100644 index 2a289cead..000000000 --- a/Dockerfile.release +++ /dev/null @@ -1,23 +0,0 @@ -# vim: ft=dockerfile - -FROM debian:bookworm - -ARG VERSION - -RUN apt-get update -qq && apt-get install curl gpg -y -RUN mkdir -p /usr/share/zerotier && \ - curl -o /usr/share/zerotier/tmp.asc "https://download.zerotier.com/contact%40zerotier.com.gpg" && \ - gpg --no-default-keyring --keyring /usr/share/zerotier/zerotier.gpg --import /usr/share/zerotier/tmp.asc && \ - rm -f /usr/share/zerotier/tmp.asc && \ - echo "deb [signed-by=/usr/share/zerotier/zerotier.gpg] http://download.zerotier.com/debian/bookworm bookworm main" > /etc/apt/sources.list.d/zerotier.list - -RUN apt-get update -qq && apt-get install zerotier-one=${VERSION} curl iproute2 net-tools iputils-ping openssl libssl3 -y -RUN rm -rf /var/lib/zerotier-one - -COPY entrypoint.sh.release /entrypoint.sh -RUN chmod 755 /entrypoint.sh - -HEALTHCHECK --interval=1s CMD bash /healthcheck.sh - -CMD [] -ENTRYPOINT ["/entrypoint.sh"] diff --git a/LICENSE.GPL-2 b/LICENSE.GPL-2 new file mode 100644 index 000000000..d159169d1 --- /dev/null +++ b/LICENSE.GPL-2 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/attic/historic/anode/LICENSE.txt b/LICENSE.GPL-3 similarity index 100% rename from attic/historic/anode/LICENSE.txt rename to LICENSE.GPL-3 diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 06a3fad64..000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,149 +0,0 @@ ------------------------------------------------------------------------------ - -Business Source License 1.1 - -License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. -"Business Source License" is a trademark of MariaDB Corporation Ab. - ------------------------------------------------------------------------------ - -Parameters - -Licensor: ZeroTier, Inc. -Licensed Work: ZeroTier Network Virtualization Engine 1.4.4 - The Licensed Work is (c)2019 ZeroTier, Inc. -Additional Use Grant: You may make use of the Licensed Work, provided you - do not use it in any of the following ways: - - * Sell hosted ZeroTier services as a "SaaS" Product - - (1) Operate or sell access to ZeroTier root servers, - network controllers, or authorization key or certificate - generation components of the Licensed Work as a - for-profit service, regardless of whether the use of - these components is sold alone or is bundled with other - services. Note that this does not apply to the use of - ZeroTier behind the scenes to operate a service not - related to ZeroTier network administration. - - * Create Non-Open-Source Commercial Derivative Works - - (2) Link or directly include the Licensed Work in a - commercial or for-profit application or other product - not distributed under an Open Source Initiative (OSI) - compliant license. See: https://opensource.org/licenses - - (3) Remove the name, logo, copyright, or other branding - material from the Licensed Work to create a "rebranded" - or "white labeled" version to distribute as part of - any commercial or for-profit product or service. - - * Certain Government Uses - - (4) Use or deploy the Licensed Work in a government - setting in support of any active government function - or operation with the exception of the following: - physical or mental health care, family and social - services, social welfare, senior care, child care, and - the care of persons with disabilities. - -Change Date: 2026-01-01 - -Change License: Apache License version 2.0 as published by the Apache - Software Foundation - https://www.apache.org/licenses/ - -Alternative Licensing - -If you would like to use the Licensed Work in any way that conflicts with -the stipulations of the Additional Use Grant, contact ZeroTier, Inc. to -obtain an alternative commercial license. - -Visit us on the web at: https://www.zerotier.com/ - -Notice - -The Business Source License (this document, or the "License") is not an Open -Source license. However, the Licensed Work will eventually be made available -under an Open Source License, as stated in this License. - -For more information on the use of the Business Source License for ZeroTier -products, please visit our pricing page which contains license details and -and license FAQ: https://zerotier.com/pricing - -For more information on the use of the Business Source License generally, -please visit the Adopting and Developing Business Source License FAQ at -https://mariadb.com/bsl-faq-adopting. - ------------------------------------------------------------------------------ - -Business Source License 1.1 - -Terms - -The Licensor hereby grants you the right to copy, modify, create derivative -works, redistribute, and make non-production use of the Licensed Work. The -Licensor may make an Additional Use Grant, above, permitting limited -production use. - -Effective on the Change Date, or the fourth anniversary of the first publicly -available distribution of a specific version of the Licensed Work under this -License, whichever comes first, the Licensor hereby grants you rights under -the terms of the Change License, and the rights granted in the paragraph -above terminate. - -If your use of the Licensed Work does not comply with the requirements -currently in effect as described in this License, you must purchase a -commercial license from the Licensor, its affiliated entities, or authorized -resellers, or you must refrain from using the Licensed Work. - -All copies of the original and modified Licensed Work, and derivative works -of the Licensed Work, are subject to this License. This License applies -separately for each version of the Licensed Work and the Change Date may vary -for each version of the Licensed Work released by Licensor. - -You must conspicuously display this License on each original or modified copy -of the Licensed Work. If you receive the Licensed Work in original or -modified form from a third party, the terms and conditions set forth in this -License apply to your use of that work. - -Any use of the Licensed Work in violation of this License will automatically -terminate your rights under this License for the current and all other -versions of the Licensed Work. - -This License does not grant you any right in any trademark or logo of -Licensor or its affiliates (provided that you may use a trademark or logo of -Licensor as expressly required by this License). - -TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON -AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, -EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND -TITLE. - ------------------------------------------------------------------------------ - -MariaDB hereby grants you permission to use this License’s text to license -your works, and to refer to it using the trademark "Business Source License", -as long as you comply with the Covenants of Licensor below. - -Covenants of Licensor - -In consideration of the right to use this License’s text and the "Business -Source License" name and trademark, Licensor covenants to MariaDB, and to all -other recipients of the licensed work to be provided by Licensor: - -1. To specify as the Change License the GPL Version 2.0 or any later version, - or a license that is compatible with GPL Version 2.0 or a later version, - where "compatible" means that software provided under the Change License can - be included in a program with software provided under GPL Version 2.0 or a - later version. Licensor may specify additional Change Licenses without - limitation. - -2. To either: (a) specify an additional grant of rights to use that does not - impose any additional restriction on the right granted in this License, as - the Additional Use Grant; or (b) insert the text "None". - -3. To specify a Change Date. - -4. Not to modify this License in any other way. diff --git a/Makefile b/Makefile index f77767fb8..5a5f6605e 100644 --- a/Makefile +++ b/Makefile @@ -11,26 +11,8 @@ ifeq ($(OSTYPE),Linux) endif ifeq ($(OSTYPE),FreeBSD) - CC=clang - CXX=clang++ - ZT_BUILD_PLATFORM=7 - include make-bsd.mk + include make-freebsd.mk endif ifeq ($(OSTYPE),OpenBSD) - CC=clang - CXX=clang++ - ZT_BUILD_PLATFORM=9 - include make-bsd.mk + include make-freebsd.mk endif - -ifeq ($(OSTYPE),NetBSD) - include make-netbsd.mk -endif - -drone: - @echo "rendering .drone.yaml from .drone.jsonnet" - drone jsonnet --format --stream - drone sign zerotier/ZeroTierOne --save - -clang-format: - find node osdep service tcp-proxy controller -iname '*.cpp' -o -iname '*.hpp' | xargs clang-format -i diff --git a/OFFICIAL-RELEASE-STEPS.md b/OFFICIAL-RELEASE-STEPS.md deleted file mode 100644 index 0c198bd68..000000000 --- a/OFFICIAL-RELEASE-STEPS.md +++ /dev/null @@ -1,33 +0,0 @@ -ZeroTier Official Release Steps -====== - -This is mostly for ZeroTier internal use, but others who want to do builds might find it helpful. - -Note: Many of these steps will require GPG and other signing keys that are kept in cold storage and must be mounted. - -# Bumping the Version and Preparing Installers - -The version must be incremented in all of the following files: - - /version.h - /zerotier-one.spec - /debian/changelog - /ext/installfiles/mac/ZeroTier One.pkgproj - /ext/installfiles/windows/ZeroTier One.aip - ../DesktopUI/mac-app-template/ZeroTier.app/Contents/Info.plist - -The final .AIP file can only be edited on Windows with [Advanced Installer Enterprise](http://www.advancedinstaller.com/). In addition to incrementing the version be sure that a new product code is generated. (The "upgrade code" GUID on the other hand must never change.) - -# Building for Supported Platforms - -## Macintosh - -Mac's easy. Just type: - - make official - -You will need [Packages](http://s.sudre.free.fr/Software/Packages/about.html) and our release signing key in the keychain. - -## Windows - -First load the Visual Studio solution and rebuild the UI and ZeroTier One in both x64, i386, and arm64 `Release` mode. Then load [Advanced Installer Enterprise](http://www.advancedinstaller.com/), check that the version is correct, and build. The build will fail if any build artifacts are missing, and Windows must have our product singing key (from DigiCert) available to sign the resulting MSI file. The MSI must then be tested on at least a few different CLEAN Windows VMs to ensure that the installer is valid and properly signed. diff --git a/README.docker.md b/README.docker.md deleted file mode 100644 index 5b046e320..000000000 --- a/README.docker.md +++ /dev/null @@ -1,73 +0,0 @@ -# ZeroTier One in a container! - -**NOTE:** _Most of this information pertains to the docker image only. For more information about ZeroTier, check out the repository_: [here](https://github.com/zerotier/ZeroTierOne) or the [commercial website](https://www.zerotier.com). - -[ZeroTier](https://www.zerotier.com) is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region. - -This is accomplished by combining a cryptographically addressed and secure peer to peer network (termed VL1) with an Ethernet emulation layer somewhat similar to VXLAN (termed VL2). Our VL2 Ethernet virtualization layer includes advanced enterprise SDN features like fine grained access control rules for network micro-segmentation and security monitoring. - -All ZeroTier traffic is encrypted end-to-end using secret keys that only you control. Most traffic flows peer to peer, though we offer free (but slow) relaying for users who cannot establish peer to peer connections. - -The goals and design principles of ZeroTier are inspired by among other things the original [Google BeyondCorp](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43231.pdf) paper and the [Jericho Forum](https://en.wikipedia.org/wiki/Jericho_Forum) with its notion of "deperimeterization." - -Visit [ZeroTier's site](https://www.zerotier.com/) for more information and [pre-built binary packages](https://www.zerotier.com/download/). Apps for Android and iOS are available for free in the Google Play and Apple app stores. - -ZeroTier is licensed under the [BSL version 1.1](https://mariadb.com/bsl11/). See [LICENSE.txt](https://github.com/zerotier/ZeroTierOne/blob/master/LICENSE.txt) and the [ZeroTier pricing page](https://www.zerotier.com/pricing) for details. ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license. - -A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md](https://github.com/zerotier/ZeroTierOne/blob/master/AUTHORS.md) for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.). - -## Building the docker image - -Due to the network being a substrate for most applications and not an application unto itself, it makes sense that many people would want to build their own image based on our formula. - -The image is based on `debian:buster`. - -The `Dockerfile.release` file contains build instructions for building the described image in the rest of the README. The build is multi-arch and multi-release capable. - -These build arguments power the build: - -- `PACKAGE_BASEURL`: The base URL of the package repository to fetch from. (default: `https://download.zerotier.com/debian/buster/pool/main/z/zerotier-one/`) -- `ARCH`: The architecture of the package, in debian format. Must match your image arch. (default: `amd64`) -- `VERSION`: **REQUIRED** the version of ZeroTier to fetch. - -You can build this image like so: - -``` -docker build -f Dockerfile.release -t mybuild --build-arg VERSION=1.6.5 . -``` - -## Using the docker image - -The `entrypoint.sh` in the docker image is a little different; zerotier will be spawned in the background and the "main process" is actually just a sleeping shell script. This allows `zerotier-one` to gracefully terminate in some situations largely unique to docker. - -The `zerotier/zerotier` image requires the `CAP_NET_ADMIN` capability and the `/dev/net/tun` device must be forwarded to it. - -To join a network, simply supply it on the command-line; you can supply multiple networks. - -``` -docker run --name myzerotier --rm --cap-add NET_ADMIN --device /dev/net/tun zerotier/zerotier:latest abcdefdeadbeef00 -``` - -Once joining all the networks you have provided, it will sleep until terminated. Note that in ZeroTier, joining a network does not necessarily mean you have an IP or can do anything, really. You will want to probe the control socket: - -``` -docker exec myzerotier zerotier-cli listnetworks -``` - -To ensure you have a network available before trying to listen on it. Without pre-configuring the identity, this usually means going to the central admin panel and clicking the checkmark against your zerotier identity. - -### Environment Variables - -You can control a few settings including the identity used and the authtoken used to interact with the control socket (which you can forward and access through `localhost:9993`). - -- `ZEROTIER_JOIN_NETWORKS`: additional way to set networks to join. -- `ZEROTIER_API_SECRET`: replaces the `authtoken.secret` before booting and allows you to manage the control socket's authentication key. -- `ZEROTIER_IDENTITY_PUBLIC`: the `identity.public` file for zerotier-one. Use `zerotier-idtool` to generate one of these for you. -- `ZEROTIER_IDENTITY_SECRET`: the `identity.secret` file for zerotier-one. Use `zerotier-idtool` to generate one of these for you. -- `ZEROTIER_LOCAL_CONF`: Sets the the `local.conf` file content for zerotier-one - -### Tips - -- Forwarding port `:9993` to somewhere outside is probably a good idea for highly trafficked services. -- Forwarding `localhost:9993` to a control network where you can drive it remotely might be a good idea, just be sure to set your authtoken properly through environment variables. -- Pre-generating your identities could be much simpler to do via our [terraform plugin](https://github.com/zerotier/terraform-provider-zerotier) diff --git a/README.md b/README.md index e881ce810..1a93a4348 100644 --- a/README.md +++ b/README.md @@ -1,197 +1,175 @@ -ZeroTier - Global Area Networking +ZeroTier One ====== -*This document is written for a software developer audience. For information on using ZeroTier, see the: [Website](https://www.zerotier.com), [Documentation Site](https://docs.zerotier.com), and [Discussion Forum](https://discuss.zerotier.com).* +ZeroTier is a software defined networking layer for Earth. -ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region. +It can be used for on-premise network virtualization, as a peer to peer VPN for mobile teams, for hybrid or multi-data-center cloud deployments, or just about anywhere else secure software defined virtual networking is useful. -This is accomplished by combining a cryptographically addressed and secure peer to peer network (termed VL1) with an Ethernet emulation layer somewhat similar to VXLAN (termed VL2). Our VL2 Ethernet virtualization layer includes advanced enterprise SDN features like fine grained access control rules for network micro-segmentation and security monitoring. +ZeroTier One is our OS-level client service. It allows Mac, Linux, Windows, FreeBSD, and soon other types of clients to join ZeroTier virtual networks like conventional VPNs or VLANs. It can run on native systems, VMs, or containers (Docker, OpenVZ, etc.). -All ZeroTier traffic is encrypted end-to-end using secret keys that only you control. Most traffic flows peer to peer, though we offer free (but slow) relaying for users who cannot establish peer to peer connections. +Visit [ZeroTier's site](https://www.zerotier.com/) for more information. You can also download professionally packaged binary installers/packages for a variety of supported OSes there if you don't want to build ZeroTier One from source. -The goals and design principles of ZeroTier are inspired by among other things the original [Google BeyondCorp](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43231.pdf) paper and the [Jericho Forum](https://en.wikipedia.org/wiki/Jericho_Forum) with its notion of "deperimeterization." +### Building from Source -Visit [ZeroTier's site](https://www.zerotier.com/) for more information and [pre-built binary packages](https://www.zerotier.com/download/). Apps for Android and iOS are available for free in the Google Play and Apple app stores. +For Mac, Linux, and BSD, just type "make" (or "gmake" on BSD). You won't need much installed; here are the requirements for various platforms: -ZeroTier is licensed under the [BSL version 1.1](https://mariadb.com/bsl11/). See [LICENSE.txt](LICENSE.txt) and the [ZeroTier pricing page](https://www.zerotier.com/pricing) for details. ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license. + * Mac: Xcode command line tools, and [Packages](http://s.sudre.free.fr/Software/Packages/about.html) if you want to build an OSX .pkg installer ("make mac-dist-pkg"). It should build on OSX 10.7 or newer. + * Linux: gcc/g++ or clang/clang++ (Makefile will use clang by default if available.) + * FreeBSD (and other BSD): C++ compiler (G++ usually) and GNU make (gmake). -A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md](AUTHORS.md) for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.). +Each supported platform has its own *make-XXX.mk* file that contains the actual make rules for the platform. The right .mk file is included by the main Makefile based on the GNU make *OSTYPE* variable. Take a look at the .mk file for your platform for other targets, debug build rules, etc. -### Getting Started +Windows, of course, is special. We build for Windows with Microsoft Visual Studio 2012 on Windows 7. A solution file is located in the *windows* subfolder. Newer versions of Visual Studio (and Windows) may work but haven't been tested. Older versions almost certainly will not, since they lack things like *stdint.h* and certain STL features. MinGW or other ports of gcc/clang to Windows should also work but haven't been tested. Build steps for Windows are a bit more complicated. For the moment you are on your own there. -Everything in the ZeroTier world is controlled by two types of identifier: 40-bit/10-digit *ZeroTier addresses* and 64-bit/16-digit *network IDs*. These identifiers are easily distinguished by their length. A ZeroTier address identifies a node or "device" (laptop, phone, server, VM, app, etc.) while a network ID identifies a virtual Ethernet network that can be joined by devices. +Mobile versions are in progress. They don't work yet, and in any case only the glue code will be included in this repository. The full mobile apps are in private repositories on our own git server. -ZeroTier addresses can be thought of as port numbers on an enormous planet-wide enterprise Ethernet smart switch supporting VLANs. Network IDs are VLAN IDs to which these ports may be assigned. A single port can be assigned to more than one VLAN. +### Supported Platforms -A ZeroTier address looks like `8056c2e21c` and a network ID looks like `8056c2e21c000001`. Network IDs are composed of the ZeroTier address of that network's primary controller and an arbitrary 24-bit ID that identifies the network on this controller. Network controllers are roughly analogous to SDN controllers in SDN protocols like [OpenFlow](https://en.wikipedia.org/wiki/OpenFlow), though as with the analogy between VXLAN and VL2 this should not be read to imply that the protocols or design are the same. You can use our convenient and inexpensive SaaS hosted controllers at [my.zerotier.com](https://my.zerotier.com/) or [run your own controller](controller/) if you don't mind messing around with JSON configuration files or writing scripts to do so. +CPU architecture shouldn't matter unless it's smaller than 32-bit or something really bizarre like a "middle-endian" processor. We have reports of ZeroTier One running on arm32, arm64, and MIPS. It builds and runs out of the box on Raspberry Pi, BeagleBone, BananaPi, and other ARM-based developer/hobbyist boards. -### Project Layout +ZeroTier is written in C and C++ (C++03 / ISO/IEC 14882:2003) and uses data structures and algorithms from the C++03 STL. We do not use any C++11 features (yet), since we want to support a few old and embedded platforms that don't have C++11 compilers. You *will* require a compiler and headers new enough to support 64-bit integers (long long) and the *stdint.h* header. The latter could also be faked by adding defines for things like *uint32\_t*, *int64\_t*, etc. -The base path contains the ZeroTier One service main entry point (`one.cpp`), self test code, makefiles, etc. - - - `artwork/`: icons, logos, etc. - - `attic/`: old stuff and experimental code that we want to keep around for reference. - - `controller/`: the reference network controller implementation, which is built and included by default on desktop and server build targets. - - `debian/`: files for building Debian packages on Linux. - - `doc/`: manual pages and other documentation. - - `ext/`: third party libraries, binaries that we ship for convenience on some platforms (Mac and Windows), and installation support files. - - `include/`: include files for the ZeroTier core. - - `java/`: a JNI wrapper used with our Android mobile app. (The whole Android app is not open source but may be made so in the future.) - - `node/`: the ZeroTier virtual Ethernet switch core, which is designed to be entirely separate from the rest of the code and able to be built as a stand-alone OS-independent library. Note to developers: do not use C++11 features in here, since we want this to build on old embedded platforms that lack C++11 support. C++11 can be used elsewhere. - - `osdep/`: code to support and integrate with OSes, including platform-specific stuff only built for certain targets. - - `rule-compiler/`: JavaScript rules language compiler for defining network-level rules. - - `service/`: the ZeroTier One service, which wraps the ZeroTier core and provides VPN-like connectivity to virtual networks for desktops, laptops, servers, VMs, and containers. - - `windows/`: Visual Studio solution files, Windows service code, and the Windows task bar app UI. - - `zeroidc/`: OIDC implementation used by ZeroTier service to log into SSO-enabled networks. (This part is written in Rust, and more Rust will be appearing in this repository in the future.) - -### Contributing - -Please do pull requests off of the `dev` branch. - -Releases are done by merging `dev` into `main` and then tagging and doing builds. - -### Build and Platform Notes - -To build on Mac and Linux just type `make`. On FreeBSD and OpenBSD `gmake` (GNU make) is required and can be installed from packages or ports. For Windows there is a Visual Studio solution in `windows/`. - - - **Mac** - - Xcode command line tools for macOS 10.13 or newer are required. - - Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*. - - **Linux** - - The minimum compiler versions required are GCC/G++ 8.x or CLANG/CLANG++ 5.x. - - Linux makefiles automatically detect and prefer clang/clang++ if present as it produces smaller and slightly faster binaries in most cases. You can override by supplying CC and CXX variables on the make command line. - - Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*. - - **Windows** - - Visual Studio 2022 on Windows 10 or newer. - - Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*. - - **FreeBSD** - - GNU make is required. Type `gmake` to build. - - `binutils` is required. Type `pkg install binutils` to install. - - Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*. - - **OpenBSD** - - There is a limit of four network memberships on OpenBSD as there are only four tap devices (`/dev/tap0` through `/dev/tap3`). - - GNU make is required. Type `gmake` to build. - - Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*. - -Typing `make selftest` will build a *zerotier-selftest* binary which unit tests various internals and reports on a few aspects of the build environment. It's a good idea to try this on novel platforms or architectures. +Typing "make selftest" will build a *zerotier-selftest* binary which unit tests various internals and reports on a few aspects of the build environment. It's a good idea to try this on novel platforms or architectures. ### Running -Running *zerotier-one* with `-h` option will show help. +Running *zerotier-one* with -h will show help. -On Linux and BSD, if you built from source, you can start the service with: +On Linux and BSD you can start the service with: sudo ./zerotier-one -d -On most distributions, macOS, and Windows, the installer will start the service and set it up to start on boot. - A home folder for your system will automatically be created. -The service is controlled via the JSON API, which by default is available at `127.0.0.1:9993`. It also listens on `0.0.0.0:9993` which is only usable if `allowManagementFrom` is properly configured in `local.conf`. We include a *zerotier-cli* command line utility to make API calls for standard things like joining and leaving networks. The *authtoken.secret* file in the home folder contains the secret token for accessing this API. See [service/README.md](service/README.md) for API documentation. +The service is controlled via the JSON API, which by default is available at 127.0.0.1 port 9993. We include a *zerotier-cli* command line utility to make API calls for standard things like joining and leaving networks. The *authtoken.secret* file in the home folder contains the secret token for accessing this API. See README.md in [service/](service/) for API documentation. Here's where home folders live (by default) on each OS: - * **Linux**: `/var/lib/zerotier-one` - * **FreeBSD** / **OpenBSD**: `/var/db/zerotier-one` - * **Mac**: `/Library/Application Support/ZeroTier/One` - * **Windows**: `\ProgramData\ZeroTier\One` (That's the default. The base 'shared app data' folder might be different if Windows is installed with a non-standard drive letter assignment or layout.) + * Linux: /var/lib/zerotier-one + * BSD: /var/db/zerotier-one + * Mac: /Library/Application Support/ZeroTier/One + * Windows: \\ProgramData\\ZeroTier\\One (That's for Windows 7. The base 'shared app data' folder might be different on different Windows versions.) -### Basic Troubleshooting +Running ZeroTier One on a Mac is the same, but OSX requires a kernel extension. We ship a signed binary build of the ZeroTier tap device driver, which can be installed on Mac with: + + sudo make install-mac-tap + +This will create the home folder for Mac, place *tap.kext* there, and set its modes correctly to enable ZeroTier One to manage it with *kextload* and *kextunload*. + +We recommend using our binary packages on Windows, since there are several prerequisites such as a tap driver that must be installed on the system *and* in the home folder. + +### Joining A Network + +ZeroTier virtual networks are identified by 16-digit hexadecimal network IDs, while devices are identified by 10-digit addresses. To get your address run: + + sudo zerotier-cli status + +(Use ./zerotier-cli if you're running it right from your build folder.) + +You should see something like: + + 200 info ########## ONLINE #.#.# + +That 10-digit hex code is you. It's derived via a one-way proof of work function from your cryptographic public key. Your public key can be found in *identity.public* in ZeroTier's home folder, while *identity.secret* contains your full identity including the secret portion of the key pair. + +(The identity files define your device's *identity*. Moving them to another system will move that identity. Be careful when cloning virtual machines that have identities stored on them. If two devices have the same identity, they'll "fight" over it and you won't know which device will receive network packets.) + +If you want to do a quick test, you can join [Earth](https://www.zerotier.com/earth.html). It's a global public network that anyone can join. Type: + + sudo zerotier-cli join 8056c2e21c000001 + +Then: + + sudo zerotier-cli listnetworks + +At first it'll be in *REQUESTING\_CONFIGURATION* state. In a few seconds to a minute you should see something like: + + 200 listnetworks 8056c2e21c000001 earth.zerotier.net ##:##:##:##:##:## OK PUBLIC zt0 ##.##.##.##/## + +Earth will assign you an IP address in the "unofficially available" globally unrouted 28.0.0.0/7 IP block so as to avoid conflicts with local networks. (Your networks can use any IP scheme, or can even leave IP addresses unmanaged.) Once you get an IP, you should be able to ping something: + + ping earth.zerotier.net + +Go to [http://earth.zerotier.net/](http://earth.zerotier.net/) to see a short little welcome page that will tell you your IP and Ethernet MAC address. + +Earth is a public place. If you don't want to stick around run: + + sudo zerotier-cli leave 8056c2e21c000001 + +The network (and associated interface) should be gone. + +Networks are created and administrated by network controllers. Most users will want to use our hosted controllers. Visit [our web site](https://www.zerotier.com/) for more information. Later in this README there are brief instructions about building ZeroTier One with network controller support for those who want to try running their own. + +Macintosh and Windows installers also install a GUI application. + +### Installing + +We don't have a "make install" rule quite yet. On Linux you can type: + + make installer + +This will build a binary that, when run, will install ZeroTier One on most current Linux distributions. We also have RPM and DEB build files in *ext/installfiles/linux* that wrap this installer in packages for RedHat/CentOS and Debian/Ubuntu derived distributions. If *rpmbuild* is present on the system, the RPM will be built. If *dpkg-deb* is present, the DEB package will be built. + +On Mac the best way is to install [Packages](http://s.sudre.free.fr/Software/Packages/about.html) and use: + + make mac-dist-pkg + +This builds a .pkg file that can be installed. + +In FreeBSD there is now an official .pkg in the FreeBSD repository. Type "pkg install zerotier". It can also be built and installed from source. + +Linux/BSD and Mac installations have an *uninstall.sh* file in their ZeroTier home folder that cleanly removes ZeroTier One from the system. Run this with: + + sudo /path/to/ZeroTier/home/folder/uninstall.sh + +Windows installers are insane. We build our .MSI installers with [Advanced Installer Enterprise](http://www.advancedinstaller.com). The Advanced Installer project file is in *ext/installfiles/windows*. To avoid lasting psychological trauma we recommend leaving Windows installers alone and using the pre-built Windows binaries on our web site. + +### Using ZeroTier One in Docker Containers + +To run the ZeroTier One service in a Docker container, run it with "--device=/dev/net/tun --cap-add=NET_ADMIN". This will allow ZeroTier One to open a "tap" virtual network port inside the container. + +Alternately, you can use Ethernet bridging to bridge the *docker0* device on your system to a ZeroTier virtual network. This allows you to run ZeroTier One on the host and bridge the entire Docker network backplane to a virtual network or other hosts. + +We're working on better "official" Docker support. In the meantime there is a [user-contributed project here](https://github.com/davide/docker-zerotier). + +### Building with Network Controller Support + +**Warning: as of beta version 1.0.3 the new network controller is not heavily tested. We recommend waiting for 1.0.4 to deploy this in production.** + +Network controllers are nodes responsible for issuing configurations and certificates to members of ZeroTier virtual networks. Most users won't need to run their own, so this code is by default not included in the ZeroTier One binary. + +You can build a network controller on Linux or Mac with: + + make ZT_ENABLE_NETWORK_CONTROLLER=1 + +This will build a version that contains the Sqlite-backed network controller and associated extensions to the JSON local service control API. You will need the development headers for sqlite3 installed. On Mac these ship as part of Xcode, while on Linux they'll be found in packages for the various distributions. + +See the JSON API documentation in [service/](service/) for more information about how to control controllers. + +### Troubleshooting For most users, it just works. -If you are running a local system firewall, we recommend adding a rules permitting zerotier. If you installed binaries for Windows this should be done automatically. Other platforms might require manual editing of local firewall rules depending on your configuration. +If you are running a local system firewall, we recommend adding a rule permitting UDP port 9993 inbound and outbound. If you installed binaries for Windows this should be done automatically. Other platforms might require manual editing of local firewall rules depending on your configuration. -See the [documentation site](https://docs.zerotier.com/zerotier/troubleshooting) for more information. +The Mac firewall can be found under "Security" in System Preferences. Linux has a variety of firewall configuration systems and tools. If you're using Ubuntu's *ufw*, you can do this: -The Mac firewall can be found under "Security" in System Preferences. Linux has a variety of firewall configuration systems and tools. + sudo ufw allow 9993/udp -On CentOS check `/etc/sysconfig/iptables` for IPTables rules. For other distributions consult your distribution's documentation. You'll also have to check the UIs or documentation for commercial third party firewall applications like Little Snitch (Mac), McAfee Firewall Enterprise (Windows), etc. if you are running any of those. Some corporate environments might have centrally managed firewall software, so you might also have to contact IT. +On CentOS check */etc/sysconfig/iptables* for IPTables rules. For other distributions consult your distribution's documentation. You'll also have to check the UIs or documentation for commercial third party firewall applications like Little Snitch (Mac), McAfee Firewall Enterprise (Windows), etc. if you are running any of those. Some corporate environments might have centrally managed firewall software, so you might also have to contact IT. ZeroTier One peers will automatically locate each other and communicate directly over a local wired LAN *if UDP port 9993 inbound is open*. If that port is filtered, they won't be able to see each others' LAN announcement packets. If you're experiencing poor performance between devices on the same physical network, check their firewall settings. Without LAN auto-location peers must attempt "loopback" NAT traversal, which sometimes fails and in any case requires that every packet traverse your external router twice. -Users behind certain types of firewalls and "symmetric" NAT devices may not be able to connect to external peers directly at all. ZeroTier has limited support for port prediction and will *attempt* to traverse symmetric NATs, but this doesn't always work. If P2P connectivity fails you'll be bouncing UDP packets off our relay servers resulting in slower performance. Some NAT router(s) have a configurable NAT mode, and setting this to "full cone" will eliminate this problem. If you do this you may also see a magical improvement for things like VoIP phones, Skype, BitTorrent, WebRTC, certain games, etc., since all of these use NAT traversal techniques similar to ours. +Users behind certain types of firewalls and "symmetric" NAT devices may not able able to connect to external peers directly at all. ZeroTier has limited support for port prediction and will *attempt* to traverse symmetric NATs, but this doesn't always work. If P2P connectivity fails you'll be bouncing UDP packets off our relay servers resulting in slower performance. Some NAT router(s) have a configurable NAT mode, and setting this to "full cone" will eliminate this problem. If you do this you may also see a magical improvement for things like VoIP phones, Skype, BitTorrent, WebRTC, certain games, etc., since all of these use NAT traversal techniques similar to ours. + +If you're interested, there's a [technical deep dive about NAT traversal on our blog](https://www.zerotier.com/blog/?p=226). A troubleshooting tool to help you diagnose NAT issues is planned for the future as are uPnP/IGD/NAT-PMP and IPv6 transport. If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to rootservers over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity. -Additional help can be found in our [knowledge base](https://zerotier.atlassian.net/wiki/spaces/SD/overview). +### Contributing -### Prometheus Metrics +There are three main branches: **edge**, **test**, and **master**. Other branches may be for specific features, tests, or use cases. In general **edge** is "bleeding" and may or may not work, while **test** should be relatively stable and **master** is the latest tagged release. Pull requests should generally be done against **test** or **edge**, since pull requests against **master** may be working against a branch that is somewhat out of date. -Prometheus Metrics are available at the `/metrics` API endpoint. This endpoint is protected by an API key stored in `metricstoken.secret` to prevent unwanted information leakage. Information that could be gleaned from the metrics include joined networks and peers your instance is talking to. +### License -Access control is via the ZeroTier control interface itself and `metricstoken.secret`. This can be sent as a bearer auth token, via the `X-ZT1-Auth` HTTP header field, or appended to the URL as `?auth=`. You can see the current metrics via `cURL` with the following command: - - // Linux - curl -H "X-ZT1-Auth: $(sudo cat /var/lib/zerotier-one/metricstoken.secret)" http://localhost:9993/metrics - - // macOS - curl -H "X-ZT1-Auth: $(sudo cat /Library/Application\ Support/ZeroTier/One/metricstoken.secret)" http://localhost:9993/metrics - - // Windows PowerShell (Admin) - Invoke-RestMethod -Headers @{'X-ZT1-Auth' = "$(Get-Content C:\ProgramData\ZeroTier\One\metricstoken.secret)"; } -Uri http://localhost:9993/metrics - -To configure a scrape job in Prometheus on the machine ZeroTier is running on, add this to your Prometheus `scrape_config`: - - - job_name: zerotier-one - honor_labels: true - scrape_interval: 15s - metrics_path: /metrics - static_configs: - - targets: - - 127.0.0.1:9993 - labels: - group: zerotier-one - node_id: $YOUR_10_CHARACTER_NODE_ID - authorization: - credentials: $YOUR_METRICS_TOKEN_SECRET - -If neither of these methods are desirable, it is probably possible to distribute metrics via [Prometheus Proxy](https://github.com/pambrose/prometheus-proxy) or some other tool. Note: We have not tested this internally, but will probably work with the correct configuration. - -Metrics are also available on disk in ZeroTier's working directory: - - // Linux - /var/lib/zerotier-one/metrics.prom - - // macOS - /Library/Application\ Support/ZeroTier/One/metrics.prom - - //Windows - C:\ProgramData\ZeroTier\One\metrics.prom - -#### Available Metrics - -| Metric Name | Labels | Metric Type | Description | -| --- | --- | --- | --- | -| zt_packet | packet_type, direction | Counter | ZeroTier packet type counts | -| zt_packet_error | error_type, direction | Counter | ZeroTier packet errors| -| zt_data | protocol, direction | Counter | number of bytes ZeroTier has transmitted or received | -| zt_num_networks | | Gauge | number of networks this instance is joined to | -| zt_network_multicast_groups_subscribed | network_id | Gauge | number of multicast groups networks are subscribed to | -| zt_network_packets | network_id, direction | Counter | number of incoming/outgoing packets per network | -| zt_peer_latency | node_id | Histogram | peer latency (ms) | -| zt_peer_path_count | node_id, status | Gauge | number of paths to peer | -| zt_peer_packets | node_id, direction | Counter | number of packets to/from a peer | -| zt_peer_packet_errors | node_id | Counter | number of incoming packet errors from a peer | - -If there are other metrics you'd like to see tracked, ask us in an Issue or send us a Pull Request! - -### HTTP / App server - -There is a static http file server suitable for hosting Single Page Apps at http://localhost:9993/app/ - -Use `zerotier-cli info -j` to find your zerotier-one service's homeDir - -``` sh -cd $ZT_HOME -sudo mkdir -p app/app1 -sudo mkdir -p app/appB -echo 'appA

hello world A' | sudo tee app/appA/index.html -echo 'app2

hello world 2' | sudo tee app/app2/index.html -curl -sL http://localhost:9993/app/appA http://localhost:9993/app/app2 -``` - -Then visit [http://localhost:9993/app/app1/](http://localhost:9993/app/app1/) and [http://localhost:9993/app/appB/](http://localhost:9993/app/appB/) - -Requests to paths don't exist return the app root index.html, as is customary for SPAs. -If you want, you can write some javascript that talks to the service or controller [api](https://docs.zerotier.com/service/v1). +The ZeroTier source code is open source and is licensed under the GNU GPL v3 (not LGPL). If you'd like to embed it in a closed-source commercial product or appliance, please e-mail [contact@zerotier.com](mailto:contact@zerotier.com) to discuss commercial licensing. Otherwise it can be used for free. diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md deleted file mode 100644 index e6582207e..000000000 --- a/RELEASE-NOTES.md +++ /dev/null @@ -1,506 +0,0 @@ -ZeroTier Release Notes -====== - -# 2024-10-23 -- Version 1.14.2 - - * Fix for missing entitlement on macOS Sequoia. - * Fix for a problem correctly parsing local.conf to enable low bandwidth mode. - * Increment versions of some dependent libraries. - * Other fixes. - -# 2024-09-12 -- Version 1.14.1 - - * Multithreaded packet I/O support! Currently this is just for Linux and must - be enabled in local.conf. It will likely make the largest difference on small - multi-core devices where CPU is a bottleneck and high throughput is desired. - It may be enabled by default in the future but we want it to be thoroughly - tested. It's a little harder than it seems at first glance due to the need - to keep packets in sequence and balance load. - * Several multipath bug fixes. - * Updated the versions on a number of libraries related to OIDC support and HTTP. - * MacOS .app now shows the correct version in its Info.plist manifest. - * Sanitize MAC addresses in JSON format rules parser. - * Some basic information about the platform (OS, CPU architecture) is now reported - to network controllers when networks are joined so it can be displayed to - network admins and in the future used in policy checking and inventory operations. - -# 2024-05-02 -- Version 1.14.0 - - * Linux I/O performance improvements under heavy load - * Improvements to multipath - * Fix for port rebinding "coma" bug after periods offline (some laptop users) - * Fixed a rules engine quirk/ambiguity (GitHub Issue #2200) - * Controller API enhancements: node names and other node meta-data - * Other bug fixes - -# 2023-09-12 -- Version 1.12.2 - - * More improvements to macOS full tunnel mode. - * Faster recovery after changes to physical network settings. - -# 2023-08-25 -- Version 1.12.1 - - * Minor release to fix a port binding issue in Linux. - * Update Debian dependencies. - * No changes for other platforms. - -# 2023-08-23 -- Version 1.12.0 - - * Experimental Windows ARM64 support - * Fix numerous sleep/wake issues on macOS and other platforms - * Faster recovery after changes to physical network settings - * Prometheus compatible metrics support! - * Fix full tunnel mode on recent macOS versions - * Numerous macOS DNS fixes - * 10-30% speed improvement on Linux - -# 2023-03-23 -- Version 1.10.6 - - * Prevent binding temporary ipv6 addresses on macos (#1910) - * Prevent path-learning loops (#1914) - * Prevent infinite loop of UAC prompts in tray app - -# 2023-03-10 -- Version 1.10.5 - - * Fix for high CPU usage bug on Windows - -# 2023-03-07 -- Version 1.10.4 - - * SECURITY FIX (Windows): this version fixes a file permission problem on - Windows that could allow non-privileged users on a Windows system to read - privileged files in the ZeroTier service's working directory. This could - allow an unprivileged local Windows user to administrate the local ZeroTier - instance without appropriate local permissions. This issue is not remotely - exploitable unless a remote user can read arbitrary local files, and does - not impact other operating systems. - - * Fix a bug in the handling of multiple IP address assignments to virtual - interfaces on macOS. - -# 2023-02-15 -- Version 1.10.3 - - * Fix for duplicate paths in client. Could cause connectivity issues. Affects all platforms. - * Fix for Ethernet Tap MTU setting, would not properly apply on Linux. - * Fix default route bugs (macOS.) - * Enable Ping automatically for ZeroTier Adapters (Windows.) - * SSO updates and minor bugfixes. - * Add low-bandwidth mode. - * Add forceTcpRelay mode (optionally enabled.) - * Fix bug that prevented setting of custom TCP relay address. - * Build script improvements and bug fixes. - -# 2022-11-01 -- Version 1.10.2 - - * Fix another SSO "stuck client" issue in zeroidc. - * Expose root-reported external IP/port information via the local JSON API for better diagnostics. - * Multipath: CLI output improvement for inspecting bonds - * Multipath: balance-aware mode - * Multipath: Custom policies - * Multipath: Link quality measurement improvements - -Note that releases are coming few and far between because most of our dev effort is going into version 2. - -# 2022-06-27 -- Version 1.10.1 - - * Fix an issue that could cause SSO clients to get "stuck" on stale auth URLs. - * A few other SSO related bug fixes. - -# 2022-06-07 -- Version 1.10.0 - - * Fix formatting problem in `zerotier-cli` when using SSO networks. - * Fix a few other minor bugs in SSO signin to prepare for general availability. - * Remove requirement for webview in desktop UI and instead just make everything available via the tray pulldown/menu. Use [libui-ng](https://github.com/libui-ng/libui-ng) for minor prompt dialogs. Saves space and eliminates installation headaches on Windows. - * Fix SSO "spam" bug in desktop UI. - * Use system default browser for SSO login so all your plugins, MFA devices, password managers, etc. will work as you have them configured. - * Minor fix for bonding/multipath. - -# 2022-05-10 -- Version 1.8.10 - - * Fixed a bug preventing SSO sign-on on Windows. - -# 2022-04-25 -- Version 1.8.9 - - * Fixed a long-standing and strange bug that was causing sporadic "phantom" packet authentication failures. Not a security problem but could be behind sporadic reports of link failures under some conditions. - * Fixed a memory leak in SSO/OIDC support. - * Fixed SSO/OIDC display error on CLI. - * Fixed a bug causing nodes to sometimes fail to push certs to each other (primarily affects SSO/OIDC use cases). - * Fixed a deadlock bug on leaving SSO/OIDC managed networks. - * Added some new Linux distributions to the build subsystem. - -# 2022-04-11 -- Version 1.8.8 - - * Fix a local privilege escalation bug in the Windows installer. - * Dependency fix for some Ubuntu versions. - * No changes for other platforms. Windows upgrade recommended, everyone else optional. - -# 2022-03-30 -- Version 1.8.7 - - * Fix for dependency installations in Windows MSI package. - * Fix for desktop UI setup when run by a non-super-user. - * Bug fix in local OIDC / SSO support for auth0 and other providers. - * Other minor fixes for e.g. old Linux distributions. - -# 2022-03-04 -- Version 1.8.6 - - * Fixed an issue that could cause the UI to be non-responsive if not joined to any networks. - * Fix dependency issues in Debian and RedHat packages for some distributions (Fedora, Mint). - * Bumped the peer cache serialization version to prevent "coma" issues on upgrade due to changes in path logic behaving badly with old values. - -# 2022-02-22 -- Version 1.8.5 - - * Plumbing under the hood for endpoint device SSO support. - * Fix in LinuxEthernetTap to tap device support on very old (2.6) Linux kernels. - * Fix an issue that could cause self-hosted roots ("moons") to fail to assist peers in making direct links. (GitHub issue #1512) - * Merge a series of changes by Joseph Henry (of ZeroTier) that should fix some edge cases where ZeroTier would "forget" valid paths. - * Minor multipath improvements for automatic path negotiation. - -# 2021-11-30 -- Version 1.8.4 - - * Fixed an ugly font problem on some older macOS versions. - * Fixed a bug that could cause the desktop tray app control panel to stop opening after a while on Windows. - * Fixed a possible double "release" in macOS tray app code that crashed on older macOS versions. - * Fixed installation on 32-bit Windows 10. - * Fixed a build flags issue that could cause ZeroTier to crash on older ARM32 CPUs. - -# 2021-11-15 -- Version 1.8.3 - - * Remove problematic spinlock, which was only used on x86_64 anyway. Just use pthread always. - * Fix fd leak on MacOS that caused non-responsiveness after some time. - * Fix Debian install scripts to set /usr/sbin/nologin as shell on service user. - * Fix regression that could prevent managed routes from being deleted. - * DesktopUI: Remove NSDate:now() call, now works on MacOS 10.13 or newer! - -# 2021-11-08 -- Version 1.8.2 - - * Fix multicast on linux. - * Fix a bug that could cause the tap adapter to have the wrong MAC on Linux. - * Update build flags to possibly support MacOS older than 10.14, but more work needs to be done. It may not work yet. - * Fix path variable setting on Windows. - -# 2021-10-28 -- Version 1.8.1 - - * Fix numerous UI issues from 1.8.0 (never fully released). - * Remove support for REALLY ancient 1.1.6 or earlier network controllers. - * MacOS IPv6 no longer binds to temporary addresses as these can cause interruptions if they expire. - * Added additional hardening against address impersonation on networks (also in 1.6.6). - * Fix an issue that could cause clobbering of MacOS IP route settings on restart. - - * NOTE: Windows 7 is no longer supported! Windows 7 users will have to use version 1.6.5 or earlier. - -# 2021-09-15 -- Version 1.8.0 (preview release only) - - * A *completely* rewritten desktop UI for Mac and Windows! - * Implement a workaround for one potential source of a "coma" bug, which can occur if buggy NATs/routers stop allowing the service to communicate on a given port. ZeroTier now reassigns a new secondary port if it's offline for a while unless a secondary port is manually specified in local.conf. Working around crummy buggy routers is an ongoing effort. - * Fix for MacOS MTU capping issue on feth devices - * Fix for mistakenly using v6 source addresses for v4 routes on some platforms - * Stop binding to temporary IPv6 addresses - * Set MAC address before bringing up Linux TAP link - * Check if DNS servers need to be applied on macOS - * Upgrade json.hpp dependency to version 3.10.2 - -# 2021-09-21 -- Version 1.6.6 - - * Backport COM hash check mitigation against network member impersonation. - -# 2021-04-13 -- Version 1.6.5 - - * Fix a bug in potential network path filtering that could in some circumstances lead to "software laser" effects. - * Fix a printf overflow in zerotier-cli (not exploitable or a security risk) - * Windows now looks up the name of ZeroTier devices instead of relying on them having "ZeroTier" in them. - -# 2021-02-15 -- Version 1.6.4 - - * The groundhog saw his shadow, which meant that the "connection coma" bug still wasn't gone. We think we found it this time. - -# 2021-02-02 -- Version 1.6.3 - - * Likely fix for GitHub issue #1334, an issue that could cause ZeroTier to - go into a "coma" on some networks. - * Also groundhog day - -# 2020-11-30 -- Version 1.6.2 - - * Fix an ARM hardware AES crypto issue (not an exploitable vulnerability). - * Fix a Linux network leave hang due to a mutex deadlock. - -# 2020-11-24 -- Version 1.6.1 - -This release fixes some minor bugs and other issues in 1.6.0. - - * Fixed a bug that caused IP addresses in the 203.0.0.0/8 block to be miscategorized as not being in global scope. - * Changed Linux builds to (hopefully) fix LXC and SELinux issues. - * Fixed unaligned memory access that caused crash on FreeBSD systems on the ARM architecture. - * Merged CLI options for controlling bonded devices into the beta multipath code. - * Updated Windows driver with Microsoft cross-signing to fix issues on some Windows systems. - -# 2020-11-19 -- Version 1.6.0 - -Version 1.6.0 is a major release that incorporates back-ported features from the 2.0 branch, which is still under development. It also fixes a number of issues. - -New features and improvements (including those listed under 1.5.0): - - * **Apple Silicon** (MacOS ARM64) native support via universal binary. ZeroTier now requires the very latest Xcode to build. - * **Linux performance improvements** for up to 25% faster tun/tap I/O performance on multi-core systems. - * **Multipath support** with modes modeled after the Linux kernel's bonding driver. This includes active-passive and active-active modes with fast failover and load balancing. See section 2.1.5 of the manual. - * **DNS configuration** push from network controllers to end nodes, with locally configurable permissions for whether or not push is allowed. - * **AES-GMAC-SIV** encryption mode, which is both somewhat more secure and significantly faster than the old Salsa20/12-Poly1305 mode on hardware that supports AES acceleration. This includes virtually all X86-64 chips and most ARM64. This mode is based on AES-SIV and has been audited by Trail of Bits to ensure that it is equivalent security-wise. - -Bug fixes: - - * **Managed route assignment fixes** to eliminate missing routes on Linux and what we believe to be the source of sporadic high CPU usage on MacOS. - * **Hang on shutdown** issues should be fixed. - * **Sporadic multicast outages** should be fixed. - -Known remaining issues: - - * AES hardware acceleration is not yet supported on 32-bit ARM, PowerPC (32 or 64), or MIPS (32 or 64) systems. Currently supported are X86-64 and ARM64/AARCH64 with crypto extensions. - -# 2020-10-05 -- Version 1.5.0 (actually 1.6.0-beta1) - -Version 1.6.0 (1.5.0 is a beta!) is a significant release that incorporates a number of back-ported fixes and features from the ZeroTier 2.0 tree. - -Major new features are: - - * **Multipath support** with modes modeled after the Linux kernel's bonding driver. This includes active-passive and active-active modes with fast failover and load balancing. See section 2.1.5 of the manual. - * **DNS configuration** push from network controllers to end nodes, with locally configurable permissions for whether or not push is allowed. - * **AES-GMAC-SIV** encryption mode, which is both somewhat more secure and significantly faster than the old Salsa20/12-Poly1305 mode on hardware that supports AES acceleration. This includes virtually all X86-64 chips and most ARM64. This mode is based on AES-SIV and has been audited by Trail of Bits to ensure that it is equivalent security-wise. - -Known issues that are not yet fixed in this beta: - - * Some Mac users have reported periods of 100% CPU in kernel_task and connection instability after leaving networks that have been joined for a period of time, or needing to kill ZeroTier and restart it to finish leaving a network. This doesn't appear to affect all users and we haven't diagnosed the root cause yet. - * The service sometimes hangs on shutdown requiring a kill -9. This also does not affect all systems or users. - * AES hardware acceleration is not yet supported on 32-bit ARM, PowerPC (32 or 64), or MIPS (32 or 64) systems. Currently supported are X86-64 and ARM64/AARCH64 with crypto extensions. - * Some users have reported multicast/broadcast outages on networks lasting up to 30 seconds. Still investigating. - -We're trying to fix all these issues before the 1.6.0 release. Stay tuned. - -# 2019-08-30 -- Version 1.4.6 - - * Update default root list to latest - * ARM32 platform build and flag fixes - * Add a clarification line to LICENSE.txt - * Fix license message in CLI - * Windows service now looks for service command line arguments - * Fixed a bug that could cause excessive queued multicasts - -# 2019-08-23 -- Version 1.4.4 - - * Change license from GPL3 to BSL 1.1, see LICENSE.txt - * Fix an issue with the "ipauth" rule and auto-generated unforgeable IPv6 addresses - * Fix socket/bind errors setting IPs and routes on Linux - -# 2019-08-12 -- Version 1.4.2 - - * Fix high CPU use bug on some platforms - * Fix issues with PostgreSQL controller DB (only affects Central) - * Restore backward compatibility with MacOS versions prior to 10.13 - -# 2019-07-29 -- Version 1.4.0 - -### Major Changes - - * Mac version no longer requires a kernel extension, instead making use of the [feth interfaces](https://apple.stackexchange.com/questions/337715/fake-ethernet-interfaces-feth-if-fake-anyone-ever-seen-this). - * Added support for concurrent multipath (multiple paths at once) with traffic weighting by link quality and faster recovery from lost links. - * Added under-the-hood support for QoS (not yet exposed) that will eventually be configurable via our rules engine. - -### Minor Changes and Bug Fixes - - * Experimental controller DB driver for [LF](https://github.com/zerotier/lf) to store network controller data (LFDB.cpp / LFDB.hpp). - * Modified credential push and direct path push timings and algorithms to somewhat reduce "chattiness" of the protocol when idle. More radical background overhead reductions will have to wait for the 2.x line. - * Removed our beta/half-baked integration of Central with the Windows UI. We're going to do a whole new UI of some kind in the future at least for Windows and Mac. - * Fixed stack overflow issues on Linux versions using musl libc. - * Fixed some alignment problems reported on ARM and ARM64, but some reports we could not reproduce so please report any issues with exact chip, OS/distro, and ZeroTier version in use. - * Fixed numerous other small issues and bugs such as ARM alignment issues causing crashes on some devices. - * Windows now sets the adapter name such that it is consistent in both the Windows UI and command line utilities. - -# 2018-07-27 -- Version 1.2.12 - - * Fixed a bug that caused exits to take a long time on Mac due to huge numbers of redundant attempts to delete managed routes. - * Fixed a socket limit problem on Windows that caused the ZeroTier service to run out of sockets, causing the UI and CLI to be unable to access the API. - * Fixed a threading bug in the ZeroTier Core, albeit one that never manifested on the regular ZeroTier One service/client. - * Fixed a bug that could cause the service to crash if an authorized local client accessed an invalid URL via the control API. (Not exploitable since you needed admin access anyway.) - -# 2018-05-08 -- Version 1.2.10 - - * Fix bug loading `moons.d/` files for federated root operation. - * Fix compile problem with ZT_DEBUG on some versions of `clang` - * Fix slow network startup bug related to loading of `networks.d/` cache files - -# 2018-04-27 -- Version 1.2.8 - - * Linux version once again builds with PIE (position independent executable) flags - * Fixed bug in zerotier-idtool file sign and verify - * Fixed minor OSX app typo - * Merged alpha NetBSD support (mostly untested, so YMMV) - * Merged several minor typo and one-liner bug fixes - -# 2018-04-17 -- Version 1.2.6 - - * Features and Core Improvements - * Path selection has been overhauled to improve path stability, simplify code, and prepare for multi-path and trunking in the next major release. - * This version introduces remote tracing for remote diagnostics. Network controllers can set a node (usually the controller itself) to receive remote tracing events from all members of the network or from select members. Events are only sent if they pertain to a given network for security reasons. - * Multicast replication can now be done by designated multicast replicators on a network (flagged as such at the controller) rather than by the sender. Most users won't want this, but it's useful for specialized use cases on hub-and-spoke networks and for low-power devices. - * Cryptographic performance improvements on several platforms. - * Multithreaded performance improvements throughout the code base, including the use of an inline lightweight spinlock for low-contention resources. - * Bugs fixed - * Disappearing routes on Mac (GitHub issue #600) - * Route flapping and path instability in some dual-stack V4/V6 networks - * Blacklist (in local.conf) doesn't work reliably (GitHub issue #656) - * Connection instabilities due to unsigned integer overflows in timing comparisons (use int64_t instead of uint64_t) - * Binaries don't run on some older or lower-end 32-bit ARM chips (build problem) - * ARM NEON crypto code crashes (build problem) - * Fixed some lock ordering issues revealed by "valgrind" tool - * The "zerotier-idtool" command could not be accessed from "zerotier-one" via command line switch - * Leaking sockets on some platforms when uPnP/NAT-PMP is enabled - * Fixed two very rare multithreading issues that were only observed on certain systems - * Platform-Specific Changes - * MacOS - * Installer now loads the kernel extension right away so that High Sierra users will see the prompt to authorize it. This is done in the "Security & Privacy" preference pane and must be done directly on the console (not via remote desktop). On High Sierra and newer kexts must be authorized at the console via security settings system preferences pane. - * Windows - * The Windows installer should now install the driver without requiring a special prompt in most cases. This should make it easier for our packages to be accepted into and updated in the Chocolatey repository and should make it easier to perform remote installs across groups of machines using IT management and provisioning tools. - * The Windows official packages are now signed with an EV certificate (with hardware key). - * The Windows UI can now log into ZeroTier Central and join networks via the Central API. - * The `zerotier-idtool` command should now work on Windows without ugly hacks. - * Upgraded the installer version. - * Made a few changes to hopefully fix sporadic "will not uninstall" problems, though we cannot duplicate these issues ourselves. - * Linux - * Device names are now generated deterministically based on network IDs for all newly joined networks. - * Android - * Multicast now works on Android in most cases! Android apps can send and receive multicast and subscribe to multicast group IPs. Note that in some cases the app must bind to the specific correct interface for this to work. - * IPv6 can be disabled in UI for cases where it causes problems. - -# 2017-04-20 -- Version 1.2.4 - - * Managed routes are now only bifurcated for the default route. This is a change in behavior, though few people will probably notice. Bifurcating all managed routes was causing more trouble than it was worth for most users. - * Up to 2X crypto speedup on x86-64 (except Windows, which will take some porting) and 32-bit ARM platforms due to integration of fast assembly language implementations of Salsa20/12 from the [supercop](http://bench.cr.yp.to/supercop.html) code base. These were written by Daniel J. Bernstein and are in the public domain. My MacBook Pro (Core i5 2.8ghz) now does almost 1.5GiB/sec Salsa20/12 per core and a Raspberry Pi got a 2X boost. 64-bit ARM support and Windows support will take some work but should not be too hard. - * Refactored code that manages credentials to greatly reduce memory use in most cases. This may also result in a small performance improvement. - * Reworked and simplified path selection and priority logic to fix path instability and dead path persistence edge cases. There have been some sporadic reports of persistent path instabilities and dead paths hanging around that take minutes to resolve. These have proven difficult to reproduce in house, but hopefully this will fix them. In any case it seems to speed up path establishment in our tests and it makes the code simpler and more readable. - * Eliminated some unused cruft from the code around path management and in the peer class. - * Fixed an issue causing build problems on some MIPS architecture systems. - * Fixed Windows forgetting routes on sleep/wake or in some other circumstances. (GitHub issue #465) - -# 2017-03-17 -- Version 1.2.2 - - * A bug causing unreliable multicast propagation (GitHub issue #461). - * A crash in ARM binaries due to a build chain and flags problem. - * A bug in the network controller preventing members from being listed (GitHub issue #460). - -# 2017-03-14 -- Version 1.2.0 - -Version 1.2.0 is a major milestone release representing almost nine months of work. It includes our rules engine for distributed network packet filtering and security monitoring, federated roots, and many other architectural and UI improvements and bug fixes. - -## New Features in 1.2.0 - -### The ZeroTier Rules Engine - -The largest new feature in 1.2.0, and the product of many months of work, is our advanced network rules engine. With this release we achieve traffic control, security monitoring, and micro-segmentation capability on par with many enterprise SDN solutions designed for use in advanced data centers and corporate networks. - -Rules allow you to filter packets on your network and vector traffic to security observers. Security observation can be performed in-band using REDIRECT or out of band using TEE. - -Tags and capabilities provide advanced methods for implementing fine grained permission structures and micro-segmentation schemes without bloating the size and complexity of your rules table. - -See the [rules engine announcement blog post](https://www.zerotier.com/blog/?p=927) for an in-depth discussion of theory and implementation. The [manual](https://www.zerotier.com/manual.shtml) contains detailed information on rule, tag, and capability use, and the `rule-compiler/` subfolder of the ZeroTier source tree contains a JavaScript function to compile rules in our human-readable rule definition language into rules suitable for import into a network controller. (ZeroTier Central uses this same script to compile rules on [my.zerotier.com](https://my.zerotier.com/).) - -### Root Server Federation - -It's now possible to create your own root servers and add them to the root server pool on your nodes. This is done by creating what's called a "moon," which is a signed enumeration of root servers and their stable points on the network. Refer to the [manual](https://www.zerotier.com/manual.shtml) for instructions. - -Federated roots achieve a number of things: - - * You can deploy your own infrastructure to reduce dependency on ours. - * You can deploy roots *inside your LAN* to ensure that network connectivity inside your facility still works if the Internet goes down. This is the first step toward making ZeroTier viable as an in-house SDN solution. - * Roots can be deployed inside national boundaries for countries with data residency laws or "great firewalls." (As of 1.2.0 there is still no way to force all traffic to use these roots, but that will be easy to do in a later version.) - * Last but not least this makes ZeroTier somewhat less centralized by eliminating any hard dependency on ZeroTier, Inc.'s infrastructure. - -Our roots will of course remain and continue to provide zero-configuration instant-on deployment, a secure global authority for identities, and free traffic relaying for those who can't establish peer to peer connections. - -### Local Configuration - -An element of our design philosophy is "features are bugs." This isn't an absolute dogma but more of a guiding principle. We try as hard as we can to avoid adding features, especially "knobs" that must be tweaked by a user. - -As of 1.2.0 we've decided that certain knobs are unavoidable, and so there is now a `local.conf` file that can be used to configure them. See the ZeroTier One documentation for these. They include: - - * Blacklisting interfaces you want to make sure ZeroTier doesn't use for network traffic, such as VPNs, slow links, or backplanes designated for only certain kinds of traffic. - * Turning uPnP/NAT-PMP on or off. - * Configuring software updates on Windows and Mac platforms. - * Defining trusted paths (the old trusted paths file is now deprecated) - * Setting the ZeroTier main port so it doesn't have to be changed on the command line, which is very inconvenient in many cases. - -### Improved In-Band Software Updates - -A good software update system for Windows and Mac clients has been a missing feature in previous versions. It does exist but we've been shy about using it so far due to its fragility in some environments. - -We've greatly improved this mechanism in 1.2.0. Not only does it now do a better job of actually invoking the update, but it also transfers updates in-band using the ZeroTier protocol. This means it can work in environments that do not allows http/https traffic or that force it through proxies. There's also now an update channel setting: `beta` or `release` (the default). - -Software updates are authenticated three ways: - - 1. ZeroTier's own signing key is used to sign all updates and this signature is checked prior to installation. ZeroTier, Inc.'s signatures are performed on an air-gapped machine. - - 2. Updates for Mac and Windows are signed using Apple and Microsoft (DigiCert EV) keys and will not install unless these signatures are also valid. - - 3. The new in-band update mechanism also authenticates the source of the update via ZeroTier's built-in security features. This provides transport security, while 1 and 2 provide security of the update at rest. - -Updates are now configurable via `local.conf`. There are three options: `disable`, `download`, and `apply`. The third (apply) is the default for official builds on Windows and Mac, making updates happen silently and automatically as they do for popular browsers like Chrome and Firefox. Updates are disabled by default on Linux and other Unix-type systems as these are typically updated through package managers. - -### Path Link Quality Awareness - -Version 1.2.0 is now aware of the link quality of direct paths with other 1.2.0 nodes. This information isn't used yet but is visible through the JSON API. (Quality always shows as 100% with pre-1.2.0 nodes.) Quality is measured passively with no additional overhead using a counter based packet loss detection algorithm. - -This information is visible from the command line via `listpeers`: - - 200 listpeers XXXXXXXXXX 199.XXX.XXX.XXX/9993;10574;15250;1.00 48 1.2.0 LEAF - 200 listpeers XXXXXXXXXX 195.XXX.XXX.XXX/45584;467;7608;0.44 290 1.2.0 LEAF - -The first peer's path is at 100% (1.00), while the second peer's path is suffering quite a bit of packet loss (0.44). - -Link quality awareness is a precursor to intelligent multi-path and QoS support, which will in future versions bring us to feature parity with SD-WAN products like Cisco iWAN. - -### Security Improvements - -Version 1.2.0 adds anti-DOS (denial of service) rate limits and other hardening for improved resiliency against a number of denial of service attack scenarios. - -It also adds a mechanism for instantaneous credential revocation. This can be used to revoke certificates of membership instantly to kick a node off a network (for private networks) and also to revoke capabilities and tags. The new controller sends revocations by default when a peer is de-authorized. - -Revocations propagate using a "rumor mill" peer to peer algorithm. This means that a controller need only successfully send a revocation to at least one member of a network with connections to other active members. At this point the revocation will flood through the network peer to peer very quickly. This helps make revocations more robust in the face of poor connectivity with the controller or attempts to incapacitate the controller with denial of service attacks, as well as making revocations faster on huge networks. - -### Windows and Macintosh UI Improvements (ZeroTier One) - -The Mac has a whole new UI built natively in Objective-C. It provides a pulldown similar in appearance and operation to the Mac WiFi task bar menu. - -The Windows UI has also been improved and now provides a task bar icon that can be right-clicked to manage networks. Both now expose managed route and IP permissions, allowing nodes to easily opt in to full tunnel operation if you have a router configured on your network. - -### Ad-Hoc Networks - -A special kind of public network called an ad-hoc network may be accessed by joining a network ID with the format: - - ffSSSSEEEE000000 - | | | | - | | | Reserved for future use, must be 0 - | | End of port range (hex) - | Start of port range (hex) - Reserved ZeroTier address prefix indicating a controller-less network - -Ad-hoc networks are public (no access control) networks that have no network controller. Instead their configuration and other credentials are generated locally. Ad-hoc networks permit only IPv6 UDP and TCP unicast traffic (no multicast or broadcast) using 6plane format NDP-emulated IPv6 addresses. In addition an ad-hoc network ID encodes an IP port range. UDP packets and TCP SYN (connection open) packets are only allowed to destination ports within the encoded range. - -For example `ff00160016000000` is an ad-hoc network allowing only SSH, while `ff0000ffff000000` is an ad-hoc network allowing any UDP or TCP port. - -Keep in mind that these networks are public and anyone in the entire world can join them. Care must be taken to avoid exposing vulnerable services or sharing unwanted files or other resources. - -### Network Controller (Partial) Rewrite - -The network controller has been largely rewritten to use a simple in-filesystem JSON data store in place of SQLite, and it is now included by default in all Windows, Mac, Linux, and BSD builds. This means any desktop or server node running ZeroTier One can now be a controller with no recompilation needed. - -If you have data in an old SQLite3 controller we've included a NodeJS script in `controller/migrate-sqlite` to migrate data to the new format. If you don't migrate, members will start getting `NOT_FOUND` when they attempt to query for updates. - -## Major Bug Fixes in 1.2.0 - - * **The Windows HyperV 100% CPU bug is FINALLY DEAD**: This long-running problem turns out to have been an issue with Windows itself, but one we were triggering by placing invalid data into the Windows registry. Microsoft is aware of the issue but we've also fixed the triggering problem on our side. ZeroTier should now co-exist quite well with HyperV and should now be able to be bridged with a HyperV virtual switch. - * **Segmentation faults on musl-libc based Linux systems**: Alpine Linux and some embedded Linux systems that use musl libc (a minimal libc) experienced segmentation faults. These were due to a smaller default stack size. A work-around that sets the stack size for new threads has been added. - * **Windows firewall blocks local JSON API**: On some Windows systems the firewall likes to block 127.0.0.1:9993 for mysterious reasons. This is now fixed in the installer via the addition of another firewall exemption rule. - * **UI crash on embedded Windows due to missing fonts**: The MSI installer now ships fonts and will install them if they are not present, so this should be fixed. - -## Other Improvements in 1.2.0 - - * **Improved dead path detection**: ZeroTier is now more aggressive about expiring paths that do not seem to be active. If a path seems marginal it is re-confirmed before re-use. - * **Minor performance improvements**: We've reduced unnecessary memcpy's and made a few other performance improvements in the core. - * **Linux static binaries**: For our official packages (the ones in the download.zerotier.com apt and yum repositories) we now build Linux binaries with static linking. Hopefully this will stop all the bug reports relating to library inconsistencies, as well as allowing our deb packages to run on a wider variety of Debian-based distributions. (There are far too many of these to support officially!) The overhead for this is very small, especially since we built our static versions against musl-libc. Distribution maintainers are of course free to build dynamically linked versions for inclusion into distributions; this only affects our official binaries. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index c539ed6a2..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,93 +0,0 @@ -# Security - -ZeroTier takes the security of our software products and services seriously, which -includes all source code repositories managed through our GitHub organization. - -## Supported Versions - -The following versions of ZeroTier One receive security updates - -| Version | Supported | -| -------- | ------------------ | -| 1.14.x | :white_check_mark: | -| 1.12.x | :white_check_mark: | -| < 1.12.0 | :x: | - -## Reporting a Vulnerability - -**Please do not report security issues through public GitHub issues** - -Instead, please report vulnerabilities via email to security@zerotier.com. If possible, -please encrypt with our PGP key (see below). - -Please include the following information, or as much as you can provide to help us -understand the nature and scope of the issue: - - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue - -## Preferred Languages - -We prefer all communications to be in English. - -## security@zerotier.com PGP key - -``` ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBGQGOVIBEACalXTnNqaiSOVLFEiqHpDMg8N/OI5D5850Xy1ZEvx3B3rz7cbn -k30ozHtJKbh+vqpyItE7DjyQAuF19gP5Q64Yh0Y+MmLHq60q/GwOwAYz7cI+UzA3 -5x8YqcmTp32LAM1xJn+iMlMLBuAmJl4kULKmOXPlpqPiyTFs5saizvm7fgRmfgJJ -HpsnIrTkaDFJhAR+jvMJohVYwmhuydeI0DsHu7KGpG1ddcHDrUjOPNqXnnAPSPwx -llw4yfKlQb8GYErsv/G5QVyzd5+SxEuiI4MARRnrk8LlMQ33CR6pzIQ/Bk5AAmye -mHqfEAknkiOf++urYhRs9BL3Kz3MdV0cg92zr9EFOg0u56jxf5OnAiTOhGUUA0hn -dS7peVGl46R9Oy2JYIazNDGi+4NIsYDFXsnsss9xOQVygPyeQd71zFHfix0jct9w -j3o/kj7Egsnm9nc13354bYT6bbalqXiRWwGH1eAFpjueNWiVFwZS6NZUP3WeNDiY -BlPo1LodvolbXiJcTILTCyEkERJPCK2zoE2nTdVfvTLWsuehw1M6Yd2/q74TVYy/ -RY+KjHkrChEBQ9PqXsXRHj6opKbT8JLfZkvU5k+3IiqqxOpB+QXFI/whj493CxWW -so7QAmzOCyJq8GDVPxzkwUac22YIkXdiOmb8i/HWq+kLY/HjQE259Gx6KwARAQAB -tClaZXJvVGllciBTZWN1cml0eSA8c2VjdXJpdHlAemVyb3RpZXIuY29tPokCTAQT -AQoANhYhBH1HQGb+4jzl6mnFqf09m6uqADkABQJkBjlSAhsDBAsJCAcEFQoJCAUW -AgMBAAIeAQIXgAAKCRD9PZurqgA5ACqPD/sFt6SG6Tu0HwTY2ofJtYsa2GBLL0pf -dYlX4cWSs1PVB5+m5Oj18y+GB2umA9GnsVtmvaSfp3XEngt2zNWX27uUsVfL35b2 -/5TVVe8RjzOedqMN+lQWMvO+f/C1zmWYXjjpC+iGjgMMaRRrofkkn+7uL4N9y6gY -rcXtpACT1rYFC+i1AKnZfUO8Vr5ji7odq0f7bDkN/N38rB0kRRwEmO8wqdpQK6gK -nxf9vgJl5ggimDk5Xtz1sfd3y28bf5N4hdOCkXUbd10nUFY3wDNTM4VxozxTGJeG -imdcc19Wuw/1fGUZ5SIjgPanCdPLGYwSTr+M6Fuern9uTtlC1GOby3BUtmVGP6EU -1pSAJSRpmoBPHKKOYtSMwV8PCboXru9P1ab8y8STKM3SKyghUJrl17gdc0LaksZa -E54pJudGPIQMFRqZjMdV6jgMuaLTozjZ4mW8EThf4mkX4xDkO8l7cOn0225ZYJZC -lZKpdnwzk9owkJA80u4KBNJxTtB4ZAPzjBsD5hFzCZQTLNQp/psU3EjZsau28eXT -E/C1QjEQHgy4ohkgQlCm1H1+clKssCWcdmsVGXuS1u8gh4K6X9b0Z6LeCGRaQvH2 -+DB8oTAdqp9nUZv9rP4pbo+sR4fF67CFLriVuxjedAiFkbM4uHMFcL4tc/X9+DRo -YN5X7oEkZvO507kCDQRkBjlSARAAz58UMF7K1qKyQjzKTcutaYZ5SaIGky9lCLZn -/2vjpFCoBogkxS/6IKQcwZk8b4S9QstaaQZDFEkxqNeKC0GiFTAMAb6SmYcK495h -EZnHl0NA5Nc2dBlZk5E/ENzTCz2bXaxCcVESc2z+xCzu07brbhGrqvliKiwOUzt9 -JzqEsar6I95OutBcZvkFCs44/Uf9bS1qf1w4klE8w3vdMtGH23umrET4tFZ+sh6o -ZFtQx0u2eKjsRdn/RMtsxLNaJlcE1DdIAqBpQrcmuwMC8v5wUGfCGZjhClzmyQlq -akUkayir7UtbHbFT/mgO+YI77YGXWk5QrwPscqqT2l8KB/YMujNDmaWa/0KV1lIY -zr5s4dzVeiwqFLR9ANFIhzFwzf3JLi6XSx123Qix0TxZoYPZCHl7yoi9qi6qybz5 -0Od2LSz3jbApeKYymZ+zjE+YV5y9DI6Wzy1j2M1FogNvTO9fMk+6dLt4HhTdSNvH -cKya462YCcy+tnZTkhmh+FTebbJlV6D4wG7skE5KCdBhjm53xLwp6XW9L6n2CrkL -W1IDBcCz0oPd1sMkXbO3wnxdXprV2XurCfsg/R2nszSNzvdJ8/xj3cr9hpoJ714R -qqyoEDRZ1Ss9kGL166o5MpN5qb/EewdkqGgWP7YFXbhsdHQiW7Z7dAqzjoaybD4O -nakkwyUAEQEAAYkCNgQYAQoAIBYhBH1HQGb+4jzl6mnFqf09m6uqADkABQJkBjlS -AhsMAAoJEP09m6uqADkAax0P/Rh8EZYRqW6dPYTl1YQusAK10rAcRNq3ekjofXGk -oXK1S7HWGoFgl5++5nfSfNgFJ5VLcgIM56wtIf49zFjWe5oC6fw8k+ghh4d2chMP -hdDILx6e0c30Iq1+EvovGR9hWa0wJ4cKTdzlwhY9ZC09q0ia+bl2mwpie1JQDR0c -zXCjt+PldLeeK9z1/XT0Q7KowYC+U18oR+KFm+EaRV4QT85JVequnIeGkmaHJrHB -lH4T5A5ib7y8edon1c0Zx3GsaxJUojkEJ0SX7ffVDu6ztUZfkHfCVpMW4VzUeGA/ -m+CtFO9ciLRGZEkRa+zhIGoBvwEXU0GiwiF4nZ0F2C8UioeW0YIEV9zl3nXJctYE -ZKc2whSENQRTGgaYHVoVZhznt71LKWgFLshwBo81UCXVkzwAjMW1ActDnmPw5M7q -xR5Qp5G49Z1GmfSozazha0HVFPKNV5i3RlTzs4yLUnZyH0yC9IvtOefMHcLjG96L -N5miEV97gvJJjrn8rhRvpUwAWgmT/9IuYjBNQTtNN40arto5HxezR76WCjdKYxdL -p3dM1iiBDShHNm7LdyZlLFhTOMU0tNBxJJ7B09ar5gakeZjD+2aB1ODX9VuFtozL -onBjI2gIkry0UIkuznHfFw05lZAZAiqHEVgVi/WTk4C/bklDZNgE0lx+IWzEz2iS -L455 -=lheL ------END PGP PUBLIC KEY BLOCK----- -``` diff --git a/artwork/AppIcon_1024x1024.png b/artwork/AppIcon_1024x1024.png deleted file mode 100644 index c423c4f73..000000000 Binary files a/artwork/AppIcon_1024x1024.png and /dev/null differ diff --git a/artwork/AppIcon_20x20.png b/artwork/AppIcon_20x20.png deleted file mode 100644 index bb10b4781..000000000 Binary files a/artwork/AppIcon_20x20.png and /dev/null differ diff --git a/artwork/AppIcon_60x60.png b/artwork/AppIcon_60x60.png deleted file mode 100644 index bb46ae750..000000000 Binary files a/artwork/AppIcon_60x60.png and /dev/null differ diff --git a/artwork/AppIcon_90x90.png b/artwork/AppIcon_90x90.png deleted file mode 100644 index 0a618bbbb..000000000 Binary files a/artwork/AppIcon_90x90.png and /dev/null differ diff --git a/artwork/ZeroTierIcon32x32.png b/artwork/ZeroTierIcon32x32.png deleted file mode 100644 index 24ff0a1cc..000000000 Binary files a/artwork/ZeroTierIcon32x32.png and /dev/null differ diff --git a/attic/Filter.cpp b/attic/Filter.cpp new file mode 100644 index 000000000..a701e8b70 --- /dev/null +++ b/attic/Filter.cpp @@ -0,0 +1,408 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include +#include +#include +#include + +#include + +#include "RuntimeEnvironment.hpp" +#include "Logger.hpp" +#include "Filter.hpp" +#include "Utils.hpp" + +namespace ZeroTier { + +const char *const Filter::UNKNOWN_NAME = "(unknown)"; +const Range Filter::ANY; + +static inline Range __parseRange(char *r) + throw(std::invalid_argument) +{ + char *saveptr = (char *)0; + unsigned int a = 0; + unsigned int b = 0; + unsigned int fn = 0; + for(char *f=Utils::stok(r,"-",&saveptr);(f);f=Utils::stok((char *)0,"-",&saveptr)) { + if (*f) { + switch(fn++) { + case 0: + if (*f != '*') + a = b = (unsigned int)strtoul(f,(char **)0,10); + break; + case 1: + if (*f != '*') + b = (unsigned int)strtoul(f,(char **)0,10); + break; + default: + throw std::invalid_argument("rule range must be , -, or *"); + } + } + } + return Range(a,b); +} + +Filter::Rule::Rule(const char *s) + throw(std::invalid_argument) +{ + char *saveptr = (char *)0; + char tmp[256]; + if (!Utils::scopy(tmp,sizeof(tmp),s)) + throw std::invalid_argument("rule string too long"); + unsigned int fn = 0; + for(char *f=Utils::stok(tmp,";",&saveptr);(f);f=Utils::stok((char *)0,";",&saveptr)) { + if (*f) { + switch(fn++) { + case 0: + _etherType = __parseRange(f); + break; + case 1: + _protocol = __parseRange(f); + break; + case 2: + _port = __parseRange(f); + break; + default: + throw std::invalid_argument("rule string has unknown extra fields"); + } + } + } + if (fn != 3) + throw std::invalid_argument("rule string must contain 3 fields"); +} + +bool Filter::Rule::operator()(unsigned int etype,const void *data,unsigned int len) const + throw(std::invalid_argument) +{ + if ((!_etherType)||(_etherType(etype))) { // ethertype is ANY, or matches + // Ethertype determines meaning of protocol and port + switch(etype) { + case ZT_ETHERTYPE_IPV4: + if (len > 20) { + if ((!_protocol)||(_protocol(((const uint8_t *)data)[9]))) { // protocol is ANY or match + if (!_port) // port is ANY + return true; + + // Don't match on fragments beyond fragment 0. If we've blocked + // fragment 0, further fragments will fall on deaf ears anyway. + if ((Utils::ntoh(((const uint16_t *)data)[3]) & 0x1fff)) + return false; + + // Internet header length determines where data begins, in multiples of 32 bits + unsigned int ihl = 4 * (((const uint8_t *)data)[0] & 0x0f); + + switch(((const uint8_t *)data)[9]) { // port's meaning depends on IP protocol + case ZT_IPPROTO_ICMP: + // For ICMP, port is ICMP type + return _port(((const uint8_t *)data)[ihl]); + case ZT_IPPROTO_TCP: + case ZT_IPPROTO_UDP: + case ZT_IPPROTO_SCTP: + case ZT_IPPROTO_UDPLITE: + // For these, port is destination port. Protocol designers were + // nice enough to put the field in the same place. + return _port(((const uint16_t *)data)[(ihl / 2) + 1]); + default: + // port has no meaning for other IP types, so ignore it + return true; + } + + return false; // no match on port + } + } else throw std::invalid_argument("undersized IPv4 packet"); + break; + + case ZT_ETHERTYPE_IPV6: + if (len > 40) { + int nextHeader = ((const uint8_t *)data)[6]; + unsigned int pos = 40; + while ((pos < len)&&(nextHeader >= 0)&&(nextHeader != 59)) { // 59 == no next header + fprintf(stderr,"[rule] V6: start header parse, header %.2x pos %d\n",nextHeader,pos); + + switch(nextHeader) { + case 0: // hop-by-hop options + case 60: // destination options + case 43: // routing + case 135: // mobility (mobile IPv6 options) + if (_protocol((unsigned int)nextHeader)) + return true; // match if our goal was to match any of these + nextHeader = ((const uint8_t *)data)[pos]; + pos += 8 + (8 * ((const uint8_t *)data)[pos + 1]); + break; + case 44: // fragment + if (_protocol(44)) + return true; // match if our goal was to match fragments + nextHeader = ((const uint8_t *)data)[pos]; + pos += 8; + break; + case ZT_IPPROTO_AH: // AH + return _protocol(ZT_IPPROTO_AH); // true if AH is matched protocol, otherwise false since packet will be IPsec + case ZT_IPPROTO_ESP: // ESP + return _protocol(ZT_IPPROTO_ESP); // true if ESP is matched protocol, otherwise false since packet will be IPsec + case ZT_IPPROTO_ICMPV6: + // Only match ICMPv6 if we've selected it specifically + if (_protocol(ZT_IPPROTO_ICMPV6)) { + // Port is interpreted as ICMPv6 type + if ((!_port)||(_port(((const uint8_t *)data)[pos]))) + return true; + } + break; + case ZT_IPPROTO_TCP: + case ZT_IPPROTO_UDP: + case ZT_IPPROTO_SCTP: + case ZT_IPPROTO_UDPLITE: + // If we encounter any of these, match if protocol matches or is wildcard as + // we'll consider these the "real payload" if present. + if ((!_protocol)||(_protocol(nextHeader))) { + if ((!_port)||(_port(((const uint16_t *)data)[(pos / 2) + 1]))) + return true; // protocol matches or is ANY, port is ANY or matches + } + break; + default: { + char foo[128]; + Utils::snprintf(foo,sizeof(foo),"unrecognized IPv6 header type %d",(int)nextHeader); + throw std::invalid_argument(foo); + } + } + + fprintf(stderr,"[rule] V6: end header parse, next header %.2x, new pos %d\n",nextHeader,pos); + } + } else throw std::invalid_argument("undersized IPv6 packet"); + break; + + default: + // For other ethertypes, protocol and port are ignored. What would they mean? + return true; + } + } + + return false; +} + +std::string Filter::Rule::toString() const +{ + char buf[128]; + std::string s; + + switch(_etherType.magnitude()) { + case 0: + s.push_back('*'); + break; + case 1: + Utils::snprintf(buf,sizeof(buf),"%u",_etherType.start); + s.append(buf); + break; + default: + Utils::snprintf(buf,sizeof(buf),"%u-%u",_etherType.start,_etherType.end); + s.append(buf); + break; + } + s.push_back(';'); + switch(_protocol.magnitude()) { + case 0: + s.push_back('*'); + break; + case 1: + Utils::snprintf(buf,sizeof(buf),"%u",_protocol.start); + s.append(buf); + break; + default: + Utils::snprintf(buf,sizeof(buf),"%u-%u",_protocol.start,_protocol.end); + s.append(buf); + break; + } + s.push_back(';'); + switch(_port.magnitude()) { + case 0: + s.push_back('*'); + break; + case 1: + Utils::snprintf(buf,sizeof(buf),"%u",_port.start); + s.append(buf); + break; + default: + Utils::snprintf(buf,sizeof(buf),"%u-%u",_port.start,_port.end); + s.append(buf); + break; + } + + return s; +} + +Filter::Filter(const char *s) + throw(std::invalid_argument) +{ + char tmp[16384]; + if (!Utils::scopy(tmp,sizeof(tmp),s)) + throw std::invalid_argument("filter string too long"); + char *saveptr = (char *)0; + unsigned int fn = 0; + for(char *f=Utils::stok(tmp,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) { + try { + _rules.push_back(Rule(f)); + ++fn; + } catch (std::invalid_argument &exc) { + char tmp[256]; + Utils::snprintf(tmp,sizeof(tmp),"invalid rule at index %u: %s",fn,exc.what()); + throw std::invalid_argument(tmp); + } + } + std::sort(_rules.begin(),_rules.end()); +} + +std::string Filter::toString() const +{ + std::string s; + + for(std::vector::const_iterator r(_rules.begin());r!=_rules.end();++r) { + if (s.length() > 0) + s.push_back(','); + s.append(r->toString()); + } + + return s; +} + +void Filter::add(const Rule &r) +{ + for(std::vector::iterator rr(_rules.begin());rr!=_rules.end();++rr) { + if (r == *rr) + return; + } + _rules.push_back(r); + std::sort(_rules.begin(),_rules.end()); +} + +const char *Filter::etherTypeName(const unsigned int etherType) + throw() +{ + switch(etherType) { + case ZT_ETHERTYPE_IPV4: return "ETHERTYPE_IPV4"; + case ZT_ETHERTYPE_ARP: return "ETHERTYPE_ARP"; + case ZT_ETHERTYPE_RARP: return "ETHERTYPE_RARP"; + case ZT_ETHERTYPE_ATALK: return "ETHERTYPE_ATALK"; + case ZT_ETHERTYPE_AARP: return "ETHERTYPE_AARP"; + case ZT_ETHERTYPE_IPX_A: return "ETHERTYPE_IPX_A"; + case ZT_ETHERTYPE_IPX_B: return "ETHERTYPE_IPX_B"; + case ZT_ETHERTYPE_IPV6: return "ETHERTYPE_IPV6"; + } + return UNKNOWN_NAME; +} + +const char *Filter::ipProtocolName(const unsigned int ipp) + throw() +{ + switch(ipp) { + case ZT_IPPROTO_ICMP: return "IPPROTO_ICMP"; + case ZT_IPPROTO_IGMP: return "IPPROTO_IGMP"; + case ZT_IPPROTO_TCP: return "IPPROTO_TCP"; + case ZT_IPPROTO_UDP: return "IPPROTO_UDP"; + case ZT_IPPROTO_GRE: return "IPPROTO_GRE"; + case ZT_IPPROTO_ESP: return "IPPROTO_ESP"; + case ZT_IPPROTO_AH: return "IPPROTO_AH"; + case ZT_IPPROTO_ICMPV6: return "IPPROTO_ICMPV6"; + case ZT_IPPROTO_OSPF: return "IPPROTO_OSPF"; + case ZT_IPPROTO_IPIP: return "IPPROTO_IPIP"; + case ZT_IPPROTO_IPCOMP: return "IPPROTO_IPCOMP"; + case ZT_IPPROTO_L2TP: return "IPPROTO_L2TP"; + case ZT_IPPROTO_SCTP: return "IPPROTO_SCTP"; + case ZT_IPPROTO_FC: return "IPPROTO_FC"; + case ZT_IPPROTO_UDPLITE: return "IPPROTO_UDPLITE"; + case ZT_IPPROTO_HIP: return "IPPROTO_HIP"; + } + return UNKNOWN_NAME; +} + +const char *Filter::icmpTypeName(const unsigned int icmpType) + throw() +{ + switch(icmpType) { + case ZT_ICMP_ECHO_REPLY: return "ICMP_ECHO_REPLY"; + case ZT_ICMP_DESTINATION_UNREACHABLE: return "ICMP_DESTINATION_UNREACHABLE"; + case ZT_ICMP_SOURCE_QUENCH: return "ICMP_SOURCE_QUENCH"; + case ZT_ICMP_REDIRECT: return "ICMP_REDIRECT"; + case ZT_ICMP_ALTERNATE_HOST_ADDRESS: return "ICMP_ALTERNATE_HOST_ADDRESS"; + case ZT_ICMP_ECHO_REQUEST: return "ICMP_ECHO_REQUEST"; + case ZT_ICMP_ROUTER_ADVERTISEMENT: return "ICMP_ROUTER_ADVERTISEMENT"; + case ZT_ICMP_ROUTER_SOLICITATION: return "ICMP_ROUTER_SOLICITATION"; + case ZT_ICMP_TIME_EXCEEDED: return "ICMP_TIME_EXCEEDED"; + case ZT_ICMP_BAD_IP_HEADER: return "ICMP_BAD_IP_HEADER"; + case ZT_ICMP_TIMESTAMP: return "ICMP_TIMESTAMP"; + case ZT_ICMP_TIMESTAMP_REPLY: return "ICMP_TIMESTAMP_REPLY"; + case ZT_ICMP_INFORMATION_REQUEST: return "ICMP_INFORMATION_REQUEST"; + case ZT_ICMP_INFORMATION_REPLY: return "ICMP_INFORMATION_REPLY"; + case ZT_ICMP_ADDRESS_MASK_REQUEST: return "ICMP_ADDRESS_MASK_REQUEST"; + case ZT_ICMP_ADDRESS_MASK_REPLY: return "ICMP_ADDRESS_MASK_REPLY"; + case ZT_ICMP_TRACEROUTE: return "ICMP_TRACEROUTE"; + case ZT_ICMP_MOBILE_HOST_REDIRECT: return "ICMP_MOBILE_HOST_REDIRECT"; + case ZT_ICMP_MOBILE_REGISTRATION_REQUEST: return "ICMP_MOBILE_REGISTRATION_REQUEST"; + case ZT_ICMP_MOBILE_REGISTRATION_REPLY: return "ICMP_MOBILE_REGISTRATION_REPLY"; + } + return UNKNOWN_NAME; +} + +const char *Filter::icmp6TypeName(const unsigned int icmp6Type) + throw() +{ + switch(icmp6Type) { + case ZT_ICMP6_DESTINATION_UNREACHABLE: return "ICMP6_DESTINATION_UNREACHABLE"; + case ZT_ICMP6_PACKET_TOO_BIG: return "ICMP6_PACKET_TOO_BIG"; + case ZT_ICMP6_TIME_EXCEEDED: return "ICMP6_TIME_EXCEEDED"; + case ZT_ICMP6_PARAMETER_PROBLEM: return "ICMP6_PARAMETER_PROBLEM"; + case ZT_ICMP6_ECHO_REQUEST: return "ICMP6_ECHO_REQUEST"; + case ZT_ICMP6_ECHO_REPLY: return "ICMP6_ECHO_REPLY"; + case ZT_ICMP6_MULTICAST_LISTENER_QUERY: return "ICMP6_MULTICAST_LISTENER_QUERY"; + case ZT_ICMP6_MULTICAST_LISTENER_REPORT: return "ICMP6_MULTICAST_LISTENER_REPORT"; + case ZT_ICMP6_MULTICAST_LISTENER_DONE: return "ICMP6_MULTICAST_LISTENER_DONE"; + case ZT_ICMP6_ROUTER_SOLICITATION: return "ICMP6_ROUTER_SOLICITATION"; + case ZT_ICMP6_ROUTER_ADVERTISEMENT: return "ICMP6_ROUTER_ADVERTISEMENT"; + case ZT_ICMP6_NEIGHBOR_SOLICITATION: return "ICMP6_NEIGHBOR_SOLICITATION"; + case ZT_ICMP6_NEIGHBOR_ADVERTISEMENT: return "ICMP6_NEIGHBOR_ADVERTISEMENT"; + case ZT_ICMP6_REDIRECT_MESSAGE: return "ICMP6_REDIRECT_MESSAGE"; + case ZT_ICMP6_ROUTER_RENUMBERING: return "ICMP6_ROUTER_RENUMBERING"; + case ZT_ICMP6_NODE_INFORMATION_QUERY: return "ICMP6_NODE_INFORMATION_QUERY"; + case ZT_ICMP6_NODE_INFORMATION_RESPONSE: return "ICMP6_NODE_INFORMATION_RESPONSE"; + case ZT_ICMP6_INV_NEIGHBOR_SOLICITATION: return "ICMP6_INV_NEIGHBOR_SOLICITATION"; + case ZT_ICMP6_INV_NEIGHBOR_ADVERTISEMENT: return "ICMP6_INV_NEIGHBOR_ADVERTISEMENT"; + case ZT_ICMP6_MLDV2: return "ICMP6_MLDV2"; + case ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST: return "ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST"; + case ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY: return "ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY"; + case ZT_ICMP6_MOBILE_PREFIX_SOLICITATION: return "ICMP6_MOBILE_PREFIX_SOLICITATION"; + case ZT_ICMP6_MOBILE_PREFIX_ADVERTISEMENT: return "ICMP6_MOBILE_PREFIX_ADVERTISEMENT"; + case ZT_ICMP6_CERTIFICATION_PATH_SOLICITATION: return "ICMP6_CERTIFICATION_PATH_SOLICITATION"; + case ZT_ICMP6_CERTIFICATION_PATH_ADVERTISEMENT: return "ICMP6_CERTIFICATION_PATH_ADVERTISEMENT"; + case ZT_ICMP6_MULTICAST_ROUTER_ADVERTISEMENT: return "ICMP6_MULTICAST_ROUTER_ADVERTISEMENT"; + case ZT_ICMP6_MULTICAST_ROUTER_SOLICITATION: return "ICMP6_MULTICAST_ROUTER_SOLICITATION"; + case ZT_ICMP6_MULTICAST_ROUTER_TERMINATION: return "ICMP6_MULTICAST_ROUTER_TERMINATION"; + case ZT_ICMP6_RPL_CONTROL_MESSAGE: return "ICMP6_RPL_CONTROL_MESSAGE"; + } + return UNKNOWN_NAME; +} + +} // namespace ZeroTier diff --git a/attic/Filter.hpp b/attic/Filter.hpp new file mode 100644 index 000000000..4bea3715d --- /dev/null +++ b/attic/Filter.hpp @@ -0,0 +1,284 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef _ZT_FILTER_HPP +#define _ZT_FILTER_HPP + +#include +#include +#include + +#include +#include +#include +#include + +#include "Range.hpp" + +/* Ethernet frame types that might be relevant to us */ +#define ZT_ETHERTYPE_IPV4 0x0800 +#define ZT_ETHERTYPE_ARP 0x0806 +#define ZT_ETHERTYPE_RARP 0x8035 +#define ZT_ETHERTYPE_ATALK 0x809b +#define ZT_ETHERTYPE_AARP 0x80f3 +#define ZT_ETHERTYPE_IPX_A 0x8137 +#define ZT_ETHERTYPE_IPX_B 0x8138 +#define ZT_ETHERTYPE_IPV6 0x86dd + +/* IP protocols we might care about */ +#define ZT_IPPROTO_ICMP 0x01 +#define ZT_IPPROTO_IGMP 0x02 +#define ZT_IPPROTO_TCP 0x06 +#define ZT_IPPROTO_UDP 0x11 +#define ZT_IPPROTO_GRE 0x2f +#define ZT_IPPROTO_ESP 0x32 +#define ZT_IPPROTO_AH 0x33 +#define ZT_IPPROTO_ICMPV6 0x3a +#define ZT_IPPROTO_OSPF 0x59 +#define ZT_IPPROTO_IPIP 0x5e +#define ZT_IPPROTO_IPCOMP 0x6c +#define ZT_IPPROTO_L2TP 0x73 +#define ZT_IPPROTO_SCTP 0x84 +#define ZT_IPPROTO_FC 0x85 +#define ZT_IPPROTO_UDPLITE 0x88 +#define ZT_IPPROTO_HIP 0x8b + +/* IPv4 ICMP types */ +#define ZT_ICMP_ECHO_REPLY 0 +#define ZT_ICMP_DESTINATION_UNREACHABLE 3 +#define ZT_ICMP_SOURCE_QUENCH 4 +#define ZT_ICMP_REDIRECT 5 +#define ZT_ICMP_ALTERNATE_HOST_ADDRESS 6 +#define ZT_ICMP_ECHO_REQUEST 8 +#define ZT_ICMP_ROUTER_ADVERTISEMENT 9 +#define ZT_ICMP_ROUTER_SOLICITATION 10 +#define ZT_ICMP_TIME_EXCEEDED 11 +#define ZT_ICMP_BAD_IP_HEADER 12 +#define ZT_ICMP_TIMESTAMP 13 +#define ZT_ICMP_TIMESTAMP_REPLY 14 +#define ZT_ICMP_INFORMATION_REQUEST 15 +#define ZT_ICMP_INFORMATION_REPLY 16 +#define ZT_ICMP_ADDRESS_MASK_REQUEST 17 +#define ZT_ICMP_ADDRESS_MASK_REPLY 18 +#define ZT_ICMP_TRACEROUTE 30 +#define ZT_ICMP_MOBILE_HOST_REDIRECT 32 +#define ZT_ICMP_MOBILE_REGISTRATION_REQUEST 35 +#define ZT_ICMP_MOBILE_REGISTRATION_REPLY 36 + +/* IPv6 ICMP types */ +#define ZT_ICMP6_DESTINATION_UNREACHABLE 1 +#define ZT_ICMP6_PACKET_TOO_BIG 2 +#define ZT_ICMP6_TIME_EXCEEDED 3 +#define ZT_ICMP6_PARAMETER_PROBLEM 4 +#define ZT_ICMP6_ECHO_REQUEST 128 +#define ZT_ICMP6_ECHO_REPLY 129 +#define ZT_ICMP6_MULTICAST_LISTENER_QUERY 130 +#define ZT_ICMP6_MULTICAST_LISTENER_REPORT 131 +#define ZT_ICMP6_MULTICAST_LISTENER_DONE 132 +#define ZT_ICMP6_ROUTER_SOLICITATION 133 +#define ZT_ICMP6_ROUTER_ADVERTISEMENT 134 +#define ZT_ICMP6_NEIGHBOR_SOLICITATION 135 +#define ZT_ICMP6_NEIGHBOR_ADVERTISEMENT 136 +#define ZT_ICMP6_REDIRECT_MESSAGE 137 +#define ZT_ICMP6_ROUTER_RENUMBERING 138 +#define ZT_ICMP6_NODE_INFORMATION_QUERY 139 +#define ZT_ICMP6_NODE_INFORMATION_RESPONSE 140 +#define ZT_ICMP6_INV_NEIGHBOR_SOLICITATION 141 +#define ZT_ICMP6_INV_NEIGHBOR_ADVERTISEMENT 142 +#define ZT_ICMP6_MLDV2 143 +#define ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST 144 +#define ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY 145 +#define ZT_ICMP6_MOBILE_PREFIX_SOLICITATION 146 +#define ZT_ICMP6_MOBILE_PREFIX_ADVERTISEMENT 147 +#define ZT_ICMP6_CERTIFICATION_PATH_SOLICITATION 148 +#define ZT_ICMP6_CERTIFICATION_PATH_ADVERTISEMENT 149 +#define ZT_ICMP6_MULTICAST_ROUTER_ADVERTISEMENT 151 +#define ZT_ICMP6_MULTICAST_ROUTER_SOLICITATION 152 +#define ZT_ICMP6_MULTICAST_ROUTER_TERMINATION 153 +#define ZT_ICMP6_RPL_CONTROL_MESSAGE 155 + +namespace ZeroTier { + +class RuntimeEnvironment; + +/** + * A simple Ethernet frame level filter + * + * This doesn't specify actions, since it's used as a deny filter. The rule + * in ZT1 is "that which is not explicitly prohibited is allowed." (Except for + * ethertypes, which are handled by a whitelist.) + */ +class Filter +{ +public: + /** + * Value returned by etherTypeName, etc. on unknown + * + * These static methods return precisely this, so a pointer equality + * check will work. + */ + static const char *const UNKNOWN_NAME; + + /** + * An empty range as a more idiomatic way of specifying a wildcard match + */ + static const Range ANY; + + /** + * A filter rule + */ + class Rule + { + public: + Rule() + throw() : + _etherType(), + _protocol(), + _port() + { + } + + /** + * Construct a rule from a string-serialized value + * + * @param s String formatted rule, such as returned by toString() + * @throws std::invalid_argument String formatted rule is not valid + */ + Rule(const char *s) + throw(std::invalid_argument); + + /** + * Construct a new rule + * + * @param etype Ethernet type or empty range for ANY + * @param prot Protocol or empty range for ANY (meaning depends on ethertype, e.g. IP protocol numbers) + * @param prt Port or empty range for ANY (only applies to some protocols) + */ + Rule(const Range &etype,const Range &prot,const Range &prt) + throw() : + _etherType(etype), + _protocol(prot), + _port(prt) + { + } + + inline const Range ðerType() const throw() { return _etherType; } + inline const Range &protocol() const throw() { return _protocol; } + inline const Range &port() const throw() { return _port; } + + /** + * Test this rule against a frame + * + * @param etype Type of ethernet frame + * @param data Ethernet frame data + * @param len Length of ethernet frame + * @return True if rule matches + * @throws std::invalid_argument Frame invalid or not parseable + */ + bool operator()(unsigned int etype,const void *data,unsigned int len) const + throw(std::invalid_argument); + + /** + * Serialize rule as string + * + * @return Human readable representation of rule + */ + std::string toString() const; + + inline bool operator==(const Rule &r) const throw() { return ((_etherType == r._etherType)&&(_protocol == r._protocol)&&(_port == r._port)); } + inline bool operator!=(const Rule &r) const throw() { return !(*this == r); } + inline bool operator<(const Rule &r) const + throw() + { + if (_etherType < r._etherType) + return true; + else if (_etherType == r._etherType) { + if (_protocol < r._protocol) + return true; + else if (_protocol == r._protocol) { + if (_port < r._port) + return true; + } + } + return false; + } + inline bool operator>(const Rule &r) const throw() { return (r < *this); } + inline bool operator<=(const Rule &r) const throw() { return !(r < *this); } + inline bool operator>=(const Rule &r) const throw() { return !(*this < r); } + + private: + Range _etherType; + Range _protocol; + Range _port; + }; + + Filter() {} + + /** + * @param s String-serialized filter representation + */ + Filter(const char *s) + throw(std::invalid_argument); + + /** + * @return Comma-delimited list of string-format rules + */ + std::string toString() const; + + /** + * Add a rule to this filter + * + * @param r Rule to add to filter + */ + void add(const Rule &r); + + inline bool operator()(unsigned int etype,const void *data,unsigned int len) const + throw(std::invalid_argument) + { + for(std::vector::const_iterator r(_rules.begin());r!=_rules.end();++r) { + if ((*r)(etype,data,len)) + return true; + } + return false; + } + + static const char *etherTypeName(const unsigned int etherType) + throw(); + static const char *ipProtocolName(const unsigned int ipp) + throw(); + static const char *icmpTypeName(const unsigned int icmpType) + throw(); + static const char *icmp6TypeName(const unsigned int icmp6Type) + throw(); + +private: + std::vector _rules; +}; + +} // namespace ZeroTier + +#endif diff --git a/attic/OSXEthernetTap.cpp.pcap-with-bridge-test b/attic/OSXEthernetTap.cpp.pcap-with-bridge-test new file mode 100644 index 000000000..60194421c --- /dev/null +++ b/attic/OSXEthernetTap.cpp.pcap-with-bridge-test @@ -0,0 +1,651 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!? +struct prf_ra { + u_char onlink : 1; + u_char autonomous : 1; + u_char reserved : 6; +} prf_ra; + +#include +#include + +// These are KERNEL_PRIVATE... why? +#ifndef SIOCAUTOCONF_START +#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */ +#endif +#ifndef SIOCAUTOCONF_STOP +#define SIOCAUTOCONF_STOP _IOWR('i', 133, struct in6_ifreq) /* stop accepting rtadv for this interface */ +#endif + +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- +// This source is from: +// http://www.opensource.apple.com/source/Libinfo/Libinfo-406.17/gen.subproj/getifmaddrs.c?txt +// It's here because OSX 10.6 does not have this convenience function. + +#define SALIGN (sizeof(uint32_t) - 1) +#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ +(SALIGN + 1)) +#define MAX_SYSCTL_TRY 5 +#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) + +/* FreeBSD uses NET_RT_IFMALIST and RTM_NEWMADDR from */ +/* We can use NET_RT_IFLIST2 and RTM_NEWMADDR2 on Darwin */ +//#define DARWIN_COMPAT + +//#ifdef DARWIN_COMPAT +#define GIM_SYSCTL_MIB NET_RT_IFLIST2 +#define GIM_RTM_ADDR RTM_NEWMADDR2 +//#else +//#define GIM_SYSCTL_MIB NET_RT_IFMALIST +//#define GIM_RTM_ADDR RTM_NEWMADDR +//#endif + +// Not in 10.6 includes so use our own +struct _intl_ifmaddrs { + struct _intl_ifmaddrs *ifma_next; + struct sockaddr *ifma_name; + struct sockaddr *ifma_addr; + struct sockaddr *ifma_lladdr; +}; + +static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif) +{ + int icnt = 1; + int dcnt = 0; + int ntry = 0; + size_t len; + size_t needed; + int mib[6]; + int i; + char *buf; + char *data; + char *next; + char *p; + struct ifma_msghdr2 *ifmam; + struct _intl_ifmaddrs *ifa, *ift; + struct rt_msghdr *rtm; + struct sockaddr *sa; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; /* protocol */ + mib[3] = 0; /* wildcard address family */ + mib[4] = GIM_SYSCTL_MIB; + mib[5] = 0; /* no flags */ + do { + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + return (-1); + if ((buf = (char *)malloc(needed)) == NULL) + return (-1); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { + free(buf); + return (-1); + } + free(buf); + buf = NULL; + } + } while (buf == NULL); + + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + switch (rtm->rtm_type) { + case GIM_RTM_ADDR: + ifmam = (struct ifma_msghdr2 *)(void *)rtm; + if ((ifmam->ifmam_addrs & RTA_IFA) == 0) + break; + icnt++; + p = (char *)(ifmam + 1); + for (i = 0; i < RTAX_MAX; i++) { + if ((RTA_MASKS & ifmam->ifmam_addrs & + (1 << i)) == 0) + continue; + sa = (struct sockaddr *)(void *)p; + len = SA_RLEN(sa); + dcnt += len; + p += len; + } + break; + } + } + + data = (char *)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt); + if (data == NULL) { + free(buf); + return (-1); + } + + ifa = (struct _intl_ifmaddrs *)(void *)data; + data += sizeof(struct _intl_ifmaddrs) * icnt; + + memset(ifa, 0, sizeof(struct _intl_ifmaddrs) * icnt); + ift = ifa; + + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + + switch (rtm->rtm_type) { + case GIM_RTM_ADDR: + ifmam = (struct ifma_msghdr2 *)(void *)rtm; + if ((ifmam->ifmam_addrs & RTA_IFA) == 0) + break; + + p = (char *)(ifmam + 1); + for (i = 0; i < RTAX_MAX; i++) { + if ((RTA_MASKS & ifmam->ifmam_addrs & + (1 << i)) == 0) + continue; + sa = (struct sockaddr *)(void *)p; + len = SA_RLEN(sa); + switch (i) { + case RTAX_GATEWAY: + ift->ifma_lladdr = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + case RTAX_IFP: + ift->ifma_name = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + case RTAX_IFA: + ift->ifma_addr = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + default: + data += len; + break; + } + p += len; + } + ift->ifma_next = ift + 1; + ift = ift->ifma_next; + break; + } + } + + free(buf); + + if (ift > ifa) { + ift--; + ift->ifma_next = NULL; + *pif = ifa; + } else { + *pif = NULL; + free(ifa); + } + return (0); +} + +static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp) +{ + free(ifmp); +} + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +#include "../node/Constants.hpp" +#include "../node/Utils.hpp" +#include "../node/Mutex.hpp" +#include "../node/Dictionary.hpp" +#include "OSUtils.hpp" +#include "OSXEthernetTap.hpp" + +// ff:ff:ff:ff:ff:ff with no ADI +static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0); + +static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptRouterAdverts) +{ + struct in6_ndireq nd; + struct in6_ifreq ifr; + + int s = socket(AF_INET6,SOCK_DGRAM,0); + if (s <= 0) + return false; + + memset(&nd,0,sizeof(nd)); + strncpy(nd.ifname,ifname,sizeof(nd.ifname)); + + if (ioctl(s,SIOCGIFINFO_IN6,&nd)) { + close(s); + return false; + } + + unsigned long oldFlags = (unsigned long)nd.ndi.flags; + + if (performNUD) + nd.ndi.flags |= ND6_IFF_PERFORMNUD; + else nd.ndi.flags &= ~ND6_IFF_PERFORMNUD; + + if (oldFlags != (unsigned long)nd.ndi.flags) { + if (ioctl(s,SIOCSIFINFO_FLAGS,&nd)) { + close(s); + return false; + } + } + + memset(&ifr,0,sizeof(ifr)); + strncpy(ifr.ifr_name,ifname,sizeof(ifr.ifr_name)); + if (ioctl(s,acceptRouterAdverts ? SIOCAUTOCONF_START : SIOCAUTOCONF_STOP,&ifr)) { + close(s); + return false; + } + + close(s); + return true; +} + +namespace ZeroTier { + +static std::set globalDeviceNames; +static Mutex globalTapCreateLock; + +OSXEthernetTap::OSXEthernetTap( + const char *homePath, + const MAC &mac, + unsigned int mtu, + unsigned int metric, + uint64_t nwid, + const char *friendlyName, + void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len), + void *arg) : + _handler(handler), + _arg(arg), + _pcap((void *)0), + _nwid(nwid), + _mac(mac), + _homePath(homePath), + _mtu(mtu), + _metric(metric), + _enabled(true) +{ + char errbuf[PCAP_ERRBUF_SIZE]; + char devname[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; + + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + + if (mtu > 2800) + throw std::runtime_error("max tap MTU is 2800"); + + Mutex::Lock _gl(globalTapCreateLock); + + std::string desiredDevice; + Dictionary devmap; + { + std::string devmapbuf; + if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmapbuf)) { + devmap.fromString(devmapbuf); + desiredDevice = devmap.get(nwids,""); + } + } + + if ((desiredDevice.length() >= 9)&&(desiredDevice.substr(0,6) == "bridge")) { + // length() >= 9 matches bridge### or bridge#### + _dev = desiredDevice; + } else { + if (globalDeviceNames.size() >= (10000 - 128)) // sanity check... this would be nuts + throw std::runtime_error("too many devices!"); + unsigned int pseudoBridgeNo = (unsigned int)((nwid ^ (nwid >> 32)) % (10000 - 128)) + 128; // range: bridge128 to bridge9999 + sprintf(devname,"bridge%u",pseudoBridgeNo); + while (globalDeviceNames.count(std::string(devname)) > 0) { + ++pseudoBridgeNo; + if (pseudoBridgeNo > 9999) + pseudoBridgeNo = 64; + sprintf(devname,"bridge%u",pseudoBridgeNo); + } + _dev = devname; + } + + // Configure MAC address and MTU, bring interface up + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"create",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + if (exitcode != 0) + throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); + } else throw std::runtime_error("unable to fork()"); + Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); + Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); + Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); + cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + if (exitcode != 0) + throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); + } else throw std::runtime_error("unable to fork()"); + + _setIpv6Stuff(_dev.c_str(),true,false); + + _pcap = (void *)pcap_create(_dev.c_str(),errbuf); + if (!_pcap) { + cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + } + throw std::runtime_error((std::string("pcap_create() on new bridge device failed: ") + errbuf).c_str()); + } + pcap_set_promisc(reinterpret_cast(_pcap),1); + pcap_set_timeout(reinterpret_cast(_pcap),120000); + pcap_set_immediate_mode(reinterpret_cast(_pcap),1); + if (pcap_set_buffer_size(reinterpret_cast(_pcap),1024 * 1024 * 16) != 0) // 16MB + fprintf(stderr,"WARNING: pcap_set_buffer_size() failed!\n"); + if (pcap_set_snaplen(reinterpret_cast(_pcap),4096) != 0) + fprintf(stderr,"WARNING: pcap_set_snaplen() failed!\n"); + if (pcap_activate(reinterpret_cast(_pcap)) != 0) { + pcap_close(reinterpret_cast(_pcap)); + cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + } + throw std::runtime_error("pcap_activate() on new bridge device failed."); + } + + globalDeviceNames.insert(_dev); + + devmap[nwids] = _dev; + OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmap.toString()); + + _thread = Thread::start(this); +} + +OSXEthernetTap::~OSXEthernetTap() +{ + _enabled = false; + + Mutex::Lock _gl(globalTapCreateLock); + globalDeviceNames.erase(_dev); + + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + if (exitcode == 0) { + // Destroying the interface nukes pcap and terminates the thread. + Thread::join(_thread); + } + } + + pcap_close(reinterpret_cast(_pcap)); +} + +static bool ___removeIp(const std::string &_dev,const InetAddress &ip) +{ + long cpid = (long)vfork(); + if (cpid == 0) { + execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet",ip.toIpString().c_str(),"-alias",(const char *)0); + _exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + waitpid(cpid,&exitcode,0); + return (exitcode == 0); + } + return false; // never reached, make compiler shut up about return value +} + +bool OSXEthernetTap::addIp(const InetAddress &ip) +{ + if (!ip) + return false; + + std::vector allIps(ips()); + if (std::binary_search(allIps.begin(),allIps.end(),ip)) + return true; + + // Remove and reconfigure if address is the same but netmask is different + for(std::vector::iterator i(allIps.begin());i!=allIps.end();++i) { + if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) { + if (___removeIp(_dev,*i)) + break; + } + } + + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + return (exitcode == 0); + } // else return false... + + return false; +} + +bool OSXEthernetTap::removeIp(const InetAddress &ip) +{ + if (!ip) + return true; + std::vector allIps(ips()); + if (!std::binary_search(allIps.begin(),allIps.end(),ip)) { + if (___removeIp(_dev,ip)) + return true; + } + return false; +} + +std::vector OSXEthernetTap::ips() const +{ + struct ifaddrs *ifa = (struct ifaddrs *)0; + if (getifaddrs(&ifa)) + return std::vector(); + + std::vector r; + + struct ifaddrs *p = ifa; + while (p) { + if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) { + switch(p->ifa_addr->sa_family) { + case AF_INET: { + struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr; + struct sockaddr_in *nm = (struct sockaddr_in *)p->ifa_netmask; + r.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr))); + } break; + case AF_INET6: { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr; + struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask; + uint32_t b[4]; + memcpy(b,nm->sin6_addr.s6_addr,sizeof(b)); + r.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3]))); + } break; + } + } + p = p->ifa_next; + } + + if (ifa) + freeifaddrs(ifa); + + std::sort(r.begin(),r.end()); + std::unique(r.begin(),r.end()); + + return r; +} + +void OSXEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) +{ + char putBuf[4096]; + if ((len <= _mtu)&&(_enabled)) { + to.copyTo(putBuf,6); + from.copyTo(putBuf + 6,6); + *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType); + memcpy(putBuf + 14,data,len); + len += 14; + int r = pcap_inject(reinterpret_cast(_pcap),putBuf,len); + if (r <= 0) { + printf("%s: pcap_inject() failed\n",_dev.c_str()); + return; + } + printf("%s: inject %s -> %s etherType==%u len=%u r==%d\n",_dev.c_str(),from.toString().c_str(),to.toString().c_str(),etherType,len,r); + } +} + +std::string OSXEthernetTap::deviceName() const +{ + return _dev; +} + +void OSXEthernetTap::setFriendlyName(const char *friendlyName) +{ +} + +void OSXEthernetTap::scanMulticastGroups(std::vector &added,std::vector &removed) +{ + std::vector newGroups; + + struct _intl_ifmaddrs *ifmap = (struct _intl_ifmaddrs *)0; + if (!_intl_getifmaddrs(&ifmap)) { + struct _intl_ifmaddrs *p = ifmap; + while (p) { + if (p->ifma_addr->sa_family == AF_LINK) { + struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name; + struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr; + if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen))) + newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0)); + } + p = p->ifma_next; + } + _intl_freeifmaddrs(ifmap); + } + + std::vector allIps(ips()); + for(std::vector::iterator ip(allIps.begin());ip!=allIps.end();++ip) + newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); + + std::sort(newGroups.begin(),newGroups.end()); + std::unique(newGroups.begin(),newGroups.end()); + + for(std::vector::iterator m(newGroups.begin());m!=newGroups.end();++m) { + if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m)) + added.push_back(*m); + } + for(std::vector::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) { + if (!std::binary_search(newGroups.begin(),newGroups.end(),*m)) + removed.push_back(*m); + } + + _multicastGroups.swap(newGroups); +} + +static void _pcapHandler(u_char *ptr,const struct pcap_pkthdr *hdr,const u_char *data) +{ + OSXEthernetTap *tap = reinterpret_cast(ptr); + if (hdr->caplen > 14) { + MAC to(data,6); + MAC from(data + 6,6); + if (from == tap->_mac) { + unsigned int etherType = ntohs(((const uint16_t *)data)[6]); + printf("%s: %s -> %s etherType==%u len==%u\n",tap->_dev.c_str(),from.toString().c_str(),to.toString().c_str(),etherType,(unsigned int)hdr->caplen); + // TODO: VLAN support + tap->_handler(tap->_arg,tap->_nwid,from,to,etherType,0,(const void *)(data + 14),hdr->len - 14); + } + } +} + +void OSXEthernetTap::threadMain() + throw() +{ + pcap_loop(reinterpret_cast(_pcap),-1,&_pcapHandler,reinterpret_cast(this)); +} + +} // namespace ZeroTier diff --git a/attic/OSXEthernetTap.cpp.utun-work-in-progress b/attic/OSXEthernetTap.cpp.utun-work-in-progress new file mode 100644 index 000000000..b7a05334d --- /dev/null +++ b/attic/OSXEthernetTap.cpp.utun-work-in-progress @@ -0,0 +1,832 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!? +struct prf_ra { + u_char onlink : 1; + u_char autonomous : 1; + u_char reserved : 6; +} prf_ra; + +#include +#include + +// These are KERNEL_PRIVATE... why? +#ifndef SIOCAUTOCONF_START +#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */ +#endif +#ifndef SIOCAUTOCONF_STOP +#define SIOCAUTOCONF_STOP _IOWR('i', 133, struct in6_ifreq) /* stop accepting rtadv for this interface */ +#endif + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- +// This source is from: +// http://www.opensource.apple.com/source/Libinfo/Libinfo-406.17/gen.subproj/getifmaddrs.c?txt +// It's here because OSX 10.6 does not have this convenience function. + +#define SALIGN (sizeof(uint32_t) - 1) +#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ +(SALIGN + 1)) +#define MAX_SYSCTL_TRY 5 +#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) + +/* FreeBSD uses NET_RT_IFMALIST and RTM_NEWMADDR from */ +/* We can use NET_RT_IFLIST2 and RTM_NEWMADDR2 on Darwin */ +//#define DARWIN_COMPAT + +//#ifdef DARWIN_COMPAT +#define GIM_SYSCTL_MIB NET_RT_IFLIST2 +#define GIM_RTM_ADDR RTM_NEWMADDR2 +//#else +//#define GIM_SYSCTL_MIB NET_RT_IFMALIST +//#define GIM_RTM_ADDR RTM_NEWMADDR +//#endif + +// Not in 10.6 includes so use our own +struct _intl_ifmaddrs { + struct _intl_ifmaddrs *ifma_next; + struct sockaddr *ifma_name; + struct sockaddr *ifma_addr; + struct sockaddr *ifma_lladdr; +}; + +static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif) +{ + int icnt = 1; + int dcnt = 0; + int ntry = 0; + size_t len; + size_t needed; + int mib[6]; + int i; + char *buf; + char *data; + char *next; + char *p; + struct ifma_msghdr2 *ifmam; + struct _intl_ifmaddrs *ifa, *ift; + struct rt_msghdr *rtm; + struct sockaddr *sa; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; /* protocol */ + mib[3] = 0; /* wildcard address family */ + mib[4] = GIM_SYSCTL_MIB; + mib[5] = 0; /* no flags */ + do { + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + return (-1); + if ((buf = (char *)malloc(needed)) == NULL) + return (-1); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { + free(buf); + return (-1); + } + free(buf); + buf = NULL; + } + } while (buf == NULL); + + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + switch (rtm->rtm_type) { + case GIM_RTM_ADDR: + ifmam = (struct ifma_msghdr2 *)(void *)rtm; + if ((ifmam->ifmam_addrs & RTA_IFA) == 0) + break; + icnt++; + p = (char *)(ifmam + 1); + for (i = 0; i < RTAX_MAX; i++) { + if ((RTA_MASKS & ifmam->ifmam_addrs & + (1 << i)) == 0) + continue; + sa = (struct sockaddr *)(void *)p; + len = SA_RLEN(sa); + dcnt += len; + p += len; + } + break; + } + } + + data = (char *)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt); + if (data == NULL) { + free(buf); + return (-1); + } + + ifa = (struct _intl_ifmaddrs *)(void *)data; + data += sizeof(struct _intl_ifmaddrs) * icnt; + + memset(ifa, 0, sizeof(struct _intl_ifmaddrs) * icnt); + ift = ifa; + + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + + switch (rtm->rtm_type) { + case GIM_RTM_ADDR: + ifmam = (struct ifma_msghdr2 *)(void *)rtm; + if ((ifmam->ifmam_addrs & RTA_IFA) == 0) + break; + + p = (char *)(ifmam + 1); + for (i = 0; i < RTAX_MAX; i++) { + if ((RTA_MASKS & ifmam->ifmam_addrs & + (1 << i)) == 0) + continue; + sa = (struct sockaddr *)(void *)p; + len = SA_RLEN(sa); + switch (i) { + case RTAX_GATEWAY: + ift->ifma_lladdr = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + case RTAX_IFP: + ift->ifma_name = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + case RTAX_IFA: + ift->ifma_addr = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + default: + data += len; + break; + } + p += len; + } + ift->ifma_next = ift + 1; + ift = ift->ifma_next; + break; + } + } + + free(buf); + + if (ift > ifa) { + ift--; + ift->ifma_next = NULL; + *pif = ifa; + } else { + *pif = NULL; + free(ifa); + } + return (0); +} + +static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp) +{ + free(ifmp); +} + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +#include "../node/Constants.hpp" +#include "../node/Utils.hpp" +#include "../node/Mutex.hpp" +#include "../node/Dictionary.hpp" +#include "Arp.hpp" +#include "OSUtils.hpp" +#include "OSXEthernetTap.hpp" + +// ff:ff:ff:ff:ff:ff with no ADI +static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0); + +static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptRouterAdverts) +{ + struct in6_ndireq nd; + struct in6_ifreq ifr; + + int s = socket(AF_INET6,SOCK_DGRAM,0); + if (s <= 0) + return false; + + memset(&nd,0,sizeof(nd)); + strncpy(nd.ifname,ifname,sizeof(nd.ifname)); + + if (ioctl(s,SIOCGIFINFO_IN6,&nd)) { + close(s); + return false; + } + + unsigned long oldFlags = (unsigned long)nd.ndi.flags; + + if (performNUD) + nd.ndi.flags |= ND6_IFF_PERFORMNUD; + else nd.ndi.flags &= ~ND6_IFF_PERFORMNUD; + + if (oldFlags != (unsigned long)nd.ndi.flags) { + if (ioctl(s,SIOCSIFINFO_FLAGS,&nd)) { + close(s); + return false; + } + } + + memset(&ifr,0,sizeof(ifr)); + strncpy(ifr.ifr_name,ifname,sizeof(ifr.ifr_name)); + if (ioctl(s,acceptRouterAdverts ? SIOCAUTOCONF_START : SIOCAUTOCONF_STOP,&ifr)) { + close(s); + return false; + } + + close(s); + return true; +} + +// Create an OSX-native utun device (utun# where # is desiredNumber) +// Adapted from public domain utun example code by Jonathan Levin +static int _make_utun(int desiredNumber) +{ + struct sockaddr_ctl sc; + struct ctl_info ctlInfo; + struct ifreq ifr; + + memset(&ctlInfo, 0, sizeof(ctlInfo)); + if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) >= sizeof(ctlInfo.ctl_name)) { + return -1; + } + + int fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); + if (fd == -1) + return -1; + if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1) { + close(fd); + return -1; + } + + sc.sc_id = ctlInfo.ctl_id; + sc.sc_len = sizeof(sc); + sc.sc_family = AF_SYSTEM; + sc.ss_sysaddr = AF_SYS_CONTROL; + sc.sc_unit = desiredNumber + 1; + + if (connect(fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) { + close(fd); + return -1; + } + + memset(&ifr,0,sizeof(ifr)); + sprintf(ifr.ifr_name,"utun%d",desiredNumber); + if (ioctl(fd,SIOCGIFFLAGS,(void *)&ifr) < 0) { + printf("SIOCGIFFLAGS failed\n"); + } + ifr.ifr_flags &= ~IFF_POINTOPOINT; + if (ioctl(fd,SIOCSIFFLAGS,(void *)&ifr) < 0) { + printf("clear IFF_POINTOPOINT failed\n"); + } + + return fd; +} + +namespace ZeroTier { + +static long globalTapsRunning = 0; +static Mutex globalTapCreateLock; + +OSXEthernetTap::OSXEthernetTap( + const char *homePath, + const MAC &mac, + unsigned int mtu, + unsigned int metric, + uint64_t nwid, + const char *friendlyName, + void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len), + void *arg) : + _handler(handler), + _arg(arg), + _arp((Arp *)0), + _nwid(nwid), + _homePath(homePath), + _mtu(mtu), + _metric(metric), + _fd(0), + _utun(false), + _enabled(true) +{ + char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; + struct stat stattmp; + + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + + if (mtu > 2800) + throw std::runtime_error("max tap MTU is 2800"); + + Mutex::Lock _gl(globalTapCreateLock); + + // Read remembered previous device name, if any -- we'll try to reuse + Dictionary devmap; + std::string desiredDevice; + { + std::string devmapbuf; + if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmapbuf)) { + devmap.fromString(devmapbuf); + desiredDevice = devmap.get(nwids,""); + } + } + + if (::stat((_homePath + ZT_PATH_SEPARATOR_S + "tap.kext").c_str(),&stattmp) == 0) { + // Try to init kext if it's there, otherwise revert to utun mode + + if (::stat("/dev/zt0",&stattmp)) { + long kextpid = (long)vfork(); + if (kextpid == 0) { + ::chdir(homePath); + OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); + ::execl("/sbin/kextload","/sbin/kextload","-q","-repository",homePath,"tap.kext",(const char *)0); + ::_exit(-1); + } else if (kextpid > 0) { + int exitcode = -1; + ::waitpid(kextpid,&exitcode,0); + } + ::usleep(500); // give tap device driver time to start up and try again + if (::stat("/dev/zt0",&stattmp)) + _utun = true; + } + + if (!_utun) { + // See if we can re-use the last device we had. + bool recalledDevice = false; + if (desiredDevice.length() > 2) { + Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",desiredDevice.c_str()); + if (stat(devpath,&stattmp) == 0) { + _fd = ::open(devpath,O_RDWR); + if (_fd > 0) { + _dev = desiredDevice; + recalledDevice = true; + } + } + } + + // Open the first unused tap device if we didn't recall a previous one. + if (!recalledDevice) { + for(int i=0;i<64;++i) { + Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i); + if (stat(devpath,&stattmp)) { + _utun = true; + break; + } + _fd = ::open(devpath,O_RDWR); + if (_fd > 0) { + char foo[16]; + Utils::snprintf(foo,sizeof(foo),"zt%d",i); + _dev = foo; + break; + } + } + } + if (_fd <= 0) + _utun = true; + } + } else { + _utun = true; + } + + if (_utun) { + // Use OSX built-in utun device if kext is not available or doesn't work + + int utunNo = 0; + + if ((desiredDevice.length() > 4)&&(desiredDevice.substr(0,4) == "utun")) { + utunNo = Utils::strToInt(desiredDevice.substr(4).c_str()); + if (utunNo >= 0) + _fd = _make_utun(utunNo); + } + + if (_fd <= 0) { + // Start at utun8 to leave lower utuns unused since other stuff might + // want them -- OpenVPN, cjdns, etc. I'm not sure if those are smart + // enough to scan upward like this. + for(utunNo=8;utunNo<=256;++utunNo) { + if ((_fd = _make_utun(utunNo)) > 0) + break; + } + } + + if (_fd <= 0) + throw std::runtime_error("unable to find/load ZeroTier tap driver OR use built-in utun driver in OSX; permission or system problem or too many open devices?"); + + Utils::snprintf(devpath,sizeof(devpath),"utun%d",utunNo); + _dev = devpath; + + // Configure address and bring it up + Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); + Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",mtustr,"metric",metstr,"up",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + if (exitcode) { + ::close(_fd); + throw std::runtime_error("ifconfig failure activating utun interface"); + } + } + + } else { + // Use our ZeroTier OSX tun/tap driver for zt# Ethernet tap device + + if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) { + ::close(_fd); + throw std::runtime_error("unable to set flags on file descriptor for TAP device"); + } + + // Configure MAC address and MTU, bring interface up + Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); + Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); + Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + if (exitcode) { + ::close(_fd); + throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); + } + } + + _setIpv6Stuff(_dev.c_str(),true,false); + } + + // Set close-on-exec so that devices cannot persist if we fork/exec for update + fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC); + + ::pipe(_shutdownSignalPipe); + + ++globalTapsRunning; + + devmap[nwids] = _dev; + OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmap.toString()); + + _thread = Thread::start(this); +} + +OSXEthernetTap::~OSXEthernetTap() +{ + Mutex::Lock _gl(globalTapCreateLock); + + ::write(_shutdownSignalPipe[1],(const void *)this,1); // writing a byte causes thread to exit + Thread::join(_thread); + + ::close(_fd); + ::close(_shutdownSignalPipe[0]); + ::close(_shutdownSignalPipe[1]); + + if (_utun) { + delete _arp; + } else { + if (--globalTapsRunning <= 0) { + globalTapsRunning = 0; // sanity check -- should not be possible + + char tmp[16384]; + sprintf(tmp,"%s/%s",_homePath.c_str(),"tap.kext"); + long kextpid = (long)vfork(); + if (kextpid == 0) { + OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); + ::execl("/sbin/kextunload","/sbin/kextunload",tmp,(const char *)0); + ::_exit(-1); + } else if (kextpid > 0) { + int exitcode = -1; + ::waitpid(kextpid,&exitcode,0); + } + } + } +} + +void OSXEthernetTap::setEnabled(bool en) +{ + _enabled = en; + // TODO: interface status change +} + +bool OSXEthernetTap::enabled() const +{ + return _enabled; +} + +static bool ___removeIp(const std::string &_dev,const InetAddress &ip) +{ + long cpid = (long)vfork(); + if (cpid == 0) { + execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet",ip.toIpString().c_str(),"-alias",(const char *)0); + _exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + waitpid(cpid,&exitcode,0); + return (exitcode == 0); + } + return false; // never reached, make compiler shut up about return value +} + +bool OSXEthernetTap::addIp(const InetAddress &ip) +{ + if (!ip) + return false; + + std::vector allIps(ips()); + if (std::binary_search(allIps.begin(),allIps.end(),ip)) + return true; + + // Remove and reconfigure if address is the same but netmask is different + for(std::vector::iterator i(allIps.begin());i!=allIps.end();++i) { + if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) { + if (___removeIp(_dev,*i)) + break; + } + } + + if (_utun) { + long cpid = (long)vfork(); + if (cpid == 0) { + if (ip.ss_family == AF_INET6) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet6",ip.toString().c_str(),"alias",(const char *)0); + } else { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.toString().c_str(),ip.toIpString().c_str(),"alias",(const char *)0); + } + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + + if (exitcode == 0) { + if (ip.ss_family == AF_INET) { + // Add route to network over tun for IPv4 -- otherwise it behaves + // as a simple point to point tunnel instead of a true route. + cpid = (long)vfork(); + if (cpid == 0) { + ::close(STDERR_FILENO); + ::close(STDOUT_FILENO); + ::execl("/sbin/route","/sbin/route","add",ip.network().toString().c_str(),ip.toIpString().c_str(),(const char *)0); + ::exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + return (exitcode == 0); + } + } else return true; + } + } + } else { + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + return (exitcode == 0); + } + } + + return false; +} + +bool OSXEthernetTap::removeIp(const InetAddress &ip) +{ + if (!ip) + return true; + std::vector allIps(ips()); + if (!std::binary_search(allIps.begin(),allIps.end(),ip)) { + if (___removeIp(_dev,ip)) + return true; + } + return false; +} + +std::vector OSXEthernetTap::ips() const +{ + struct ifaddrs *ifa = (struct ifaddrs *)0; + if (getifaddrs(&ifa)) + return std::vector(); + + std::vector r; + + struct ifaddrs *p = ifa; + while (p) { + if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) { + switch(p->ifa_addr->sa_family) { + case AF_INET: { + struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr; + struct sockaddr_in *nm = (struct sockaddr_in *)p->ifa_netmask; + r.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr))); + } break; + case AF_INET6: { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr; + struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask; + uint32_t b[4]; + memcpy(b,nm->sin6_addr.s6_addr,sizeof(b)); + r.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3]))); + } break; + } + } + p = p->ifa_next; + } + + if (ifa) + freeifaddrs(ifa); + + std::sort(r.begin(),r.end()); + std::unique(r.begin(),r.end()); + + return r; +} + +void OSXEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) +{ + char putBuf[4096]; + if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) { + to.copyTo(putBuf,6); + from.copyTo(putBuf + 6,6); + *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType); + memcpy(putBuf + 14,data,len); + len += 14; + ::write(_fd,putBuf,len); + } +} + +std::string OSXEthernetTap::deviceName() const +{ + return _dev; +} + +void OSXEthernetTap::setFriendlyName(const char *friendlyName) +{ +} + +void OSXEthernetTap::scanMulticastGroups(std::vector &added,std::vector &removed) +{ + std::vector newGroups; + + struct _intl_ifmaddrs *ifmap = (struct _intl_ifmaddrs *)0; + if (!_intl_getifmaddrs(&ifmap)) { + struct _intl_ifmaddrs *p = ifmap; + while (p) { + if (p->ifma_addr->sa_family == AF_LINK) { + struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name; + struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr; + if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen))) + newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0)); + } + p = p->ifma_next; + } + _intl_freeifmaddrs(ifmap); + } + + std::vector allIps(ips()); + for(std::vector::iterator ip(allIps.begin());ip!=allIps.end();++ip) + newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); + + std::sort(newGroups.begin(),newGroups.end()); + std::unique(newGroups.begin(),newGroups.end()); + + for(std::vector::iterator m(newGroups.begin());m!=newGroups.end();++m) { + if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m)) + added.push_back(*m); + } + for(std::vector::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) { + if (!std::binary_search(newGroups.begin(),newGroups.end(),*m)) + removed.push_back(*m); + } + + _multicastGroups.swap(newGroups); +} + +void OSXEthernetTap::threadMain() + throw() +{ + fd_set readfds,nullfds; + MAC to,from; + int n,nfds,r; + char getBuf[8194]; + + Thread::sleep(500); + + FD_ZERO(&readfds); + FD_ZERO(&nullfds); + nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1; + + r = 0; + for(;;) { + FD_SET(_shutdownSignalPipe[0],&readfds); + FD_SET(_fd,&readfds); + select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0); + + if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread + break; + + if (FD_ISSET(_fd,&readfds)) { + n = (int)::read(_fd,getBuf + r,sizeof(getBuf) - r); + if (n < 0) { + if ((errno != EINTR)&&(errno != ETIMEDOUT)) + break; + } else { + // Some tap drivers like to send the ethernet frame and the + // payload in two chunks, so handle that by accumulating + // data until we have at least a frame. + r += n; + if (r > 14) { + if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms + r = _mtu + 14; + + if (_enabled) { + to.setTo(getBuf,6); + from.setTo(getBuf + 6,6); + unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); + // TODO: VLAN support + _handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); + } + + r = 0; + } + } + } + } +} + +} // namespace ZeroTier diff --git a/attic/OSXEthernetTap.hpp.pcap-with-bridge-test b/attic/OSXEthernetTap.hpp.pcap-with-bridge-test new file mode 100644 index 000000000..33f1948c1 --- /dev/null +++ b/attic/OSXEthernetTap.hpp.pcap-with-bridge-test @@ -0,0 +1,96 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef ZT_OSXETHERNETTAP_HPP +#define ZT_OSXETHERNETTAP_HPP + +#include +#include + +#include +#include +#include + +#include "../node/Constants.hpp" +#include "../node/MAC.hpp" +#include "../node/InetAddress.hpp" +#include "../node/MulticastGroup.hpp" + +#include "Thread.hpp" + +namespace ZeroTier { + +/** + * OSX Ethernet tap using ZeroTier kernel extension zt# devices + */ +class OSXEthernetTap +{ +public: + OSXEthernetTap( + const char *homePath, + const MAC &mac, + unsigned int mtu, + unsigned int metric, + uint64_t nwid, + const char *friendlyName, + void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void *arg); + + ~OSXEthernetTap(); + + inline void setEnabled(bool en) { _enabled = en; } + inline bool enabled() const { return _enabled; } + bool addIp(const InetAddress &ip); + bool removeIp(const InetAddress &ip); + std::vector ips() const; + void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + std::string deviceName() const; + void setFriendlyName(const char *friendlyName); + void scanMulticastGroups(std::vector &added,std::vector &removed); + + void threadMain() + throw(); + + // Private members of OSXEthernetTap have public visibility to be accessable + // from an internal bounce function; don't modify directly. + void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + void *_arg; + void *_pcap; // pcap_t * + uint64_t _nwid; + MAC _mac; + Thread _thread; + std::string _homePath; + std::string _dev; + std::vector _multicastGroups; + unsigned int _mtu; + unsigned int _metric; + volatile bool _enabled; +}; + +} // namespace ZeroTier + +#endif diff --git a/attic/OSXEthernetTap.hpp.utun-work-in-progress b/attic/OSXEthernetTap.hpp.utun-work-in-progress new file mode 100644 index 000000000..8ece87b31 --- /dev/null +++ b/attic/OSXEthernetTap.hpp.utun-work-in-progress @@ -0,0 +1,101 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef ZT_OSXETHERNETTAP_HPP +#define ZT_OSXETHERNETTAP_HPP + +#include +#include + +#include +#include +#include + +#include "../node/Constants.hpp" +#include "../node/MAC.hpp" +#include "../node/InetAddress.hpp" +#include "../node/MulticastGroup.hpp" + +#include "Thread.hpp" + +namespace ZeroTier { + +class Arp; + +/** + * OSX Ethernet tap supporting either ZeroTier tun/tap kext or OSX-native utun + */ +class OSXEthernetTap +{ +public: + OSXEthernetTap( + const char *homePath, + const MAC &mac, + unsigned int mtu, + unsigned int metric, + uint64_t nwid, + const char *friendlyName, + void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void *arg); + + ~OSXEthernetTap(); + + void setEnabled(bool en); + bool enabled() const; + bool addIp(const InetAddress &ip); + bool removeIp(const InetAddress &ip); + std::vector ips() const; + void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + std::string deviceName() const; + void setFriendlyName(const char *friendlyName); + void scanMulticastGroups(std::vector &added,std::vector &removed); + + inline bool isNativeUtun() const { return _utun; } + + void threadMain() + throw(); + +private: + void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + void *_arg; + Arp *_arp; // created and used if utun is enabled + uint64_t _nwid; + Thread _thread; + std::string _homePath; + std::string _dev; + std::vector _multicastGroups; + unsigned int _mtu; + unsigned int _metric; + int _fd; + int _shutdownSignalPipe[2]; + bool _utun; + volatile bool _enabled; +}; + +} // namespace ZeroTier + +#endif diff --git a/attic/README.md b/attic/README.md new file mode 100644 index 000000000..768bccd4a --- /dev/null +++ b/attic/README.md @@ -0,0 +1,4 @@ +Retired Code and Miscellaneous Junk +====== + +This directory is for old code that isn't used but we don't want to lose track of, and for anything else random like debug scripts. diff --git a/attic/big-http-test/2015-11-10_01_50000.out.xz b/attic/big-http-test/2015-11-10_01_50000.out.xz new file mode 100644 index 000000000..d3e2a6666 Binary files /dev/null and b/attic/big-http-test/2015-11-10_01_50000.out.xz differ diff --git a/attic/big-http-test/2015-11-10_02_50000.out.xz b/attic/big-http-test/2015-11-10_02_50000.out.xz new file mode 100644 index 000000000..0154da791 Binary files /dev/null and b/attic/big-http-test/2015-11-10_02_50000.out.xz differ diff --git a/attic/big-http-test/2015-11-10_03_12500_ec2-east-only.out.xz b/attic/big-http-test/2015-11-10_03_12500_ec2-east-only.out.xz new file mode 100644 index 000000000..3ae3555e6 Binary files /dev/null and b/attic/big-http-test/2015-11-10_03_12500_ec2-east-only.out.xz differ diff --git a/attic/big-http-test/Dockerfile b/attic/big-http-test/Dockerfile new file mode 100644 index 000000000..e19b3feef --- /dev/null +++ b/attic/big-http-test/Dockerfile @@ -0,0 +1,24 @@ +FROM centos:latest + +MAINTAINER https://www.zerotier.com/ + +EXPOSE 9993/udp + +ADD nodesource-el.repo /etc/yum.repos.d/nodesource-el.repo +RUN yum -y update && yum install -y nodejs && yum clean all + +RUN mkdir -p /var/lib/zerotier-one +RUN mkdir -p /var/lib/zerotier-one/networks.d +RUN touch /var/lib/zerotier-one/networks.d/ffffffffffffffff.conf + +ADD package.json / +RUN npm install + +ADD zerotier-one / +RUN chmod a+x /zerotier-one + +ADD agent.js / +ADD docker-main.sh / +RUN chmod a+x /docker-main.sh + +CMD ["./docker-main.sh"] diff --git a/attic/big-http-test/README.md b/attic/big-http-test/README.md new file mode 100644 index 000000000..23a956054 --- /dev/null +++ b/attic/big-http-test/README.md @@ -0,0 +1,12 @@ +HTTP one-to-all test +====== + +*This is really internal use code. You're free to test it out but expect to do some editing/tweaking to make it work. We used this to run some massive scale tests of our new geo-cluster-based root server infrastructure prior to taking it live.* + +Before using this code you will want to edit agent.js to change SERVER_HOST to the IP address of where you will run server.js. This should typically be an open Internet IP, since this makes reporting not dependent upon the thing being tested. Also note that this thing does no security of any kind. It's designed for one-off tests run over a short period of time, not to be anything that runs permanently. You will also want to edit the Dockerfile if you want to build containers and change the network ID to the network you want to run tests over. + +This code can be deployed across a large number of VMs or containers to test and benchmark HTTP traffic within a virtual network at scale. The agent acts as a server and can query other agents, while the server collects agent data and tells agents about each other. It's designed to use RFC4193-based ZeroTier IPv6 addresses within the cluster, which allows the easy provisioning of a large cluster without IP conflicts. + +The Dockerfile builds an image that launches the agent. The image must be "docker run" with "--device=/dev/net/tun --privileged" to permit it to open a tun/tap device within the container. (Unfortunately CAP_NET_ADMIN may not work due to a bug in Docker and/or Linux.) You can run a bunch with a command like: + + for ((n=0;n<10;n++)); do docker run --device=/dev/net/tun --privileged -d zerotier/http-test; done diff --git a/attic/big-http-test/agent.js b/attic/big-http-test/agent.js new file mode 100644 index 000000000..9ab2e019b --- /dev/null +++ b/attic/big-http-test/agent.js @@ -0,0 +1,196 @@ +// ZeroTier distributed HTTP test agent + +// --------------------------------------------------------------------------- +// Customizable parameters: + +// Time between startup and first test attempt +var TEST_STARTUP_LAG = 10000; + +// Maximum interval between test attempts (actual timing is random % this) +var TEST_INTERVAL_MAX = (60000 * 10); + +// Test timeout in ms +var TEST_TIMEOUT = 30000; + +// Where should I get other agents' IDs and POST results? +var SERVER_HOST = '52.26.196.147'; +var SERVER_PORT = 18080; + +// Which port do agents use to serve up test data to each other? +var AGENT_PORT = 18888; + +// Payload size in bytes +var PAYLOAD_SIZE = 5000; + +// --------------------------------------------------------------------------- + +var ipaddr = require('ipaddr.js'); +var os = require('os'); +var http = require('http'); +var async = require('async'); + +var express = require('express'); +var app = express(); + +// Find our ZeroTier-assigned RFC4193 IPv6 address +var thisAgentId = null; +var interfaces = os.networkInterfaces(); +if (!interfaces) { + console.error('FATAL: os.networkInterfaces() failed.'); + process.exit(1); +} +for(var ifname in interfaces) { + var ifaddrs = interfaces[ifname]; + if (Array.isArray(ifaddrs)) { + for(var i=0;i 1) { + + var target = agents[Math.floor(Math.random() * agents.length)]; + while (target === thisAgentId) + target = agents[Math.floor(Math.random() * agents.length)]; + + var testRequest = null; + var timeoutId = null; + timeoutId = setTimeout(function() { + if (testRequest !== null) + testRequest.abort(); + timeoutId = null; + },TEST_TIMEOUT); + var startTime = Date.now(); + + testRequest = http.get({ + host: agentIdToIp(target), + port: AGENT_PORT, + path: '/' + },function(res) { + var bytes = 0; + res.on('data',function(chunk) { bytes += chunk.length; }); + res.on('end',function() { + lastTestResult = { + source: thisAgentId, + target: target, + time: (Date.now() - startTime), + bytes: bytes, + timedOut: (timeoutId === null), + error: null + }; + if (timeoutId !== null) + clearTimeout(timeoutId); + return setTimeout(doTest,Math.round(Math.random() * TEST_INTERVAL_MAX) + 1); + }); + }).on('error',function(e) { + lastTestResult = { + source: thisAgentId, + target: target, + time: (Date.now() - startTime), + bytes: 0, + timedOut: (timeoutId === null), + error: e.toString() + }; + if (timeoutId !== null) + clearTimeout(timeoutId); + return setTimeout(doTest,Math.round(Math.random() * TEST_INTERVAL_MAX) + 1); + }); + + } else { + return setTimeout(doTest,1000); + } + + }); + }).on('error',function(e) { + console.log('POST failed: '+e.toString()); + return setTimeout(doTest,1000); + }); + if (lastTestResult !== null) { + submit.write(JSON.stringify(lastTestResult)); + lastTestResult = null; + } + submit.end(); +}; + +// Agents just serve up a test payload +app.get('/',function(req,res) { return res.status(200).send(payload); }); + +var expressServer = app.listen(AGENT_PORT,function () { + // Start timeout-based loop + setTimeout(doTest(),TEST_STARTUP_LAG); +}); diff --git a/attic/big-http-test/big-test-kill.sh b/attic/big-http-test/big-test-kill.sh new file mode 100755 index 000000000..fa7f3cc46 --- /dev/null +++ b/attic/big-http-test/big-test-kill.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Kills all running Docker containers on all big-test-hosts + +export PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/sbin + +pssh -h big-test-hosts -x '-t -t' -i -OUserKnownHostsFile=/dev/null -OStrictHostKeyChecking=no -t 0 -p 256 "sudo docker ps -aq | xargs -r sudo docker rm -f" + +exit 0 diff --git a/attic/big-http-test/big-test-start.sh b/attic/big-http-test/big-test-start.sh new file mode 100755 index 000000000..2411eeda4 --- /dev/null +++ b/attic/big-http-test/big-test-start.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# More than 500 container seems to result in a lot of sporadic failures, probably due to Linux kernel scaling issues with virtual network ports +# 250 with a 16GB RAM VM like Amazon m4.xlarge seems good +NUM_CONTAINERS=250 +CONTAINER_IMAGE=zerotier/http-test +SCALE_UP_DELAY=10 + +export PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/sbin + +pssh -h big-test-hosts -x '-t -t' -i -OUserKnownHostsFile=/dev/null -OStrictHostKeyChecking=no -t 0 -p 256 "sudo sysctl -w net.netfilter.nf_conntrack_max=262144 ; for ((n=0;n<$NUM_CONTAINERS;n++)); do sudo docker run --device=/dev/net/tun --privileged -d $CONTAINER_IMAGE; sleep $SCALE_UP_DELAY; done" + +exit 0 diff --git a/attic/big-http-test/crunch-results.js b/attic/big-http-test/crunch-results.js new file mode 100644 index 000000000..50e5c49a4 --- /dev/null +++ b/attic/big-http-test/crunch-results.js @@ -0,0 +1,65 @@ +// +// Pipe the output of server.js into this to convert raw test results into bracketed statistics +// suitable for graphing. +// + +// Time duration per statistical bracket +var BRACKET_SIZE = 10000; + +// Number of bytes expected from each test +var EXPECTED_BYTES = 5000; + +var readline = require('readline'); +var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false +}); + +var count = 0.0; +var overallCount = 0.0; +var totalFailures = 0.0; +var totalOverallFailures = 0.0; +var totalMs = 0; +var totalData = 0; +var devices = {}; +var lastBracketTs = 0; + +rl.on('line',function(line) { + line = line.trim(); + var ls = line.split(','); + if (ls.length == 7) { + var ts = parseInt(ls[0]); + var fromId = ls[1]; + var toId = ls[2]; + var ms = parseFloat(ls[3]); + var bytes = parseInt(ls[4]); + var timedOut = (ls[5] == 'true') ? true : false; + var errMsg = ls[6]; + + count += 1.0; + overallCount += 1.0; + if ((bytes !== EXPECTED_BYTES)||(timedOut)) { + totalFailures += 1.0; + totalOverallFailures += 1.0; + } + totalMs += ms; + totalData += bytes; + + devices[fromId] = true; + devices[toId] = true; + + if (lastBracketTs === 0) + lastBracketTs = ts; + + if (((ts - lastBracketTs) >= BRACKET_SIZE)&&(count > 0.0)) { + console.log(count.toString()+','+overallCount.toString()+','+(totalMs / count)+','+(totalFailures / count)+','+(totalOverallFailures / overallCount)+','+totalData+','+Object.keys(devices).length); + + count = 0.0; + totalFailures = 0.0; + totalMs = 0; + totalData = 0; + lastBracketTs = ts; + } + } // else ignore junk +}); diff --git a/attic/big-http-test/docker-main.sh b/attic/big-http-test/docker-main.sh new file mode 100755 index 000000000..29cdced9c --- /dev/null +++ b/attic/big-http-test/docker-main.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin + +/zerotier-one -d >>zerotier-one.out 2>&1 + +# Wait for ZeroTier to start and join the network +while [ ! -d "/proc/sys/net/ipv6/conf/zt0" ]; do + sleep 0.25 +done + +# Wait just a bit longer for stuff to settle +sleep 5 + +exec node --harmony /agent.js >>agent.out 2>&1 +#exec node --harmony /agent.js diff --git a/attic/big-http-test/nodesource-el.repo b/attic/big-http-test/nodesource-el.repo new file mode 100644 index 000000000..b785d3d07 --- /dev/null +++ b/attic/big-http-test/nodesource-el.repo @@ -0,0 +1,6 @@ +[nodesource] +name=Node.js Packages for Enterprise Linux 7 - $basearch +baseurl=https://rpm.nodesource.com/pub_4.x/el/7/$basearch +failovermethod=priority +enabled=1 +gpgcheck=0 diff --git a/attic/big-http-test/package.json b/attic/big-http-test/package.json new file mode 100644 index 000000000..173a6f99b --- /dev/null +++ b/attic/big-http-test/package.json @@ -0,0 +1,16 @@ +{ + "name": "zerotier-test-http", + "version": "1.0.0", + "description": "ZeroTier in-network HTTP test", + "main": "agent.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "ZeroTier, Inc.", + "license": "GPL-3.0", + "dependencies": { + "async": "^1.5.0", + "express": "^4.13.3", + "ipaddr.js": "^1.0.3" + } +} diff --git a/attic/big-http-test/server.js b/attic/big-http-test/server.js new file mode 100644 index 000000000..629784da3 --- /dev/null +++ b/attic/big-http-test/server.js @@ -0,0 +1,53 @@ +// ZeroTier distributed HTTP test coordinator and result-reporting server + +// --------------------------------------------------------------------------- +// Customizable parameters: + +var SERVER_PORT = 18080; + +// --------------------------------------------------------------------------- + +var fs = require('fs'); + +var express = require('express'); +var app = express(); + +app.use(function(req,res,next) { + req.rawBody = ''; + req.on('data', function(chunk) { req.rawBody += chunk.toString(); }); + req.on('end', function() { return next(); }); +}); + +var knownAgents = {}; + +app.post('/:agentId',function(req,res) { + var agentId = req.params.agentId; + if ((!agentId)||(agentId.length !== 32)) + return res.status(404).send(''); + + if (req.rawBody) { + var receiveTime = Date.now(); + var resultData = null; + try { + resultData = JSON.parse(req.rawBody); + console.log(Date.now().toString()+','+resultData.source+','+resultData.target+','+resultData.time+','+resultData.bytes+','+resultData.timedOut+',"'+((resultData.error) ? resultData.error : '')+'"'); + } catch (e) {} + } + + knownAgents[agentId] = true; + var thisUpdate = []; + var agents = Object.keys(knownAgents); + if (agents.length < 100) + thisUpdate = agents; + else { + for(var xx=0;xx<100;++xx) + thisUpdate.push(agents[Math.floor(Math.random() * agents.length)]); + } + + return res.status(200).send(JSON.stringify(thisUpdate)); +}); + +var expressServer = app.listen(SERVER_PORT,function () { + console.log('LISTENING ON '+SERVER_PORT); + console.log(''); +}); diff --git a/attic/historic/anode/config.mk.Darwin b/attic/historic/anode/config.mk.Darwin deleted file mode 100644 index a5cbeeecf..000000000 --- a/attic/historic/anode/config.mk.Darwin +++ /dev/null @@ -1,17 +0,0 @@ -CC=gcc -CXX=g++ - -#ARCH_FLAGS=-arch x86_64 -arch i386 -arch ppc - -DEFS=-DHAS_DEV_URANDOM -CXXDEFS=-DBOOST_DISABLE_ASSERTS -DBOOST_NO_TYPEID -DNDEBUG - -CFLAGS=-mmacosx-version-min=10.4 -std=c99 -O6 -ftree-vectorize -Wall $(DEFS) $(ARCH_FLAGS) -CXXFLAGS=-mmacosx-version-min=10.4 -Drestrict=__restrict__ -O6 -ftree-vectorize -Wall $(DEFS) $(CXXDEFS) $(ARCH_FLAGS) - -LDFLAGS=-mmacosx-version-min=10.4 $(ARCH_FLAGS) -DLLFLAGS=$(ARCH_FLAGS) -shared -DLLEXT=dylib - -LIBANODE_LIBS=-lcrypto -lpthread -lresolv -LIBSPARK_LIBS=-lz diff --git a/attic/historic/anode/config.mk.Linux b/attic/historic/anode/config.mk.Linux deleted file mode 100644 index 072fa4ceb..000000000 --- a/attic/historic/anode/config.mk.Linux +++ /dev/null @@ -1,17 +0,0 @@ -CC=gcc -CXX=g++ - -DEFS=-DHAS_DEV_URANDOM - -CFLAGS=-std=c99 -O6 -fPIC -Wall $(DEFS) -CXXFLAGS=-Drestrict=__restrict__ -O6 -Wall $(DEFS) -I.. - -#CFLAGS=-g -Wall $(DEFS) -#CXXFLAGS=-g -Wall $(DEFS) - -LDFLAGS= -DLLFLAGS=-shared -DLLEXT=so - -LIBANODE_LIBS=-lcrypto -lresolv -pthread -LIBSPARK_LIBS=-lz diff --git a/attic/historic/anode/docs/anode_protocol.txt b/attic/historic/anode/docs/anode_protocol.txt deleted file mode 100644 index 0adb92367..000000000 --- a/attic/historic/anode/docs/anode_protocol.txt +++ /dev/null @@ -1,764 +0,0 @@ -***************************************************************************** -Anode Protocol Specification Draft -Version 0.8 - -(c)2009-2010 Adam Ierymenko -***************************************************************************** - -Table of Contents - -***************************************************************************** - -1. Introduction - -Anode provides three components that work together to provide a global, -secure, and mobile addressing system for computer networks: - -1) An addressing system based on public key cryptography enabling network - devices or applications to assign themselves secure, unique, and globally - reachable network addresses in a flat address space. - -2) A system enabling network participants holding global addresses to locate - one another on local or global networks with "zero configuration." - -3) A communications protocol for communication between addressed network - participants that requires no special operating system support and no - changes to existing network infrastructure. - -Using Anode, both fixed and mobile applications and devices can communicate -directly as if they were all connected to the same VPN. Anode restores the -original vision of the Internet as a "flat" network where anything can talk -to anything, and adds the added benefits of address mobility and strong -protection against address spoofing and other protocol level attacks. - -1.1. Design Philosophy - -Anode's design philosophy is the classical "KISS" principle: "Keep It Simple -Stupid." Anode's design principles are: - -#1: Do not try to solve too many problems at once, and stay in scope. - -Anode does not attempt to solve too many problems at once. It attempts to -solve the problems of mobile addressing, address portability, and "flat" -addressing in the presence of NAT or other barriers. - -It does not attempt to duplicate the full functionality of SSL, X.509, SSH, -XMPP, an enterprise service bus, a pub/sub architecture, BitTorrent, etc. All -of those protocols and services can be used over Anode if their functionality -is desired. - -#2: Avoid state management. - -State multiplies the complexity and failure modes of network protocols. State -also tends to get in the way of the achievement of new features implicitly -(see principle #4). Avoid state whenever possible. - -#3: Avoid algorithm and dependency bloat. - -Anode uses only elliptic curve Diffie-Hellman (EC-DH) and AES-256. No other -cryptographic algorithms or hash functions are presently necessary. This -yields implementations compact enough for embedded devices. - -Anode also requires few or no dependencies, depending on whether the two -needed cryptographic algorithms are obtained through a library or included. -No other protocols or libraries are required in an implementation. - -#4: Achieve features implicitly. - -Use a simple stateless design that allows features to be achieved implicitly -rather than specified explicitly. For example, Anode can do multi-homing and -could be used to build a mesh network, but neither of these features is -explicitly specified. - -***************************************************************************** - -2. Core Concepts and Algorithms - -This section describes addresses, zones, common algorithms, and other core -concepts. - -2.1. Zones - -A zone is a 32-bit integer encoded into every Anode address. Zones serve to -assist in the location of peers by address on global IP networks. They are -not presently significant for local communications, though they could be -used to partition addresses into groups or link them with configuration -options. - -Each zone has a corresponding zone file which can be fetched in a number of -ways (see below). A zone file is a flat text format dictionary of the format -"key=value" separated by carriage returns. Line feeds are ignored, and any -character may be escaped with a backslash (\) character. Blank lines are -ignored. - -The following entries must appear in a zone file: - -n= -d= -c= -r= -ttl= - -Additional fields may appear as well, including fields specific to special -applications or protocols supported within the zone. Some of these are -defined in this document. - -Zone file fetching mechanisms are described below. Multiple mechanisms are -specified to enable fallback in the event that one mechanism is not available. - -2.1.1. Zone File Retrieval - -Zone files are retrieved via HTTP, with the HTTP address being formed in one -of two ways. - -The preferred DNS method: - -To fetch a zone file via DNS, use the zone ID to generate a host name and URI -of the form: - - http://a--XXXXXXXX.net/z - -The XXXXXXXX field is the zone ID in hexadecimal. - -The fallback IP method: - -For fallback in the absence of DNS, the zone ID can be used directly as an -IPv4 or IPv4-mapped-to-IPv6 IP address. A URI is generated of the form: - - http://ip_address/z - -Support for this method requires that a zone ID be chosen to correspond to a -permanent IPv4 (preferably mappable to IPv6 space as well) IP address. - -2.1.2. Zone ID Reservation - -By convention, a zone ID is considered reserved when a domain of the form -"a--XXXXXXXX.net" (where XXXXXXXX is the ID in hex) is registered. - -It is recommended that this be done even for zone IDs not used for global -address location in order to globally reserve them. - -2.2. Addresses - -Anode addresses are binary strings containing a 32-bit zone ID, a public key, -and possibly other fields. Only one address type is presently defined: - -|---------------------------------------------------------------------------| -| Name | Type ID | Elliptic Curve Parameters | Total Length | -|---------------------------------------------------------------------------| -| ANODE-256-40 | 1 | NIST-P-256 | 40 | -|---------------------------------------------------------------------------| - -|---------------------------------------------------------------------------| -| Name | Binary Layout | -|---------------------------------------------------------------------------| -| ANODE-256-40 | | -|---------------------------------------------------------------------------| - -The public key is a "compressed" form elliptic curve public key as described -in RFC5480. - -The unused section of the address must be zero. These bytes are reserved for -future use. - -2.2.1. ASCII Format For Addresses - -Addresses are encoded in ASCII using base-32, which provides a quotable and -printable encoding that is of manageable length and is case-insensitive. For -example, an ANODE-256-40 address is 64 characters long in base-32 encoding. - -2.3. Relaying - -An Anode peer may optionally relay packets to any other reachable peer. -Relaying is accomplished by sending a packet to a peer with the recipient set -to the final recipient. The receiving peer will, if relaying is allowed and if -it knows of or can reach the recipient, forward the packet. - -No error is returned if relaying fails, so relay paths are treated as possible -paths for communication until a return is received in the same way as direct -paths. - -Relaying can be used by peers to send messages indirectly, locate one -another, and determine network location information to facilitate the -establishment of direct communications. - -Peers may refuse to relay or may limit the transmission rate at which packets -can be relayed. - -2.3.1. Zone Relays - -If a zone's addresses are globally reachable on global IP networks, it must -have one or more zone relays. These must have globally reachable public -static IP addresses. - -Zone relays are specified in the zone file in the following format: - - zr.
=[,]::: - -The address checksum is the sum of the bytes in the Anode address modulus -the number of "zr" entries, in hexadecimal. For example, if a zone had four -global relays its zone file could contain the lines: - - zr.0=1.2.3.4:4343:4344:klj4j3... - zr.1=2.3.4.5:4343:4344:00194j... - zr.2=3.4.5.6:4343:4344:1j42zz... - zr.3=4.5.6.7:4343:4344:z94j1q... - -The relay would be chosen by taking the sum of the bytes in the address -modulo 4. For example, if the bytes of an address sum to 5081 then relay -zr.1 would be used to communicate with that address. - -If more than one IP address is listed for a given relay, the peer must choose -at random from among the addresses of the desired type (IPv4 or IPv6). - -Each relay must have one Anode address for every address type supported within -the zone. (At present there is only one address type defined.) - -Peers should prefer UDP and fall back to TCP only if UDP is not available. - -To make itself available, a peer must make itself known to its designated zone -relay. This is accomplished by sending a PING message. - -2.4. Key Agreement and Derivation - -Key agreement is performed using elliptic curve Diffie-Hellman. This yields -a raw key whose size depends on the elliptic curve parameters in use. - -The following algorithm is used to derive a key of any length from a raw -key generated through key agreement: - -1) Zero the derived key buffer. -2) Determine the largest of the original raw key or the derived key. -3) Loop from 0 to the largest length determined in step 2, XOR each byte of - the derived key buffer with the corresponding byte of the original key - buffer with each index being modulus the length of the respective buffer. - -2.5. Message Authentication - -For message authentication, CMAC-AES (with AES-256) is used. This is also -known in some literature as OMAC1-AES. The key is derived from key agreement -between the key pair of the sending peer and the address of the recipient. - -2.6. AES-DIGEST - -To maintain cryptographic algorithm frugality, a cryptographic hash function -is constructed from the AES-256 cipher. This hash function uses the common -Davis-Meyer construction with Merkle-Damgård length padding. - -It is described by the following pseudocode: - - byte previous_digest[16] - byte digest[16] = { 0,0,... } - byte block[32] = { 0,0,... } - integer block_counter = 0 - - ; digest message - for each byte b of message - block[block_counter] = b - block_counter = block_counter + 1 - if block_counter == 32 then - block_counter = 0 - save digest[] in previous_digest[] - encrypt digest[] with aes-256 using block[] as 256-bit aes-256 key - xor digest[] with previous_digest[] - end if - next - - ; append end marker, do final block - block[block_counter] = 0x80 - block_counter = block_counter + 1 - zero rest of block[] from block_counter to 15 - save digest[] in previous_digest[] - encrypt digest[] with aes-256 using block[] as 256-bit aes-256 key - xor digest[] with previous_digest[] - - ; Merkle-Damgård length padding - zero first 8 bytes of block[] - fill last 8 bytes of block[] w/64-bit length in big-endian order - save digest[] in previous_digest[] - encrypt digest[] with aes-256 using block[] as 256-bit aes-128 key - xor digest[] with previous_digest[] - - ; digest[] now contains 128-bit message digest - -2.7. Short Address Identifiers (Address IDs) - -A short 8-byte version of the Anode address is used in the protocol to reduce -transmission overhead when both sides are already aware of the other's full -address. - -The short address identifier is formed by computing the AES-DIGEST of the -full address and then XORing the first 8 bytes of the digest with the last -8 bytes to yield an 8-byte shortened digest. - -2.8. DNS Resolution of Anode Addresses - -Anode addresses can be saved in DNS TXT records in the following format: - -anode:
- -This permits Anode addresses to be resolved from normal DNS host name. - -2.9. Packet Transmission Mechanisms - -2.9.1. UDP Transmission - -The recommended method of sending Anode packets is UDP. Each packet is simply -sent as a UDP packet. - -2.9.2. TCP Transmission - -To send packets over TCP, each packet is prefixed by its size as a 16-bit -integer. - -2.9.3. HTTP Transmission - -Anode packets may be submitted in HTTP POST transactions for transport over -networks where HTTP is the only available protocol. - -Anode packets are simply prefixed with a 16-byte packet size and concatenated -together just as they are in a TCP stream. One or more packets may be sent -with each HTTP POST transaction for improved performance. - -Since this method is intended for use in "hostile" or highly restricted -circumstances, no additional details such as special headers or MIME types -are specified to allow maximum flexibility. Peers should ignore anything -other than the payload. - -2.10. Endpoints - -An endpoint indicates a place where Anode packets may be sent. The following -endpoint types are specified: - -|---------------------------------------------------------------------------| -| Endpoint Type | Description | Address Format | -|---------------------------------------------------------------------------| -| 0x00 | Unspecified | (none) | -| 0x01 | Ethernet | | -| 0x02 | UDP/IPv4 | | -| 0x03 | TCP/IPv4 | | -| 0x04 | UDP/IPv6 | | -| 0x05 | TCP/IPv6 | | -| 0x06 | HTTP | | -|---------------------------------------------------------------------------| - -Endpoints are encoded by beginning with a single byte indicating the endpoint -type followed by the address information required for the given type. - -Note that IP ports bear no relationship to Anode protocol ports. - -2.11. Notes - -All integers in the protocol are transmitted in network (big endian) byte -order. - -***************************************************************************** - -3. Common Packet Format - -A common header is used for all Anode packets: - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Hop Count | 1 | 8-bit hop count (not included in MAC) | -| Flags | 1 | 8-bit flags | -| MAC | 8 | 8 byte shortened CMAC-AES of packet | -| Sender Address | ? | Full address or short ID of sender | -| Recipient Address | ? | Full address or short ID of recipient | -| Peer IDs | 1 | Two 4-bit peer IDs: sender, recipient | -| Message Type | 1 | 8-bit message type | -| Message | ? | Message payload | -|---------------------------------------------------------------------------| - -3.1. Hop Count - -The hop count begins at zero and must be incremented by each peer that relays -the packet to another peer. The hop count must not wrap to zero at 255. - -Because the hop count is modified in transit, it is not included in MAC -calculation or authentication. - -The hop count is used to prioritize endpoints that are direct over endpoints -that involve relaying, or to prioritize closer routes over more distant -ones. - -3.2. Flags and Flag Behavior - -|---------------------------------------------------------------------------| -| Flag | Description | -|---------------------------------------------------------------------------| -| 0x01 | Sender address fully specified | -| 0x02 | Recipient address fully specified | -| 0x04 | Authentication error response | -|---------------------------------------------------------------------------| - -If flag 0x01 is set, then the sender address will be the full address rather -than a short address identifier. The length of the address can be determined -from the first byte of the address, which always specifies the address type. -Flag 0x02 has the same meaning for the recipient address. - -A peer must send fully specified sender addresses until it receives a response -from the recipient. At this point the sender may assume that the recipient -knows its address and use short a short sender address instead. This -assumption should time out, with a recommended timeout of 60 seconds. - -There is presently no need to send fully specified recipient addresses, but -the flag is present in case it is needed and must be honored. - -Flag 0x04 indicates that this is an error response containing a failed -authentication error. Since authentication failed, this packet may not have -a valid MAC. Packets with this flag must never have any effect other than -to inform of an error. This error, since it is unauthenticated, must never -have any side effects such as terminating a connection. - -3.3. MAC - -The MAC is calculated as follows: - -1) Temporarily set the 64-bit/8-byte MAC field in the packet to the packet's - size as a 64-bit big-endian integer. -2) Calculate the MAC for the entire packet (excluding the first byte) using - the key agreed upon between the sender and the recipient, resulting in a - 16 byte full CMAC-AES MAC. -3) Derive the 8 byte packet MAC by XORing the first 8 bytes of the full 16 - byte CMAC-AES MAC with the last 8 bytes. Place this into the packet's MAC - field. - -3.4. Peer IDs - -Peer IDs provide a method for up to 15 different peers to share an address, -each with a unique ID allowing packets to be routed to them individually. - -A peer ID of zero indicates "any" or "unspecified." Real peers must have a -nonzero peer ID. In the normal single peer per address case, any peer ID may -be used. If multiple peers are to share an address, some implementation- -dependent method must be used to ensure that each peer has a unique peer ID. - -Relaying peers must follow these rules based on the recipient peer ID when -relaying messages: - - - IF the peer ID is zero or if the peer ID is not known, the message must - be forwarded to a random endpoint for the given recipient address. - - IF the peer ID is nonzero and matches one or more known endpoints for the - given recipient address and peer ID, the message must only be sent to - a matching endpoint. - -A receiving peer should process any message that it receives regardless of -whether its recipient peer ID is correct. The peer ID is primarily for relays. - -Peers should typically send messages with a nonzero recipient peer ID when -responding to or involved in a conversation with a specific peer (e.g. a -streaming connection), and send zero recipient peer IDs otherwise. - -3.5. Short Address Conflict Disambiguation - -In the unlikely event of two Anode addresses with the same short identifier, -the recipient should use MAC validation to disambiguate. The peer ID must not -be relied upon for this purpose. - -***************************************************************************** - -4. Basic Signaling and Transport Protocol - -4.1. Message Types - -|---------------------------------------------------------------------------| -| Type | ID | Description | -|---------------------------------------------------------------------------| -| ERROR | 0x00 | Error response | -| PING | 0x01 | Echo request | -| PONG | 0x02 | Echo response | -| EPC_REQ | 0x03 | Endpoint check request | -| EPC | 0x04 | Endpoint check response | -| EPI | 0x05 | Endpoint information | -| NAT_T | 0x06 | NAT traversal message | -| NETID_REQ | 0x07 | Request network address identification and/or test | -| NETID | 0x08 | Response to network address identification request | -| DGRAM | 0x09 | Simple UDP-like datagram | -|---------------------------------------------------------------------------| - -4.2. Message Details - -4.2.1. ERROR - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Error Code | 2 | 16-bit error code | -| Error Arguments | ? | Error arguments, depending on error type | -|---------------------------------------------------------------------------| - -Error arguments are empty unless otherwise stated below. - -Error codes: - -|---------------------------------------------------------------------------| -| Error Code | Description | -|---------------------------------------------------------------------------| -| 0x01 | Message not valid | -| 0x02 | Message authentication or decryption failed | -| 0x03 | Relaying and related features not authorized | -| 0x04 | Relay recipient not reachable | -|---------------------------------------------------------------------------| - -Generation of errors is optional. A peer may choose to ignore invalid -messages or to throttle the sending of errors. - -4.2.2. PING - -(Payload unspecified.) - -Request echo of payload as PONG message. - -4.2.3. PONG - -(Payload unspecified.) - -Echoed payload of received PING message. - -4.2.4. EPC_REQ - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Request ID | 4 | 32-bit request ID | -|---------------------------------------------------------------------------| - -Request echo of request ID in EPC message, used to check and learn endpoints. - -To learn a network endpoint for a peer, CHECK_REQ is sent. If CHECK is -returned with a valid request ID, the endpoint is considered valid. - -4.2.5. EPC - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Request ID | 4 | 32-bit request ID echoed back | -|---------------------------------------------------------------------------| - -Response to EPC_REQ containing request ID. - -4.2.6. EPI - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Flags | 1 | 8-bit flags | -| Endpoint | ? | Endpoint type and address | -| NAT-T mode | 1 | 8-bit NAT traversal mode | -| NAT-T options | ? | Options related to specified NAT-T mode | -|---------------------------------------------------------------------------| - -EPI stands for EndPoint Identification, and is sent to notify another peer of -a network endpoint where the sending peer is reachable. - -If the receiving peer is interested in communicating with the sending peer, -the receiving peer must send EPC_REQ to the sending peer at the specified -endpoint to check the validity of that endpoint. The endpoint is learned if a -valid EPC is returned. - -If the endpoint in EPI is unspecified, the actual source of the EPI message -is the endpoint. This allows EPI messages to be broadcast on a local LAN -segment to advertise the presence of an address on a local network. EPI -broadcasts on local IP networks must be made to UDP port 8737. - -Usually EPI is sent via relays (usually zone relays) to inform a peer of an -endpoint for direct communication. - -There are presently no flags, so flags must be zero. - -4.2.7. NAT_T - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| NAT-T mode | 1 | 8-bit NAT traversal mode | -| NAT-T options | ? | Options related to specified NAT-T mode | -|---------------------------------------------------------------------------| - -NAT_T is used to send messages specific to certain NAT traversal modes. - -4.2.8. NETID_REQ - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Request ID | 4 | 32-bit request ID | -| Endpoint | ? | Endpoint type and address information | -|---------------------------------------------------------------------------| - -When a NETID_REQ message is received, the recipient attempts to echo it back -as a NETID message to the specified endpoint address. If the endpoint is -unspecified, the recipient must fill it in with the actual origin of the -NETID_REQ message. This allows a peer to cooperate with another peer (usually -a zone relay) to empirically determine its externally visible network -address information. - -A peer may ignore NETID_REQ or respond with an error if it does not allow -relaying. - -4.2.9. NETID - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Request ID | 4 | 32-bit request ID echoed back | -| Endpoint Type | 1 | 8-bit endpoint type | -| Endpoint Address | ? | Endpoint Address (size depends on type) | -|---------------------------------------------------------------------------| - -NETID is sent in response to NETID_REQ to the specified endpoint address. It -always contains the endpoint address to which it was sent. - -4.2.10. DGRAM - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Source Port | 2 | 16-bit source port | -| Destination Port | 2 | 16-bit destination port | -| Payload | ? | Datagram packet payload | -|---------------------------------------------------------------------------| - -A datagram is a UDP-like message without flow control or delivery assurance. - -***************************************************************************** - -5. Stream Protocol - -The stream protocol is very similar to TCP, though it omits some features -that are not required since they are taken care of by the encapsulating -protocol. SCTP was also an inspiration in the design. - -5.1. Message Types - -|---------------------------------------------------------------------------| -| Type | ID | Description | -|---------------------------------------------------------------------------| -| S_OPEN | 20 | Initiate a streaming connection (like TCP SYN) | -| S_CLOSE | 21 | Terminate a streaming connection (like TCP RST/FIN) | -| S_DATA | 22 | Data packet | -| S_ACK | 23 | Acknowedge receipt of one or more data packets | -| S_DACK | 24 | Combination of DATA and ACK | -|---------------------------------------------------------------------------| - -5.2. Message Details - -5.2.1. S_OPEN - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Sender Link ID | 2 | 16-bit sender link ID | -| Destination Port | 2 | 16-bit destination port | -| Window Size | 2 | 16-bit window size in 1024-byte increments | -| Init. Seq. Number | 4 | 32-bit initial sequence number | -| Flags | 1 | 8-bit flags | -|---------------------------------------------------------------------------| - -The OPEN message corresponds to TCP SYN, and initiates a connection. It -specifies the initial window size for the sender and the sender's initial -sequence number, which should be randomly chosen to prevent replay attacks. - -If OPEN is successful, the recipient sends its own OPEN to establish the -connetion. If OPEN is unsuccessful, CLOSE is sent with its initial and current -sequence numbers equal and an appropriate reason such as "connection refused." - -The sender link ID must be unique for a given recipient. - -If flag 01 is set, the sender link ID is actually a source port where the -sender might be listening for connections as well. This exactly duplicates -the behavior of standard TCP. Otherwise, the sender link ID is simply an -arbitrary number that the sender uses to identify the connection with this -recipient and there is no port of origin. Ports of origin are optional for -Anode streaming connections to permit greater scalability. - -5.2.2. S_CLOSE - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Sender Link ID | 2 | 16-bit sender link ID | -| Destination Port | 2 | 16-bit destination port | -| Flags | 1 | 8-bit flags | -| Reason | 1 | 8-bit close reason | -| Init. Seq. Number | 4 | 32-bit initial sequence number | -| Sequence Number | 4 | 32-bit current sequence number | -|---------------------------------------------------------------------------| - -The CLOSE message serves a function similar to TCP FIN. The initial sequence -number is the original starting sequence number sent with S_OPEN, while the -current sequence number is the sequence number corresponding to the close -and must be ACKed to complete the close operation. The use of the initial -sequence number helps to serve as a key to prevent replay attacks. - -CLOSE is also used to indicate a failed OPEN attempt. In this case the current -sequence number will be equal to the initial sequence number and no ACK will -be expected. - -There are currently no flags, so flags must be zero. - -The reason field describes the reason for the close: - -|---------------------------------------------------------------------------| -| Reason Code | Description | -|---------------------------------------------------------------------------| -| 00 | Application closed connection | -| 01 | Connection refused | -| 02 | Protocol error | -| 03 | Timed out | -|---------------------------------------------------------------------------| - -Established connections will usually be closed with reason 00, while reason -01 is usually provided if an OPEN is received but the port is not bound. - -5.2.3. S_DATA - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Sender Link ID | 2 | 16-bit sender link ID | -| Destination Port | 2 | 16-bit destination port | -| Sequence Number | 4 | 32-bit sequence number | -| Payload | ? | Data payload | -|---------------------------------------------------------------------------| - -The DATA message carries a packet of data, with the sequence number -determining order. The sequence number is monotonically incremented with -each data packet, and wraps at the maximum value of an unsigned 32-bit -integer. - -5.2.4. S_ACK - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Sender Link ID | 2 | 16-bit sender link ID | -| Destination Port | 2 | 16-bit destination port | -| Window Size | 2 | 16-bit window size in 1024-byte increments | -| Acknowledgements | ? | One or more acknowledgements (see below) | -|---------------------------------------------------------------------------| - -Each acknowledgement is a 32-bit integer followed by an 8-bit integer (5 bytes -total). The 32-bit integer is the first sequence number to acknowledge, and -the 8-bit integer is the number of sequential following sequence numbers to -acknowledge. For example "1, 4" would acknowledge sequence numbers 1, 2, 3, -and 4. - -5.2.5. S_DACK - -|---------------------------------------------------------------------------| -| Field | Length | Description | -|---------------------------------------------------------------------------| -| Sender Link ID | 2 | 16-bit sender link ID | -| Destination Port | 2 | 16-bit destination port | -| Window Size | 2 | 16-bit window size in 1024-byte increments | -| Num. Acks | 1 | 8-bit number of acknowledgements | -| Acknowledgements | ? | One or more acknowledgements | -| Payload | ? | Data payload | -|---------------------------------------------------------------------------| - -The DACK message combines ACK and DATA, allowing two peers that are both -transmitting data to efficiently ACK without a separate packet. diff --git a/attic/historic/anode/libanode/Makefile b/attic/historic/anode/libanode/Makefile deleted file mode 100644 index 088587bdd..000000000 --- a/attic/historic/anode/libanode/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -SYSNAME:=${shell uname} -SYSNAME!=uname -include ../config.mk.${SYSNAME} - -LIBANODE_OBJS= \ - impl/aes.o \ - impl/dictionary.o \ - impl/dns_txt.o \ - impl/ec.o \ - impl/environment.o \ - impl/misc.o \ - impl/thread.o \ - address.o \ - aes_digest.o \ - errors.o \ - identity.o \ - network_address.o \ - secure_random.o \ - system_transport.o \ - uri.o -# zone.o - -all: $(LIBANODE_OBJS) - ar rcs libanode.a $(LIBANODE_OBJS) - ranlib libanode.a - $(CC) $(CFLAGS) -o utils/anode-make-identity utils/anode-make-identity.c $(LIBANODE_OBJS) $(LIBANODE_LIBS) - -clean: force - rm -f $(LIBANODE_OBJS) - rm -f libanode.$(DLLEXT) libanode.a - rm -f utils/anode-make-identity - -force: ; diff --git a/attic/historic/anode/libanode/address.c b/attic/historic/anode/libanode/address.c deleted file mode 100644 index e7ab78378..000000000 --- a/attic/historic/anode/libanode/address.c +++ /dev/null @@ -1,98 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include "impl/aes.h" -#include "impl/ec.h" -#include "impl/misc.h" -#include "impl/types.h" -#include "anode.h" - -int AnodeAddress_calc_short_id( - const AnodeAddress *address, - AnodeAddressId *short_address_id) -{ - unsigned char digest[16]; - - switch(AnodeAddress_get_type(address)) { - case ANODE_ADDRESS_ANODE_256_40: - Anode_aes_digest(address->bits,ANODE_ADDRESS_LENGTH_ANODE_256_40,digest); - break; - default: - return ANODE_ERR_ADDRESS_INVALID; - } - - *((uint64_t *)short_address_id->bits) = ((uint64_t *)digest)[0] ^ ((uint64_t *)digest)[1]; - - return 0; -} - -int AnodeAddress_get_zone(const AnodeAddress *address,AnodeZone *zone) -{ - switch(AnodeAddress_get_type(address)) { - case ANODE_ADDRESS_ANODE_256_40: - *((uint32_t *)&(zone->bits[0])) = *((uint32_t *)&(address->bits[1])); - return 0; - } - return ANODE_ERR_ADDRESS_INVALID; -} - -int AnodeAddress_to_string(const AnodeAddress *address,char *buf,int len) -{ - const unsigned char *inptr; - char *outptr; - unsigned int i; - - switch(AnodeAddress_get_type(address)) { - case ANODE_ADDRESS_ANODE_256_40: - if (len < (((ANODE_ADDRESS_LENGTH_ANODE_256_40 / 5) * 8) + 1)) - return ANODE_ERR_BUFFER_TOO_SMALL; - inptr = (const unsigned char *)address->bits; - outptr = buf; - for(i=0;i<(ANODE_ADDRESS_LENGTH_ANODE_256_40 / 5);++i) { - Anode_base32_5_to_8(inptr,outptr); - inptr += 5; - outptr += 8; - } - *outptr = (char)0; - return ((ANODE_ADDRESS_LENGTH_ANODE_256_40 / 5) * 8); - } - return ANODE_ERR_ADDRESS_INVALID; -} - -int AnodeAddress_from_string(const char *str,AnodeAddress *address) -{ - const char *blk_start = str; - const char *ptr = str; - unsigned int address_len = 0; - - while (*ptr) { - if ((unsigned long)(ptr - blk_start) == 8) { - if ((address_len + 5) > sizeof(address->bits)) - return ANODE_ERR_ADDRESS_INVALID; - Anode_base32_8_to_5(blk_start,(unsigned char *)&(address->bits[address_len])); - address_len += 5; - blk_start = ptr; - } - ++ptr; - } - - if (ptr != blk_start) - return ANODE_ERR_ADDRESS_INVALID; - if (AnodeAddress_get_type(address) != ANODE_ADDRESS_ANODE_256_40) - return ANODE_ERR_ADDRESS_INVALID; - - return 0; -} diff --git a/attic/historic/anode/libanode/aes_digest.c b/attic/historic/anode/libanode/aes_digest.c deleted file mode 100644 index 07b0fc7ac..000000000 --- a/attic/historic/anode/libanode/aes_digest.c +++ /dev/null @@ -1,85 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include "anode.h" -#include "impl/aes.h" -#include "impl/misc.h" -#include "impl/types.h" - -void Anode_aes_digest(const void *const message,unsigned long message_len,void *const hash) -{ - unsigned char previous_digest[16]; - unsigned char digest[16]; - unsigned char block[32]; - const unsigned char *in = (const unsigned char *)message; - const unsigned char *end = in + message_len; - unsigned long block_counter; - AnodeAesExpandedKey expkey; - - ((uint64_t *)digest)[0] = 0ULL; - ((uint64_t *)digest)[1] = 0ULL; - ((uint64_t *)block)[0] = 0ULL; - ((uint64_t *)block)[1] = 0ULL; - ((uint64_t *)block)[2] = 0ULL; - ((uint64_t *)block)[3] = 0ULL; - - /* Davis-Meyer hash function built from block cipher */ - block_counter = 0; - while (in != end) { - block[block_counter++] = *(in++); - if (block_counter == 32) { - block_counter = 0; - ((uint64_t *)previous_digest)[0] = ((uint64_t *)digest)[0]; - ((uint64_t *)previous_digest)[1] = ((uint64_t *)digest)[1]; - Anode_aes256_expand_key(block,&expkey); - Anode_aes256_encrypt(&expkey,digest,digest); - ((uint64_t *)digest)[0] ^= ((uint64_t *)previous_digest)[0]; - ((uint64_t *)digest)[1] ^= ((uint64_t *)previous_digest)[1]; - } - } - - /* Davis-Meyer end marker */ - block[block_counter++] = 0x80; - while (block_counter != 32) block[block_counter++] = 0; - ((uint64_t *)previous_digest)[0] = ((uint64_t *)digest)[0]; - ((uint64_t *)previous_digest)[1] = ((uint64_t *)digest)[1]; - Anode_aes256_expand_key(block,&expkey); - Anode_aes256_encrypt(&expkey,digest,digest); - ((uint64_t *)digest)[0] ^= ((uint64_t *)previous_digest)[0]; - ((uint64_t *)digest)[1] ^= ((uint64_t *)previous_digest)[1]; - - /* Merkle-Damgård length padding */ - ((uint64_t *)block)[0] = 0ULL; - if (sizeof(message_len) >= 8) { /* 32/64 bit? this will get optimized out */ - block[8] = (uint8_t)((uint64_t)message_len >> 56); - block[9] = (uint8_t)((uint64_t)message_len >> 48); - block[10] = (uint8_t)((uint64_t)message_len >> 40); - block[11] = (uint8_t)((uint64_t)message_len >> 32); - } else ((uint32_t *)block)[2] = 0; - block[12] = (uint8_t)(message_len >> 24); - block[13] = (uint8_t)(message_len >> 16); - block[14] = (uint8_t)(message_len >> 8); - block[15] = (uint8_t)message_len; - ((uint64_t *)previous_digest)[0] = ((uint64_t *)digest)[0]; - ((uint64_t *)previous_digest)[1] = ((uint64_t *)digest)[1]; - Anode_aes256_expand_key(block,&expkey); - Anode_aes256_encrypt(&expkey,digest,digest); - ((uint64_t *)digest)[0] ^= ((uint64_t *)previous_digest)[0]; - ((uint64_t *)digest)[1] ^= ((uint64_t *)previous_digest)[1]; - - ((uint64_t *)hash)[0] = ((uint64_t *)digest)[0]; - ((uint64_t *)hash)[1] = ((uint64_t *)digest)[1]; -} diff --git a/attic/historic/anode/libanode/anode.h b/attic/historic/anode/libanode/anode.h deleted file mode 100644 index e0c51e2eb..000000000 --- a/attic/historic/anode/libanode/anode.h +++ /dev/null @@ -1,795 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _ANODE_ANODE_H -#define _ANODE_ANODE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#define ANODE_ADDRESS_LENGTH_ANODE_256_40 40 -#define ANODE_ADDRESS_MAX_LENGTH 40 -#define ANODE_ADDRESS_SECRET_LENGTH_ANODE_256_40 32 -#define ANODE_ADDRESS_MAX_SECRET_LENGTH 32 - -#define ANODE_ADDRESS_ID_LENGTH 8 -#define ANODE_ZONE_LENGTH 4 - -#define ANODE_ERR_NONE 0 -#define ANODE_ERR_INVALID_ARGUMENT (-10000) -#define ANODE_ERR_OUT_OF_MEMORY (-10001) -#define ANODE_ERR_INVALID_URI (-10002) -#define ANODE_ERR_BUFFER_TOO_SMALL (-10003) -#define ANODE_ERR_ADDRESS_INVALID (-10010) -#define ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED (-10011) -#define ANODE_ERR_CONNECTION_CLOSED (-10012) -#define ANODE_ERR_CONNECTION_CLOSED_BY_REMOTE (-10013) -#define ANODE_ERR_CONNECT_FAILED (-10014) -#define ANODE_ERR_UNABLE_TO_BIND (-10015) -#define ANODE_ERR_TOO_MANY_OPEN_SOCKETS (-10016) -#define ANODE_ERR_DNS_NAME_NOT_FOUND_OR_TIMED_OUT (-10017) - -/** - * Get a human-readable error description for an error code - * - * The value of 'err' can be either negative or positive. - * - * @param err Error code - * @return Human-readable description - */ -extern const char *Anode_strerror(int err); - -/* ----------------------------------------------------------------------- */ -/* Secure random source */ -/* ----------------------------------------------------------------------- */ - -/** - * Opaque secure random instance - */ -typedef void AnodeSecureRandom; - -/** - * Initialize a secure random source - * - * No cleanup/destructor is necessary. - * - * @param srng Random structure to initialize - */ -extern AnodeSecureRandom *AnodeSecureRandom_new(); - -/** - * Generate random bytes - * - * @param srng Secure random source - * @param buf Buffer to fill - * @param count Number of bytes to generate - */ -extern void AnodeSecureRandom_gen_bytes(AnodeSecureRandom *srng,void *buf,long count); - -/** - * Destroy and free a secure random instance - * - * @param srng Secure random source - */ -extern void AnodeSecureRandom_delete(AnodeSecureRandom *srng); - -/* ----------------------------------------------------------------------- */ -/* AES-256 derived Davis-Meyer hash function */ -/* ----------------------------------------------------------------------- */ - -/** - * Digest a message using AES-DIGEST to yield a 16-byte hash code - * - * @param message Message to digest - * @param message_len Length of message in bytes - * @param hash Buffer to store 16 byte hash code - */ -extern void Anode_aes_digest( - const void *const message, - unsigned long message_len, - void *const hash); - -/* ----------------------------------------------------------------------- */ -/* Address Types and Components */ -/* ----------------------------------------------------------------------- */ - -/** - * Anode address - * - * The first byte always identifies the address type, which right now can - * only be type 1 (ANODE-256-40). - */ -typedef struct -{ - char bits[ANODE_ADDRESS_MAX_LENGTH]; -} AnodeAddress; - -/** - * 8-byte short Anode address ID - */ -typedef struct -{ - char bits[ANODE_ADDRESS_ID_LENGTH]; -} AnodeAddressId; - -/** - * 4-byte Anode zone ID - */ -typedef struct -{ - char bits[ANODE_ZONE_LENGTH]; -} AnodeZone; - -/** - * Anode address types - */ -enum AnodeAddressType -{ - ANODE_ADDRESS_ANODE_256_40 = 1 -}; - -/** - * Get the type of an Anode address - * - * This is a shortcut macro for just looking at the first byte and casting - * it to the AnodeAddressType enum. - * - * @param a Pointer to address - * @return Type as enum AnodeAddressType - */ -#define AnodeAddress_get_type(a) ((enum AnodeAddressType)((a)->bits[0])) - -/** - * Calculate the short 8 byte address ID from an address - * - * @param address Binary address - * @param short_address_id Buffer to store 8-byte short address ID - * @return 0 on success or error code on failure - */ -extern int AnodeAddress_calc_short_id( - const AnodeAddress *address, - AnodeAddressId *short_address_id); - -/** - * Extract the zone from an anode address - * - * @param address Binary address - * @param zone Zone value-result parameter to fill on success - * @return 0 on success or error code on failure - */ -extern int AnodeAddress_get_zone(const AnodeAddress *address,AnodeZone *zone); - -/** - * Convert an address to an ASCII string - * - * Anode addresses are 64 characters in ASCII form, so the buffer should - * have 65 bytes of space. - * - * @param address Address to convert - * @param buf Buffer to receive address in string form (should have 65 bytes of space) - * @param len Length of buffer - * @return Length of resulting string or a negative error code on error - */ -extern int AnodeAddress_to_string(const AnodeAddress *address,char *buf,int len); - -/** - * Convert a string into an address - * - * @param str Address in string form - * @param address Address buffer to receive result - * @return Zero on sucess or error code on error - */ -extern int AnodeAddress_from_string(const char *str,AnodeAddress *address); - -/** - * Supported network address types - */ -enum AnodeNetworkAddressType -{ - ANODE_NETWORK_ADDRESS_IPV4 = 0, - ANODE_NETWORK_ADDRESS_IPV6 = 1, - ANODE_NETWORK_ADDRESS_ETHERNET = 2, /* reserved but unused */ - ANODE_NETWORK_ADDRESS_USB = 3, /* reserved but unused */ - ANODE_NETWORK_ADDRESS_BLUETOOTH = 4, /* reserved but unused */ - ANODE_NETWORK_ADDRESS_IPC = 5, /* reserved but unused */ - ANODE_NETWORK_ADDRESS_80211S = 6, /* reserved but unused */ - ANODE_NETWORK_ADDRESS_SERIAL = 7, /* reserved but unused */ - ANODE_NETWORK_ADDRESS_ANODE_256_40 = 8 -}; - -/** - * Anode network address - * - * This can contain an address of any type: IPv4, IPv6, or Anode, and is used - * with the common transport API. - * - * The length of the address stored in bits[] is determined by the type. - */ -typedef struct -{ - enum AnodeNetworkAddressType type; - char bits[ANODE_ADDRESS_MAX_LENGTH]; -} AnodeNetworkAddress; - -/** - * An endpoint with an address and a port - */ -typedef struct -{ - AnodeNetworkAddress address; - int port; -} AnodeNetworkEndpoint; - -/* Constants for binding to any address (v4 or v6) */ -extern const AnodeNetworkAddress AnodeNetworkAddress_IP_ANY_V4; -extern const AnodeNetworkAddress AnodeNetworkAddress_IP_ANY_V6; - -/* Local host address in v4 and v6 */ -extern const AnodeNetworkAddress AnodeNetworkAddress_IP_LOCAL_V4; -extern const AnodeNetworkAddress AnodeNetworkAddress_IP_LOCAL_V6; - -/** - * Convert a network address to an ASCII string - * - * The buffer must have room for a 15 character string for IPv4, a 40 byte - * string for IPv6, and a 64 byte string for Anode addresses. This does not - * include the trailing null. - * - * @param address Address to convert - * @param buf Buffer to receive address in string form - * @param len Length of buffer - * @return Length of resulting string or a negative error code on error - */ -extern int AnodeNetworkAddress_to_string(const AnodeNetworkAddress *address,char *buf,int len); - -/** - * Convert a string into a network address of the correct type - * - * @param str Address in string form - * @param address Address buffer to receive result - * @return Zero on sucess or error code on error - */ -extern int AnodeNetworkAddress_from_string(const char *str,AnodeNetworkAddress *address); - -/** - * Fill a network endpoint from a C-API sockaddr structure - * - * The argument must be struct sockaddr_in for IPv4 or sockaddr_in6 for IPv6. - * The common sin_family field will be used to differentiate. - * - * @param sockaddr Pointer to proper sockaddr structure - * @param endpoint Endpoint structure to fill - * @return Zero on success or error on failure - */ -extern int AnodeNetworkEndpoint_from_sockaddr(const void *sockaddr,AnodeNetworkEndpoint *endpoint); - -/** - * Fill a sockaddr from a network endpoint - * - * To support either IPv4 or IPv6 addresses, there is a sockaddr_storage - * structure in most C APIs. If you supply anything other than an IP address - * such as an Anode address, this will return an error. - * - * @param endpoint Endpoint structure to convert - * @param sockaddr Sockaddr structure storage - * @param sockaddr_len Length of sockaddr structure storage in bytes - * @return Zero on success or error on failure - */ -extern int AnodeNetworkEndpoint_to_sockaddr(const AnodeNetworkEndpoint *endpoint,void *sockaddr,int sockaddr_len); - -/* ----------------------------------------------------------------------- */ -/* Identity Generation and Management */ -/* ----------------------------------------------------------------------- */ - -/** - * Anode identity structure containing address and secret key - * - * This structure is memcpy-safe, and its members are accessible. - */ -typedef struct -{ - /* The public Anode address */ - AnodeAddress address; - - /* Short address ID */ - AnodeAddressId address_id; - - /* The secret key corresponding with the public address */ - /* Secret length is determined by address type */ - char secret[ANODE_ADDRESS_MAX_SECRET_LENGTH]; -} AnodeIdentity; - -/** - * Generate a new identity - * - * This generates a public/private key pair and from that generates an - * identity containing an address and a secret key. - * - * @param identity Destination structure to store new identity - * @param zone Zone ID - * @param type Type of identity to generate - * @return Zero on success, error on failure - */ -extern int AnodeIdentity_generate( - AnodeIdentity *identity, - const AnodeZone *zone, - enum AnodeAddressType type); - -/** - * Convert an Anode identity to a string representation - * - * @param identity Identity to convert - * @param dest String buffer - * @param dest_len Length of string buffer - * @return Length of string created or negative error code on failure - */ -extern int AnodeIdentity_to_string( - const AnodeIdentity *identity, - char *dest, - int dest_len); - -/** - * Convert a string representation to an Anode identity structure - * - * @param identity Destination structure to fill - * @param str C-string containing string representation - * @return Zero on success or negative error code on failure - */ -extern int AnodeIdentity_from_string( - AnodeIdentity *identity, - const char *str); - -/* ----------------------------------------------------------------------- */ -/* Transport API */ -/* ----------------------------------------------------------------------- */ - -struct _AnodeTransport; -typedef struct _AnodeTransport AnodeTransport; -struct _AnodeEvent; -typedef struct _AnodeEvent AnodeEvent; - -/** - * Anode socket - */ -typedef struct -{ - /* Type of socket (read-only) */ - enum { - ANODE_SOCKET_DATAGRAM = 1, - ANODE_SOCKET_STREAM_LISTEN = 2, - ANODE_SOCKET_STREAM_CONNECTION = 3 - } type; - - /* Socket state */ - enum { - ANODE_SOCKET_CLOSED = 0, - ANODE_SOCKET_OPEN = 1, - ANODE_SOCKET_CONNECTING = 2, - } state; - - /* Local address or remote address for stream connections (read-only) */ - AnodeNetworkEndpoint endpoint; - - /* Name of owning class (read-only) */ - const char *class_name; - - /* Pointers for end user use (writable) */ - void *user_ptr[2]; - - /* Special handler to receive events or null for default (writable) */ - void (*event_handler)(const AnodeEvent *event); -} AnodeSocket; - -/** - * Anode transport I/O event - */ -struct _AnodeEvent -{ - enum { - ANODE_TRANSPORT_EVENT_DATAGRAM_RECEIVED = 1, - ANODE_TRANSPORT_EVENT_STREAM_INCOMING_CONNECT = 2, - ANODE_TRANSPORT_EVENT_STREAM_OUTGOING_CONNECT_ESTABLISHED = 3, - ANODE_TRANSPORT_EVENT_STREAM_OUTGOING_CONNECT_FAILED = 4, - ANODE_TRANSPORT_EVENT_STREAM_CLOSED = 5, - ANODE_TRANSPORT_EVENT_STREAM_DATA_RECEIVED = 6, - ANODE_TRANSPORT_EVENT_STREAM_AVAILABLE_FOR_WRITE = 7, - ANODE_TRANSPORT_EVENT_DNS_RESULT = 8 - } type; - - AnodeTransport *transport; - - /* Anode socket corresponding to this event */ - AnodeSocket *sock; - - /* Originating endpoint for incoming datagrams */ - AnodeNetworkEndpoint *datagram_from; - - /* DNS lookup results */ - const char *dns_name; - AnodeNetworkAddress *dns_addresses; - int dns_address_count; - - /* Error code or 0 for none */ - int error_code; - - /* Data for incoming datagrams and stream received events */ - int data_length; - char *data; -}; - -/** - * Enum used for dns_resolve method in transport to specify query rules - * - * This can be specified for ipv4, ipv6, and Anode address types to tell the - * DNS resolver when to bother querying for addresses of the given type. - * NEVER means to never query for this type, and ALWAYS means to always - * query. IF_NO_PREVIOUS means to query for this type if no addresses were - * found in previous queries. Addresses are queried in the order of ipv4, - * ipv6, then Anode, so if you specify IF_NO_PREVIOUS for all three you will - * get addresses in that order of priority. - */ -enum AnodeTransportDnsIncludeMode -{ - ANODE_TRANSPORT_DNS_QUERY_NEVER = 0, - ANODE_TRANSPORT_DNS_QUERY_ALWAYS = 1, - ANODE_TRANSPORT_DNS_QUERY_IF_NO_PREVIOUS = 2 -}; - -struct _AnodeTransport -{ - /** - * Set the default event handler - * - * @param transport Transport engine - * @param event_handler Default event handler - */ - void (*set_default_event_handler)(AnodeTransport *transport, - void (*event_handler)(const AnodeEvent *event)); - - /** - * Enqueue a function to be executed during a subsequent call to poll() - * - * This can be called from other threads, so it can be used to pass a - * message to the I/O thread in multithreaded applications. - * - * If it is called from the same thread, the function is still queued to be - * run later rather than being run instantly. - * - * The order in which invoked functions are called is undefined. - * - * @param transport Transport engine - * @param ptr Arbitrary pointer to pass to function to be called - * @param func Function to be called - */ - void (*invoke)(AnodeTransport *transport, - void *ptr, - void (*func)(void *)); - - /** - * Initiate a forward DNS query - * - * @param transport Transport instance - * @param name DNS name to query - * @param event_handler Event handler or null for default event path - * @param ipv4_include_mode Inclusion mode for IPv4 addresses - * @param ipv6_include_mode Inclusion mode for IPv6 addresses - * @param anode_include_mode Inclusion mode for Anode addresses - */ - void (*dns_resolve)(AnodeTransport *transport, - const char *name, - void (*event_handler)(const AnodeEvent *), - enum AnodeTransportDnsIncludeMode ipv4_include_mode, - enum AnodeTransportDnsIncludeMode ipv6_include_mode, - enum AnodeTransportDnsIncludeMode anode_include_mode); - - /** - * Open a datagram socket - * - * @param transport Transport instance - * @param local_address Local address to bind - * @param local_port Local port to bind - * @param error_code Value-result parameter to receive error code on error - * @return Listen socket or null if error (check error_code in error case) - */ - AnodeSocket *(*datagram_listen)(AnodeTransport *transport, - const AnodeNetworkAddress *local_address, - int local_port, - int *error_code); - - /** - * Open a socket to listen for incoming stream connections - * - * @param transport Transport instance - * @param local_address Local address to bind - * @param local_port Local port to bind - * @param error_code Value-result parameter to receive error code on error - * @return Listen socket or null if error (check error_code in error case) - */ - AnodeSocket *(*stream_listen)(AnodeTransport *transport, - const AnodeNetworkAddress *local_address, - int local_port, - int *error_code); - - /** - * Send a datagram to a network endpoint - * - * @param transport Transport instance - * @param socket Originating datagram socket - * @param data Data to send - * @param data_len Length of data to send - * @param to_endpoint Destination endpoint - * @return Zero on success or error code on error - */ - int (*datagram_send)(AnodeTransport *transport, - AnodeSocket *sock, - const void *data, - int data_len, - const AnodeNetworkEndpoint *to_endpoint); - - /** - * Initiate an outgoing stream connection attempt - * - * For IPv4 and IPv6 addresses, this will initiate a TCP connection. For - * Anode addresses, Anode's internal streaming protocol will be used. - * - * @param transport Transport instance - * @param to_endpoint Destination endpoint - * @param error_code Error code value-result parameter, filled on error - * @return Stream socket object or null on error (check error_code) - */ - AnodeSocket *(*stream_connect)(AnodeTransport *transport, - const AnodeNetworkEndpoint *to_endpoint, - int *error_code); - - /** - * Indicate that you are interested in writing to a stream - * - * This does nothing if the socket is not a stream connection or is not - * connected. - * - * @param transport Transport instance - * @param sock Stream connection - */ - void (*stream_start_writing)(AnodeTransport *transport, - AnodeSocket *sock); - - /** - * Indicate that you are no longer interested in writing to a stream - * - * This does nothing if the socket is not a stream connection or is not - * connected. - * - * @param transport Transport instance - * @param sock Stream connection - */ - void (*stream_stop_writing)(AnodeTransport *transport, - AnodeSocket *sock); - - /** - * Send data to a stream connection - * - * This must be called after a stream is indicated to be ready for writing. - * It returns the number of bytes actually written, or a negative error - * code on failure. - * - * A return value of zero can occur here, and simply indicates that nothing - * was sent. This may occur with certain network stacks on certain - * platforms. - * - * @param transport Transport engine - * @param sock Stream socket - * @param data Data to send - * @param data_len Maximum data to send in bytes - * @return Actual data sent or negative error code on error - */ - int (*stream_send)(AnodeTransport *transport, - AnodeSocket *sock, - const void *data, - int data_len); - - /** - * Close a socket - * - * If the socket is a stream connection in the connected state, this - * will generate a stream closed event with a zero error_code to indicate - * a normal close. - * - * @param transport Transport engine - * @param sock Socket object - */ - void (*close)(AnodeTransport *transport, - AnodeSocket *sock); - - /** - * Run main polling loop - * - * This should be called repeatedly from the I/O thread of your main - * process. It blocks until one or more events occur, and then returns - * the number of events. Error returns here are fatal and indicate - * serious problems such as build or platform issues or a lack of any - * network interface. - * - * Functions queued with invoke() are also called inside here. - * - * @param transport Transport engine - * @return Number of events handled or negative on (fatal) error - */ - int (*poll)(AnodeTransport *transport); - - /** - * Check whether transport supports an address type - * - * Inheriting classes should call their base if they do not natively - * speak the specified type. - * - * @param transport Transport engine - * @param at Address type - * @return Nonzero if true - */ - int (*supports_address_type)(const AnodeTransport *transport, - enum AnodeNetworkAddressType at); - - /** - * Get the instance of AnodeTransport under this one (if any) - * - * @param transport Transport engine - * @return Base instance or null if none - */ - AnodeTransport *(*base_instance)(const AnodeTransport *transport); - - /** - * @param transport Transport engine - * @return Class name of this instance - */ - const char *(*class_name)(AnodeTransport *transport); - - /** - * Delete this transport and its base transports - * - * The 'transport' pointer and any streams or sockets it owns are no longer - * valid after this call. - * - * @param transport Transport engine - */ - void (*delete)(AnodeTransport *transport); -}; - -/** - * Construct a new system transport - * - * This is the default base for AnodeTransport, and it is constructed - * automatically if 'base' is null in AnodeTransport_new(). However, it also - * exposed to the user so that specialized transports (such as those that use - * proxy servers) can be developed on top of it. These in turn can be supplied - * as 'base' to AnodeTransport_new() to talk Anode over these transports. - * - * The system transport supports IP protocols and possibly others. - * - * @param base Base class or null for none (usually null) - * @return Base transport engine instance - */ -extern AnodeTransport *AnodeSystemTransport_new(AnodeTransport *base); - -/** - * Construct a new Anode core transport - * - * This is the transport that talks Anode using the specified base transport. - * Requests for other address types are passed through to the base. If the - * base is null, an instance of AnodeSystemTransport is used. - * - * Since transport engines inherit their functionality, this transport - * will also do standard IP and everything else that the system transport - * supports. Most users will just want to construct this with a null base. - * - * @param base Base transport to use, or null to use SystemTransport - * @return Anode transport engine or null on error - */ -extern AnodeTransport *AnodeCoreTransport_new(AnodeTransport *base); - -/* ----------------------------------------------------------------------- */ -/* URI Parser */ -/* ----------------------------------------------------------------------- */ - -/** - * URI broken down by component - */ -typedef struct -{ - char scheme[8]; - char username[64]; - char password[64]; - char host[128]; - char path[256]; - char query[256]; - char fragment[64]; - int port; -} AnodeURI; - -/** - * URI parser - * - * A buffer too small error will occur if any field is too large for the - * AnodeURI structure. - * - * @param parsed_uri Structure to fill with parsed URI data - * @param uri_string URI in string format - * @return Zero on success or error on failure - */ -extern int AnodeURI_parse(AnodeURI *parsed_uri,const char *uri_string); - -/** - * Output a URI in string format - * - * @param uri URI to output as string - * @param buf Buffer to store URI string - * @param len Length of buffer - * @return Buffer or null on error - */ -extern char *AnodeURI_to_string(const AnodeURI *uri,char *buf,int len); - -/* ----------------------------------------------------------------------- */ -/* Zone File Lookup and Dictionary */ -/* ----------------------------------------------------------------------- */ - -/** - * Zone file dictionary - */ -typedef void AnodeZoneFile; - -/** - * Start asynchronous zone fetch - * - * When the zone is retrieved, the lookup handler is called. If zone lookup - * failed, the zone file argument to the handler will be null. - * - * @param transport Transport engine - * @param zone Zone ID - * @param user_ptr User pointer - * @param zone_lookup_handler Handler for Anode zone lookup - */ -extern void AnodeZoneFile_lookup( - AnodeTransport *transport, - const AnodeZone *zone, - void *ptr, - void (*zone_lookup_handler)(const AnodeZone *,AnodeZoneFile *,void *)); - -/** - * Look up a key in a zone file - * - * @param zone Zone file object - * @param key Key to get in zone file - */ -extern const char *AnodeZoneFile_get(const AnodeZoneFile *zone,const char *key); - -/** - * Free a zone file - * - * @param zone Zone to free - */ -extern void AnodeZoneFile_free(AnodeZoneFile *zone); - -/* ----------------------------------------------------------------------- */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/attic/historic/anode/libanode/errors.c b/attic/historic/anode/libanode/errors.c deleted file mode 100644 index 6836bdc44..000000000 --- a/attic/historic/anode/libanode/errors.c +++ /dev/null @@ -1,52 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include "anode.h" - -struct AnodeErrDesc -{ - int code; - const char *desc; -}; - -#define TOTAL_ERRORS 12 -static const struct AnodeErrDesc ANODE_ERRORS[TOTAL_ERRORS] = { - { ANODE_ERR_NONE, "No error (success)" }, - { ANODE_ERR_INVALID_ARGUMENT, "Invalid argument" }, - { ANODE_ERR_OUT_OF_MEMORY, "Out of memory" }, - { ANODE_ERR_INVALID_URI, "Invalid URI" }, - { ANODE_ERR_BUFFER_TOO_SMALL, "Supplied buffer too small" }, - { ANODE_ERR_ADDRESS_INVALID, "Address invalid" }, - { ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED, "Address type not supported"}, - { ANODE_ERR_CONNECTION_CLOSED, "Connection closed"}, - { ANODE_ERR_CONNECT_FAILED, "Connect failed"}, - { ANODE_ERR_UNABLE_TO_BIND, "Unable to bind to address"}, - { ANODE_ERR_TOO_MANY_OPEN_SOCKETS, "Too many open sockets"}, - { ANODE_ERR_DNS_NAME_NOT_FOUND_OR_TIMED_OUT, "DNS name not found or timed out"} -}; - -extern const char *Anode_strerror(int err) -{ - int i; - int negerr = -err; - - for(i=0;i - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "impl/types.h" -#include "impl/ec.h" -#include "impl/misc.h" -#include "anode.h" - -int AnodeIdentity_generate(AnodeIdentity *identity,const AnodeZone *zone,enum AnodeAddressType type) -{ - struct AnodeECKeyPair kp; - - switch(type) { - case ANODE_ADDRESS_ANODE_256_40: - if (!AnodeECKeyPair_generate(&kp)) - return ANODE_ERR_OUT_OF_MEMORY; - - identity->address.bits[0] = (unsigned char)ANODE_ADDRESS_ANODE_256_40; - - identity->address.bits[1] = zone->bits[0]; - identity->address.bits[2] = zone->bits[1]; - identity->address.bits[3] = zone->bits[2]; - identity->address.bits[4] = zone->bits[3]; - - identity->address.bits[5] = 0; - identity->address.bits[6] = 0; - - Anode_memcpy((void *)&(identity->address.bits[7]),(const void *)kp.pub.key,ANODE_EC_PUBLIC_KEY_BYTES); - Anode_memcpy((void *)identity->secret,(const void *)kp.priv.key,kp.priv.bytes); - - AnodeAddress_calc_short_id(&identity->address,&identity->address_id); - - AnodeECKeyPair_destroy(&kp); - - return 0; - } - - return ANODE_ERR_INVALID_ARGUMENT; -} - -int AnodeIdentity_to_string(const AnodeIdentity *identity,char *dest,int dest_len) -{ - char hexbuf[128]; - char strbuf[128]; - int n; - - if ((n = AnodeAddress_to_string(&identity->address,strbuf,sizeof(strbuf))) <= 0) - return n; - - switch(AnodeAddress_get_type(&identity->address)) { - case ANODE_ADDRESS_ANODE_256_40: - Anode_to_hex((const unsigned char *)identity->secret,ANODE_ADDRESS_SECRET_LENGTH_ANODE_256_40,hexbuf,sizeof(hexbuf)); - n = snprintf(dest,dest_len,"ANODE-256-40:%s:%s",strbuf,hexbuf); - if (n >= dest_len) - return ANODE_ERR_BUFFER_TOO_SMALL; - return n; - } - - return ANODE_ERR_INVALID_ARGUMENT; -} - -int AnodeIdentity_from_string(AnodeIdentity *identity,const char *str) -{ - char buf[1024]; - char *id_name; - char *address; - char *secret; - int ec; - - Anode_str_copy(buf,str,sizeof(buf)); - - id_name = buf; - if (!id_name) return 0; - if (!*id_name) return 0; - address = (char *)Anode_strchr(id_name,':'); - if (!address) return 0; - if (!*address) return 0; - *(address++) = (char)0; - secret = (char *)Anode_strchr(address,':'); - if (!secret) return 0; - if (!*secret) return 0; - *(secret++) = (char)0; - - if (Anode_strcaseeq("ANODE-256-40",id_name)) { - if ((ec = AnodeAddress_from_string(address,&identity->address))) - return ec; - if (Anode_strlen(secret) != (ANODE_ADDRESS_SECRET_LENGTH_ANODE_256_40 * 2)) - return ANODE_ERR_INVALID_ARGUMENT; - Anode_from_hex(secret,(unsigned char *)identity->secret,sizeof(identity->secret)); - AnodeAddress_calc_short_id(&identity->address,&identity->address_id); - return 0; - } - - return ANODE_ERR_INVALID_ARGUMENT; -} diff --git a/attic/historic/anode/libanode/impl/aes.c b/attic/historic/anode/libanode/impl/aes.c deleted file mode 100644 index 90e5e23ba..000000000 --- a/attic/historic/anode/libanode/impl/aes.c +++ /dev/null @@ -1,72 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include "aes.h" - -void Anode_cmac_aes256( - const AnodeAesExpandedKey *expkey, - const unsigned char *restrict data, - unsigned long data_len, - unsigned char *restrict mac) -{ - unsigned char cbc[16]; - unsigned char pad[16]; - const unsigned char *restrict pos = data; - unsigned long i; - unsigned long remaining = data_len; - unsigned char c; - - ((uint64_t *)((void *)cbc))[0] = 0ULL; - ((uint64_t *)((void *)cbc))[1] = 0ULL; - - while (remaining >= 16) { - ((uint64_t *)((void *)cbc))[0] ^= ((uint64_t *)((void *)pos))[0]; - ((uint64_t *)((void *)cbc))[1] ^= ((uint64_t *)((void *)pos))[1]; - pos += 16; - if (remaining > 16) - Anode_aes256_encrypt(expkey,cbc,cbc); - remaining -= 16; - } - - ((uint64_t *)((void *)pad))[0] = 0ULL; - ((uint64_t *)((void *)pad))[1] = 0ULL; - Anode_aes256_encrypt(expkey,pad,pad); - - c = pad[0] & 0x80; - for(i=0;i<15;++i) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[15] <<= 1; - if (c) - pad[15] ^= 0x87; - - if (remaining||(!data_len)) { - for(i=0;i> 7); - pad[15] <<= 1; - if (c) - pad[15] ^= 0x87; - } - - ((uint64_t *)((void *)mac))[0] = ((uint64_t *)((void *)pad))[0] ^ ((uint64_t *)((void *)cbc))[0]; - ((uint64_t *)((void *)mac))[1] = ((uint64_t *)((void *)pad))[1] ^ ((uint64_t *)((void *)cbc))[1]; - - Anode_aes256_encrypt(expkey,mac,mac); -} diff --git a/attic/historic/anode/libanode/impl/aes.h b/attic/historic/anode/libanode/impl/aes.h deleted file mode 100644 index 25e33933d..000000000 --- a/attic/historic/anode/libanode/impl/aes.h +++ /dev/null @@ -1,64 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _ANODE_AES_H -#define _ANODE_AES_H - -#include -#include "types.h" - -/* This just glues us to OpenSSL's built-in AES-256 implementation */ - -#define ANODE_AES_BLOCK_SIZE 16 -#define ANODE_AES_KEY_SIZE 32 - -typedef AES_KEY AnodeAesExpandedKey; - -#define Anode_aes256_expand_key(k,ek) AES_set_encrypt_key((const unsigned char *)(k),256,(AES_KEY *)(ek)) - -/* Note: in and out can be the same thing */ -#define Anode_aes256_encrypt(ek,in,out) AES_encrypt((const unsigned char *)(in),(unsigned char *)(out),(const AES_KEY *)(ek)) - -/* Note: iv is modified */ -static inline void Anode_aes256_cfb_encrypt( - const AnodeAesExpandedKey *expkey, - const unsigned char *in, - unsigned char *out, - unsigned char *iv, - unsigned long len) -{ - int tmp = 0; - AES_cfb128_encrypt(in,out,len,(const AES_KEY *)expkey,iv,&tmp,AES_ENCRYPT); -} -static inline void Anode_aes256_cfb_decrypt( - const AnodeAesExpandedKey *expkey, - const unsigned char *in, - unsigned char *out, - unsigned char *iv, - unsigned long len) -{ - int tmp = 0; - AES_cfb128_encrypt(in,out,len,(const AES_KEY *)expkey,iv,&tmp,AES_DECRYPT); -} - -/* CMAC message authentication code */ -void Anode_cmac_aes256( - const AnodeAesExpandedKey *expkey, - const unsigned char *restrict data, - unsigned long data_len, - unsigned char *restrict mac); - -#endif diff --git a/attic/historic/anode/libanode/impl/dictionary.c b/attic/historic/anode/libanode/impl/dictionary.c deleted file mode 100644 index 060c38150..000000000 --- a/attic/historic/anode/libanode/impl/dictionary.c +++ /dev/null @@ -1,239 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "dictionary.h" - -static const char *EMPTY_STR = ""; - -void AnodeDictionary_clear(struct AnodeDictionary *d) -{ - struct AnodeDictionaryEntry *e,*ne; - int oldcs; - unsigned int i; - - oldcs = d->case_sensitive; - - for(i=0;iht[i]; - while (e) { - ne = e->next; - if ((e->key)&&(e->key != EMPTY_STR)) free((void *)e->key); - if ((e->value)&&(e->value != EMPTY_STR)) free((void *)e->value); - free((void *)e); - e = ne; - } - } - - Anode_zero((void *)d,sizeof(struct AnodeDictionary)); - - d->case_sensitive = oldcs; -} - -void AnodeDictionary_put(struct AnodeDictionary *d,const char *key,const char *value) -{ - struct AnodeDictionaryEntry *e; - char *p1; - const char *p2; - unsigned int bucket = (d->case_sensitive) ? AnodeDictionary__get_bucket(key) : AnodeDictionary__get_bucket_ci(key); - unsigned int len,i; - - e = d->ht[bucket]; - while (e) { - if (((d->case_sensitive) ? Anode_streq(key,e->key) : Anode_strcaseeq(key,e->key))) { - if (!d->case_sensitive) { - p1 = e->key; - p2 = key; - while (*p2) *(p1++) = *(p2++); - } - - len = 0; - while (value[len]) ++len; - if (len) { - if ((e->value)&&(e->value != EMPTY_STR)) - e->value = (char *)realloc((void *)e->value,len + 1); - else e->value = (char *)malloc(len + 1); - for(i=0;ivalue[i] = value[i]; - e->value[i] = (char)0; - } else { - if ((e->value)&&(e->value != EMPTY_STR)) free((void *)e->value); - e->value = (char *)EMPTY_STR; - } - return; - } - e = e->next; - } - - e = (struct AnodeDictionaryEntry *)malloc(sizeof(struct AnodeDictionaryEntry)); - - len = 0; - while (key[len]) ++len; - if (len) { - e->key = (char *)malloc(len + 1); - for(i=0;ikey[i] = key[i]; - e->key[i] = (char)0; - } else e->key = (char *)EMPTY_STR; - - len = 0; - while (value[len]) ++len; - if (len) { - e->value = (char *)malloc(len + 1); - for(i=0;ivalue[i] = value[i]; - e->value[i] = (char)0; - } else e->value = (char *)EMPTY_STR; - - e->next = d->ht[bucket]; - d->ht[bucket] = e; - - ++d->size; -} - -void AnodeDictionary_read( - struct AnodeDictionary *d, - char *in, - const char *line_breaks, - const char *kv_breaks, - const char *comment_chars, - char escape_char, - int trim_whitespace_from_keys, - int trim_whitespace_from_values) -{ - char *line = in; - char *key; - char *value; - char *p1,*p2,*p3; - char last = ~escape_char; - int eof_state = 0; - - for(;;) { - if ((!*in)||((Anode_strchr(line_breaks,*in))&&((last != escape_char)||(!escape_char)))) { - if (!*in) - eof_state = 1; - else *in = (char)0; - - if ((*line)&&((comment_chars)&&(!Anode_strchr(comment_chars,*line)))) { - key = line; - - while (*line) { - if ((Anode_strchr(kv_breaks,*line))&&((last != escape_char)||(!escape_char))) { - *(line++) = (char)0; - break; - } else last = *(line++); - } - while ((*line)&&(Anode_strchr(kv_breaks,*line))&&((last != escape_char)||(!escape_char))) - last = *(line++); - value = line; - - if (escape_char) { - p1 = key; - while (*p1) { - if (*p1 == escape_char) { - p2 = p1; - p3 = p1 + 1; - while (*p3) - *(p2++) = *(p3++); - *p2 = (char)0; - } - ++p1; - } - p1 = value; - while (*p1) { - if (*p1 == escape_char) { - p2 = p1; - p3 = p1 + 1; - while (*p3) - *(p2++) = *(p3++); - *p2 = (char)0; - } - ++p1; - } - } - - if (trim_whitespace_from_keys) - Anode_trim(key); - if (trim_whitespace_from_values) - Anode_trim(value); - - AnodeDictionary_put(d,key,value); - } - - if (eof_state) - break; - else line = in + 1; - } - last = *(in++); - } -} - -long AnodeDictionary_write( - struct AnodeDictionary *d, - char *out, - long out_size, - const char *line_break, - const char *kv_break) -{ - struct AnodeDictionaryEntry *e; - const char *tmp; - long ptr = 0; - unsigned int bucket; - - if (out_size <= 0) - return -1; - - for(bucket=0;bucketht[bucket]; - while (e) { - tmp = e->key; - if (tmp) { - while (*tmp) { - out[ptr++] = *tmp++; - if (ptr >= (out_size - 1)) return -1; - } - } - - tmp = kv_break; - if (tmp) { - while (*tmp) { - out[ptr++] = *tmp++; - if (ptr >= (out_size - 1)) return -1; - } - } - - tmp = e->value; - if (tmp) { - while (*tmp) { - out[ptr++] = *tmp++; - if (ptr >= (out_size - 1)) return -1; - } - } - - tmp = line_break; - if (tmp) { - while (*tmp) { - out[ptr++] = *tmp++; - if (ptr >= (out_size - 1)) return -1; - } - } - - e = e->next; - } - } - - out[ptr] = (char)0; - - return ptr; -} diff --git a/attic/historic/anode/libanode/impl/dictionary.h b/attic/historic/anode/libanode/impl/dictionary.h deleted file mode 100644 index 48e1642a0..000000000 --- a/attic/historic/anode/libanode/impl/dictionary.h +++ /dev/null @@ -1,126 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -/* This is a simple string hash table suitable for small tables such as zone - * files or HTTP header lists. */ - -#ifndef _ANODE_DICTIONARY_H -#define _ANODE_DICTIONARY_H - -#include "misc.h" - -/* This is a fixed hash table and is designed for relatively small numbers - * of keys for things like zone files. */ -#define ANODE_DICTIONARY_FIXED_HASH_TABLE_SIZE 16 -#define ANODE_DICTIONARY_FIXED_HASH_TABLE_MASK 15 - -/* Computes a hash code for a string and returns the hash bucket */ -static inline unsigned int AnodeDictionary__get_bucket(const char *s) -{ - unsigned int hc = 3; - while (*s) - hc = ((hc << 4) + hc) + (unsigned int)*(s++); - return ((hc ^ (hc >> 4)) & ANODE_DICTIONARY_FIXED_HASH_TABLE_MASK); -} -/* Case insensitive version of get_bucket */ -static inline unsigned int AnodeDictionary__get_bucket_ci(const char *s) -{ - unsigned int hc = 3; - while (*s) - hc = ((hc << 4) + hc) + (unsigned int)Anode_tolower(*(s++)); - return ((hc ^ (hc >> 4)) & ANODE_DICTIONARY_FIXED_HASH_TABLE_MASK); -} - -struct AnodeDictionaryEntry -{ - char *key; - char *value; - struct AnodeDictionaryEntry *next; -}; - -struct AnodeDictionary -{ - struct AnodeDictionaryEntry *ht[ANODE_DICTIONARY_FIXED_HASH_TABLE_SIZE]; - unsigned int size; - int case_sensitive; -}; - -static inline void AnodeDictionary_init(struct AnodeDictionary *d,int case_sensitive) -{ - Anode_zero((void *)d,sizeof(struct AnodeDictionary)); - d->case_sensitive = case_sensitive; -} - -void AnodeDictionary_clear(struct AnodeDictionary *d); - -static inline void AnodeDictionary_destroy(struct AnodeDictionary *d) -{ - AnodeDictionary_clear(d); -} - -void AnodeDictionary_put(struct AnodeDictionary *d,const char *key,const char *value); - -static inline const char *AnodeDictionary_get(struct AnodeDictionary *d,const char *key) -{ - struct AnodeDictionaryEntry *e; - unsigned int bucket = (d->case_sensitive) ? AnodeDictionary__get_bucket(key) : AnodeDictionary__get_bucket_ci(key); - - e = d->ht[bucket]; - while (e) { - if ((d->case_sensitive ? Anode_streq(key,e->key) : Anode_strcaseeq(key,e->key))) - return e->value; - e = e->next; - } - - return (const char *)0; -} - -static inline void AnodeDictionary_iterate( - struct AnodeDictionary *d, - void *arg, - int (*func)(void *,const char *,const char *)) -{ - struct AnodeDictionaryEntry *e; - unsigned int bucket; - - for(bucket=0;bucketht[bucket]; - while (e) { - if (!func(arg,e->key,e->value)) - return; - e = e->next; - } - } -} - -void AnodeDictionary_read( - struct AnodeDictionary *d, - char *in, - const char *line_breaks, - const char *kv_breaks, - const char *comment_chars, - char escape_char, - int trim_whitespace_from_keys, - int trim_whitespace_from_values); - -long AnodeDictionary_write( - struct AnodeDictionary *d, - char *out, - long out_size, - const char *line_break, - const char *kv_break); - -#endif diff --git a/attic/historic/anode/libanode/impl/dns_txt.c b/attic/historic/anode/libanode/impl/dns_txt.c deleted file mode 100644 index b5cf13184..000000000 --- a/attic/historic/anode/libanode/impl/dns_txt.c +++ /dev/null @@ -1,93 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dns_txt.h" - -#ifndef C_IN -#define C_IN ns_c_in -#endif -#ifndef T_TXT -#define T_TXT ns_t_txt -#endif - -static volatile int Anode_resolver_initialized = 0; - -int Anode_sync_resolve_txt(const char *host,char *txt,unsigned int txt_len) -{ - unsigned char answer[16384],*pptr,*end; - char name[16384]; - int len,explen,i; - - if (!Anode_resolver_initialized) { - Anode_resolver_initialized = 1; - res_init(); - } - - /* Do not taunt happy fun ball. */ - - len = res_search(host,C_IN,T_TXT,answer,sizeof(answer)); - if (len > 12) { - pptr = answer + 12; - end = answer + len; - - explen = dn_expand(answer,end,pptr,name,sizeof(name)); - if (explen > 0) { - pptr += explen; - - if ((pptr + 2) >= end) return 2; - if (ntohs(*((uint16_t *)pptr)) == T_TXT) { - pptr += 4; - if (pptr >= end) return 2; - - explen = dn_expand(answer,end,pptr,name,sizeof(name)); - if (explen > 0) { - pptr += explen; - - if ((pptr + 2) >= end) return 2; - if (ntohs(*((uint16_t *)pptr)) == T_TXT) { - pptr += 10; - if (pptr >= end) return 2; - - len = *(pptr++); - if (len <= 0) return 2; - if ((pptr + len) > end) return 2; - - if (txt_len < (len + 1)) - return 4; - else { - for(i=0;i - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _ANODE_DNS_TXT_H -#define _ANODE_DNS_TXT_H - -/** - * Synchronous TXT resolver routine - * - * Error codes: - * 1 - I/O error - * 2 - Invalid response - * 3 - TXT record not found - * 4 - Destination buffer too small for result - * - * @param host Host name - * @param txt Buffer to store TXT result - * @param txt_len Size of buffer - * @return Zero on success, special error code on failure - */ -int Anode_sync_resolve_txt(const char *host,char *txt,unsigned int txt_len); - -#endif - diff --git a/attic/historic/anode/libanode/impl/ec.c b/attic/historic/anode/libanode/impl/ec.c deleted file mode 100644 index 2604b4a97..000000000 --- a/attic/historic/anode/libanode/impl/ec.c +++ /dev/null @@ -1,219 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "types.h" -#include "misc.h" -#include "ec.h" - -static EC_GROUP *AnodeEC_group = (EC_GROUP *)0; - -static void *AnodeEC_KDF(const void *in,size_t inlen,void *out,size_t *outlen) -{ - unsigned long i,longest_length; - - if (!*outlen) - return out; - - for(i=0;i<(unsigned long)*outlen;++i) - ((unsigned char *)out)[i] = (unsigned char)0; - - longest_length = inlen; - if (longest_length < *outlen) - longest_length = *outlen; - for(i=0;i ANODE_EC_PRIME_BYTES)||(len < 0)) { - EC_KEY_free(key); - return 0; - } - BN_bn2bin(EC_KEY_get0_private_key(key),&(pair->priv.key[ANODE_EC_PRIME_BYTES - len])); - pair->priv.bytes = ANODE_EC_PRIME_BYTES; - - len = EC_POINT_point2oct(AnodeEC_group,EC_KEY_get0_public_key(key),POINT_CONVERSION_COMPRESSED,pair->pub.key,sizeof(pair->pub.key),0); - if (len != ANODE_EC_PUBLIC_KEY_BYTES) { - EC_KEY_free(key); - return 0; - } - pair->pub.bytes = ANODE_EC_PUBLIC_KEY_BYTES; - - /* Keep a copy of OpenSSL's structure around so we don't have to re-init - * it every time we use our key pair structure. */ - pair->internal_key = key; - - return 1; -} - -int AnodeECKeyPair_init(struct AnodeECKeyPair *pair,const struct AnodeECKey *pub,const struct AnodeECKey *priv) -{ - EC_KEY *key; - EC_POINT *kxy; - BIGNUM *pn; - - if (!AnodeEC_group) { - AnodeEC_group = EC_GROUP_new_by_curve_name(ANODE_EC_GROUP); - if (!AnodeEC_group) return 0; - } - - key = EC_KEY_new(); - if (!key) - return 0; - - if (!EC_KEY_set_group(key,AnodeEC_group)) { - EC_KEY_free(key); - return 0; - } - - /* Grab the private key */ - if (priv->bytes != ANODE_EC_PRIME_BYTES) { - EC_KEY_free(key); - return 0; - } - pn = BN_new(); - if (!pn) { - EC_KEY_free(key); - return 0; - } - if (!BN_bin2bn(priv->key,ANODE_EC_PRIME_BYTES,pn)) { - BN_free(pn); - EC_KEY_free(key); - return 0; - } - if (!EC_KEY_set_private_key(key,pn)) { - BN_free(pn); - EC_KEY_free(key); - return 0; - } - BN_free(pn); - - /* Set the public key */ - if (pub->bytes != ANODE_EC_PUBLIC_KEY_BYTES) { - EC_KEY_free(key); - return 0; - } - kxy = EC_POINT_new(AnodeEC_group); - if (!kxy) { - EC_KEY_free(key); - return 0; - } - EC_POINT_oct2point(AnodeEC_group,kxy,pub->key,ANODE_EC_PUBLIC_KEY_BYTES,0); - if (!EC_KEY_set_public_key(key,kxy)) { - EC_POINT_free(kxy); - EC_KEY_free(key); - return 0; - } - EC_POINT_free(kxy); - - Anode_zero(pair,sizeof(struct AnodeECKeyPair)); - Anode_memcpy((void *)&(pair->pub),(const void *)pub,sizeof(struct AnodeECKey)); - Anode_memcpy((void *)&(pair->priv),(const void *)priv,sizeof(struct AnodeECKey)); - pair->internal_key = key; - - return 1; -} - -void AnodeECKeyPair_destroy(struct AnodeECKeyPair *pair) -{ - if (pair) { - if (pair->internal_key) - EC_KEY_free((EC_KEY *)pair->internal_key); - } -} - -int AnodeECKeyPair_agree(const struct AnodeECKeyPair *my_key_pair,const struct AnodeECKey *their_pub_key,unsigned char *key_buf,unsigned int key_len) -{ - EC_POINT *pub; - int i; - - if (!AnodeEC_group) { - AnodeEC_group = EC_GROUP_new_by_curve_name(ANODE_EC_GROUP); - if (!AnodeEC_group) return 0; - } - - if (!my_key_pair->internal_key) - return 0; - - if (their_pub_key->bytes != ANODE_EC_PUBLIC_KEY_BYTES) - return 0; - pub = EC_POINT_new(AnodeEC_group); - if (!pub) - return 0; - EC_POINT_oct2point(AnodeEC_group,pub,their_pub_key->key,ANODE_EC_PUBLIC_KEY_BYTES,0); - - i = ECDH_compute_key(key_buf,key_len,pub,(EC_KEY *)my_key_pair->internal_key,&AnodeEC_KDF); - if (i != (int)key_len) { - EC_POINT_free(pub); - return 0; - } - - EC_POINT_free(pub); - - return 1; -} - -void AnodeEC_random(unsigned char *buf,unsigned int len) -{ - RAND_pseudo_bytes(buf,len); -} diff --git a/attic/historic/anode/libanode/impl/ec.h b/attic/historic/anode/libanode/impl/ec.h deleted file mode 100644 index f1262664d..000000000 --- a/attic/historic/anode/libanode/impl/ec.h +++ /dev/null @@ -1,61 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -/* Elliptic curve glue -- hides OpenSSL code behind this source module */ - -#ifndef _ANODE_EC_H -#define _ANODE_EC_H - -#include "misc.h" - -/* Right now, only one mode is supported: NIST-P-256. This is the only mode - * supported in the spec as well, and should be good for quite some time. - * If other modes are needed this code will need to be refactored. */ - -/* NIST-P-256 prime size in bytes */ -#define ANODE_EC_PRIME_BYTES 32 - -/* Sizes of key fields */ -#define ANODE_EC_GROUP NID_X9_62_prime256v1 -#define ANODE_EC_PUBLIC_KEY_BYTES (ANODE_EC_PRIME_BYTES + 1) -#define ANODE_EC_PRIVATE_KEY_BYTES ANODE_EC_PRIME_BYTES - -/* Larger of public or private key bytes, used for buffers */ -#define ANODE_EC_MAX_BYTES ANODE_EC_PUBLIC_KEY_BYTES - -struct AnodeECKey -{ - unsigned char key[ANODE_EC_MAX_BYTES]; - unsigned int bytes; -}; - -struct AnodeECKeyPair -{ - struct AnodeECKey pub; - struct AnodeECKey priv; - void *internal_key; -}; - -/* Key management functions */ -int AnodeECKeyPair_generate(struct AnodeECKeyPair *pair); -int AnodeECKeyPair_init(struct AnodeECKeyPair *pair,const struct AnodeECKey *pub,const struct AnodeECKey *priv); -void AnodeECKeyPair_destroy(struct AnodeECKeyPair *pair); -int AnodeECKeyPair_agree(const struct AnodeECKeyPair *my_key_pair,const struct AnodeECKey *their_pub_key,unsigned char *key_buf,unsigned int key_len); - -/* Provides access to the secure PRNG used to generate keys */ -void AnodeEC_random(unsigned char *buf,unsigned int len); - -#endif diff --git a/attic/historic/anode/libanode/impl/environment.c b/attic/historic/anode/libanode/impl/environment.c deleted file mode 100644 index 16e8ebe3d..000000000 --- a/attic/historic/anode/libanode/impl/environment.c +++ /dev/null @@ -1,118 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "environment.h" - -#ifdef WINDOWS -#include -#else -#include -#include -#endif - -static char Anode_cache_base[1024] = { 0 }; - -const char *Anode_get_cache() -{ - if (Anode_cache_base[0]) - return Anode_cache_base; - -#ifdef WINDOWS -#else - char tmp[1024]; - char home[1024]; - unsigned int i; - struct stat st; - const char *_home = getenv("HOME"); - - if (!_home) - return (const char *)0; - for(i=0;i - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _ANODE_ENVIRONMENT_H -#define _ANODE_ENVIRONMENT_H - -#ifdef WINDOWS -#define ANODE_PATH_SEPARATOR '\\' -#else -#define ANODE_PATH_SEPARATOR '/' -#endif - -const char *Anode_get_cache(); -char *Anode_get_cache_sub(const char *cache_subdir,char *buf,unsigned int len); - -#endif - diff --git a/attic/historic/anode/libanode/impl/http_client.c b/attic/historic/anode/libanode/impl/http_client.c deleted file mode 100644 index a398a5857..000000000 --- a/attic/historic/anode/libanode/impl/http_client.c +++ /dev/null @@ -1,558 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include "http_client.h" -#include "misc.h" -#include "types.h" - -/* How much to increment read buffer at each capacity top? */ -#define ANODE_HTTP_CAPACITY_INCREMENT 4096 - -static void AnodeHttpClient_close_and_fail(struct AnodeHttpClient *client) -{ - if (client->impl.tcp_connection) { - client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection); - client->impl.tcp_connection = (AnodeTransportTcpConnection *)0; - } - - client->response.data_length = 0; - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED; - - if (client->handler) - client->handler(client); -} - -static void AnodeHttpClient_do_initiate_client(struct AnodeHttpClient *client) -{ - const char *method = ""; - long l,i; - - switch(client->method) { - case ANODE_HTTP_GET: method = "GET"; break; - case ANODE_HTTP_HEAD: method = "HEAD"; break; - case ANODE_HTTP_POST: method = "POST"; break; - } - client->impl.outbuf_len = snprintf((char *)client->impl.outbuf,sizeof(client->impl.outbuf), - "%s %s%s%s HTTP/1.1\r\nHost: %s:%d\r\n%s", - method, - client->uri.path, - ((client->uri.query[0]) ? "?" : ""), - client->uri.query, - client->uri.host, - ((client->uri.port > 0) ? client->uri.port : 80), - ((client->keepalive) ? "" : "Connection: close\r\n") - ); - if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE; - AnodeHttpClient_close_and_fail(client); - return; - } - - if (client->method == ANODE_HTTP_POST) { - if ((client->data)&&(client->data_length)) { - client->impl.outbuf_len += snprintf((char *)client->impl.outbuf + client->impl.outbuf_len,sizeof(client->impl.outbuf) - client->impl.outbuf_len, - "Content-Type: %s\r\n", - (client->data_content_type ? client->data_content_type : "application/x-www-form-urlencoded") - ); - if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE; - AnodeHttpClient_close_and_fail(client); - return; - } - client->impl.outbuf_len += snprintf((char *)client->impl.outbuf + client->impl.outbuf_len,sizeof(client->impl.outbuf) - client->impl.outbuf_len, - "Content-Length: %u\r\n", - client->data_length - ); - if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE; - AnodeHttpClient_close_and_fail(client); - return; - } - } else { - client->impl.outbuf_len += snprintf((char *)client->impl.outbuf + client->impl.outbuf_len,sizeof(client->impl.outbuf) - client->impl.outbuf_len, - "Content-Length: 0\r\n" - ); - if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE; - AnodeHttpClient_close_and_fail(client); - return; - } - } - } - - l = AnodeDictionary_write(&(client->headers),(char *)client->impl.outbuf + client->impl.outbuf_len,(long)(sizeof(client->impl.outbuf) - client->impl.outbuf_len - 2),"\r\n",": "); - if (l < 0) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE; - AnodeHttpClient_close_and_fail(client); - return; - } - - client->impl.outbuf_len += (unsigned int)l; - if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) { /* sanity check */ - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE; - AnodeHttpClient_close_and_fail(client); - return; - } - - client->impl.outbuf[client->impl.outbuf_len++] = '\r'; - client->impl.outbuf[client->impl.outbuf_len++] = '\n'; - - if ((client->method == ANODE_HTTP_POST)&&(client->data)&&(client->data_length)) { - i = sizeof(client->impl.outbuf) - client->impl.outbuf_len; - if (i > client->data_length) - i = client->data_length; - Anode_memcpy((client->impl.outbuf + client->impl.outbuf_len),client->data,i); - client->impl.request_data_ptr += i; - client->impl.outbuf_len += i; - } - - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_SEND; - client->impl.transport_engine->tcp_start_writing(client->impl.transport_engine,client->impl.tcp_connection); -} - -static void AnodeHttpClient_tcp_outgoing_connect_handler( - AnodeTransportEngine *transport, - AnodeTransportTcpConnection *connection, - int error_code) -{ - struct AnodeHttpClient *client; - - if (!(client = (struct AnodeHttpClient *)(connection->ptr))) - return; - - if ((client->impl.phase == ANODE_HTTP_REQUEST_PHASE_CONNECT)&&(!client->impl.freed)) { - if (error_code) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_CONNECT_FAILED; - AnodeHttpClient_close_and_fail(client); - } else { - client->impl.tcp_connection = connection; - AnodeHttpClient_do_initiate_client(client); - } - } else transport->tcp_close(transport,connection); -} - -static void AnodeHttpClient_tcp_connection_terminated_handler( - AnodeTransportEngine *transport, - AnodeTransportTcpConnection *connection, - int error_code) -{ - struct AnodeHttpClient *client; - - if (!(client = (struct AnodeHttpClient *)(connection->ptr))) - return; - if (client->impl.freed) - return; - - client->response.data_length = 0; - client->impl.tcp_connection = (AnodeTransportTcpConnection *)0; - if ((client->impl.phase != ANODE_HTTP_REQUEST_PHASE_KEEPALIVE)&&(client->impl.phase != ANODE_HTTP_REQUEST_PHASE_CLOSED)) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_SERVER_CLOSED_CONNECTION; - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED; - AnodeHttpClient_close_and_fail(client); - } else client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED; -} - -static void AnodeHttpClient_tcp_receive_handler( - AnodeTransportEngine *transport, - AnodeTransportTcpConnection *connection, - void *data, - unsigned int data_length) -{ - struct AnodeHttpClient *client; - char *p1,*p2; - unsigned int i; - long l; - - if (!(client = (struct AnodeHttpClient *)(connection->ptr))) - return; - if (client->impl.freed) { - transport->tcp_close(transport,connection); - return; - } - - if (!client->response.data) - client->response.data = malloc(client->impl.response_data_capacity = ANODE_HTTP_CAPACITY_INCREMENT); - - i = 0; - while (i < data_length) { - switch(client->impl.read_mode) { - case ANODE_HTTP_READ_MODE_WAITING: - for(;iresponse.data)[client->response.data_length] = (char)0; - client->response.data_length = 0; - - p1 = (char *)Anode_strchr((char *)client->response.data,' '); - if (!p1) - p1 = (char *)Anode_strchr((char *)client->response.data,'\t'); - if (p1) { - while ((*p1 == ' ')||(*p1 == '\t')) ++p1; - if (!*p1) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE; - AnodeHttpClient_close_and_fail(client); - return; - } - p2 = p1 + 1; - while (*p2) { - if ((*p2 == ' ')||(*p2 == '\t')||(*p2 == '\r')||(*p2 == '\n')) { - *p2 = (char)0; - break; - } else ++p2; - } - client->response.code = (int)strtol(p1,(char **)0,10); - client->impl.read_mode = ANODE_HTTP_READ_MODE_HEADERS; - ++i; break; /* Exit inner for() */ - } - } else { - ((char *)client->response.data)[client->response.data_length++] = ((const char *)data)[i]; - if (client->response.data_length >= client->impl.response_data_capacity) - client->response.data = realloc(client->response.data,client->impl.response_data_capacity += ANODE_HTTP_CAPACITY_INCREMENT); - } - } - break; - case ANODE_HTTP_READ_MODE_HEADERS: - case ANODE_HTTP_READ_MODE_CHUNKED_FOOTER: - for(;iimpl.header_line_buf[client->impl.header_line_buf_ptr] = (char)0; - client->impl.header_line_buf_ptr = 0; - - if ((!client->impl.header_line_buf[0])||((client->impl.header_line_buf[0] == '\r')&&(!client->impl.header_line_buf[1]))) { - /* If the line is empty (or is empty with \r\n as the - * line terminator), we're at the end. */ - if (client->impl.read_mode == ANODE_HTTP_READ_MODE_CHUNKED_FOOTER) { - /* If this is a chunked footer, we finally end the - * chunked response. */ - client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING; - if (client->keepalive) - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_KEEPALIVE; - else { - client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection); - client->impl.tcp_connection = (AnodeTransportTcpConnection *)0; - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED; - } - if (client->handler) - client->handler(client); - if (client->impl.freed) - return; - } else { - /* Otherwise, this is a regular header block */ - if (client->response.code == 100) { - /* Ignore 100 Continue messages */ - client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING; - ++i; break; /* Exit inner for() */ - } else if ((client->response.code == 200)&&(client->method != ANODE_HTTP_HEAD)) { - /* Other messages get their headers parsed to determine - * how to read them. */ - p1 = (char *)AnodeDictionary_get(&(client->response.headers),"transfer-encoding"); - if ((p1)&&(Anode_strcaseeq(p1,"chunked"))) { - /* Chunked encoding enters chunked mode */ - client->impl.header_line_buf_ptr = 0; - client->impl.read_mode = ANODE_HTTP_READ_MODE_CHUNKED_CHUNK_SIZE; - ++i; break; /* Exit inner for() */ - } else { - /* Else we must have a Content-Length header */ - p1 = (char *)AnodeDictionary_get(&(client->response.headers),"content-length"); - if (!p1) { - /* No chunked or content length is not supported */ - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE; - AnodeHttpClient_close_and_fail(client); - return; - } else { - /* Enter block read mode with content length */ - l = strtol(p1,(char **)0,10); - if (l <= 0) { - /* Zero length data is all done... */ - client->impl.expecting_response_length = 0; - client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING; - if (client->keepalive) - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_KEEPALIVE; - else { - client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection); - client->impl.tcp_connection = (AnodeTransportTcpConnection *)0; - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED; - } - - if (client->handler) - client->handler(client); - if (client->impl.freed) - return; - - ++i; break; /* Exit inner for() */ - } else { - /* Else start reading... */ - client->impl.expecting_response_length = (unsigned int)l; - client->impl.read_mode = ANODE_HTTP_READ_MODE_BLOCK; - ++i; break; /* Exit inner for() */ - } - } - } - } else { - /* HEAD clients or non-200 codes get headers only */ - client->impl.expecting_response_length = 0; - client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING; - if (client->keepalive) - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_KEEPALIVE; - else { - client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection); - client->impl.tcp_connection = (AnodeTransportTcpConnection *)0; - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED; - } - - if (client->handler) - client->handler(client); - if (client->impl.freed) - return; - - ++i; break; /* Exit inner for() */ - } - } - } else { - /* Otherwise this is another header, add to dictionary */ - AnodeDictionary_read( - &(client->response.headers), - client->impl.header_line_buf, - "\r\n", - ": \t", - "", - (char)0, - 1, - 1 - ); - } - } else { - client->impl.header_line_buf[client->impl.header_line_buf_ptr++] = ((const char *)data)[i]; - if (client->impl.header_line_buf_ptr >= sizeof(client->impl.header_line_buf)) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE; - AnodeHttpClient_close_and_fail(client); - return; - } - } - } - break; - case ANODE_HTTP_READ_MODE_BLOCK: - if ((client->response.data_length + client->impl.expecting_response_length) > client->impl.response_data_capacity) - client->response.data = realloc(client->response.data,client->impl.response_data_capacity = (client->response.data_length + client->impl.expecting_response_length)); - - for(;((iimpl.expecting_response_length));++i) { - ((char *)client->response.data)[client->response.data_length++] = ((const char *)data)[i]; - --client->impl.expecting_response_length; - } - - if (!client->impl.expecting_response_length) { - client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING; - if (client->keepalive) - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_KEEPALIVE; - else { - client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection); - client->impl.tcp_connection = (AnodeTransportTcpConnection *)0; - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED; - } - - if (client->handler) - client->handler(client); - if (client->impl.freed) - return; - } - break; - case ANODE_HTTP_READ_MODE_CHUNKED_CHUNK_SIZE: - for(;iimpl.header_line_buf[client->impl.header_line_buf_ptr] = (char)0; - client->impl.header_line_buf_ptr = 0; - - p1 = client->impl.header_line_buf; - while (*p1) { - if ((*p1 == ';')||(*p1 == ' ')||(*p1 == '\r')||(*p1 == '\n')||(*p1 == '\t')) { - *p1 = (char)0; - break; - } else ++p1; - } - - if (client->impl.header_line_buf[0]) { - l = strtol(client->impl.header_line_buf,(char **)0,16); - if (l <= 0) { - /* Zero length ends chunked and enters footer mode */ - client->impl.expecting_response_length = 0; - client->impl.read_mode = ANODE_HTTP_READ_MODE_CHUNKED_FOOTER; - } else { - /* Otherwise the next chunk is to be read */ - client->impl.expecting_response_length = (unsigned int)l; - client->impl.read_mode = ANODE_HTTP_READ_MODE_CHUNKED_DATA; - } - ++i; break; /* Exit inner for() */ - } - } else { - client->impl.header_line_buf[client->impl.header_line_buf_ptr++] = ((const char *)data)[i]; - if (client->impl.header_line_buf_ptr >= sizeof(client->impl.header_line_buf)) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE; - AnodeHttpClient_close_and_fail(client); - return; - } - } - } - break; - case ANODE_HTTP_READ_MODE_CHUNKED_DATA: - if ((client->response.data_length + client->impl.expecting_response_length) > client->impl.response_data_capacity) - client->response.data = realloc(client->response.data,client->impl.response_data_capacity = (client->response.data_length + client->impl.expecting_response_length)); - - for(;((iimpl.expecting_response_length));++i) { - ((char *)client->response.data)[client->response.data_length++] = ((const char *)data)[i]; - --client->impl.expecting_response_length; - } - - if (!client->impl.expecting_response_length) - client->impl.read_mode = ANODE_HTTP_READ_MODE_CHUNKED_CHUNK_SIZE; - break; - } - } -} - -static void AnodeHttpClient_tcp_available_for_write_handler( - AnodeTransportEngine *transport, - AnodeTransportTcpConnection *connection) -{ - struct AnodeHttpClient *client; - unsigned int i,j; - int n; - - if (!(client = (struct AnodeHttpClient *)(connection->ptr))) - return; - if (client->impl.freed) { - transport->tcp_close(transport,connection); - return; - } - - if (client->impl.phase == ANODE_HTTP_REQUEST_PHASE_SEND) { - n = client->impl.transport_engine->tcp_send(client->impl.transport_engine,client->impl.tcp_connection,(const void *)client->impl.outbuf,(int)client->impl.outbuf_len); - if (n < 0) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_SERVER_CLOSED_CONNECTION; - AnodeHttpClient_close_and_fail(client); - } else if (n > 0) { - for(i=0,j=(client->impl.outbuf_len - (unsigned int)n);iimpl.outbuf[i] = client->impl.outbuf[i + (unsigned int)n]; - client->impl.outbuf_len -= (unsigned int)n; - - if ((client->method == ANODE_HTTP_POST)&&(client->data)&&(client->data_length)) { - i = sizeof(client->impl.outbuf) - client->impl.outbuf_len; - j = client->data_length - client->impl.request_data_ptr; - if (i > j) - i = j; - Anode_memcpy((client->impl.outbuf + client->impl.outbuf_len),client->data,i); - client->impl.request_data_ptr += i; - client->impl.outbuf_len += i; - } - - if (!client->impl.outbuf_len) { - client->impl.transport_engine->tcp_stop_writing(client->impl.transport_engine,client->impl.tcp_connection); - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_RECEIVE; - } - } - } else client->impl.transport_engine->tcp_stop_writing(client->impl.transport_engine,client->impl.tcp_connection); -} - -static void AnodeHttpClient_dns_result_handler( - AnodeTransportEngine *transport, - void *ptr, - int error_code, - const char *name, - const AnodeTransportIpAddress *ip_addresses, - unsigned int ip_address_count, - const AnodeAddress *anode_address) -{ - struct AnodeHttpClient *client; - AnodeTransportIpEndpoint to_endpoint; - - if (!(client = (struct AnodeHttpClient *)ptr)) - return; - if (client->impl.freed) - return; - - if ((error_code)||(!ip_address_count)) { - if (client->impl.phase == ANODE_HTTP_REQUEST_PHASE_RESOLVE) { - client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_DNS_RESOLVE_FAILED; - AnodeHttpClient_close_and_fail(client); - } - } else { - client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CONNECT; - Anode_memcpy(&to_endpoint.address,ip_addresses,sizeof(AnodeTransportIpAddress)); - to_endpoint.port = (client->uri.port > 0) ? client->uri.port : 80; - client->impl.transport_engine->tcp_connect( - client->impl.transport_engine, - client, - &AnodeHttpClient_tcp_outgoing_connect_handler, - &AnodeHttpClient_tcp_connection_terminated_handler, - &AnodeHttpClient_tcp_receive_handler, - &AnodeHttpClient_tcp_available_for_write_handler, - &to_endpoint); - } -} - -struct AnodeHttpClient *AnodeHttpClient_new(AnodeTransportEngine *transport_engine) -{ - struct AnodeHttpClient *req = malloc(sizeof(struct AnodeHttpClient)); - Anode_zero(req,sizeof(struct AnodeHttpClient)); - - AnodeDictionary_init(&(req->headers),0); - AnodeDictionary_init(&(req->response.headers),0); - - req->impl.transport_engine = transport_engine; - - return req; -} - -void AnodeHttpClient_send(struct AnodeHttpClient *client) -{ - client->response.code = 0; - client->response.data_length = 0; - AnodeDictionary_clear(&(client->response.headers)); - - client->impl.request_data_ptr = 0; - client->impl.expecting_response_length = 0; - client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING; - client->impl.outbuf_len = 0; - - if (!client->impl.tcp_connection) { - client->impl.transport_engine->dns_resolve( - client->impl.transport_engine, - &AnodeHttpClient_dns_result_handler, - client, - client->uri.host, - ANODE_TRANSPORT_DNS_QUERY_ALWAYS, - ANODE_TRANSPORT_DNS_QUERY_IF_NO_PREVIOUS, - ANODE_TRANSPORT_DNS_QUERY_NEVER); - } else AnodeHttpClient_do_initiate_client(client); -} - -void AnodeHttpClient_free(struct AnodeHttpClient *client) -{ - AnodeDictionary_destroy(&(client->headers)); - AnodeDictionary_destroy(&(client->response.headers)); - - if (client->impl.tcp_connection) { - client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection); - client->impl.tcp_connection = (AnodeTransportTcpConnection *)0; - } - - if (client->response.data) - free(client->response.data); - - client->impl.freed = 1; - client->impl.transport_engine->run_later(client->impl.transport_engine,client,&free); -} diff --git a/attic/historic/anode/libanode/impl/http_client.h b/attic/historic/anode/libanode/impl/http_client.h deleted file mode 100644 index f16730976..000000000 --- a/attic/historic/anode/libanode/impl/http_client.h +++ /dev/null @@ -1,200 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _ANODE_HTTP_CLIENT_H -#define _ANODE_HTTP_CLIENT_H - -#include -#include -#include "dictionary.h" -#include "../anode.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * HTTP request type - */ -enum AnodeHttpClientRequestMethod -{ - ANODE_HTTP_GET = 0, - ANODE_HTTP_HEAD = 1, - ANODE_HTTP_POST = 2 -}; - -/* - * Special response codes to indicate I/O errors - */ -#define ANODE_HTTP_SPECIAL_RESPONSE_DNS_RESOLVE_FAILED -1 -#define ANODE_HTTP_SPECIAL_RESPONSE_CONNECT_FAILED -2 -#define ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE -3 -#define ANODE_HTTP_SPECIAL_RESPONSE_SERVER_CLOSED_CONNECTION -4 -#define ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE -5 - -/** - * Simple HTTP client - */ -struct AnodeHttpClient -{ - /** - * Request URI - */ - AnodeURI uri; - - /** - * Request method: GET, PUT, HEAD, or POST - */ - enum AnodeHttpClientRequestMethod method; - - /** - * Data for POST requests - * - * It is your responsibility to manage and/or free this pointer. The HTTP - * client only reads from it. - */ - const void *data; - unsigned int data_length; - - /** - * Content type for data, or null for application/x-www-form-urlencoded - */ - const char *data_content_type; - - /** - * Set to non-zero to use HTTP connection keepalive - * - * If keepalive is enabled, this request can be modified and re-used and - * its associated connection will stay open (being reopened if needed) - * until it is freed. - * - * Note that this client is too dumb to pool connections and pick them on - * the basis of host. Keepalive mode should only be set if the next request - * will be from the same host and port, otherwise you will get a '404'. - */ - int keepalive; - - /** - * Function pointer to be called when request is complete (or fails) - */ - void (*handler)(struct AnodeHttpClient *); - - /** - * Two arbitrary pointers that can be stored here for use by the handler. - * These are not accessed or modified by the client. - */ - void *ptr[2]; - - /** - * Request headers - */ - struct AnodeDictionary headers; - - struct { - /** - * Response code, set on completion or failure before handler is called - * - * Also check for the special response codes defined in http_client.h as - * these negative codes indicate network or other errors. - */ - int code; - - /** - * Response data, for GET and POST requests - */ - void *data; - - /** - * Length of response data - */ - unsigned int data_length; - - /** - * Response headers - */ - struct AnodeDictionary headers; - } response; - - /** - * Internal fields used by implementation - */ - struct { - /* Transport engine being used by request */ - AnodeTransportEngine *transport_engine; - - /* Connection to which request has been sent, or null if none */ - struct AnodeHttpConnection *connection; - - /* Buffer for reading chunked mode chunk lines (can't use data buf) */ - char header_line_buf[256]; - unsigned int header_line_buf_ptr; - - /* Where are we in sending request data? */ - unsigned int request_data_ptr; - - /* Capacity of response_data buffer */ - unsigned int response_data_capacity; - - /* How much response data are we currently expecting? */ - /* This is content-length in block mode or chunk length in chunked mode */ - unsigned int expecting_response_length; - - /* Read mode */ - enum { - ANODE_HTTP_READ_MODE_WAITING = 0, - ANODE_HTTP_READ_MODE_HEADERS = 1, - ANODE_HTTP_READ_MODE_BLOCK = 2, - ANODE_HTTP_READ_MODE_CHUNKED_CHUNK_SIZE = 3, - ANODE_HTTP_READ_MODE_CHUNKED_DATA = 4, - ANODE_HTTP_READ_MODE_CHUNKED_FOOTER = 5 - } read_mode; - - /* Connection from transport engine */ - AnodeTransportTcpConnection *tcp_connection; - - /* Write buffer */ - unsigned char outbuf[16384]; - unsigned int outbuf_len; - - /* Phase of request state machine */ - enum { - ANODE_HTTP_REQUEST_PHASE_RESOLVE = 0, - ANODE_HTTP_REQUEST_PHASE_CONNECT = 1, - ANODE_HTTP_REQUEST_PHASE_SEND = 2, - ANODE_HTTP_REQUEST_PHASE_RECEIVE = 3, - ANODE_HTTP_REQUEST_PHASE_KEEPALIVE = 4, - ANODE_HTTP_REQUEST_PHASE_CLOSED = 5 - } phase; - - /* Has request object been freed? */ - int freed; - - /** - * Pointer used internally for putting requests into linked lists - */ - struct AnodeHttpClient *next; - } impl; -}; - -struct AnodeHttpClient *AnodeHttpClient_new(AnodeTransportEngine *transport_engine); -void AnodeHttpClient_send(struct AnodeHttpClient *client); -void AnodeHttpClient_free(struct AnodeHttpClient *client); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/attic/historic/anode/libanode/impl/misc.c b/attic/historic/anode/libanode/impl/misc.c deleted file mode 100644 index edc73978c..000000000 --- a/attic/historic/anode/libanode/impl/misc.c +++ /dev/null @@ -1,190 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include "misc.h" -#include "types.h" - -static const char Anode_hex_chars[16] = { - '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' -}; - -static const char Anode_base32_chars[32] = { - 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', - 'r','s','t','u','v','w','x','y','z','2','3','4','5','6','7' -}; -static const unsigned char Anode_base32_bits[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5, - 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0,0,1,2, - 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; - -/* Table for converting ASCII chars to lower case */ -const unsigned char Anode_ascii_tolower_table[256] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -void Anode_trim(char *s) -{ - char *dest = s; - char *last; - while ((*s)&&((*s == ' ')||(*s == '\t')||(*s == '\r')||(*s == '\n'))) - ++s; - last = s; - while ((*dest = *s)) { - if ((*dest != ' ')&&(*dest != '\t')&&(*dest != '\r')&&(*dest != '\n')) - last = dest; - ++dest; - ++s; - } - if (*last) - *(++last) = (char)0; -} - -unsigned int Anode_rand() -{ - static volatile int need_seed = 1; - - if (need_seed) { - need_seed = 0; - srandom((unsigned long)Anode_time64()); - } - - return (unsigned int)random(); -} - -void Anode_to_hex(const unsigned char *b,unsigned int len,char *h,unsigned int hlen) -{ - unsigned int i; - - if ((len * 2) >= hlen) - len = (hlen - 1) / 2; - - for(i=0;i> 4]; - *(h++) = Anode_hex_chars[b[i] & 0xf]; - } - *h = (char)0; -} - -void Anode_from_hex(const char *h,unsigned char *b,unsigned int blen) -{ - unsigned char *end = b + blen; - unsigned char v = (unsigned char)0; - - while (b != end) { - switch(*(h++)) { - case '0': v = 0x00; break; - case '1': v = 0x10; break; - case '2': v = 0x20; break; - case '3': v = 0x30; break; - case '4': v = 0x40; break; - case '5': v = 0x50; break; - case '6': v = 0x60; break; - case '7': v = 0x70; break; - case '8': v = 0x80; break; - case '9': v = 0x90; break; - case 'a': v = 0xa0; break; - case 'b': v = 0xb0; break; - case 'c': v = 0xc0; break; - case 'd': v = 0xd0; break; - case 'e': v = 0xe0; break; - case 'f': v = 0xf0; break; - default: return; - } - - switch(*(h++)) { - case '0': v |= 0x00; break; - case '1': v |= 0x01; break; - case '2': v |= 0x02; break; - case '3': v |= 0x03; break; - case '4': v |= 0x04; break; - case '5': v |= 0x05; break; - case '6': v |= 0x06; break; - case '7': v |= 0x07; break; - case '8': v |= 0x08; break; - case '9': v |= 0x09; break; - case 'a': v |= 0x0a; break; - case 'b': v |= 0x0b; break; - case 'c': v |= 0x0c; break; - case 'd': v |= 0x0d; break; - case 'e': v |= 0x0e; break; - case 'f': v |= 0x0f; break; - default: return; - } - - *(b++) = v; - } -} - -void Anode_base32_5_to_8(const unsigned char *in,char *out) -{ - out[0] = Anode_base32_chars[(in[0]) >> 3]; - out[1] = Anode_base32_chars[(in[0] & 0x07) << 2 | (in[1] & 0xc0) >> 6]; - out[2] = Anode_base32_chars[(in[1] & 0x3e) >> 1]; - out[3] = Anode_base32_chars[(in[1] & 0x01) << 4 | (in[2] & 0xf0) >> 4]; - out[4] = Anode_base32_chars[(in[2] & 0x0f) << 1 | (in[3] & 0x80) >> 7]; - out[5] = Anode_base32_chars[(in[3] & 0x7c) >> 2]; - out[6] = Anode_base32_chars[(in[3] & 0x03) << 3 | (in[4] & 0xe0) >> 5]; - out[7] = Anode_base32_chars[(in[4] & 0x1f)]; -} - -void Anode_base32_8_to_5(const char *in,unsigned char *out) -{ - out[0] = ((Anode_base32_bits[(unsigned int)in[0]]) << 3) | (Anode_base32_bits[(unsigned int)in[1]] & 0x1C) >> 2; - out[1] = ((Anode_base32_bits[(unsigned int)in[1]] & 0x03) << 6) | (Anode_base32_bits[(unsigned int)in[2]]) << 1 | (Anode_base32_bits[(unsigned int)in[3]] & 0x10) >> 4; - out[2] = ((Anode_base32_bits[(unsigned int)in[3]] & 0x0F) << 4) | (Anode_base32_bits[(unsigned int)in[4]] & 0x1E) >> 1; - out[3] = ((Anode_base32_bits[(unsigned int)in[4]] & 0x01) << 7) | (Anode_base32_bits[(unsigned int)in[5]]) << 2 | (Anode_base32_bits[(unsigned int)in[6]] & 0x18) >> 3; - out[4] = ((Anode_base32_bits[(unsigned int)in[6]] & 0x07) << 5) | (Anode_base32_bits[(unsigned int)in[7]]); -} diff --git a/attic/historic/anode/libanode/impl/misc.h b/attic/historic/anode/libanode/impl/misc.h deleted file mode 100644 index 38ddea7c0..000000000 --- a/attic/historic/anode/libanode/impl/misc.h +++ /dev/null @@ -1,193 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -/* This contains miscellaneous functions, including some re-implementations - * of some functions from string.h. This is to help us port to some platforms - * (cough Windows Mobile cough) that lack a lot of the basic C library. */ - -#ifndef _ANODE_MISC_H -#define _ANODE_MISC_H - -#include -#include -#include "types.h" - -#ifndef ANODE_NO_STRING_H -#include -#include -#endif - -/* Table mapping ASCII characters to themselves or their lower case */ -extern const unsigned char Anode_ascii_tolower_table[256]; - -/* Get the lower case version of an ASCII char */ -#define Anode_tolower(c) ((char)Anode_ascii_tolower_table[((unsigned long)((unsigned char)(c)))]) - -/* Test strings for equality, return nonzero if equal */ -static inline unsigned int Anode_streq(const char *restrict a,const char *restrict b) -{ - if ((!a)||(!b)) - return 0; - while (*a == *(b++)) { - if (!*(a++)) - return 1; - } - return 0; -} - -/* Equality test ignoring (ASCII) case */ -static inline unsigned int Anode_strcaseeq(const char *restrict a,const char *restrict b) -{ - if ((!a)||(!b)) - return 0; - while (Anode_tolower(*a) == Anode_tolower(*(b++))) { - if (!*(a++)) - return 1; - } - return 0; -} - -/* Safe c-string copy, ensuring that dest[] always ends with zero */ -static inline void Anode_str_copy(char *restrict dest,const char *restrict src,unsigned int dest_size) -{ - char *restrict dest_end = dest + (dest_size - 1); - while ((*src)&&(dest != dest_end)) - *(dest++) = *(src++); - *dest = (char)0; -} - -/* Simple memcpy() */ -#ifdef ANODE_NO_STRING_H -static inline void Anode_memcpy(void *restrict dest,const void *restrict src,unsigned int len) -{ - unsigned int i; - for(i=0;i 8 base32 characters and vice versa */ -void Anode_base32_5_to_8(const unsigned char *in,char *out); -void Anode_base32_8_to_5(const char *in,unsigned char *out); - -#endif diff --git a/attic/historic/anode/libanode/impl/mutex.h b/attic/historic/anode/libanode/impl/mutex.h deleted file mode 100644 index b20eb82bd..000000000 --- a/attic/historic/anode/libanode/impl/mutex.h +++ /dev/null @@ -1,34 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _ANODE_MUTEX_H -#define _ANODE_MUTEX_H - -#ifdef WINDOWS - -#else /* WINDOWS */ - -#include - -#define AnodeMutex pthread_mutex_t -#define AnodeMutex_init(m) pthread_mutex_init((m),(const pthread_mutexattr_t *)0) -#define AnodeMutex_destroy(m) pthread_mutex_destroy((m)) -#define AnodeMutex_lock(m) pthread_mutex_lock((m)) -#define AnodeMutex_unlock(m) pthread_mutex_unlock((m)) - -#endif /* WINDOWS */ - -#endif diff --git a/attic/historic/anode/libanode/impl/thread.c b/attic/historic/anode/libanode/impl/thread.c deleted file mode 100644 index c20704622..000000000 --- a/attic/historic/anode/libanode/impl/thread.c +++ /dev/null @@ -1,58 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include "thread.h" -#include - -#ifdef WINDOWS - -#else /* not WINDOWS */ - -struct _AnodeThread -{ - void (*func)(void *); - void *arg; - int wait_for_join; - pthread_t thread; -}; - -static void *_AnodeThread_main(void *arg) -{ - ((struct _AnodeThread *)arg)->func(((struct _AnodeThread *)arg)->arg); - if (!((struct _AnodeThread *)arg)->wait_for_join) - free(arg); - return (void *)0; -} - -AnodeThread *AnodeThread_create(void (*func)(void *),void *arg,int wait_for_join) -{ - struct _AnodeThread *t = malloc(sizeof(struct _AnodeThread)); - t->func = func; - t->arg = arg; - t->wait_for_join = wait_for_join; - pthread_create(&t->thread,(const pthread_attr_t *)0,&_AnodeThread_main,(void *)t); - if (!wait_for_join) - pthread_detach(t->thread); - return (AnodeThread *)t; -} - -void AnodeThread_join(AnodeThread *thread) -{ - pthread_join(((struct _AnodeThread *)thread)->thread,(void **)0); - free((void *)thread); -} - -#endif /* WINDOWS / not WINDOWS */ diff --git a/attic/historic/anode/libanode/impl/thread.h b/attic/historic/anode/libanode/impl/thread.h deleted file mode 100644 index accf173ac..000000000 --- a/attic/historic/anode/libanode/impl/thread.h +++ /dev/null @@ -1,65 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _ANODE_THREAD_H -#define _ANODE_THREAD_H - -#ifdef WINDOWS - -#include -#include -typedef DWORD AnodeThreadId; - -#else /* not WINDOWS */ - -#include -typedef pthread_t AnodeThreadId; - -#define AnodeThread_self() pthread_self() -#define AnodeThreadId_equal(a,b) pthread_equal((pthread_t)(a),(pthread_t)(b)) - -#endif - -typedef void AnodeThread; - -/** - * Create and launch a new thread - * - * If wait_for_join is true (nonzero), the thread can and must be joined. The - * thread object won't be freed until join is called and returns. If - * wait_for_join is false, the thread object frees itself automatically on - * termination. - * - * If wait_for_join is false (zero), there is really no need to keep track of - * the thread object. - * - * @param func Function to call as thread main - * @param arg Argument to pass to function - * @param wait_for_join If false, thread deletes itself when it terminates - */ -AnodeThread *AnodeThread_create(void (*func)(void *),void *arg,int wait_for_join); - -/** - * Wait for a thread to terminate and delete thread object - * - * This can only be used for threads created with wait_for_join set to true. - * The thread object is no longer valid after this call. - * - * @param thread Thread to wait for termination and delete - */ -void AnodeThread_join(AnodeThread *thread); - -#endif diff --git a/attic/historic/anode/libanode/impl/types.h b/attic/historic/anode/libanode/impl/types.h deleted file mode 100644 index 5f070e5a4..000000000 --- a/attic/historic/anode/libanode/impl/types.h +++ /dev/null @@ -1,25 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _ANODE_TYPES_H -#define _ANODE_TYPES_H - -#ifdef WINDOWS -#else -#include -#endif - -#endif diff --git a/attic/historic/anode/libanode/network_address.c b/attic/historic/anode/libanode/network_address.c deleted file mode 100644 index 86ec054f1..000000000 --- a/attic/historic/anode/libanode/network_address.c +++ /dev/null @@ -1,136 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "impl/misc.h" -#include "impl/types.h" -#include "anode.h" - -const AnodeNetworkAddress AnodeNetworkAddress_ANY4 = { - ANODE_NETWORK_ADDRESS_IPV4, - { 0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } -}; -const AnodeNetworkAddress AnodeNetworkAddress_ANY6 = { - ANODE_NETWORK_ADDRESS_IPV6, - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } -}; -const AnodeNetworkAddress AnodeNetworkAddress_LOCAL4 = { - ANODE_NETWORK_ADDRESS_IPV4, - { 127,0,0,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } -}; -const AnodeNetworkAddress AnodeNetworkAddress_LOCAL6 = { - ANODE_NETWORK_ADDRESS_IPV6, - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } -}; - -int AnodeNetworkAddress_to_string(const AnodeNetworkAddress *address,char *buf,int len) -{ - const char *s; - - switch(address->type) { - case ANODE_NETWORK_ADDRESS_IPV4: - s = inet_ntop(AF_INET,(const void *)address->bits,buf,len); - if (s) - return Anode_strlen(s); - else return ANODE_ERR_INVALID_ARGUMENT; - break; - case ANODE_NETWORK_ADDRESS_IPV6: - s = inet_ntop(AF_INET6,address->bits,buf,len); - if (s) - return Anode_strlen(s); - else return ANODE_ERR_INVALID_ARGUMENT; - /* - case ANODE_NETWORK_ADDRESS_ETHERNET: - break; - case ANODE_NETWORK_ADDRESS_USB: - break; - case ANODE_NETWORK_ADDRESS_BLUETOOTH: - break; - case ANODE_NETWORK_ADDRESS_IPC: - break; - case ANODE_NETWORK_ADDRESS_80211S: - break; - case ANODE_NETWORK_ADDRESS_SERIAL: - break; - */ - case ANODE_NETWORK_ADDRESS_ANODE_256_40: - return AnodeAddress_to_string((const AnodeAddress *)address->bits,buf,len); - default: - return ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED; - } -} - -int AnodeNetworkAddress_from_string(const char *str,AnodeNetworkAddress *address) -{ - unsigned int dots = Anode_count_char(str,'.'); - unsigned int colons = Anode_count_char(str,':'); - - if ((dots == 3)&&(!colons)) { - address->type = ANODE_NETWORK_ADDRESS_IPV4; - if (inet_pton(AF_INET,str,address->bits) > 0) - return 0; - else return ANODE_ERR_INVALID_ARGUMENT; - } else if ((colons)&&(!dots)) { - address->type = ANODE_NETWORK_ADDRESS_IPV6; - if (inet_pton(AF_INET6,str,address->bits) > 0) - return 0; - else return ANODE_ERR_INVALID_ARGUMENT; - } else { - address->type = ANODE_NETWORK_ADDRESS_ANODE_256_40; - return AnodeAddress_from_string(str,(AnodeAddress *)address->bits); - } -} - -int AnodeNetworkEndpoint_from_sockaddr(const void *sockaddr,AnodeNetworkEndpoint *endpoint) -{ - switch(((struct sockaddr_storage *)sockaddr)->ss_family) { - case AF_INET: - *((uint32_t *)endpoint->address.bits) = (uint32_t)(((struct sockaddr_in *)sockaddr)->sin_addr.s_addr); - endpoint->port = (int)ntohs(((struct sockaddr_in *)sockaddr)->sin_port); - return 0; - case AF_INET6: - Anode_memcpy(endpoint->address.bits,((struct sockaddr_in6 *)sockaddr)->sin6_addr.s6_addr,16); - endpoint->port = (int)ntohs(((struct sockaddr_in6 *)sockaddr)->sin6_port); - return 0; - default: - return ANODE_ERR_INVALID_ARGUMENT; - } -} - -int AnodeNetworkEndpoint_to_sockaddr(const AnodeNetworkEndpoint *endpoint,void *sockaddr,int sockaddr_len) -{ - switch(endpoint->address.type) { - case ANODE_NETWORK_ADDRESS_IPV4: - if (sockaddr_len < (int)sizeof(struct sockaddr_in)) - return ANODE_ERR_BUFFER_TOO_SMALL; - Anode_zero(sockaddr,sizeof(struct sockaddr_in)); - ((struct sockaddr_in *)sockaddr)->sin_family = AF_INET; - ((struct sockaddr_in *)sockaddr)->sin_port = htons((uint16_t)endpoint->port); - ((struct sockaddr_in *)sockaddr)->sin_addr.s_addr = *((uint32_t *)endpoint->address.bits); - return 0; - case ANODE_NETWORK_ADDRESS_IPV6: - if (sockaddr_len < (int)sizeof(struct sockaddr_in6)) - return ANODE_ERR_BUFFER_TOO_SMALL; - Anode_zero(sockaddr,sizeof(struct sockaddr_in6)); - ((struct sockaddr_in6 *)sockaddr)->sin6_family = AF_INET6; - ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons((uint16_t)endpoint->port); - Anode_memcpy(((struct sockaddr_in6 *)sockaddr)->sin6_addr.s6_addr,endpoint->address.bits,16); - return 0; - default: - return ANODE_ERR_INVALID_ARGUMENT; - } -} diff --git a/attic/historic/anode/libanode/secure_random.c b/attic/historic/anode/libanode/secure_random.c deleted file mode 100644 index 4322d7de6..000000000 --- a/attic/historic/anode/libanode/secure_random.c +++ /dev/null @@ -1,88 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "impl/aes.h" -#include "impl/misc.h" -#include "anode.h" - -#ifdef WINDOWS -#include -#include -#endif - -struct AnodeSecureRandomImpl -{ - AnodeAesExpandedKey key; - unsigned char state[ANODE_AES_BLOCK_SIZE]; - unsigned char block[ANODE_AES_BLOCK_SIZE]; - unsigned int ptr; -}; - -AnodeSecureRandom *AnodeSecureRandom_new() -{ - unsigned char keybuf[ANODE_AES_KEY_SIZE + ANODE_AES_BLOCK_SIZE + ANODE_AES_BLOCK_SIZE]; - unsigned int i; - struct AnodeSecureRandomImpl *srng; - -#ifdef WINDOWS - HCRYPTPROV hProv; - if (CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) { - CryptGenRandom(hProv,sizeof(keybuf),keybuf); - CryptReleaseContext(hProv,0); - } -#else - FILE *urandf = fopen("/dev/urandom","rb"); - if (urandf) { - fread((void *)keybuf,sizeof(keybuf),1,urandf); - fclose(urandf); - } -#endif - - for(i=0;i> 5); - - srng = malloc(sizeof(struct AnodeSecureRandomImpl)); - Anode_aes256_expand_key(keybuf,&srng->key); - for(i=0;istate[i] = keybuf[ANODE_AES_KEY_SIZE + i]; - for(i=0;iblock[i] = keybuf[ANODE_AES_KEY_SIZE + ANODE_AES_KEY_SIZE + i]; - srng->ptr = ANODE_AES_BLOCK_SIZE; - - return (AnodeSecureRandom *)srng; -} - -void AnodeSecureRandom_gen_bytes(AnodeSecureRandom *srng,void *buf,long count) -{ - long i,j; - - for(i=0;iptr == ANODE_AES_BLOCK_SIZE) { - Anode_aes256_encrypt(&((struct AnodeSecureRandomImpl *)srng)->key,((struct AnodeSecureRandomImpl *)srng)->state,((struct AnodeSecureRandomImpl *)srng)->state); - for(j=0;jblock[j] ^= ((struct AnodeSecureRandomImpl *)srng)->state[j]; - ((struct AnodeSecureRandomImpl *)srng)->ptr = 0; - } - ((unsigned char *)buf)[i] = ((struct AnodeSecureRandomImpl *)srng)->block[((struct AnodeSecureRandomImpl *)srng)->ptr++]; - } -} - -void AnodeSecureRandom_delete(AnodeSecureRandom *srng) -{ - free(srng); -} diff --git a/attic/historic/anode/libanode/system_transport.c b/attic/historic/anode/libanode/system_transport.c deleted file mode 100644 index 4bfb143ee..000000000 --- a/attic/historic/anode/libanode/system_transport.c +++ /dev/null @@ -1,948 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include -#include -#include -#include "anode.h" -#include "impl/mutex.h" -#include "impl/thread.h" -#include "impl/misc.h" -#include "impl/dns_txt.h" - -#ifdef WINDOWS -#include -#include -#define AnodeSystemTransport__close_socket(s) closesocket((s)) -#define ANODE_USE_SELECT 1 -#else -#include -#include -#define AnodeSystemTransport__close_socket(s) close((s)) -#endif - -static const char *AnodeSystemTransport_CLASS = "SystemTransport"; - -/* ======================================================================== */ - -struct AnodeSystemTransport; - -struct AnodeSystemTransport_AnodeSocket -{ - AnodeSocket base; /* must be first */ - unsigned int entry_idx; -}; - -#define ANODE_SYSTEM_TRANSPORT_DNS_MAX_RESULTS 16 -struct AnodeSystemTransport__dns_request -{ - struct AnodeSystemTransport__dns_request *next; - - AnodeThread *thread; - struct AnodeSystemTransport *owner; - - void (*event_handler)(const AnodeEvent *event); - - char name[256]; - enum AnodeTransportDnsIncludeMode ipv4_include_mode; - enum AnodeTransportDnsIncludeMode ipv6_include_mode; - enum AnodeTransportDnsIncludeMode anode_include_mode; - - AnodeNetworkAddress addresses[ANODE_SYSTEM_TRANSPORT_DNS_MAX_RESULTS]; - unsigned int address_count; - - int error_code; -}; - -#ifdef ANODE_USE_SELECT -typedef int AnodeSystemTransport__poll_fd; /* for select() */ -#else -typedef struct pollfd AnodeSystemTransport__poll_fd; /* for poll() */ -#endif - -struct AnodeSystemTransport -{ - AnodeTransport interface; /* must be first */ - - AnodeTransport *base; - -#ifdef ANODE_USE_SELECT - FD_SET readfds; - FD_SET writefds; -#endif - - void (*default_event_handler)(const AnodeEvent *event); - - AnodeSystemTransport__poll_fd *fds; - struct AnodeSystemTransport_AnodeSocket *sockets; - unsigned int fd_count; - unsigned int fd_capacity; - - struct AnodeSystemTransport__dns_request *pending_dns_requests; - - int invoke_pipe[2]; - AnodeMutex invoke_pipe_m; - void *invoke_pipe_buf[2]; - unsigned int invoke_pipe_buf_ptr; -}; - -/* ======================================================================== */ -/* Internal helper methods */ - -static unsigned int AnodeSystemTransport__add_entry(struct AnodeSystemTransport *transport) -{ - if ((transport->fd_count + 1) > transport->fd_capacity) { - transport->fd_capacity += 8; - transport->fds = realloc(transport->fds,sizeof(AnodeSystemTransport__poll_fd) * transport->fd_capacity); - transport->sockets = realloc(transport->sockets,sizeof(struct AnodeSystemTransport_AnodeSocket) * transport->fd_capacity); - } - return transport->fd_count++; -} - -static void AnodeSystemTransport__remove_entry(struct AnodeSystemTransport *transport,const unsigned int idx) -{ - unsigned int i; - - --transport->fd_count; - for(i=idx;ifd_count;++i) { - Anode_memcpy(&transport->fds[i],&transport->fds[i+1],sizeof(AnodeSystemTransport__poll_fd)); - Anode_memcpy(&transport->sockets[i],&transport->sockets[i+1],sizeof(struct AnodeSystemTransport_AnodeSocket)); - } - - if ((transport->fd_capacity - transport->fd_count) > 16) { - transport->fd_capacity -= 16; - transport->fds = realloc(transport->fds,sizeof(AnodeSystemTransport__poll_fd) * transport->fd_capacity); - transport->sockets = realloc(transport->sockets,sizeof(struct AnodeSystemTransport_AnodeSocket) * transport->fd_capacity); - } -} - -static void AnodeSystemTransport__dns_invoke_on_completion(void *_dreq) -{ - struct AnodeSystemTransport__dns_request *dreq = (struct AnodeSystemTransport__dns_request *)_dreq; - struct AnodeSystemTransport__dns_request *ptr,**lastnext; - - AnodeThread_join(dreq->thread); - - ptr = dreq->owner->pending_dns_requests; - lastnext = &dreq->owner->pending_dns_requests; - while (ptr) { - if (ptr == dreq) { - *lastnext = ptr->next; - break; - } else { - lastnext = &ptr->next; - ptr = ptr->next; - } - } - - free(dreq); -} - -static void AnodeSystemTransport__dns_thread_main(void *_dreq) -{ - struct AnodeSystemTransport__dns_request *dreq = (struct AnodeSystemTransport__dns_request *)_dreq; - - dreq->owner->interface.invoke((AnodeTransport *)dreq->owner,dreq,&AnodeSystemTransport__dns_invoke_on_completion); -} - -static void AnodeSystemTransport__do_close(struct AnodeSystemTransport *transport,struct AnodeSystemTransport_AnodeSocket *sock,const int error_code,const int generate_event) -{ - AnodeEvent evbuf; - int fd; - - if (sock->base.class_name == AnodeSystemTransport_CLASS) { -#ifdef ANODE_USE_SELECT - fd = (int)(transport->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx]); -#else - fd = transport->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx].fd; -#endif - - if ((sock->base.type == ANODE_SOCKET_STREAM_CONNECTION)&&(sock->base.state != ANODE_SOCKET_CLOSED)) { - sock->base.state = ANODE_SOCKET_CLOSED; - - if (generate_event) { - evbuf.type = ANODE_TRANSPORT_EVENT_STREAM_CLOSED; - evbuf.transport = (AnodeTransport *)transport; - evbuf.sock = (AnodeSocket *)sock; - evbuf.datagram_from = NULL; - evbuf.dns_name = NULL; - evbuf.dns_addresses = NULL; - evbuf.dns_address_count = 0; - evbuf.error_code = error_code; - evbuf.data_length = 0; - evbuf.data = NULL; - - if (sock->base.event_handler) - sock->base.event_handler(&evbuf); - else if (transport->default_event_handler) - transport->default_event_handler(&evbuf); - } - } - - AnodeSystemTransport__close_socket(fd); - AnodeSystemTransport__remove_entry(transport,((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx); - -#ifdef ANODE_USE_SELECT - FD_CLR(sock,&THIS->readfds); - FD_CLR(sock,&THIS->writefds); -#endif - } else transport->base->close(transport->base,(AnodeSocket *)sock); -} - -static int AnodeSystemTransport__populate_network_endpoint(const struct sockaddr_storage *saddr,AnodeNetworkEndpoint *ep) -{ - switch(saddr->ss_family) { - case AF_INET: - ep->address.type = ANODE_NETWORK_ADDRESS_IPV4; - *((uint32_t *)ep->address.bits) = ((struct sockaddr_in *)saddr)->sin_addr.s_addr; - ep->port = ntohs(((struct sockaddr_in *)saddr)->sin_port); - return 1; - case AF_INET6: - ep->address.type = ANODE_NETWORK_ADDRESS_IPV6; - Anode_memcpy(ep->address.bits,((struct sockaddr_in6 *)saddr)->sin6_addr.s6_addr,16); - ep->port = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); - return 1; - } - return 0; -} - -/* ======================================================================== */ - -#ifdef THIS -#undef THIS -#endif -#define THIS ((struct AnodeSystemTransport *)transport) - -static void AnodeSystemTransport_invoke(AnodeTransport *transport, - void *ptr, - void (*func)(void *)) -{ - void *invoke_msg[2]; - - invoke_msg[0] = ptr; - invoke_msg[1] = (void *)func; - - AnodeMutex_lock(&THIS->invoke_pipe_m); - write(THIS->invoke_pipe[1],(void *)(&invoke_msg),sizeof(invoke_msg)); - AnodeMutex_unlock(&THIS->invoke_pipe_m); -} - -static void AnodeSystemTransport_dns_resolve(AnodeTransport *transport, - const char *name, - void (*event_handler)(const AnodeEvent *), - enum AnodeTransportDnsIncludeMode ipv4_include_mode, - enum AnodeTransportDnsIncludeMode ipv6_include_mode, - enum AnodeTransportDnsIncludeMode anode_include_mode) -{ - struct AnodeSystemTransport__dns_request *dreq = malloc(sizeof(struct AnodeSystemTransport__dns_request)); - - dreq->owner = THIS; - dreq->event_handler = event_handler; - Anode_str_copy(dreq->name,name,sizeof(dreq->name)); - dreq->ipv4_include_mode = ipv4_include_mode; - dreq->ipv6_include_mode = ipv6_include_mode; - dreq->anode_include_mode = anode_include_mode; - - dreq->address_count = 0; - dreq->error_code = 0; - - dreq->next = THIS->pending_dns_requests; - THIS->pending_dns_requests = dreq; - - dreq->thread = AnodeThread_create(&AnodeSystemTransport__dns_thread_main,dreq,0); -} - -static AnodeSocket *AnodeSystemTransport_datagram_listen(AnodeTransport *transport, - const AnodeNetworkAddress *local_address, - int local_port, - int *error_code) -{ - struct sockaddr_in sin4; - struct sockaddr_in6 sin6; - struct AnodeSystemTransport_AnodeSocket *sock; - unsigned int entry_idx; - int fd; - int tmp; - - switch(local_address->type) { - case ANODE_NETWORK_ADDRESS_IPV4: - fd = socket(AF_INET,SOCK_DGRAM,0); - if (fd <= 0) { - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - tmp = 1; - setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&tmp,sizeof(tmp)); - fcntl(fd,F_SETFL,O_NONBLOCK); - - Anode_zero(&sin4,sizeof(struct sockaddr_in)); - sin4.sin_family = AF_INET; - sin4.sin_port = htons(local_port); - sin4.sin_addr.s_addr = *((uint32_t *)local_address->bits); - - if (bind(fd,(const struct sockaddr *)&sin4,sizeof(sin4))) { - AnodeSystemTransport__close_socket(fd); - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - break; - case ANODE_NETWORK_ADDRESS_IPV6: - fd = socket(AF_INET6,SOCK_DGRAM,0); - if (fd <= 0) { - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - tmp = 1; setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&tmp,sizeof(tmp)); - fcntl(fd,F_SETFL,O_NONBLOCK); -#ifdef IPV6_V6ONLY - tmp = 1; setsockopt(fd,IPPROTO_IPV6,IPV6_V6ONLY,&tmp,sizeof(tmp)); -#endif - - Anode_zero(&sin6,sizeof(struct sockaddr_in6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_port = htons(local_port); - Anode_memcpy(sin6.sin6_addr.s6_addr,local_address->bits,16); - - if (bind(fd,(const struct sockaddr *)&sin6,sizeof(sin6))) { - AnodeSystemTransport__close_socket(fd); - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - break; - default: - if (THIS->base) - return THIS->base->datagram_listen(THIS->base,local_address,local_port,error_code); - else { - *error_code = ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED; - return (AnodeSocket *)0; - } - } - - entry_idx = AnodeSystemTransport__add_entry(THIS); - sock = &(THIS->sockets[entry_idx]); - - sock->base.type = ANODE_SOCKET_DATAGRAM; - sock->base.state = ANODE_SOCKET_OPEN; - Anode_memcpy(&sock->base.endpoint.address,local_address,sizeof(AnodeNetworkAddress)); - sock->base.endpoint.port = local_port; - sock->base.class_name = AnodeSystemTransport_CLASS; - sock->base.user_ptr[0] = NULL; - sock->base.user_ptr[1] = NULL; - sock->base.event_handler = NULL; - sock->entry_idx = entry_idx; - - THIS->fds[entry_idx].fd = fd; - THIS->fds[entry_idx].events = POLLIN; - THIS->fds[entry_idx].revents = 0; - - *error_code = 0; - return (AnodeSocket *)sock; -} - -static AnodeSocket *AnodeSystemTransport_stream_listen(AnodeTransport *transport, - const AnodeNetworkAddress *local_address, - int local_port, - int *error_code) -{ - struct sockaddr_in sin4; - struct sockaddr_in6 sin6; - struct AnodeSystemTransport_AnodeSocket *sock; - unsigned int entry_idx; - int fd; - int tmp; - - switch(local_address->type) { - case ANODE_NETWORK_ADDRESS_IPV4: - fd = socket(AF_INET,SOCK_STREAM,0); - if (fd < 0) { - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - fcntl(fd,F_SETFL,O_NONBLOCK); - - Anode_zero(&sin4,sizeof(struct sockaddr_in)); - sin4.sin_family = AF_INET; - sin4.sin_port = htons(local_port); - sin4.sin_addr.s_addr = *((uint32_t *)local_address->bits); - - if (bind(fd,(const struct sockaddr *)&sin4,sizeof(sin4))) { - AnodeSystemTransport__close_socket(fd); - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - if (listen(fd,8)) { - AnodeSystemTransport__close_socket(fd); - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - break; - case ANODE_NETWORK_ADDRESS_IPV6: - fd = socket(AF_INET6,SOCK_STREAM,0); - if (fd < 0) { - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - fcntl(fd,F_SETFL,O_NONBLOCK); -#ifdef IPV6_V6ONLY - tmp = 1; setsockopt(fd,IPPROTO_IPV6,IPV6_V6ONLY,&tmp,sizeof(tmp)); -#endif - - Anode_zero(&sin6,sizeof(struct sockaddr_in6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_port = htons(local_port); - Anode_memcpy(sin6.sin6_addr.s6_addr,local_address->bits,16); - - if (bind(fd,(const struct sockaddr *)&sin6,sizeof(sin6))) { - AnodeSystemTransport__close_socket(fd); - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - if (listen(fd,8)) { - AnodeSystemTransport__close_socket(fd); - *error_code = ANODE_ERR_UNABLE_TO_BIND; - return (AnodeSocket *)0; - } - break; - default: - if (THIS->base) - return THIS->base->stream_listen(THIS->base,local_address,local_port,error_code); - else { - *error_code = ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED; - return (AnodeSocket *)0; - } - } - - entry_idx = AnodeSystemTransport__add_entry(THIS); - sock = &(THIS->sockets[entry_idx]); - - sock->base.type = ANODE_SOCKET_STREAM_LISTEN; - sock->base.state = ANODE_SOCKET_OPEN; - Anode_memcpy(&sock->base.endpoint.address,local_address,sizeof(AnodeNetworkAddress)); - sock->base.endpoint.port = local_port; - sock->base.class_name = AnodeSystemTransport_CLASS; - sock->base.user_ptr[0] = NULL; - sock->base.user_ptr[1] = NULL; - sock->base.event_handler = NULL; - sock->entry_idx = entry_idx; - - THIS->fds[entry_idx].fd = fd; - THIS->fds[entry_idx].events = POLLIN; - THIS->fds[entry_idx].revents = 0; - - *error_code = 0; - return (AnodeSocket *)sock; -} - -static int AnodeSystemTransport_datagram_send(AnodeTransport *transport, - AnodeSocket *sock, - const void *data, - int data_len, - const AnodeNetworkEndpoint *to_endpoint) -{ - struct sockaddr_in sin4; - struct sockaddr_in6 sin6; - -#ifdef ANODE_USE_SELECT - const int fd = (int)(THIS->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx]); -#else - const int fd = THIS->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx].fd; -#endif - - switch(to_endpoint->address.type) { - case ANODE_NETWORK_ADDRESS_IPV4: - Anode_zero(&sin4,sizeof(struct sockaddr_in)); - sin4.sin_family = AF_INET; - sin4.sin_port = htons((uint16_t)to_endpoint->port); - sin4.sin_addr.s_addr = *((uint32_t *)to_endpoint->address.bits); - sendto(fd,data,data_len,0,(struct sockaddr *)&sin4,sizeof(sin4)); - return 0; - case ANODE_NETWORK_ADDRESS_IPV6: - Anode_zero(&sin6,sizeof(struct sockaddr_in6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_port = htons((uint16_t)to_endpoint->port); - Anode_memcpy(sin6.sin6_addr.s6_addr,to_endpoint->address.bits,16); - sendto(fd,data,data_len,0,(struct sockaddr *)&sin6,sizeof(sin6)); - return 0; - default: - if (THIS->base) - return THIS->base->datagram_send(THIS->base,sock,data,data_len,to_endpoint); - else return ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED; - } -} - -static AnodeSocket *AnodeSystemTransport_stream_connect(AnodeTransport *transport, - const AnodeNetworkEndpoint *to_endpoint, - int *error_code) -{ - struct sockaddr_in sin4; - struct sockaddr_in6 sin6; - struct AnodeSystemTransport_AnodeSocket *sock; - unsigned int entry_idx; - int fd; - - switch(to_endpoint->address.type) { - case ANODE_NETWORK_ADDRESS_IPV4: - Anode_zero(&sin4,sizeof(struct sockaddr_in)); - sin4.sin_family = AF_INET; - sin4.sin_port = htons(to_endpoint->port); - sin4.sin_addr.s_addr = *((uint32_t *)to_endpoint->address.bits); - - fd = socket(AF_INET,SOCK_STREAM,0); - if (fd < 0) { - *error_code = ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED; - return (AnodeSocket *)0; - } - fcntl(fd,F_SETFL,O_NONBLOCK); - - if (connect(fd,(struct sockaddr *)&sin4,sizeof(sin4))) { - if (errno != EINPROGRESS) { - *error_code = ANODE_ERR_CONNECT_FAILED; - AnodeSystemTransport__close_socket(fd); - return (AnodeSocket *)0; - } - } - break; - case ANODE_NETWORK_ADDRESS_IPV6: - Anode_zero(&sin6,sizeof(struct sockaddr_in6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_port = htons(to_endpoint->port); - Anode_memcpy(sin6.sin6_addr.s6_addr,to_endpoint->address.bits,16); - - fd = socket(AF_INET6,SOCK_STREAM,0); - if (fd < 0) { - *error_code = ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED; - return (AnodeSocket *)0; - } - fcntl(fd,F_SETFL,O_NONBLOCK); - - if (connect(fd,(struct sockaddr *)&sin6,sizeof(sin6))) { - if (errno == EINPROGRESS) { - *error_code = ANODE_ERR_CONNECT_FAILED; - AnodeSystemTransport__close_socket(fd); - return (AnodeSocket *)0; - } - } - break; - default: - if (THIS->base) - return THIS->base->stream_connect(THIS->base,to_endpoint,error_code); - else { - *error_code = ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED; - return (AnodeSocket *)0; - } - } - - entry_idx = AnodeSystemTransport__add_entry(THIS); - sock = &(THIS->sockets[entry_idx]); - - sock->base.type = ANODE_SOCKET_STREAM_CONNECTION; - sock->base.state = ANODE_SOCKET_CONNECTING; - Anode_memcpy(&sock->base.endpoint,to_endpoint,sizeof(AnodeNetworkEndpoint)); - sock->base.class_name = AnodeSystemTransport_CLASS; - sock->base.user_ptr[0] = NULL; - sock->base.user_ptr[1] = NULL; - sock->base.event_handler = NULL; - sock->entry_idx = entry_idx; - - THIS->fds[entry_idx].fd = fd; - THIS->fds[entry_idx].events = POLLIN|POLLOUT; - THIS->fds[entry_idx].revents = 0; - - return (AnodeSocket *)sock; -} - -static void AnodeSystemTransport_stream_start_writing(AnodeTransport *transport, - AnodeSocket *sock) -{ - if ((sock->type == ANODE_SOCKET_STREAM_CONNECTION)&&(((struct AnodeSystemTransport_AnodeSocket *)sock)->base.state == ANODE_SOCKET_OPEN)) { - if (sock->class_name == AnodeSystemTransport_CLASS) { -#ifdef ANODE_USE_SELECT - FD_SET((int)(THIS->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx]),&THIS->writefds); -#else - THIS->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx].events = (POLLIN|POLLOUT); -#endif - } else THIS->base->stream_start_writing(THIS->base,sock); - } -} - -static void AnodeSystemTransport_stream_stop_writing(AnodeTransport *transport, - AnodeSocket *sock) -{ - if ((sock->type == ANODE_SOCKET_STREAM_CONNECTION)&&(((struct AnodeSystemTransport_AnodeSocket *)sock)->base.state == ANODE_SOCKET_OPEN)) { - if (sock->class_name == AnodeSystemTransport_CLASS) { -#ifdef ANODE_USE_SELECT - FD_CLR((int)(THIS->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx]),&THIS->writefds); -#else - THIS->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx].events = POLLIN; -#endif - } else THIS->base->stream_stop_writing(THIS->base,sock); - } -} - -static int AnodeSystemTransport_stream_send(AnodeTransport *transport, - AnodeSocket *sock, - const void *data, - int data_len) -{ - int result; - - if (sock->type == ANODE_SOCKET_STREAM_CONNECTION) { - if (sock->class_name == AnodeSystemTransport_CLASS) { - if (((struct AnodeSystemTransport_AnodeSocket *)sock)->base.state != ANODE_SOCKET_OPEN) - return ANODE_ERR_CONNECTION_CLOSED; - -#ifdef ANODE_USE_SELECT - result = send((int)(THIS->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx]),data,data_len,0); -#else - result = send(THIS->fds[((struct AnodeSystemTransport_AnodeSocket *)sock)->entry_idx].fd,data,data_len,0); -#endif - - if (result >= 0) - return result; - else { - AnodeSystemTransport__do_close(THIS,(struct AnodeSystemTransport_AnodeSocket *)sock,ANODE_ERR_CONNECTION_CLOSED_BY_REMOTE,1); - return ANODE_ERR_CONNECTION_CLOSED; - } - } else return THIS->base->stream_send(THIS->base,sock,data,data_len); - } else return ANODE_ERR_INVALID_ARGUMENT; -} - -static void AnodeSystemTransport_close(AnodeTransport *transport, - AnodeSocket *sock) -{ - AnodeSystemTransport__do_close(THIS,(struct AnodeSystemTransport_AnodeSocket *)sock,0,1); -} - -static void AnodeSystemTransport__poll_do_read_datagram(struct AnodeSystemTransport *transport,int fd,struct AnodeSystemTransport_AnodeSocket *sock) -{ - char buf[16384]; - struct sockaddr_storage fromaddr; - AnodeNetworkEndpoint tmp_ep; - AnodeEvent evbuf; - socklen_t addrlen; - int n; - - addrlen = sizeof(struct sockaddr_storage); - n = recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&fromaddr,&addrlen); - if ((n >= 0)&&(AnodeSystemTransport__populate_network_endpoint(&fromaddr,&tmp_ep))) { - evbuf.type = ANODE_TRANSPORT_EVENT_DATAGRAM_RECEIVED; - evbuf.transport = (AnodeTransport *)transport; - evbuf.sock = (AnodeSocket *)sock; - evbuf.datagram_from = &tmp_ep; - evbuf.dns_name = NULL; - evbuf.dns_addresses = NULL; - evbuf.dns_address_count = 0; - evbuf.error_code = 0; - evbuf.data_length = n; - evbuf.data = buf; - - if (sock->base.event_handler) - sock->base.event_handler(&evbuf); - else if (transport->default_event_handler) - transport->default_event_handler(&evbuf); - } -} - -static void AnodeSystemTransport__poll_do_accept_incoming_connection(struct AnodeSystemTransport *transport,int fd,struct AnodeSystemTransport_AnodeSocket *sock) -{ - struct sockaddr_storage fromaddr; - AnodeNetworkEndpoint tmp_ep; - AnodeEvent evbuf; - struct AnodeSystemTransport_AnodeSocket *newsock; - socklen_t addrlen; - int n; - unsigned int entry_idx; - - addrlen = sizeof(struct sockaddr_storage); - n = accept(fd,(struct sockaddr *)&fromaddr,&addrlen); - if ((n >= 0)&&(AnodeSystemTransport__populate_network_endpoint(&fromaddr,&tmp_ep))) { - entry_idx = AnodeSystemTransport__add_entry(transport); - newsock = &(transport->sockets[entry_idx]); - - newsock->base.type = ANODE_SOCKET_STREAM_CONNECTION; - newsock->base.state = ANODE_SOCKET_OPEN; - Anode_memcpy(&newsock->base.endpoint,&tmp_ep,sizeof(AnodeNetworkEndpoint)); - newsock->base.class_name = AnodeSystemTransport_CLASS; - newsock->base.user_ptr[0] = NULL; - newsock->base.user_ptr[1] = NULL; - newsock->base.event_handler = NULL; - newsock->entry_idx = entry_idx; - - THIS->fds[entry_idx].fd = n; - THIS->fds[entry_idx].events = POLLIN; - THIS->fds[entry_idx].revents = 0; - - evbuf.type = ANODE_TRANSPORT_EVENT_STREAM_INCOMING_CONNECT; - evbuf.transport = (AnodeTransport *)transport; - evbuf.sock = (AnodeSocket *)newsock; - evbuf.datagram_from = NULL; - evbuf.dns_name = NULL; - evbuf.dns_addresses = NULL; - evbuf.dns_address_count = 0; - evbuf.error_code = 0; - evbuf.data_length = 0; - evbuf.data = NULL; - - if (sock->base.event_handler) - sock->base.event_handler(&evbuf); - else if (transport->default_event_handler) - transport->default_event_handler(&evbuf); - } -} - -static void AnodeSystemTransport__poll_do_read_stream(struct AnodeSystemTransport *transport,int fd,struct AnodeSystemTransport_AnodeSocket *sock) -{ - char buf[65536]; - AnodeEvent evbuf; - int n; - - n = recv(fd,buf,sizeof(buf),0); - if (n > 0) { - evbuf.type = ANODE_TRANSPORT_EVENT_STREAM_DATA_RECEIVED; - evbuf.transport = (AnodeTransport *)transport; - evbuf.sock = (AnodeSocket *)sock; - evbuf.datagram_from = NULL; - evbuf.dns_name = NULL; - evbuf.dns_addresses = NULL; - evbuf.dns_address_count = 0; - evbuf.error_code = 0; - evbuf.data_length = n; - evbuf.data = buf; - - if (sock->base.event_handler) - sock->base.event_handler(&evbuf); - else if (transport->default_event_handler) - transport->default_event_handler(&evbuf); - } else AnodeSystemTransport__do_close(transport,sock,ANODE_ERR_CONNECTION_CLOSED_BY_REMOTE,1); -} - -static void AnodeSystemTransport__poll_do_stream_available_for_write(struct AnodeSystemTransport *transport,int fd,struct AnodeSystemTransport_AnodeSocket *sock) -{ - AnodeEvent evbuf; - - evbuf.type = ANODE_TRANSPORT_EVENT_STREAM_DATA_RECEIVED; - evbuf.transport = (AnodeTransport *)transport; - evbuf.sock = (AnodeSocket *)sock; - evbuf.datagram_from = NULL; - evbuf.dns_name = NULL; - evbuf.dns_addresses = NULL; - evbuf.dns_address_count = 0; - evbuf.error_code = 0; - evbuf.data_length = 0; - evbuf.data = NULL; - - if (sock->base.event_handler) - sock->base.event_handler(&evbuf); - else if (transport->default_event_handler) - transport->default_event_handler(&evbuf); -} - -static void AnodeSystemTransport__poll_do_outgoing_connect(struct AnodeSystemTransport *transport,int fd,struct AnodeSystemTransport_AnodeSocket *sock) -{ - AnodeEvent evbuf; - int err_code; - socklen_t optlen; - - optlen = sizeof(err_code); - if (getsockopt(fd,SOL_SOCKET,SO_ERROR,(void *)&err_code,&optlen)) { - /* Error getting result, so we assume a failure */ - evbuf.type = ANODE_TRANSPORT_EVENT_STREAM_OUTGOING_CONNECT_FAILED; - evbuf.transport = (AnodeTransport *)transport; - evbuf.sock = (AnodeSocket *)sock; - evbuf.datagram_from = NULL; - evbuf.dns_name = NULL; - evbuf.dns_addresses = NULL; - evbuf.dns_address_count = 0; - evbuf.error_code = ANODE_ERR_CONNECT_FAILED; - evbuf.data_length = 0; - evbuf.data = NULL; - - AnodeSystemTransport__do_close(transport,sock,0,0); - } else if (err_code) { - /* Error code is nonzero, so connect failed */ - evbuf.type = ANODE_TRANSPORT_EVENT_STREAM_OUTGOING_CONNECT_FAILED; - evbuf.transport = (AnodeTransport *)transport; - evbuf.sock = (AnodeSocket *)sock; - evbuf.datagram_from = NULL; - evbuf.dns_name = NULL; - evbuf.dns_addresses = NULL; - evbuf.dns_address_count = 0; - evbuf.error_code = ANODE_ERR_CONNECT_FAILED; - evbuf.data_length = 0; - evbuf.data = NULL; - - AnodeSystemTransport__do_close(transport,sock,0,0); - } else { - /* Connect succeeded */ - evbuf.type = ANODE_TRANSPORT_EVENT_STREAM_OUTGOING_CONNECT_ESTABLISHED; - evbuf.transport = (AnodeTransport *)transport; - evbuf.sock = (AnodeSocket *)sock; - evbuf.datagram_from = NULL; - evbuf.dns_name = NULL; - evbuf.dns_addresses = NULL; - evbuf.dns_address_count = 0; - evbuf.error_code = 0; - evbuf.data_length = 0; - evbuf.data = NULL; - } - - if (sock->base.event_handler) - sock->base.event_handler(&evbuf); - else if (transport->default_event_handler) - transport->default_event_handler(&evbuf); -} - -static int AnodeSystemTransport_poll(AnodeTransport *transport) -{ - int timeout = -1; - unsigned int fd_idx; - int event_count = 0; - int n; - - if (poll((struct pollfd *)THIS->fds,THIS->fd_count,timeout) > 0) { - for(fd_idx=0;fd_idxfd_count;++fd_idx) { - if ((THIS->fds[fd_idx].revents & (POLLERR|POLLHUP|POLLNVAL))) { - if (THIS->sockets[fd_idx].base.type == ANODE_SOCKET_STREAM_CONNECTION) { - if (THIS->sockets[fd_idx].base.state == ANODE_SOCKET_CONNECTING) - AnodeSystemTransport__poll_do_outgoing_connect(THIS,THIS->fds[fd_idx].fd,&THIS->sockets[fd_idx]); - else AnodeSystemTransport__do_close(THIS,&THIS->sockets[fd_idx],ANODE_ERR_CONNECTION_CLOSED_BY_REMOTE,1); - ++event_count; - } - } else { - if ((THIS->fds[fd_idx].revents & POLLIN)) { - if (THIS->fds[fd_idx].fd == THIS->invoke_pipe[0]) { - n = read(THIS->invoke_pipe[0],&(((unsigned char *)(&(THIS->invoke_pipe_buf)))[THIS->invoke_pipe_buf_ptr]),sizeof(THIS->invoke_pipe_buf) - THIS->invoke_pipe_buf_ptr); - if (n > 0) { - THIS->invoke_pipe_buf_ptr += (unsigned int)n; - if (THIS->invoke_pipe_buf_ptr >= sizeof(THIS->invoke_pipe_buf)) { - THIS->invoke_pipe_buf_ptr -= sizeof(THIS->invoke_pipe_buf); - ((void (*)(void *))(THIS->invoke_pipe_buf[1]))(THIS->invoke_pipe_buf[0]); - } - } - } else { - switch(THIS->sockets[fd_idx].base.type) { - case ANODE_SOCKET_DATAGRAM: - AnodeSystemTransport__poll_do_read_datagram(THIS,THIS->fds[fd_idx].fd,&THIS->sockets[fd_idx]); - break; - case ANODE_SOCKET_STREAM_LISTEN: - AnodeSystemTransport__poll_do_accept_incoming_connection(THIS,THIS->fds[fd_idx].fd,&THIS->sockets[fd_idx]); - break; - case ANODE_SOCKET_STREAM_CONNECTION: - if (THIS->sockets[fd_idx].base.state == ANODE_SOCKET_CONNECTING) - AnodeSystemTransport__poll_do_outgoing_connect(THIS,THIS->fds[fd_idx].fd,&THIS->sockets[fd_idx]); - else AnodeSystemTransport__poll_do_read_stream(THIS,THIS->fds[fd_idx].fd,&THIS->sockets[fd_idx]); - break; - } - ++event_count; - } - } - - if ((THIS->fds[fd_idx].revents & POLLOUT)) { - if (THIS->sockets[fd_idx].base.state == ANODE_SOCKET_CONNECTING) - AnodeSystemTransport__poll_do_outgoing_connect(THIS,THIS->fds[fd_idx].fd,&THIS->sockets[fd_idx]); - else AnodeSystemTransport__poll_do_stream_available_for_write(THIS,THIS->fds[fd_idx].fd,&THIS->sockets[fd_idx]); - ++event_count; - } - } - } - } - - return event_count; -} - -static int AnodeSystemTransport_supports_address_type(const AnodeTransport *transport, - enum AnodeNetworkAddressType at) -{ - switch(at) { - case ANODE_NETWORK_ADDRESS_IPV4: - return 1; - case ANODE_NETWORK_ADDRESS_IPV6: - return 1; - default: - if (THIS->base) - return THIS->base->supports_address_type(THIS->base,at); - return 0; - } -} - -static AnodeTransport *AnodeSystemTransport_base_instance(const AnodeTransport *transport) -{ - return THIS->base; -} - -static const char *AnodeSystemTransport_class_name(AnodeTransport *transport) -{ - return AnodeSystemTransport_CLASS; -} - -static void AnodeSystemTransport_delete(AnodeTransport *transport) -{ - close(THIS->invoke_pipe[0]); - close(THIS->invoke_pipe[1]); - - AnodeMutex_destroy(&THIS->invoke_pipe_m); - - if (THIS->fds) free(THIS->fds); - if (THIS->sockets) free(THIS->sockets); - - if (THIS->base) THIS->base->delete(THIS->base); - - free(transport); -} - -/* ======================================================================== */ - -AnodeTransport *AnodeSystemTransport_new(AnodeTransport *base) -{ - struct AnodeSystemTransport *t; - unsigned int entry_idx; - - t = malloc(sizeof(struct AnodeSystemTransport)); - if (!t) return (AnodeTransport *)0; - Anode_zero(t,sizeof(struct AnodeSystemTransport)); - - t->interface.invoke = &AnodeSystemTransport_invoke; - t->interface.dns_resolve = &AnodeSystemTransport_dns_resolve; - t->interface.datagram_listen = &AnodeSystemTransport_datagram_listen; - t->interface.stream_listen = &AnodeSystemTransport_stream_listen; - t->interface.datagram_send = &AnodeSystemTransport_datagram_send; - t->interface.stream_connect = &AnodeSystemTransport_stream_connect; - t->interface.stream_start_writing = &AnodeSystemTransport_stream_start_writing; - t->interface.stream_stop_writing = &AnodeSystemTransport_stream_stop_writing; - t->interface.stream_send = &AnodeSystemTransport_stream_send; - t->interface.close = &AnodeSystemTransport_close; - t->interface.poll = &AnodeSystemTransport_poll; - t->interface.supports_address_type = &AnodeSystemTransport_supports_address_type; - t->interface.base_instance = &AnodeSystemTransport_base_instance; - t->interface.class_name = &AnodeSystemTransport_class_name; - t->interface.delete = &AnodeSystemTransport_delete; - - t->base = base; - - pipe(t->invoke_pipe); - fcntl(t->invoke_pipe[0],F_SETFL,O_NONBLOCK); - entry_idx = AnodeSystemTransport__add_entry(t); - t->fds[entry_idx].fd = t->invoke_pipe[0]; - t->fds[entry_idx].events = POLLIN; - t->fds[entry_idx].revents = 0; - AnodeMutex_init(&t->invoke_pipe_m); - - return (AnodeTransport *)t; -} diff --git a/attic/historic/anode/libanode/tests/Makefile b/attic/historic/anode/libanode/tests/Makefile deleted file mode 100644 index a479092c2..000000000 --- a/attic/historic/anode/libanode/tests/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -all: force clean anode-utils-test anode-zone-test aes-test ec-test - -aes-test: - gcc -Wall -O6 -ftree-vectorize -std=c99 -o aes-test aes-test.c ../aes_digest.c -lcrypto - -http_client-test: - gcc -O0 -g -std=c99 -o http_client-test http_client-test.c ../anode-utils.c ../misc.c ../http_client.c ../dictionary.c ../iptransport.c ../anode-transport.c -lcrypto - -anode-utils-test: - gcc -O0 -g -std=c99 -o anode-utils-test anode-utils-test.c ../anode-utils.c ../misc.c - -ec-test: - gcc -O0 -g -std=c99 -o ec-test ec-test.c ../impl/ec.c ../impl/misc.c -lcrypto - -anode-zone-test: - gcc -O0 -g -std=c99 -o anode-zone-test anode-zone-test.c ../anode-zone.c ../http_client.c ../dictionary.c ../misc.c ../anode-transport.c ../iptransport.c ../environment.c - -system_transport-test: - gcc -O0 -g -std=c99 -o system_transport-test system_transport-test.c ../system_transport.c ../network_address.c ../address.c ../aes_digest.c ../impl/misc.c ../impl/thread.c ../impl/dns_txt.c ../impl/aes.c -lresolv -lcrypto - -clean: force - rm -rf *.dSYM - rm -f http_client-test anode-utils-test anode-zone-test ec-test aes-test system_transport-test - -force: ; diff --git a/attic/historic/anode/libanode/tests/aes-test.c b/attic/historic/anode/libanode/tests/aes-test.c deleted file mode 100644 index bca63b892..000000000 --- a/attic/historic/anode/libanode/tests/aes-test.c +++ /dev/null @@ -1,191 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include -#include "../impl/aes.h" -#include "../anode.h" - -static const unsigned char AES_TEST_KEY[32] = { - 0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A, - 0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E -}; -static const unsigned char AES_TEST_IN[16] = { - 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21 -}; -static const unsigned char AES_TEST_OUT[16] = { - 0x08,0x0e,0x95,0x17,0xeb,0x16,0x77,0x71,0x9a,0xcf,0x72,0x80,0x86,0x04,0x0a,0xe3 -}; - -static const unsigned char CMAC_TEST_KEY[32] = { - 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, - 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 -}; - -static const unsigned char CMAC_TEST1_OUT[16] = { - 0x02,0x89,0x62,0xf6,0x1b,0x7b,0xf8,0x9e,0xfc,0x6b,0x55,0x1f,0x46,0x67,0xd9,0x83 -}; - -static const unsigned char CMAC_TEST2_IN[16] = { - 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a -}; -static const unsigned char CMAC_TEST2_OUT[16] = { - 0x28,0xa7,0x02,0x3f,0x45,0x2e,0x8f,0x82,0xbd,0x4b,0xf2,0x8d,0x8c,0x37,0xc3,0x5c -}; - -static const unsigned char CMAC_TEST3_IN[40] = { - 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, - 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, - 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11 -}; -static const unsigned char CMAC_TEST3_OUT[16] = { - 0xaa,0xf3,0xd8,0xf1,0xde,0x56,0x40,0xc2,0x32,0xf5,0xb1,0x69,0xb9,0xc9,0x11,0xe6 -}; - -static const unsigned char CMAC_TEST4_IN[64] = { - 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, - 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, - 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, - 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 -}; -static const unsigned char CMAC_TEST4_OUT[16] = { - 0xe1,0x99,0x21,0x90,0x54,0x9f,0x6e,0xd5,0x69,0x6a,0x2c,0x05,0x6c,0x31,0x54,0x10 -}; - -static void test_cmac(const AnodeAesExpandedKey *expkey,const unsigned char *in,unsigned int inlen,const unsigned char *expected) -{ - unsigned int i; - unsigned char out[16]; - - printf("Testing CMAC with %u byte input:\n",inlen); - printf(" IN: "); - for(i=0;i - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "../anode.h" -#include "../misc.h" - -int main(int argc,char **argv) -{ - unsigned char test[10005]; - unsigned int i; - AnodeSecureRandom srng; - - AnodeSecureRandom_init(&srng); - - AnodeSecureRandom_gen_bytes(&srng,test,sizeof(test)); - - for(i=0;i - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "../anode.h" -#include "../misc.h" - -static const char *testuris[22] = { - "http://www.test.com", - "http://www.test.com/", - "http://www.test.com/path/to/something", - "http://user@www.test.com", - "http://user@www.test.com/path/to/something", - "http://user:password@www.test.com/path/to/something", - "http://www.test.com/path/to/something?query=foo&bar=baz", - "http://www.test.com/path/to/something#fragment", - "http://www.test.com/path/to/something?query=foo&bar=baz#fragment", - "http://user:password@www.test.com/path/to/something#fragment", - "http://user:password@www.test.com/path/to/something?query=foo&bar=baz#fragment", - "http://@www.test.com/", - "http://:@www.test.com/", - "http://www.test.com:8080/path/to/something", - "http://user:password@www.test.com:8080/path/to/something?query=foo#fragment", - "http://", - "http://www.test.com/path/to/something?#", - "http://www.test.com/path/to/something?#fragment", - "http:", - "http", - "mailto:this_is_a_urn@somedomain.com", - "" -}; - -int main(int argc,char **argv) -{ - int i,r; - char reconstbuf[2048]; - char *reconst; - AnodeURI uri; - - for(i=0;i<22;++i) { - printf("\"%s\":\n",testuris[i]); - r = AnodeURI_parse(&uri,testuris[i]); - if (r) { - printf(" error: %d\n",r); - } else { - printf(" scheme: %s\n",uri.scheme); - printf(" username: %s\n",uri.username); - printf(" password: %s\n",uri.password); - printf(" host: %s\n",uri.host); - printf(" port: %d\n",uri.port); - printf(" path: %s\n",uri.path); - printf(" query: %s\n",uri.query); - printf(" fragment: %s\n",uri.fragment); - } - reconst = AnodeURI_to_string(&uri,reconstbuf,sizeof(reconstbuf)); - printf("Reconstituted URI: %s\n",reconst ? reconst : "(null)"); - printf("\n"); - } - - return 0; -} diff --git a/attic/historic/anode/libanode/tests/anode-zone-test.c b/attic/historic/anode/libanode/tests/anode-zone-test.c deleted file mode 100644 index 08396716c..000000000 --- a/attic/historic/anode/libanode/tests/anode-zone-test.c +++ /dev/null @@ -1,47 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include "../anode.h" -#include "../dictionary.h" - -static int got_it = 0; - -static void zone_lookup_handler(void *ptr,long zone_id,AnodeZone *zone) -{ - if (zone) - printf("got %.8lx: %d entries\n",(unsigned long)zone_id & 0xffffffff,((struct AnodeDictionary *)zone)->size); - else printf("failed.\n"); - got_it = 1; -} - -int main(int argc,char **argv) -{ - AnodeTransportEngine transport; - - Anode_init_ip_transport_engine(&transport); - - AnodeZone_lookup(&transport,0,0,&zone_lookup_handler); - - while (!got_it) - transport.poll(&transport); - - transport.destroy(&transport); - - return 0; -} diff --git a/attic/historic/anode/libanode/tests/dictionary-test.c b/attic/historic/anode/libanode/tests/dictionary-test.c deleted file mode 100644 index 12a5fb2fd..000000000 --- a/attic/historic/anode/libanode/tests/dictionary-test.c +++ /dev/null @@ -1,149 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include -#include "../dictionary.h" - -static const char *HASH_TESTS[16] = { - "test", - "testt", - "", - "foo", - "fooo", - "1", - "2", - "3", - "4", - "11", - "22", - "33", - "44", - "adklfjklejrer", - "erngnetbekjrq", - "erklerqqqqre" -}; - -int diterate(void *arg,const char *key,const char *value) -{ - printf(" %s: %s\n",key ? key : "(null)",value ? value : "(null)"); - return 1; -} - -int main(int argc,char **argv) -{ - char tmp[1024]; - char fuzzparam1[16],fuzzparam2[16],fuzzparam3[16]; - struct AnodeDictionary d; - unsigned int i,j,k,cs; - - srandom(time(0)); - - printf("Trying out hash function a little...\n"); - for(i=0;i<16;++i) - printf(" %s: %u\n",HASH_TESTS[i],(unsigned int)AnodeDictionary__get_bucket(HASH_TESTS[i])); - - for(cs=0;cs<2;++cs) { - printf("\nTesting with case sensitivity = %d\n",cs); - AnodeDictionary_init(&d,cs); - - printf("\nTesting dictionary by adding and retrieving some keys...\n"); - AnodeDictionary_put(&d,"test1","This is the first test"); - AnodeDictionary_put(&d,"test2","This is the second test"); - AnodeDictionary_put(&d,"test3","This is the third test (lower case)"); - AnodeDictionary_put(&d,"TEST3","This is the third test (UPPER CASE)"); - AnodeDictionary_iterate(&d,(void *)0,&diterate); - if (d.size != (cs ? 4 : 3)) { - printf("Failed (size).\n"); - return 1; - } - - AnodeDictionary_clear(&d); - if (d.size||(AnodeDictionary_get(&d,"test1"))) { - printf("Failed (clear).\n"); - return 1; - } - - printf("\nTesting read, trial 1: simple key=value with unterminated line\n"); - strcpy(tmp,"foo=bar\nbar=baz\ntest1=Happy happy joyjoy!\ntest2=foobarbaz\nlinewithnocr=thisworked"); - AnodeDictionary_read(&d,tmp,"\r\n","=","",'\\',0,0); - printf("Results:\n"); - AnodeDictionary_iterate(&d,(void *)0,&diterate); - AnodeDictionary_clear(&d); - - printf("\nTesting read, trial 2: key=value with escape chars, escaped CRs\n"); - strcpy(tmp,"foo=bar\r\nbar==baz\nte\\=st1=\\=Happy happy joyjoy!\ntest2=foobarbaz\\\nfoobarbaz on next line\r\n"); - AnodeDictionary_read(&d,tmp,"\r\n","=","",'\\',0,0); - printf("Results:\n"); - AnodeDictionary_iterate(&d,(void *)0,&diterate); - AnodeDictionary_clear(&d); - - printf("\nTesting read, trial 3: HTTP header-like dictionary\n"); - strcpy(tmp,"Host: some.host.net\r\nX-Some-Header: foo bar\r\nX-Some-Other-Header: y0y0y0y0y0\r\n"); - AnodeDictionary_read(&d,tmp,"\r\n",": ","",0,0,0); - printf("Results:\n"); - AnodeDictionary_iterate(&d,(void *)0,&diterate); - AnodeDictionary_clear(&d); - - printf("\nTesting read, trial 4: single line key/value\n"); - strcpy(tmp,"Header: one line only"); - AnodeDictionary_read(&d,tmp,"\r\n",": ","",0,0,0); - printf("Results:\n"); - AnodeDictionary_iterate(&d,(void *)0,&diterate); - AnodeDictionary_clear(&d); - - printf("\nFuzzing dictionary reader...\n"); fflush(stdout); - for(i=0;i<200000;++i) { - j = random() % (sizeof(tmp) - 1); - for(k=0;k> 3); - if (!tmp[k]) tmp[k] = 1; - } - tmp[j] = (char)0; - - j = random() % (sizeof(fuzzparam1) - 1); - for(k=0;k> 3); - if (!fuzzparam1[k]) fuzzparam1[k] = 1; - } - fuzzparam1[j] = (char)0; - - j = random() % (sizeof(fuzzparam2) - 1); - for(k=0;k> 3); - if (!fuzzparam2[k]) fuzzparam2[k] = 1; - } - fuzzparam2[j] = (char)0; - - j = random() % (sizeof(fuzzparam3) - 1); - for(k=0;k> 3); - if (!fuzzparam3[k]) fuzzparam3[k] = 1; - } - fuzzparam3[j] = (char)0; - - AnodeDictionary_read(&d,tmp,fuzzparam1,fuzzparam2,fuzzparam3,random() & 3,random() & 1,random() & 1); - AnodeDictionary_clear(&d); - } - - AnodeDictionary_destroy(&d); - } - - return 0; -} diff --git a/attic/historic/anode/libanode/tests/ec-test.c b/attic/historic/anode/libanode/tests/ec-test.c deleted file mode 100644 index 49f04265b..000000000 --- a/attic/historic/anode/libanode/tests/ec-test.c +++ /dev/null @@ -1,97 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include "../impl/ec.h" -#include "../impl/misc.h" - -#define TEST_KEY_LEN 128 -#define AnodeEC_key_to_hex(k,b,l) Anode_to_hex((k)->key,(k)->bytes,(b),l) - -int main(int argc,char **argv) -{ - struct AnodeECKeyPair pair1; - struct AnodeECKeyPair pair2; - struct AnodeECKeyPair pair3; - unsigned char key[TEST_KEY_LEN]; - char str[16384]; - - printf("Creating key pair #1...\n"); - if (!AnodeECKeyPair_generate(&pair1)) { - printf("Could not create key pair.\n"); - return 1; - } - AnodeEC_key_to_hex(&pair1.pub,str,sizeof(str)); - printf("Public: %s\n",str); - AnodeEC_key_to_hex(&pair1.priv,str,sizeof(str)); - printf("Private: %s\n\n",str); - - printf("Creating key pair #2...\n"); - if (!AnodeECKeyPair_generate(&pair2)) { - printf("Could not create key pair.\n"); - return 1; - } - AnodeEC_key_to_hex(&pair2.pub,str,sizeof(str)); - printf("Public: %s\n",str); - AnodeEC_key_to_hex(&pair2.priv,str,sizeof(str)); - printf("Private: %s\n\n",str); - - printf("Key agreement between public #2 and private #1...\n"); - if (!AnodeECKeyPair_agree(&pair1,&pair2.pub,key,TEST_KEY_LEN)) { - printf("Agreement failed.\n"); - return 1; - } - Anode_to_hex(key,TEST_KEY_LEN,str,sizeof(str)); - printf("Agreed secret: %s\n\n",str); - - printf("Key agreement between public #1 and private #2...\n"); - if (!AnodeECKeyPair_agree(&pair2,&pair1.pub,key,TEST_KEY_LEN)) { - printf("Agreement failed.\n"); - return 1; - } - Anode_to_hex(key,TEST_KEY_LEN,str,sizeof(str)); - printf("Agreed secret: %s\n\n",str); - - printf("Testing key pair init function (init #3 from #2's parts)...\n"); - if (!AnodeECKeyPair_init(&pair3,&(pair2.pub),&(pair2.priv))) { - printf("Init failed.\n"); - return 1; - } - - printf("Key agreement between public #1 and private #3...\n"); - if (!AnodeECKeyPair_agree(&pair3,&pair1.pub,key,TEST_KEY_LEN)) { - printf("Agreement failed.\n"); - return 1; - } - Anode_to_hex(key,TEST_KEY_LEN,str,sizeof(str)); - printf("Agreed secret: %s\n\n",str); - - printf("Key agreement between public #1 and private #1...\n"); - if (!AnodeECKeyPair_agree(&pair1,&pair1.pub,key,TEST_KEY_LEN)) { - printf("Agreement failed.\n"); - return 1; - } - Anode_to_hex(key,TEST_KEY_LEN,str,sizeof(str)); - printf("Agreed secret (should not match): %s\n\n",str); - - AnodeECKeyPair_destroy(&pair1); - AnodeECKeyPair_destroy(&pair2); - AnodeECKeyPair_destroy(&pair3); - - return 0; -} diff --git a/attic/historic/anode/libanode/tests/environment-test.c b/attic/historic/anode/libanode/tests/environment-test.c deleted file mode 100644 index c481a1296..000000000 --- a/attic/historic/anode/libanode/tests/environment-test.c +++ /dev/null @@ -1,28 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "../environment.h" - -int main(int argc,char **argv) -{ - const char *cache = Anode_get_cache(); - - printf("Cache folder: %s\n",cache ? cache : "(null)"); - - return 0; -} diff --git a/attic/historic/anode/libanode/tests/http_client-test.c b/attic/historic/anode/libanode/tests/http_client-test.c deleted file mode 100644 index e1f93967f..000000000 --- a/attic/historic/anode/libanode/tests/http_client-test.c +++ /dev/null @@ -1,233 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include "../anode.h" -#include "../misc.h" -#include "../http_client.h" -#include "../dictionary.h" - -struct TestCase -{ - int method; - AnodeURI uri; - const void *client_data; - unsigned int client_data_len; - const char *expected_sha1; - char actual_sha1[64]; - int got_it; - int keepalive; - struct TestCase *next; -}; - -#define NUM_TEST_CASES 7 -static struct TestCase test_cases[NUM_TEST_CASES]; - -static void init_test_cases(int keepalive) -{ - AnodeURI_parse(&(test_cases[0].uri),"http://zerotier.com/for_unit_tests/test1.txt"); - test_cases[0].method = ANODE_HTTP_GET; - test_cases[0].client_data_len = 0; - test_cases[0].expected_sha1 = "0828324174b10cc867b7255a84a8155cf89e1b8b"; - test_cases[0].actual_sha1[0] = (char)0; - test_cases[0].got_it = 0; - test_cases[0].keepalive = keepalive; - test_cases[0].next = &(test_cases[1]); - - AnodeURI_parse(&(test_cases[1].uri),"http://zerotier.com/for_unit_tests/test2.bin"); - test_cases[1].method = ANODE_HTTP_GET; - test_cases[1].client_data_len = 0; - test_cases[1].expected_sha1 = "6b67c635786ab52666211d02412c0d0f0372980d"; - test_cases[1].actual_sha1[0] = (char)0; - test_cases[1].got_it = 0; - test_cases[1].keepalive = keepalive; - test_cases[1].next = &(test_cases[2]); - - AnodeURI_parse(&(test_cases[2].uri),"http://zerotier.com/for_unit_tests/test3.bin"); - test_cases[2].method = ANODE_HTTP_GET; - test_cases[2].client_data_len = 0; - test_cases[2].expected_sha1 = "efa7722029fdbb6abd0e3ed32a0b44bfb982cff0"; - test_cases[2].actual_sha1[0] = (char)0; - test_cases[2].got_it = 0; - test_cases[2].keepalive = keepalive; - test_cases[2].next = &(test_cases[3]); - - AnodeURI_parse(&(test_cases[3].uri),"http://zerotier.com/for_unit_tests/test4.bin"); - test_cases[3].method = ANODE_HTTP_GET; - test_cases[3].client_data_len = 0; - test_cases[3].expected_sha1 = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; - test_cases[3].actual_sha1[0] = (char)0; - test_cases[3].got_it = 0; - test_cases[3].keepalive = keepalive; - test_cases[3].next = &(test_cases[4]); - - AnodeURI_parse(&(test_cases[4].uri),"http://zerotier.com/for_unit_tests/echo.php?echo=foobar"); - test_cases[4].method = ANODE_HTTP_GET; - test_cases[4].client_data_len = 0; - test_cases[4].expected_sha1 = "8843d7f92416211de9ebb963ff4ce28125932878"; - test_cases[4].actual_sha1[0] = (char)0; - test_cases[4].got_it = 0; - test_cases[4].keepalive = keepalive; - test_cases[4].next = &(test_cases[5]); - - AnodeURI_parse(&(test_cases[5].uri),"http://zerotier.com/for_unit_tests/echo.php"); - test_cases[5].method = ANODE_HTTP_POST; - test_cases[5].client_data = "echo=foobar"; - test_cases[5].client_data_len = strlen((char *)test_cases[5].client_data); - test_cases[5].expected_sha1 = "8843d7f92416211de9ebb963ff4ce28125932878"; - test_cases[5].actual_sha1[0] = (char)0; - test_cases[5].got_it = 0; - test_cases[5].keepalive = keepalive; - test_cases[5].next = &(test_cases[6]); - - AnodeURI_parse(&(test_cases[6].uri),"http://zerotier.com/for_unit_tests/test3.bin"); - test_cases[6].method = ANODE_HTTP_HEAD; - test_cases[6].client_data_len = 0; - test_cases[6].expected_sha1 = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; - test_cases[6].actual_sha1[0] = (char)0; - test_cases[6].got_it = 0; - test_cases[6].keepalive = keepalive; - test_cases[6].next = 0; -} - -static int http_handler_dump_headers(void *arg,const char *key,const char *value) -{ - printf(" H %s: %s\n",key,value); - return 1; -} - -static void http_handler(struct AnodeHttpClient *client) -{ - const char *method = "???"; - char buf[1024]; - unsigned char sha[20]; - struct TestCase *test = (struct TestCase *)client->ptr[0]; - - switch(client->method) { - case ANODE_HTTP_GET: - method = "GET"; - break; - case ANODE_HTTP_HEAD: - method = "HEAD"; - break; - case ANODE_HTTP_POST: - method = "POST"; - break; - } - - if (client->response.code == 200) { - SHA1((unsigned char *)client->response.data,client->response.data_length,sha); - Anode_to_hex(sha,20,test->actual_sha1,sizeof(test->actual_sha1)); - printf("%s %s\n * SHA1: %s exp: %s\n",method,AnodeURI_to_string(&(test->uri),buf,sizeof(buf)),test->actual_sha1,test->expected_sha1); - if (strcmp(test->actual_sha1,test->expected_sha1)) - printf(" ! SHA1 MISMATCH!\n"); - AnodeDictionary_iterate(&(client->response.headers),0,&http_handler_dump_headers); - } else printf("%s %s: ERROR: %d\n",method,AnodeURI_to_string(&(test->uri),buf,sizeof(buf)),client->response.code); - - test->got_it = 1; - - if (!test->keepalive) - AnodeHttpClient_free(client); - else { - test = test->next; - if (test) { - memcpy((void *)&(client->uri),(const void *)&(test->uri),sizeof(AnodeURI)); - - client->data = test->client_data; - client->data_length = test->client_data_len; - client->ptr[0] = test; - client->keepalive = test->keepalive; - client->method = test->method; - client->handler = &http_handler; - - AnodeHttpClient_send(client); - } else { - AnodeHttpClient_free(client); - } - } -} - -int main(int argc,char **argv) -{ - struct AnodeHttpClient *client; - AnodeTransportEngine transport_engine; - int i; - - if (Anode_init_ip_transport_engine(&transport_engine)) { - printf("Failed (transport engine init)\n"); - return 1; - } - - printf("Testing without keepalive...\n\n"); - init_test_cases(0); - for(i=0;iuri),(const void *)&(test_cases[i].uri),sizeof(AnodeURI)); - client->data = test_cases[i].client_data; - client->data_length = test_cases[i].client_data_len; - client->ptr[0] = &test_cases[i]; - client->keepalive = test_cases[i].keepalive; - client->method = test_cases[i].method; - client->handler = &http_handler; - - AnodeHttpClient_send(client); - } - - for(;;) { - for(i=0;iuri),(const void *)&(test_cases[i].uri),sizeof(AnodeURI)); - client->data = test_cases[i].client_data; - client->data_length = test_cases[i].client_data_len; - client->ptr[0] = &test_cases[i]; - client->keepalive = test_cases[i].keepalive; - client->method = test_cases[i].method; - client->handler = &http_handler; - - AnodeHttpClient_send(client); - - for(;;) { - for(i=0;i - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include -#include "../misc.h" - -int main(int argc,char **argv) -{ - const char *base32TestStr = "asdf"; - char *fields[16]; - char buf[1024]; - char buf2[1024]; - char buf3[4096]; - unsigned int i; - unsigned long tmpl,tmpl2; - unsigned long long tmp64; - - srand(time(0)); - - Anode_base32_5_to_8((const unsigned char *)base32TestStr,buf); - printf("Base32 from test string: %s\n",buf); - Anode_base32_8_to_5("MFZWIZQA",(unsigned char *)buf2); - printf("Test string from Base32 (upper case): %s\n",buf2); - Anode_base32_8_to_5("mfzwizqa",(unsigned char *)buf2); - printf("Test string from Base32 (lower case): %s\n",buf2); - printf("Testing variable length encoding/decoded with pad5 functions...\n"); - for(i=0;i<1024;++i) { - tmpl = rand() % (sizeof(buf) - 8); - if (!tmpl) - tmpl = 1; - for(tmpl2=0;tmpl2> 3)); - if (!Anode_base32_encode_pad5(buf2,tmpl,buf3,sizeof(buf3))) { - printf("Failed (encode failed).\n"); - return 1; - } - memset(buf2,0,sizeof(buf2)); - if (!Anode_base32_decode_pad5(buf3,buf2,sizeof(buf2))) { - printf("Failed (decode failed).\n"); - return 1; - } - if (memcmp(buf,buf2,tmpl)) { - printf("Failed (compare failed).\n"); - return 1; - } - } - - printf("Anode_htonll(0x0102030405060708) == 0x%.16llx\n",tmp64 = Anode_htonll(0x0102030405060708ULL)); - printf("Anode_ntohll(0x%.16llx) == 0x%.16llx\n",tmp64,Anode_ntohll(tmp64)); - if (Anode_ntohll(tmp64) != 0x0102030405060708ULL) { - printf("Failed.\n"); - return 1; - } - - strcpy(buf,"foo bar baz"); - Anode_trim(buf); - printf("Testing string trim: 'foo bar baz' -> '%s'\n",buf); - strcpy(buf,"foo bar baz "); - Anode_trim(buf); - printf("Testing string trim: 'foo bar baz ' -> '%s'\n",buf); - strcpy(buf," foo bar baz"); - Anode_trim(buf); - printf("Testing string trim: ' foo bar baz' -> '%s'\n",buf); - strcpy(buf," foo bar baz "); - Anode_trim(buf); - printf("Testing string trim: ' foo bar baz ' -> '%s'\n",buf); - strcpy(buf,""); - Anode_trim(buf); - printf("Testing string trim: '' -> '%s'\n",buf); - strcpy(buf," "); - Anode_trim(buf); - printf("Testing string trim: ' ' -> '%s'\n",buf); - - printf("Testing string split.\n"); - strcpy(buf,"66.246.138.121,5323,0"); - i = Anode_split(buf,';',fields,16); - if (i != 1) { - printf("Failed.\n"); - return 1; - } else printf("Fields: %s\n",fields[0]); - strcpy(buf,"a;b;c"); - i = Anode_split(buf,';',fields,16); - if (i != 3) { - printf("Failed.\n"); - return 1; - } else printf("Fields: %s %s %s\n",fields[0],fields[1],fields[2]); - strcpy(buf,";;"); - i = Anode_split(buf,';',fields,16); - if (i != 3) { - printf("Failed.\n"); - return 1; - } else printf("Fields: %s %s %s\n",fields[0],fields[1],fields[2]); - strcpy(buf,"a;b;"); - i = Anode_split(buf,';',fields,16); - if (i != 3) { - printf("Failed.\n"); - return 1; - } else printf("Fields: %s %s %s\n",fields[0],fields[1],fields[2]); - strcpy(buf,"a;;c"); - i = Anode_split(buf,';',fields,16); - if (i != 3) { - printf("Failed.\n"); - return 1; - } else printf("Fields: %s %s %s\n",fields[0],fields[1],fields[2]); - strcpy(buf,";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"); - i = Anode_split(buf,';',fields,16); - if (i != 16) { - printf("Failed.\n"); - return 1; - } - strcpy(buf,""); - i = Anode_split(buf,';',fields,16); - if (i != 0) { - printf("Failed.\n"); - return 1; - } - printf("Passed.\n"); - - return 0; -} diff --git a/attic/historic/anode/libanode/tests/system_transport-test.c b/attic/historic/anode/libanode/tests/system_transport-test.c deleted file mode 100644 index bda575ed8..000000000 --- a/attic/historic/anode/libanode/tests/system_transport-test.c +++ /dev/null @@ -1,70 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include "../anode.h" -#include "../impl/thread.h" - -static int do_client() -{ - AnodeTransport *st; - AnodeSocket *udp_sock; - int run = 1; - - st = AnodeSystemTransport_new(NULL); - if (!st) { - printf("FAILED: unable to construct AnodeSystemTransport.\n"); - return -1; - } - printf("Created AnodeSystemTransport.\n"); - - while (run) - st->poll(st); -} - -static int do_server() -{ - AnodeTransport *st; - AnodeSocket *udp_sock; - AnodeSocket *tcp_sock; - int run = 1; - - st = AnodeSystemTransport_new(NULL); - if (!st) { - printf("FAILED: unable to construct AnodeSystemTransport.\n"); - return -1; - } - printf("Created AnodeSystemTransport.\n"); - - while (run) - st->poll(st); -} - -int main(int argc,char **argv) -{ - if (argc == 2) { - if (!strcmp(argv[1],"client")) - return do_client(); - else if (!strcmp(argv[1],"server")) - return do_server(); - } - - printf("Usage: system_transport-test \n"); - return -1; -} diff --git a/attic/historic/anode/libanode/uri.c b/attic/historic/anode/libanode/uri.c deleted file mode 100644 index ca644b6aa..000000000 --- a/attic/historic/anode/libanode/uri.c +++ /dev/null @@ -1,185 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include "impl/misc.h" -#include "anode.h" - -int AnodeURI_parse(AnodeURI *parsed_uri,const char *uri_string) -{ - char buf[sizeof(AnodeURI)]; - unsigned long ptr = 0; - char c; - char *p1,*p2; - - Anode_zero((void *)parsed_uri,sizeof(AnodeURI)); - - /* Get the scheme */ - for(;;) { - c = *(uri_string++); - if (!c) { - parsed_uri->scheme[ptr] = (char)0; - return ANODE_ERR_INVALID_URI; - } else if (c == ':') { - parsed_uri->scheme[ptr] = (char)0; - break; - } else { - parsed_uri->scheme[ptr++] = c; - if (ptr == sizeof(parsed_uri->scheme)) - return ANODE_ERR_BUFFER_TOO_SMALL; - } - } - - if (*uri_string == '/') { - /* If it starts with /, it's a URL */ - - /* Skip double slash */ - if (!(*(++uri_string))) - return 0; /* Scheme with no path */ - if (*uri_string == '/') { - if (!(*(++uri_string))) - return 0; /* Scheme with no path */ - } - - /* Get the host section and put it in buf[] */ - ptr = 0; - while ((*uri_string)&&(*uri_string != '/')) { - buf[ptr++] = *(uri_string++); - if (ptr == sizeof(buf)) - return ANODE_ERR_BUFFER_TOO_SMALL; - } - buf[ptr] = (char)0; - - /* Parse host section for host, username, password, and port */ - if (buf[0]) { - p1 = (char *)Anode_strchr(buf,'@'); - if (p1) { - *(p1++) = (char)0; - if (*p1) { - p2 = (char *)Anode_strchr(buf,':'); - if (p2) { - *(p2++) = (char)0; - Anode_str_copy(parsed_uri->password,p2,sizeof(parsed_uri->password)); - } - Anode_str_copy(parsed_uri->username,buf,sizeof(parsed_uri->username)); - } else return ANODE_ERR_INVALID_URI; - } else p1 = buf; - - p2 = (char *)Anode_strchr(p1,':'); - if (p2) { - *(p2++) = (char)0; - if (*p2) - parsed_uri->port = (int)strtoul(p2,(char **)0,10); - } - Anode_str_copy(parsed_uri->host,p1,sizeof(parsed_uri->host)); - } - - /* Get the path, query, and fragment section and put it in buf[] */ - ptr = 0; - while ((buf[ptr++] = *(uri_string++))) { - if (ptr == sizeof(buf)) - return ANODE_ERR_BUFFER_TOO_SMALL; - } - - /* Parse path section for path, query, and fragment */ - if (buf[0]) { - p1 = (char *)Anode_strchr(buf,'?'); - if (p1) { - *(p1++) = (char)0; - p2 = (char *)Anode_strchr(p1,'#'); - if (p2) { - *(p2++) = (char)0; - Anode_str_copy(parsed_uri->fragment,p2,sizeof(parsed_uri->fragment)); - } - Anode_str_copy(parsed_uri->query,p1,sizeof(parsed_uri->query)); - } else { - p2 = (char *)Anode_strchr(buf,'#'); - if (p2) { - *(p2++) = (char)0; - Anode_str_copy(parsed_uri->fragment,p2,sizeof(parsed_uri->fragment)); - } - } - Anode_str_copy(parsed_uri->path,buf,sizeof(parsed_uri->path)); - } - } else { - /* Otherwise, it's a URN and what remains is all path */ - ptr = 0; - while ((parsed_uri->path[ptr++] = *(uri_string++))) { - if (ptr == sizeof(parsed_uri->path)) - return ANODE_ERR_BUFFER_TOO_SMALL; - } - } - - return 0; -} - -char *AnodeURI_to_string(const AnodeURI *uri,char *buf,int len) -{ - int i = 0; - char portbuf[16]; - const char *p; - - p = uri->scheme; - while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; } - - buf[i++] = ':'; if (i >= len) return (char *)0; - - if (uri->host[0]) { - buf[i++] = '/'; if (i >= len) return (char *)0; - buf[i++] = '/'; if (i >= len) return (char *)0; - - if (uri->username[0]) { - p = uri->username; - while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; } - if (uri->password[0]) { - buf[i++] = ':'; if (i >= len) return (char *)0; - p = uri->password; - while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; } - } - buf[i++] = '@'; if (i >= len) return (char *)0; - } - - p = uri->host; - while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; } - - if ((uri->port > 0)&&(uri->port <= 0xffff)) { - buf[i++] = ':'; if (i >= len) return (char *)0; - snprintf(portbuf,sizeof(portbuf),"%d",uri->port); - p = portbuf; - while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; } - } - } - - p = uri->path; - while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; } - - if (uri->query[0]) { - buf[i++] = '?'; if (i >= len) return (char *)0; - p = uri->query; - while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; } - } - - if (uri->fragment[0]) { - buf[i++] = '#'; if (i >= len) return (char *)0; - p = uri->fragment; - while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; } - } - - buf[i] = (char)0; - - return buf; -} diff --git a/attic/historic/anode/libanode/utils/anode-make-identity.c b/attic/historic/anode/libanode/utils/anode-make-identity.c deleted file mode 100644 index 99a3897a4..000000000 --- a/attic/historic/anode/libanode/utils/anode-make-identity.c +++ /dev/null @@ -1,50 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include "../anode.h" -#include "../impl/misc.h" -#include "../impl/types.h" - -int main(int argc,char **argv) -{ - char str[1024]; - AnodeZone zone; - AnodeIdentity identity; - - if (argc < 2) { - printf("Usage: anode-make-identity <32-bit zone ID hex>\n"); - return 0; - } - - *((uint32_t *)zone.bits) = htonl((uint32_t)strtoul(argv[1],(char **)0,16)); - - if (AnodeIdentity_generate(&identity,&zone,ANODE_ADDRESS_ANODE_256_40)) { - fprintf(stderr,"Error: identity key pair generation failed (check build settings).\n"); - return 1; - } - if (AnodeIdentity_to_string(&identity,str,sizeof(str)) <= 0) { - fprintf(stderr,"Error: internal error converting identity to string.\n"); - return -1; - } - - printf("%s\n",str); - - return 0; -} diff --git a/attic/historic/anode/libanode/zone.c b/attic/historic/anode/libanode/zone.c deleted file mode 100644 index a6e397ae8..000000000 --- a/attic/historic/anode/libanode/zone.c +++ /dev/null @@ -1,184 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009-2010 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#include -#include -#include -#include -#include -#include -#include "impl/types.h" -#include "impl/misc.h" -#include "impl/dictionary.h" -#include "impl/environment.h" -#include "impl/http_client.h" -#include "anode.h" - -static const char *_MONTHS[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; -static const char *_DAYS_OF_WEEK[7] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; -static inline unsigned long get_file_time_for_http(const char *path,char *buf,unsigned int len) -{ - struct stat st; - struct tm *gmt; - - if (!stat(path,(struct stat *)&st)) { - gmt = gmtime(&st.st_mtime); - if (gmt) { - snprintf(buf,len,"%s, %d %s %d %d:%d:%d GMT", - _DAYS_OF_WEEK[gmt->tm_wday], - gmt->tm_mday, - _MONTHS[gmt->tm_mon], - (1900 + gmt->tm_year), - gmt->tm_hour, - gmt->tm_min, - gmt->tm_sec); - buf[len - 1] = (char)0; - return (unsigned long)st.st_size; - } - } - - return 0; -} - -struct AnodeZoneLookupJob -{ - char cached_zone_file[2048]; - struct AnodeDictionary *zone_dict; - AnodeZone zone; - void *ptr; - void (*zone_lookup_handler)(void *,const AnodeZone *,AnodeZoneFile *); - int had_cached_zone; -}; - -static void AnodeZone_lookup_http_handler(struct AnodeHttpClient *client) -{ - char *data_tmp; - struct AnodeZoneLookupJob *job = (struct AnodeZoneLookupJob *)client->ptr[0]; - FILE *zf; - - if ((client->response.code == 200)&&(client->response.data_length > 0)) { - zf = fopen(job->cached_zone_file,"w"); - if (zf) { - fwrite(client->response.data,1,client->response.data_length,zf); - fclose(zf); - } - - data_tmp = (char *)malloc(client->response.data_length + 1); - Anode_memcpy((void *)data_tmp,client->response.data,client->response.data_length); - data_tmp[client->response.data_length] = (char)0; - - AnodeDictionary_clear(job->zone_dict); - AnodeDictionary_read( - job->zone_dict, - data_tmp, - "\r\n", - "=", - ";", - '\\', - 1,1); - - free((void *)data_tmp); - - job->zone_lookup_handler(job->ptr,&job->zone,(AnodeZoneFile *)job->zone_dict); - } else if (job->had_cached_zone) - job->zone_lookup_handler(job->ptr,&job->zone,(AnodeZoneFile *)job->zone_dict); - else { - AnodeDictionary_destroy(job->zone_dict); - free((void *)job->zone_dict); - job->zone_lookup_handler(job->ptr,&job->zone,(AnodeZoneFile *)0); - } - - free((void *)job); - AnodeHttpClient_free(client); -} - -void AnodeZone_lookup( - AnodeTransportEngine *transport, - const AnodeZone *zone, - void *ptr, - void (*zone_lookup_handler)(void *,const AnodeZone *,AnodeZone *)) -{ - char cached_zones_folder[2048]; - char cached_zone_file[2048]; - char if_modified_since[256]; - unsigned long file_size; - struct AnodeZoneLookupJob *job; - struct AnodeHttpClient *client; - char *file_data; - FILE *zf; - - if (Anode_get_cache_sub("zones",cached_zones_folder,sizeof(cached_zones_folder))) { - snprintf(cached_zone_file,sizeof(cached_zone_file),"%s%c%.2x%.2x%.2x%.2x.z",cached_zones_folder,ANODE_PATH_SEPARATOR,(unsigned int)zone->bits[0],(unsigned int)zone->bits[1],(unsigned int)zone->bits[2],(unsigned int)zone->bits[3]); - cached_zone_file[sizeof(cached_zone_file)-1] = (char)0; - - job = (struct AnodeZoneLookupJob *)malloc(sizeof(struct AnodeZoneLookupJob)); - Anode_str_copy(job->cached_zone_file,cached_zone_file,sizeof(job->cached_zone_file)); - job->zone_dict = (struct AnodeDictionary *)malloc(sizeof(struct AnodeDictionary)); - AnodeDictionary_init(job->zone_dict,0); - job->zone.bits[0] = zone->bits[0]; - job->zone.bits[1] = zone->bits[1]; - job->zone.bits[2] = zone->bits[2]; - job->zone.bits[3] = zone->bits[3]; - job->ptr = ptr; - job->zone_lookup_handler = zone_lookup_handler; - job->had_cached_zone = 0; - - client = AnodeHttpClient_new(transport); - - Anode_str_copy(client->uri.scheme,"http",sizeof(client->uri.scheme)); - snprintf(client->uri.host,sizeof(client->uri.host),"a--%.2x%.2x%.2x%.2x.net",(unsigned int)zone->bits[0],(unsigned int)zone->bits[1],(unsigned int)zone->bits[2],(unsigned int)zone->bits[3]); - client->uri.host[sizeof(client->uri.host)-1] = (char)0; - Anode_str_copy(client->uri.path,"/z",sizeof(client->uri.path)); - - client->handler = &AnodeZone_lookup_http_handler; - client->ptr[0] = job; - - if ((file_size = get_file_time_for_http(cached_zone_file,if_modified_since,sizeof(if_modified_since)))) { - zf = fopen(cached_zone_file,"r"); - if (zf) { - AnodeDictionary_put(&client->headers,"If-Modified-Since",if_modified_since); - file_data = (char *)malloc(file_size + 1); - if (fread((void *)file_data,1,file_size,zf)) { - file_data[file_size] = (char)0; - AnodeDictionary_read( - job->zone_dict, - file_data, - "\r\n", - "=", - ";", - '\\', - 1,1); - job->had_cached_zone = 1; - } - free((void *)file_data); - fclose(zf); - } - } - - AnodeHttpClient_send(client); - } else zone_lookup_handler(ptr,zone,(AnodeZone *)0); -} - -const char *AnodeZoneFile_get(AnodeZoneFile *zone,const char *key) -{ - return AnodeDictionary_get((struct AnodeDictionary *)zone,key); -} - -void AnodeZoneFile_free(AnodeZoneFile *zone) -{ - AnodeDictionary_destroy((struct AnodeDictionary *)zone); - free((void *)zone); -} diff --git a/attic/historic/anode/libspark/Makefile b/attic/historic/anode/libspark/Makefile deleted file mode 100644 index 0d3fedd87..000000000 --- a/attic/historic/anode/libspark/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -SYSNAME:=${shell uname} -SYSNAME!=uname -include ../config.mk.${SYSNAME} - -LIBSPARK_OBJS= - -all: libspark - -libspark: $(LIBSPARK_OBJS) - ar rcs libspark.a $(LIBSPARK_OBJS) - ranlib libspark.a - -clean: force - rm -f *.a *.so *.dylib *.dll *.lib *.exe *.o - -force: ; diff --git a/attic/historic/anode/libspark/experiments/FindGoodSegmentDelimiters.cpp b/attic/historic/anode/libspark/experiments/FindGoodSegmentDelimiters.cpp deleted file mode 100644 index 9b1ecaa15..000000000 --- a/attic/historic/anode/libspark/experiments/FindGoodSegmentDelimiters.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// Searches for good delimiters to cut streams into relatively well sized -// segments. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Desired size range -#define MIN_DESIRED_SIZE 4096 -#define MAX_DESIRED_SIZE 131072 - -#define DELIMITER_SET_SIZE 1 -typedef boost::array DelimArray; - -struct BestEntry -{ - DelimArray best; - double bestScore; - std::vector data; -}; - -boost::mutex bestLock; -boost::mutex outLock; -std::map best; - -static void runThread(const std::string &fileName) -{ - char tmp[4096]; - - boost::mt19937 prng; - { - boost::uint32_t seed; - FILE *ur = fopen("/dev/urandom","r"); - fread((void *)&seed,1,sizeof(seed),ur); - fclose(ur); - prng.seed(seed); - } - - BestEntry *myEntry; - { - boost::mutex::scoped_lock l(bestLock); - myEntry = &(best[fileName]); - myEntry->bestScore = 99999999.0; - } - - { - boost::mutex::scoped_lock l(outLock); - - std::cout << "*** Reading test data from: " << fileName << std::endl; - FILE *f = fopen(fileName.c_str(),"r"); - if (f) { - int n; - while ((n = fread((void *)tmp,1,sizeof(tmp),f)) > 0) { - for(int i=0;idata.push_back((unsigned char)tmp[i]); - } - fclose(f); - } - - if (myEntry->data.size() <= 0) { - std::cout << "Error: no data read." << std::endl; - exit(1); - } else std::cout << "*** Read " << myEntry->data.size() << " bytes of test data." << std::endl; - - std::cout.flush(); - } - - DelimArray current; - for(unsigned int i=0;i::iterator i=myEntry->data.begin();i!=myEntry->data.end();++i) { - shiftRegister <<= 1; - shiftRegister |= (((boost::uint32_t)*i) & 1); - - ++segSize; - - boost::uint16_t transformedShiftRegister = (boost::uint16_t)(shiftRegister); - - for(DelimArray::iterator d=current.begin();d!=current.end();++d) { - if (transformedShiftRegister == *d) { - if (segSize < MIN_DESIRED_SIZE) - ++numTooShort; - else if (segSize > MAX_DESIRED_SIZE) - ++numTooLong; - else ++numGood; - segSize = 0; - break; - } - } - } - if (segSize) { - if (segSize < MIN_DESIRED_SIZE) - ++numTooShort; - else if (segSize > MAX_DESIRED_SIZE) - ++numTooLong; - else ++numGood; - } - - if (numGood) { - double score = ((double)(numTooShort + numTooLong)) / ((double)numGood); - - if (score < myEntry->bestScore) { - myEntry->best = current; - myEntry->bestScore = score; - - boost::mutex::scoped_lock l(outLock); - - std::cout << fileName << ": "; - - for(DelimArray::iterator d=current.begin();d!=current.end();++d) { - sprintf(tmp,"0x%.4x",(unsigned int)*d); - if (d != current.begin()) - std::cout << ','; - std::cout << tmp; - } - - std::cout << ": " << numTooShort << " / " << numGood << " / " << numTooLong << " (" << score << ")" << std::endl; - std::cout.flush(); - - if ((numTooShort == 0)&&(numTooLong == 0)) - break; - } - } - - for(DelimArray::iterator i=current.begin();i!=current.end();++i) - *i = (boost::uint16_t)prng(); - } -} - -int main(int argc,char **argv) -{ - std::vector< boost::shared_ptr > threads; - - for(int i=1;i t(new boost::thread(boost::bind(&runThread,std::string(argv[i])))); - threads.push_back(t); - } - - for(std::vector< boost::shared_ptr >::iterator i=threads.begin();i!=threads.end();++i) - (*i)->join(); - - return 0; -} diff --git a/attic/historic/anode/libspark/experiments/Makefile b/attic/historic/anode/libspark/experiments/Makefile deleted file mode 100644 index 83aa4f67b..000000000 --- a/attic/historic/anode/libspark/experiments/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -all: - g++ -O6 -ftree-vectorize -o FindGoodSegmentDelimiters FindGoodSegmentDelimiters.cpp -lboost_thread -lpthread - -clean: - rm FindGoodSegmentDelimiters diff --git a/attic/historic/anode/libspark/streamencoder.h b/attic/historic/anode/libspark/streamencoder.h deleted file mode 100644 index b487ca402..000000000 --- a/attic/historic/anode/libspark/streamencoder.h +++ /dev/null @@ -1,108 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _SPARK_STREAMENCODER_H -#define _SPARK_STREAMENCODER_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - unsigned char *input_buf; - unsigned long input_buf_capacity; - unsigned long input_length; - - unsigned char *stream_out_buf; - unsigned long stream_out_buf_capacity; - unsigned long stream_out_length; - - void (*data_segment_add_func)(const void *data,unsigned long len,const void *global_hash,unsigned long global_hash_len); -} SparkStreamEncoder; - -/** - * Initialize a spark stream encoder - * - * @param enc Encoder structure to initialize - * @param data_segment_add_func Function to call to store or cache data - */ -void SparkStreamEncoder_init( - SparkStreamEncoder *enc, - void (*data_segment_add_func)( - const void *data, - unsigned long len, - const void *global_hash, - unsigned long global_hash_len)); - -/** - * Clean up a spark stream encoder structure - * - * @param enc Structure to clear - */ -void SparkStreamEncoder_destroy(SparkStreamEncoder *enc); - -/** - * Add data to encode - * - * @param enc Encoder structure - * @param data Data to encode - * @param len Length of data in bytes - * @return Number of bytes of result stream now available - */ -unsigned long SparkStreamEncoder_put( - SparkStreamEncoder *enc, - const void *data, - unsigned long len); - -/** - * Flush all data currently in input buffer - * - * @param enc Encoder structure to flush - */ -void SparkStreamEncoder_flush(SparkStreamEncoder *enc); - -/** - * @return Number of bytes of output stream available - */ -static inline unsigned long SparkStreamEncoder_available(SparkStreamEncoder *enc) -{ - return enc->stream_out_length; -} - -/** - * @return Pointer to result stream bytes (may return null if none available) - */ -static inline const void *SparkStreamEncoder_get(SparkStreamEncoder *enc) -{ - return (const void *)(enc->stream_out_buf); -} - -/** - * @return "Consume" result stream bytes after they're read or sent - */ -static inline void SparkStreamEncoder_consume(SparkStreamEncoder *enc,unsigned long len) -{ - unsigned long i; - for(i=len;istream_out_length;++i) - enc->stream_out_buf[i - len] = enc->stream_out_buf[i]; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/attic/historic/anode/libspark/wrapper.h b/attic/historic/anode/libspark/wrapper.h deleted file mode 100644 index eb8c593da..000000000 --- a/attic/historic/anode/libspark/wrapper.h +++ /dev/null @@ -1,66 +0,0 @@ -/* libanode: the Anode C reference implementation - * Copyright (C) 2009 Adam Ierymenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ - -#ifndef _SPARK_WRAPPER_H -#define _SPARK_WRAPPER_H - -#include -#include "../libanode/aes128.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Spark uses SHA-256 with hash length 32 */ -#define SPARK_HASH_LENGTH 32 - -// Wrap a segment for forward propagation -static inline void Spark_wrap(void *data,unsigned long len,void *plaintext_hash_buf,void *global_hash_buf) -{ - unsigned char expkey[ANODE_AES128_EXP_KEY_SIZE]; - - SHA256((const unsigned char *)data,len,(unsigned char *)plaintext_hash_buf); - - Anode_aes128_expand_key(expkey,(const unsigned char *)plaintext_hash_buf); - Anode_aes128_cfb_encrypt(expkey,((const unsigned char *)plaintext_hash_buf) + 16,(unsigned char *)data,len); - - SHA256((const unsigned char *)data,len,(unsigned char *)global_hash_buf); -} - -// Unwrap a segment and check its integrity -static inline int Spark_unwrap(void *data,unsigned long len,const void *plaintext_hash) -{ - unsigned char expkey[ANODE_AES128_EXP_KEY_SIZE]; - unsigned char check_hash[32]; - unsigned long i; - - Anode_aes128_expand_key(expkey,(const unsigned char *)plaintext_hash); - Anode_aes128_cfb_decrypt(expkey,((const unsigned char *)plaintext_hash) + 16,(unsigned char *)data,len); - - SHA256((const unsigned char *)data,len,check_hash); - - for(i=0;i<32;++i) { - if (check_hash[i] != ((const unsigned char *)plaintext_hash)[i]) - return 0; - } - return 1; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/attic/world/build.sh b/attic/world/build.sh deleted file mode 100755 index f3bcfabc9..000000000 --- a/attic/world/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -c++ -std=c++11 -I../.. -I../../ext -I.. -g -o mkworld ../../node/C25519.cpp ../../node/Salsa20.cpp ../../node/SHA512.cpp ../../node/Identity.cpp ../../node/Utils.cpp ../../node/InetAddress.cpp ../../osdep/OSUtils.cpp mkworld.cpp -lm diff --git a/attic/world/mkworld.cpp b/attic/world/mkworld.cpp deleted file mode 100644 index ed2c499a0..000000000 --- a/attic/world/mkworld.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This utility makes the World from the configuration specified below. - * It probably won't be much use to anyone outside ZeroTier, Inc. except - * for testing and experimentation purposes. - * - * If you want to make your own World you must edit this file. - * - * When run, it expects two files in the current directory: - * - * previous.c25519 - key pair to sign this world (key from previous world) - * current.c25519 - key pair whose public key should be embedded in this world - * - * If these files do not exist, they are both created with the same key pair - * and a self-signed initial World is born. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace ZeroTier; - -int main(int argc,char **argv) -{ - std::string previous,current; - if ((!OSUtils::readFile("previous.c25519",previous))||(!OSUtils::readFile("current.c25519",current))) { - ECC::Pair np(ECC::generate()); - previous = std::string(); - previous.append((const char *)np.pub.data,ZT_C25519_PUBLIC_KEY_LEN); - previous.append((const char *)np.priv.data,ZT_C25519_PRIVATE_KEY_LEN); - current = previous; - OSUtils::writeFile("previous.c25519",previous); - OSUtils::writeFile("current.c25519",current); - fprintf(stderr,"INFO: created initial world keys: previous.c25519 and current.c25519 (both initially the same)" ZT_EOL_S); - } - - if ((previous.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))||(current.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))) { - fprintf(stderr,"FATAL: previous.c25519 or current.c25519 empty or invalid" ZT_EOL_S); - return 1; - } - ECC::Pair previousKP; - memcpy(previousKP.pub.data,previous.data(),ZT_C25519_PUBLIC_KEY_LEN); - memcpy(previousKP.priv.data,previous.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN); - ECC::Pair currentKP; - memcpy(currentKP.pub.data,current.data(),ZT_C25519_PUBLIC_KEY_LEN); - memcpy(currentKP.priv.data,current.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN); - - // ========================================================================= - // EDIT BELOW HERE - - std::vector roots; - - const uint64_t id = ZT_WORLD_ID_EARTH; - const uint64_t ts = 1567191349589ULL; // August 30th, 2019 - - // Los Angeles - roots.push_back(World::Root()); - roots.back().identity = Identity("3a46f1bf30:0:76e66fab33e28549a62ee2064d1843273c2c300ba45c3f20bef02dbad225723bb59a9bb4b13535730961aeecf5a163ace477cceb0727025b99ac14a5166a09a3"); - roots.back().stableEndpoints.push_back(InetAddress("185.180.13.82/9993")); - roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c815::/9993")); - - // Miami - roots.push_back(World::Root()); - roots.back().identity = Identity("de8950a8b2:0:1b3ada8251b91b6b6fa6535b8c7e2460918f4f729abdec97d3c7f3796868fb02f0de0b0ee554b2d59fc3524743eebfcf5315e790ed6d92db5bd10c28c09b40ef"); - roots.back().stableEndpoints.push_back(InetAddress("207.246.73.245/443")); - roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:9002:5cb:ec4:7aff:fe8f:69d9/443")); - - // Tokyo - roots.push_back(World::Root()); - roots.back().identity = Identity("34e0a5e174:0:93efb50934788f856d5cfb9ca5be88e85b40965586b75befac900df77352c145a1ba7007569d37c77bfe52c0999f3bdc67a47a4a6000b720a883ce47aa2fb7f8"); - roots.back().stableEndpoints.push_back(InetAddress("147.75.92.2/443")); - roots.back().stableEndpoints.push_back(InetAddress("2604:1380:3000:7100::1/443")); - - // Amsterdam - roots.push_back(World::Root()); - roots.back().identity = Identity("992fcf1db7:0:206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c50af43322bcfc8e13d3301a1f1003ceb6"); - roots.back().stableEndpoints.push_back(InetAddress("195.181.173.159/443")); - roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c024::/443")); - - // Alice - //roots.push_back(World::Root()); - //roots.back().identity = Identity("9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e"); - //roots.back().stableEndpoints.push_back(InetAddress("188.166.94.177/9993")); // Amsterdam - //roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:2:d0::7d:1/9993")); // Amsterdam - //roots.back().stableEndpoints.push_back(InetAddress("154.66.197.33/9993")); // Johannesburg - //roots.back().stableEndpoints.push_back(InetAddress("2c0f:f850:154:197::33/9993")); // Johannesburg - //roots.back().stableEndpoints.push_back(InetAddress("159.203.97.171/9993")); // New York - //roots.back().stableEndpoints.push_back(InetAddress("2604:a880:800:a1::54:6001/9993")); // New York - //roots.back().stableEndpoints.push_back(InetAddress("131.255.6.16/9993")); // Buenos Aires - //roots.back().stableEndpoints.push_back(InetAddress("2803:eb80:0:e::2/9993")); // Buenos Aires - //roots.back().stableEndpoints.push_back(InetAddress("107.170.197.14/9993")); // San Francisco - //roots.back().stableEndpoints.push_back(InetAddress("2604:a880:1:20::200:e001/9993")); // San Francisco - //roots.back().stableEndpoints.push_back(InetAddress("128.199.197.217/9993")); // Singapore - //roots.back().stableEndpoints.push_back(InetAddress("2400:6180:0:d0::b7:4001/9993")); // Singapore - - // Bob - //roots.push_back(World::Root()); - //roots.back().identity = Identity("8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c"); - //roots.back().stableEndpoints.push_back(InetAddress("45.32.198.130/9993")); // Dallas - //roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6400:81c3:5400:00ff:fe18:1d61/9993")); // Dallas - //roots.back().stableEndpoints.push_back(InetAddress("46.101.160.249/9993")); // Frankfurt - //roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:3:d0::6a:3001/9993")); // Frankfurt - //roots.back().stableEndpoints.push_back(InetAddress("107.191.46.210/9993")); // Paris - //roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6800:83a4::64/9993")); // Paris - //roots.back().stableEndpoints.push_back(InetAddress("45.32.246.179/9993")); // Sydney - //roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:5800:8bf8:5400:ff:fe15:b39a/9993")); // Sydney - //roots.back().stableEndpoints.push_back(InetAddress("45.32.248.87/9993")); // Tokyo - //roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:7000:9bc9:5400:00ff:fe15:c4f5/9993")); // Tokyo - //roots.back().stableEndpoints.push_back(InetAddress("159.203.2.154/9993")); // Toronto - //roots.back().stableEndpoints.push_back(InetAddress("2604:a880:cad:d0::26:7001/9993")); // Toronto - - // END WORLD DEFINITION - // ========================================================================= - - fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu" ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts); - - World nw = World::make(World::TYPE_PLANET,id,ts,currentKP.pub,roots,previousKP); - - Buffer outtmp; - nw.serialize(outtmp,false); - World testw; - testw.deserialize(outtmp,0); - if (testw != nw) { - fprintf(stderr,"FATAL: serialization test failed!" ZT_EOL_S); - return 1; - } - - OSUtils::writeFile("world.bin",std::string((const char *)outtmp.data(),outtmp.size())); - fprintf(stderr,"INFO: world.bin written with %u bytes of binary world data." ZT_EOL_S,outtmp.size()); - - fprintf(stdout,ZT_EOL_S); - fprintf(stdout,"#define ZT_DEFAULT_WORLD_LENGTH %u" ZT_EOL_S,outtmp.size()); - fprintf(stdout,"static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {"); - for(unsigned int i=0;i 0) - fprintf(stdout,","); - fprintf(stdout,"0x%.2x",(unsigned int)d[i]); - } - fprintf(stdout,"};" ZT_EOL_S); - - return 0; -} diff --git a/attic/world/world.bin b/attic/world/world.bin deleted file mode 100644 index 88049ccdc..000000000 Binary files a/attic/world/world.bin and /dev/null differ diff --git a/attic/world/world.c b/attic/world/world.c deleted file mode 100644 index ecf30e6f0..000000000 --- a/attic/world/world.c +++ /dev/null @@ -1,3 +0,0 @@ - -#define ZT_DEFAULT_WORLD_LENGTH 732 -static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x6b,0xd4,0x16,0x08,0xc1,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x16,0x93,0xf4,0xe5,0xbd,0x20,0xda,0x10,0xad,0xc7,0x05,0xf4,0x99,0xfe,0x04,0x08,0x9b,0xe0,0x9e,0x77,0x1d,0x9f,0x47,0x16,0xaa,0x92,0x4f,0x10,0x16,0x3d,0xc7,0xec,0xd3,0x90,0x9e,0xd1,0x74,0xfc,0xb3,0xb5,0x07,0x9c,0x4d,0x95,0xc5,0x17,0x8b,0x3d,0x0b,0x60,0x76,0xe8,0x51,0xbb,0xb6,0x3d,0x74,0xb5,0x21,0x83,0x7b,0x95,0x1d,0x02,0x9b,0xcd,0xaf,0x5c,0x3e,0x96,0xdf,0x37,0x2c,0x56,0x6d,0xfa,0x75,0x0f,0xda,0x55,0x85,0x13,0xf4,0x76,0x1a,0x66,0x4d,0x3b,0x8d,0xcf,0x12,0xc9,0x34,0xb9,0x0d,0x61,0x03,0x3a,0x46,0xf1,0xbf,0x30,0x00,0x76,0xe6,0x6f,0xab,0x33,0xe2,0x85,0x49,0xa6,0x2e,0xe2,0x06,0x4d,0x18,0x43,0x27,0x3c,0x2c,0x30,0x0b,0xa4,0x5c,0x3f,0x20,0xbe,0xf0,0x2d,0xba,0xd2,0x25,0x72,0x3b,0xb5,0x9a,0x9b,0xb4,0xb1,0x35,0x35,0x73,0x09,0x61,0xae,0xec,0xf5,0xa1,0x63,0xac,0xe4,0x77,0xcc,0xeb,0x07,0x27,0x02,0x5b,0x99,0xac,0x14,0xa5,0x16,0x6a,0x09,0xa3,0x00,0x02,0x04,0xb9,0xb4,0x0d,0x52,0x27,0x09,0x06,0x2a,0x02,0x6e,0xa0,0xc8,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x09,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x7d,0x00,0x01,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x54,0x60,0x01,0x27,0x09,0x04,0x83,0xff,0x06,0x10,0x27,0x09,0x06,0x28,0x03,0xeb,0x80,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0xe0,0x01,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb7,0x40,0x01,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x6a,0x30,0x01,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x26,0x70,0x01,0x27,0x09}; diff --git a/ci/Dockerfile-build.deb b/ci/Dockerfile-build.deb deleted file mode 100644 index 09ed717f8..000000000 --- a/ci/Dockerfile-build.deb +++ /dev/null @@ -1,13 +0,0 @@ -ARG ZT_NAME -FROM 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-builder as builder -WORKDIR /work/build -COPY . . -RUN pwd -RUN ls -la . -RUN make clean -RUN make debian -RUN ls -ls /work - -FROM scratch AS export -ARG ZT_NAME -COPY --from=builder /work/*.deb ./${ZT_NAME}/ diff --git a/ci/Dockerfile-build.el6 b/ci/Dockerfile-build.el6 deleted file mode 100644 index c5848c984..000000000 --- a/ci/Dockerfile-build.el6 +++ /dev/null @@ -1,36 +0,0 @@ -ARG DOCKER_ARCH -FROM --platform=linux/${DOCKER_ARCH} alpine:edge AS builder - -RUN apk update -RUN apk add curl -RUN apk add bash -RUN apk add file -RUN apk add rust -RUN apk add cargo -RUN apk add make -RUN apk add cmake -RUN apk add clang -RUN apk add openssl-dev -RUN apk add linux-headers -RUN apk add build-base -RUN apk add openssl-libs-static - -COPY . . -RUN ZT_STATIC=1 make -RUN ls -la - -ARG DOCKER_ARCH -FROM --platform=linux/${DOCKER_ARCH} centos:6 AS stage -WORKDIR /root/rpmbuild/BUILD -COPY . . -COPY --from=builder zerotier-* ./ -RUN curl https://gist.githubusercontent.com/someara/b363002ba6e57b3c474dd027d4daef85/raw/4ac5534139752fc92fbe1a53599a390214f69615/el6%2520vault --output /etc/yum.repos.d/CentOS-Base.repo -RUN uname -a -RUN yum -y install make gcc rpm-build -RUN pwd -RUN ls -la -RUN make redhat - -FROM scratch AS export -ARG ZT_NAME -COPY --from=stage /root/rpmbuild/RPMS/*/*.rpm ./${ZT_NAME}/ diff --git a/ci/Dockerfile-build.rpm b/ci/Dockerfile-build.rpm deleted file mode 100644 index cab00a06d..000000000 --- a/ci/Dockerfile-build.rpm +++ /dev/null @@ -1,9 +0,0 @@ -ARG ZT_NAME -FROM 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-builder as builder -WORKDIR /root/rpmbuild/BUILD -COPY . . -RUN make redhat - -FROM scratch AS export -ARG ZT_NAME -COPY --from=builder /root/rpmbuild/RPMS/*/*.rpm ./${ZT_NAME}/ diff --git a/ci/Dockerfile-test.deb b/ci/Dockerfile-test.deb deleted file mode 100644 index 7c709a863..000000000 --- a/ci/Dockerfile-test.deb +++ /dev/null @@ -1,13 +0,0 @@ -ARG ZT_NAME -FROM 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-tester -ARG BASEURL -ARG VERSION -ARG DEB_ARCH -ARG ZT_NAME -ARG DISTRO -RUN curl -s http://${BASEURL}/key.gpg -o /etc/apt/trusted.gpg.d/zerotier.gpg -RUN echo "deb [arch=${DEB_ARCH} signed-by=/etc/apt/trusted.gpg.d/zerotier.gpg] http://${BASEURL}/${DISTRO} ${ZT_NAME} main" > /etc/apt/sources.list.d/zerotier.list -RUN apt-get -qq update -RUN apt-get -qq install zerotier-one=${VERSION} - -RUN ldd $(which zerotier-cli) diff --git a/ci/Dockerfile-test.el6 b/ci/Dockerfile-test.el6 deleted file mode 100644 index 499667313..000000000 --- a/ci/Dockerfile-test.el6 +++ /dev/null @@ -1,4 +0,0 @@ -ARG DOCKER_ARCH -FROM --platform=linux/${DOCKER_ARCH} centos:6 -RUN printf "[C6.10-base]\nname=CentOS-6.10 - Base\nbaseurl=http://vault.epel.cloud/6.10/os/\$basearch/\ngpgcheck=1\ngpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6\nenabled=1\nmetadata_expire=never\n" > /etc/yum.repos.d/CentOS-Base.repo -RUN yum -y install curl diff --git a/ci/Dockerfile-test.rpm b/ci/Dockerfile-test.rpm deleted file mode 100644 index 6a98607b9..000000000 --- a/ci/Dockerfile-test.rpm +++ /dev/null @@ -1,17 +0,0 @@ -ARG ZT_NAME -FROM 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-tester -ARG BASEURL -ARG VERSION -ARG DEB_ARCH -ARG ZT_NAME -ARG DISTRO -ARG DNF_ARCH -RUN curl -s http://${BASEURL}/key.asc -o /etc/pki/rpm-gpg/RPM-GPG-KEY-zerotier -RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-zerotier -RUN rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' -RUN printf "[zerotier]\nname=zerotier\nbaseurl=http://${BASEURL}/${DISTRO}/${ZT_NAME}/$basearch/\nenabled=1\ngpgcheck=1\ngpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-zerotier\n" > /etc/yum.repos.d/zerotier.repo - -# RUN yum -v repolist -RUN setarch ${DNF_ARCH} yum -y install zerotier-one-${VERSION} -RUN file $(which zerotier-cli) -RUN ldd $(which zerotier-cli) diff --git a/ci/scripts/build.sh b/ci/scripts/build.sh deleted file mode 100755 index a4b8ca94b..000000000 --- a/ci/scripts/build.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -set -euo pipefail -IFS=$'\n\t' - -ZT_NAME="$1" ; shift -DISTRO="$1" ; shift -ZT_ISA="$1" ; shift -VERSION="$1" ; shift -BUILD_EVENT="$1" ; shift - -source "$(dirname $0)/lib.sh" - -if [ -f "ci/Dockerfile-build.${ZT_NAME}" ]; then - DOCKERFILE="ci/Dockerfile-build.${ZT_NAME}" -else - DOCKERFILE="ci/Dockerfile-build.${PKGFMT}" -fi - -echo "#~~~~~~~~~~~~~~~~~~~~" -echo "$0 variables:" -echo "nproc: $(nproc)" -echo "ZT_NAME: ${ZT_NAME}" -echo "DISTRO: ${DISTRO}" -echo "ZT_ISA: ${ZT_ISA}" -echo "VERSION: ${VERSION}" -echo "BUILD_EVENT: ${BUILD_EVENT}" -echo "DOCKER_ARCH: ${DOCKER_ARCH}" -echo "DNF_ARCH: ${DNF_ARCH}" -echo "RUST_TRIPLET: ${RUST_TRIPLET}" -echo "PKGFMT: ${PKGFMT}" -echo "PWD: ${PWD}" -echo "DOCKERFILE: ${DOCKERFILE}" -echo "#~~~~~~~~~~~~~~~~~~~~" - -make munge_rpm zerotier-one.spec VERSION=${VERSION} -make munge_deb debian/changelog VERSION=${VERSION} - -docker buildx build \ - --no-cache=true \ - --build-arg ZT_NAME="${ZT_NAME}" \ - --build-arg RUST_TRIPLET="${RUST_TRIPLET}" \ - --build-arg DOCKER_ARCH="${DOCKER_ARCH}" \ - --build-arg DNF_ARCH="${DNF_ARCH}" \ - --platform linux/${DOCKER_ARCH} \ - -f ${DOCKERFILE} \ - -t build \ - . \ - --output type=local,dest=. \ - --target export diff --git a/ci/scripts/lib.sh b/ci/scripts/lib.sh deleted file mode 100755 index 43c35762b..000000000 --- a/ci/scripts/lib.sh +++ /dev/null @@ -1,63 +0,0 @@ - -case $ZT_NAME in - el*|fc*|amzn*) - export PKGFMT=rpm - ;; - *) - export PKGFMT=deb -esac - -case $ZT_ISA in - 386) - export DOCKER_ARCH=386 - export DEB_ARCH=i386 - export DNF_ARCH=i686 - export RUST_TRIPLET=i686-unknown-linux-gnu - ;; - amd64) - export DOCKER_ARCH=amd64 - export DEB_ARCH=amd64 - export DNF_ARCH=x86_64 - export RUST_TRIPLET=x86_64-unknown-linux-gnu - ;; - armv7) - export DOCKER_ARCH=arm/v7 - export DNF_ARCH=armv7 - export DEB_ARCH=armhf - export RUST_TRIPLET=armv7-unknown-linux-gnueabihf - ;; - arm64) - export DOCKER_ARCH=arm64/v8 - export DEB_ARCH=arm64 - export DNF_ARCH=linux64 - export RUST_TRIPLET=aarch64-unknown-linux-gnu - ;; - riscv64) - export DOCKER_ARCH=riscv64 - export DEB_ARCH=riscv64 - export DNF_ARCH=riscv64 - export RUST_TRIPLET=riscv64gc-unknown-linux-gnu - ;; - ppc64le) - export DOCKER_ARCH=ppc64le - export DEB_ARCH=ppc64el - export DNF_ARCH=ppc64le - export RUST_TRIPLET=powerpc64le-unknown-linux-gnu - ;; - mips64le) - export DOCKER_ARCH=mips64le - export DEB_ARCH=mips64le - export DNF_ARCH=mips64le - export RUST_TRIPLET=mips64el-unknown-linux-gnuabi64 - ;; - s390x) - export DOCKER_ARCH=s390x - export DEB_ARCH=s390x - export DNF_ARCH=s390x - export RUST_TRIPLET=s390x-unknown-linux-gnu - ;; - *) - echo "ERROR: could not determine architecture settings. PLEASE FIX ME" - exit 1 - ;; -esac diff --git a/ci/scripts/munge_debian_changelog.sh b/ci/scripts/munge_debian_changelog.sh deleted file mode 100755 index d37cb0638..000000000 --- a/ci/scripts/munge_debian_changelog.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -set -euo pipefail -IFS=$'\n\t' - -export FILE=$1 -export VERSION=$2 -export NAME=$3 -export MESSAGE=$4 -export DATE=$(date "+%a, %d %b %Y %T %z") -# export DATE=$(date "+%a %b %d %Y") - -set +e -grep --version | grep BSD &> /dev/null -if [ $? == 0 ]; then BSDGREP=true ; else BSDGREP=false ; fi -set -e - -# echo "#~~~~~~~~~~~~~~~~~~~~" -# echo "$0 variables:" -# echo "VERSION: ${VERSION}" -# echo "NAME: ${NAME}" -# echo "MESSAGE: ${MESSAGE}" -# echo "DATE: ${DATE}" -# echo "BSDGREP: ${BSDGREP}" -# echo "#~~~~~~~~~~~~~~~~~~~~" -# echo - -if $BSDGREP ; then - sed -i '' s/^Version:.*/"Version: ${VERSION}"/ ${FILE} -else - sed -i s/^Version:.*/"Version: ${VERSION}"/ ${FILE} -fi - -awk -v version=${VERSION} -v date=${DATE} -v name=${NAME} -v message=${MESSAGE} \ - 'BEGIN{print "zerotier-one (" version ") stable; urgency=medium\n\n * " message "\n\n -- " name " " date "\n" }{ print }' \ - ${FILE} > ${FILE}.new - -mv ${FILE}.new ${FILE} diff --git a/ci/scripts/munge_rpm_spec.sh b/ci/scripts/munge_rpm_spec.sh deleted file mode 100755 index 289df1ed4..000000000 --- a/ci/scripts/munge_rpm_spec.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash -set -euo pipefail -IFS=$'\n\t' - -export FILE=$1 -export VERSION=$2 -export NAME=$3 -export MESSAGE=$4 -export DATE=$(date "+%a %b %d %Y") - -set +e -grep --version | grep BSD &> /dev/null -if [ $? == 0 ]; then BSDGREP=true ; else BSDGREP=false ; fi -set -e - -# echo "#~~~~~~~~~~~~~~~~~~~~" -# echo "$0 variables:" -# echo "VERSION: ${VERSION}" -# echo "NAME: ${NAME}" -# echo "MESSAGE: ${MESSAGE}" -# echo "DATE: ${DATE}" -# echo "BSDGREP: ${BSDGREP}" -# echo "#~~~~~~~~~~~~~~~~~~~~" -# echo - -if $BSDGREP ; then - sed -i '' s/^Version:.*/"Version: ${VERSION}"/ ${FILE} -else - sed -i s/^Version:.*/"Version: ${VERSION}"/ ${FILE} -fi - -awk -v version=${VERSION} -v date=${DATE} -v name=${NAME} -v message=${MESSAGE} \ - 'FNR==NR{ if (/%changelog/) p=NR; next} 1; FNR==p{ print "* " date " " name " - " version "\n- " message "\n" }' \ - ${FILE} ${FILE} > ${FILE}.new - -mv ${FILE}.new ${FILE} diff --git a/ci/scripts/publish.sh b/ci/scripts/publish.sh deleted file mode 100755 index fa1e2468a..000000000 --- a/ci/scripts/publish.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -set -euo pipefail -IFS=$'\n\t' - -ZT_NAME="$1" ; shift -DISTRO="$1" ; shift -ZT_ISA="$1" ; shift -VERSION="$1" ; shift -BUILD_EVENT="$1" ; shift - -source "$(dirname $0)/lib.sh" - -if [ ${BUILD_EVENT} == "tag" ]; then - CHANNEL="zerotier-releases" -else - CHANNEL="zerotier-builds" -fi - -function publish_rpm { - mkdir -p /${CHANNEL}/${DISTRO} - ls -la /${CHANNEL} - ls -la . - cp -a ${ZT_NAME} /${CHANNEL}/${DISTRO} -} - -function publish_deb { - mkdir -p /${CHANNEL}/${DISTRO}/pool/dists/${ZT_NAME}/main - cp -a ${ZT_NAME}/* /${CHANNEL}/${DISTRO}/pool/dists/${ZT_NAME}/main -} - -case ${PKGFMT} in - "rpm") - publish_rpm - ;; - "deb") - publish_deb -esac - diff --git a/ci/scripts/test.sh b/ci/scripts/test.sh deleted file mode 100755 index 931e9bb91..000000000 --- a/ci/scripts/test.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash -set -euo pipefail -IFS=$'\n\t' - -ZT_NAME="$1" ; shift -DISTRO="$1" ; shift -ZT_ISA="$1" ; shift -VERSION="$1" ; shift -BUILD_EVENT="$1" ; shift - -source "$(dirname $0)/lib.sh" - -if [ -f "ci/Dockerfile-test.${ZT_NAME}" ]; then - DOCKERFILE="ci/Dockerfile-test.${ZT_NAME}" -else - DOCKERFILE="ci/Dockerfile-test.${PKGFMT}" -fi - -if [ ${BUILD_EVENT} == "tag" ]; then - BASEURL="zerotier-releases.home.arpa" -else - BASEURL="zerotier-builds.home.arpa" -fi - -echo "#~~~~~~~~~~~~~~~~~~~~" -echo "$0 variables:" -echo "nproc: $(nproc)" -echo "ZT_NAME: ${ZT_NAME}" -echo "DISTRO: ${DISTRO}" -echo "ZT_ISA: ${ZT_ISA}" -echo "VERSION: ${VERSION}" -echo "BUILD_EVENT: ${BUILD_EVENT}" -echo "DOCKER_ARCH: ${DOCKER_ARCH}" -echo "DNF_ARCH: ${DNF_ARCH}" -echo "RUST_TRIPLET: ${RUST_TRIPLET}" -echo "PKGFMT: ${PKGFMT}" -echo "PWD: ${PWD}" -echo "DOCKERFILE: ${DOCKERFILE}" -echo "#~~~~~~~~~~~~~~~~~~~~" - -# docker pull -q --platform="linux/${DOCKER_ARCH}" 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-tester - -docker buildx build \ - --build-arg BASEURL="${BASEURL}" \ - --build-arg ZT_NAME="${ZT_NAME}" \ - --build-arg DISTRO="${DISTRO}" \ - --build-arg DEB_ARCH="${DEB_ARCH}" \ - --build-arg DNF_ARCH="${DNF_ARCH}" \ - --build-arg VERSION="${VERSION}" \ - --build-arg DOCKER_ARCH="${DOCKER_ARCH}" \ - --platform "linux/${DOCKER_ARCH}" \ - --no-cache \ - -f ${DOCKERFILE} \ - -t test \ - . diff --git a/controller/CV1.cpp b/controller/CV1.cpp deleted file mode 100644 index 95d85a280..000000000 --- a/controller/CV1.cpp +++ /dev/null @@ -1,2092 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "CV1.hpp" - -#ifdef ZT_CONTROLLER_USE_LIBPQ - -#include "../node/Constants.hpp" -#include "../node/SHA512.hpp" -#include "../version.h" -#include "CtlUtil.hpp" -#include "EmbeddedNetworkController.hpp" -#include "Redis.hpp" -#include "opentelemetry/trace/provider.h" - -#include -#include -#include -#include -#include -#include - -// #define REDIS_TRACE 1 - -using json = nlohmann::json; - -namespace { - -static const int DB_MINIMUM_VERSION = 38; - -} // anonymous namespace - -using namespace ZeroTier; - -using Attrs = std::vector >; -using Item = std::pair; -using ItemStream = std::vector; - -CV1::CV1(const Identity& myId, const char* path, int listenPort, RedisConfig* rc) - : DB() - , _pool() - , _myId(myId) - , _myAddress(myId.address()) - , _ready(0) - , _connected(1) - , _run(1) - , _waitNoticePrinted(false) - , _listenPort(listenPort) - , _rc(rc) - , _redis(NULL) - , _cluster(NULL) - , _redisMemberStatus(false) - , _smee(NULL) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::CV1"); - auto scope = tracer->WithActiveSpan(span); - - char myAddress[64]; - _myAddressStr = myId.address().toString(myAddress); - _connString = std::string(path); - auto f = std::make_shared(_connString); - _pool = std::make_shared >(15, 5, std::static_pointer_cast(f)); - - memset(_ssoPsk, 0, sizeof(_ssoPsk)); - char* const ssoPskHex = getenv("ZT_SSO_PSK"); -#ifdef ZT_TRACE - fprintf(stderr, "ZT_SSO_PSK: %s\n", ssoPskHex); -#endif - if (ssoPskHex) { - // SECURITY: note that ssoPskHex will always be null-terminated if libc actually - // returns something non-NULL. If the hex encodes something shorter than 48 bytes, - // it will be padded at the end with zeroes. If longer, it'll be truncated. - Utils::unhex(ssoPskHex, _ssoPsk, sizeof(_ssoPsk)); - } - const char* redisMemberStatus = getenv("ZT_REDIS_MEMBER_STATUS"); - if (redisMemberStatus && (strcmp(redisMemberStatus, "true") == 0)) { - _redisMemberStatus = true; - fprintf(stderr, "Using redis for member status\n"); - } - - auto c = _pool->borrow(); - pqxx::work txn { *c->c }; - - pqxx::row r { txn.exec1("SELECT version FROM ztc_database") }; - int dbVersion = r[0].as(); - txn.commit(); - - if (dbVersion < DB_MINIMUM_VERSION) { - fprintf(stderr, "Central database schema version too low. This controller version requires a minimum schema version of %d. Please upgrade your Central instance", DB_MINIMUM_VERSION); - exit(1); - } - _pool->unborrow(c); - - if (_rc != NULL) { - auto innerspan = tracer->StartSpan("cv1::CV1::configureRedis"); - auto innerscope = tracer->WithActiveSpan(innerspan); - - sw::redis::ConnectionOptions opts; - sw::redis::ConnectionPoolOptions poolOpts; - opts.host = _rc->hostname; - opts.port = _rc->port; - opts.password = _rc->password; - opts.db = 0; - opts.keep_alive = true; - opts.connect_timeout = std::chrono::seconds(3); - poolOpts.size = 25; - poolOpts.wait_timeout = std::chrono::seconds(5); - poolOpts.connection_lifetime = std::chrono::minutes(3); - poolOpts.connection_idle_time = std::chrono::minutes(1); - if (_rc->clusterMode) { - innerspan->SetAttribute("cluster_mode", "true"); - fprintf(stderr, "Using Redis in Cluster Mode\n"); - _cluster = std::make_shared(opts, poolOpts); - } - else { - innerspan->SetAttribute("cluster_mode", "false"); - fprintf(stderr, "Using Redis in Standalone Mode\n"); - _redis = std::make_shared(opts, poolOpts); - } - } - - _readyLock.lock(); - - fprintf(stderr, "[%s] NOTICE: %.10llx controller PostgreSQL waiting for initial data download..." ZT_EOL_S, ::_timestr(), (unsigned long long)_myAddress.toInt()); - _waitNoticePrinted = true; - - initializeNetworks(); - initializeMembers(); - - _heartbeatThread = std::thread(&CV1::heartbeat, this); - _membersDbWatcher = std::thread(&CV1::membersDbWatcher, this); - _networksDbWatcher = std::thread(&CV1::networksDbWatcher, this); - for (int i = 0; i < ZT_CENTRAL_CONTROLLER_COMMIT_THREADS; ++i) { - _commitThread[i] = std::thread(&CV1::commitThread, this); - } - _onlineNotificationThread = std::thread(&CV1::onlineNotificationThread, this); - - configureSmee(); -} - -CV1::~CV1() -{ - if (_smee != NULL) { - smeeclient::smee_client_delete(_smee); - _smee = NULL; - } - - _run = 0; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - _heartbeatThread.join(); - _membersDbWatcher.join(); - _networksDbWatcher.join(); - _commitQueue.stop(); - for (int i = 0; i < ZT_CENTRAL_CONTROLLER_COMMIT_THREADS; ++i) { - _commitThread[i].join(); - } - _onlineNotificationThread.join(); -} - -void CV1::configureSmee() -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::configureSmee"); - auto scope = tracer->WithActiveSpan(span); - - const char* TEMPORAL_SCHEME = "ZT_TEMPORAL_SCHEME"; - const char* TEMPORAL_HOST = "ZT_TEMPORAL_HOST"; - const char* TEMPORAL_PORT = "ZT_TEMPORAL_PORT"; - const char* TEMPORAL_NAMESPACE = "ZT_TEMPORAL_NAMESPACE"; - const char* SMEE_TASK_QUEUE = "ZT_SMEE_TASK_QUEUE"; - - const char* scheme = getenv(TEMPORAL_SCHEME); - if (scheme == NULL) { - scheme = "http"; - } - const char* host = getenv(TEMPORAL_HOST); - const char* port = getenv(TEMPORAL_PORT); - const char* ns = getenv(TEMPORAL_NAMESPACE); - const char* task_queue = getenv(SMEE_TASK_QUEUE); - - if (scheme != NULL && host != NULL && port != NULL && ns != NULL && task_queue != NULL) { - fprintf(stderr, "creating smee client\n"); - std::string hostPort = std::string(scheme) + std::string("://") + std::string(host) + std::string(":") + std::string(port); - this->_smee = smeeclient::smee_client_new(hostPort.c_str(), ns, task_queue); - } - else { - fprintf(stderr, "Smee client not configured\n"); - } -} - -bool CV1::waitForReady() -{ - while (_ready < 2) { - _readyLock.lock(); - _readyLock.unlock(); - } - return true; -} - -bool CV1::isReady() -{ - return ((_ready == 2) && (_connected)); -} - -bool CV1::save(nlohmann::json& record, bool notifyListeners) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::save"); - auto scope = tracer->WithActiveSpan(span); - - bool modified = false; - try { - if (! record.is_object()) { - fprintf(stderr, "record is not an object?!?\n"); - return false; - } - const std::string objtype = record["objtype"]; - if (objtype == "network") { - // fprintf(stderr, "network save\n"); - const uint64_t nwid = OSUtils::jsonIntHex(record["id"], 0ULL); - if (nwid) { - nlohmann::json old; - get(nwid, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - _commitQueue.post(std::pair(record, notifyListeners)); - modified = true; - } - } - } - else if (objtype == "member") { - std::string networkId = record["nwid"]; - std::string memberId = record["id"]; - const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"], 0ULL); - const uint64_t id = OSUtils::jsonIntHex(record["id"], 0ULL); - // fprintf(stderr, "member save %s-%s\n", networkId.c_str(), memberId.c_str()); - if ((id) && (nwid)) { - nlohmann::json network, old; - get(nwid, network, id, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - // fprintf(stderr, "commit queue post\n"); - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - _commitQueue.post(std::pair(record, notifyListeners)); - modified = true; - } - else { - // fprintf(stderr, "no change\n"); - } - } - } - else { - fprintf(stderr, "uhh waaat\n"); - } - } - catch (std::exception& e) { - fprintf(stderr, "Error on PostgreSQL::save: %s\n", e.what()); - } - catch (...) { - fprintf(stderr, "Unknown error on PostgreSQL::save\n"); - } - return modified; -} - -void CV1::eraseNetwork(const uint64_t networkId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::eraseNetwork"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - - fprintf(stderr, "PostgreSQL::eraseNetwork\n"); - char tmp2[24]; - waitForReady(); - Utils::hex(networkId, tmp2); - std::pair tmp; - tmp.first["id"] = tmp2; - tmp.first["objtype"] = "_delete_network"; - tmp.second = true; - _commitQueue.post(tmp); - nlohmann::json nullJson; - _networkChanged(tmp.first, nullJson, true); -} - -void CV1::eraseMember(const uint64_t networkId, const uint64_t memberId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::eraseMember"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - - fprintf(stderr, "PostgreSQL::eraseMember\n"); - char tmp2[24]; - waitForReady(); - std::pair tmp, nw; - Utils::hex(networkId, tmp2); - tmp.first["nwid"] = tmp2; - Utils::hex(memberId, tmp2); - tmp.first["id"] = tmp2; - tmp.first["objtype"] = "_delete_member"; - tmp.second = true; - _commitQueue.post(tmp); - nlohmann::json nullJson; - _memberChanged(tmp.first, nullJson, true); -} - -void CV1::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::nodeIsOnline"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - char ipStr[INET6_ADDRSTRLEN]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - span->SetAttribute("physical_address", physicalAddress.toString(ipStr)); - span->SetAttribute("os_arch", osArch); - - std::lock_guard l(_lastOnline_l); - NodeOnlineRecord& i = _lastOnline[std::pair(networkId, memberId)]; - i.lastSeen = OSUtils::now(); - if (physicalAddress) { - i.physicalAddress = physicalAddress; - } - i.osArch = std::string(osArch); -} - -void CV1::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) -{ - this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown"); -} - -AuthInfo CV1::getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::getSSOAuthInfo"); - auto scope = tracer->WithActiveSpan(span); - - Metrics::db_get_sso_info++; - // NONCE is just a random character string. no semantic meaning - // state = HMAC SHA384 of Nonce based on shared sso key - // - // need nonce timeout in database? make sure it's used within X time - // X is 5 minutes for now. Make configurable later? - // - // how do we tell when a nonce is used? if auth_expiration_time is set - std::string networkId = member["nwid"]; - std::string memberId = member["id"]; - - char authenticationURL[4096] = { 0 }; - AuthInfo info; - info.enabled = true; - - // if (memberId == "a10dccea52" && networkId == "8056c2e21c24673d") { - // fprintf(stderr, "invalid authinfo for grant's machine\n"); - // info.version=1; - // return info; - // } - // fprintf(stderr, "PostgreSQL::updateMemberOnLoad: %s-%s\n", networkId.c_str(), memberId.c_str()); - std::shared_ptr c; - try { - c = _pool->borrow(); - pqxx::work w(*c->c); - - char nonceBytes[16] = { 0 }; - std::string nonce = ""; - - // check if the member exists first. - pqxx::row count = w.exec_params1("SELECT count(id) FROM ztc_member WHERE id = $1 AND network_id = $2 AND deleted = false", memberId, networkId); - if (count[0].as() == 1) { - // get active nonce, if exists. - pqxx::result r = w.exec_params( - "SELECT nonce FROM ztc_sso_expiry " - "WHERE network_id = $1 AND member_id = $2 " - "AND ((NOW() AT TIME ZONE 'UTC') <= authentication_expiry_time) AND ((NOW() AT TIME ZONE 'UTC') <= nonce_expiration)", - networkId, - memberId); - - if (r.size() == 0) { - // no active nonce. - // find an unused nonce, if one exists. - pqxx::result r = w.exec_params( - "SELECT nonce FROM ztc_sso_expiry " - "WHERE network_id = $1 AND member_id = $2 " - "AND authentication_expiry_time IS NULL AND ((NOW() AT TIME ZONE 'UTC') <= nonce_expiration)", - networkId, - memberId); - - if (r.size() == 1) { - // we have an existing nonce. Use it - nonce = r.at(0)[0].as(); - Utils::unhex(nonce.c_str(), nonceBytes, sizeof(nonceBytes)); - } - else if (r.empty()) { - // create a nonce - Utils::getSecureRandom(nonceBytes, 16); - char nonceBuf[64] = { 0 }; - Utils::hex(nonceBytes, sizeof(nonceBytes), nonceBuf); - nonce = std::string(nonceBuf); - - pqxx::result ir = w.exec_params0( - "INSERT INTO ztc_sso_expiry " - "(nonce, nonce_expiration, network_id, member_id) VALUES " - "($1, TO_TIMESTAMP($2::double precision/1000), $3, $4)", - nonce, - OSUtils::now() + 300000, - networkId, - memberId); - - w.commit(); - } - else { - // > 1 ?!? Thats an error! - fprintf(stderr, "> 1 unused nonce!\n"); - exit(6); - } - } - else if (r.size() == 1) { - nonce = r.at(0)[0].as(); - Utils::unhex(nonce.c_str(), nonceBytes, sizeof(nonceBytes)); - } - else { - // more than 1 nonce in use? Uhhh... - fprintf(stderr, "> 1 nonce in use for network member?!?\n"); - exit(7); - } - - r = w.exec_params( - "SELECT oc.client_id, oc.authorization_endpoint, oc.issuer, oc.provider, oc.sso_impl_version " - "FROM ztc_network AS n " - "INNER JOIN ztc_org o " - " ON o.owner_id = n.owner_id " - "LEFT OUTER JOIN ztc_network_oidc_config noc " - " ON noc.network_id = n.id " - "LEFT OUTER JOIN ztc_oidc_config oc " - " ON noc.client_id = oc.client_id AND oc.org_id = o.org_id " - "WHERE n.id = $1 AND n.sso_enabled = true", - networkId); - - std::string client_id = ""; - std::string authorization_endpoint = ""; - std::string issuer = ""; - std::string provider = ""; - uint64_t sso_version = 0; - - if (r.size() == 1) { - client_id = r.at(0)[0].as >().value_or(""); - authorization_endpoint = r.at(0)[1].as >().value_or(""); - issuer = r.at(0)[2].as >().value_or(""); - provider = r.at(0)[3].as >().value_or(""); - sso_version = r.at(0)[4].as >().value_or(1); - } - else if (r.size() > 1) { - fprintf(stderr, "ERROR: More than one auth endpoint for an organization?!?!? NetworkID: %s\n", networkId.c_str()); - } - else { - fprintf(stderr, "No client or auth endpoint?!?\n"); - } - - info.version = sso_version; - - // no catch all else because we don't actually care if no records exist here. just continue as normal. - if ((! client_id.empty()) && (! authorization_endpoint.empty())) { - uint8_t state[48]; - HMACSHA384(_ssoPsk, nonceBytes, sizeof(nonceBytes), state); - char state_hex[256]; - Utils::hex(state, 48, state_hex); - - if (info.version == 0) { - char url[2048] = { 0 }; - OSUtils::ztsnprintf( - url, - sizeof(authenticationURL), - "%s?response_type=id_token&response_mode=form_post&scope=openid+email+profile&redirect_uri=%s&nonce=%s&state=%s&client_id=%s", - authorization_endpoint.c_str(), - url_encode(redirectURL).c_str(), - nonce.c_str(), - state_hex, - client_id.c_str()); - info.authenticationURL = std::string(url); - } - else if (info.version == 1) { - info.ssoClientID = client_id; - info.issuerURL = issuer; - info.ssoProvider = provider; - info.ssoNonce = nonce; - info.ssoState = std::string(state_hex) + "_" + networkId; - info.centralAuthURL = redirectURL; -#ifdef ZT_DEBUG - fprintf( - stderr, - "ssoClientID: %s\nissuerURL: %s\nssoNonce: %s\nssoState: %s\ncentralAuthURL: %s\nprovider: %s\n", - info.ssoClientID.c_str(), - info.issuerURL.c_str(), - info.ssoNonce.c_str(), - info.ssoState.c_str(), - info.centralAuthURL.c_str(), - provider.c_str()); -#endif - } - } - else { - fprintf(stderr, "client_id: %s\nauthorization_endpoint: %s\n", client_id.c_str(), authorization_endpoint.c_str()); - } - } - - _pool->unborrow(c); - } - catch (std::exception& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "ERROR: Error updating member on load for network %s: %s\n", networkId.c_str(), e.what()); - } - - return info; // std::string(authenticationURL); -} - -void CV1::initializeNetworks() -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::initializeNetworks"); - auto scope = tracer->WithActiveSpan(span); - - try { - std::string setKey = "networks:{" + _myAddressStr + "}"; - - fprintf(stderr, "Initializing Networks...\n"); - - if (_redisMemberStatus) { - fprintf(stderr, "Init Redis for networks...\n"); - try { - if (_rc->clusterMode) { - _cluster->del(setKey); - } - else { - _redis->del(setKey); - } - } - catch (sw::redis::Error& e) { - // ignore. if this key doesn't exist, there's no reason to delete it - } - } - - std::unordered_set networkSet; - - char qbuf[2048] = { 0 }; - sprintf( - qbuf, - "SELECT n.id, (EXTRACT(EPOCH FROM n.creation_time AT TIME ZONE 'UTC')*1000)::bigint as creation_time, n.capabilities, " - "n.enable_broadcast, (EXTRACT(EPOCH FROM n.last_modified AT TIME ZONE 'UTC')*1000)::bigint AS last_modified, n.mtu, n.multicast_limit, n.name, n.private, n.remote_trace_level, " - "n.remote_trace_target, n.revision, n.rules, n.tags, n.v4_assign_mode, n.v6_assign_mode, n.sso_enabled, (CASE WHEN n.sso_enabled THEN noc.client_id ELSE NULL END) as client_id, " - "(CASE WHEN n.sso_enabled THEN oc.authorization_endpoint ELSE NULL END) as authorization_endpoint, " - "(CASE WHEN n.sso_enabled THEN oc.provider ELSE NULL END) as provider, d.domain, d.servers, " - "ARRAY(SELECT CONCAT(host(ip_range_start),'|', host(ip_range_end)) FROM ztc_network_assignment_pool WHERE network_id = n.id) AS assignment_pool, " - "ARRAY(SELECT CONCAT(host(address),'/',bits::text,'|',COALESCE(host(via), 'NULL'))FROM ztc_network_route WHERE network_id = n.id) AS routes " - "FROM ztc_network n " - "LEFT OUTER JOIN ztc_org o " - " ON o.owner_id = n.owner_id " - "LEFT OUTER JOIN ztc_network_oidc_config noc " - " ON noc.network_id = n.id " - "LEFT OUTER JOIN ztc_oidc_config oc " - " ON noc.client_id = oc.client_id AND oc.org_id = o.org_id " - "LEFT OUTER JOIN ztc_network_dns d " - " ON d.network_id = n.id " - "WHERE deleted = false AND controller_id = '%s'", - _myAddressStr.c_str()); - auto c = _pool->borrow(); - auto c2 = _pool->borrow(); - pqxx::work w { *c->c }; - - fprintf(stderr, "Load networks from psql...\n"); - auto stream = pqxx::stream_from::query(w, qbuf); - - std::tuple< - std::string // network ID - , - std::optional // creationTime - , - std::optional // capabilities - , - std::optional // enableBroadcast - , - std::optional // lastModified - , - std::optional // mtu - , - std::optional // multicastLimit - , - std::optional // name - , - bool // private - , - std::optional // remoteTraceLevel - , - std::optional // remoteTraceTarget - , - std::optional // revision - , - std::optional // rules - , - std::optional // tags - , - std::optional // v4AssignMode - , - std::optional // v6AssignMode - , - std::optional // ssoEnabled - , - std::optional // clientId - , - std::optional // authorizationEndpoint - , - std::optional // ssoProvider - , - std::optional // domain - , - std::optional // servers - , - std::string // assignmentPoolString - , - std::string // routeString - > - row; - - uint64_t count = 0; - auto tmp = std::chrono::high_resolution_clock::now(); - uint64_t total = 0; - while (stream >> row) { - auto start = std::chrono::high_resolution_clock::now(); - - json empty; - json config; - - initNetwork(config); - - std::string nwid = std::get<0>(row); - std::optional creationTime = std::get<1>(row); - std::optional capabilities = std::get<2>(row); - std::optional enableBroadcast = std::get<3>(row); - std::optional lastModified = std::get<4>(row); - std::optional mtu = std::get<5>(row); - std::optional multicastLimit = std::get<6>(row); - std::optional name = std::get<7>(row); - bool isPrivate = std::get<8>(row); - std::optional remoteTraceLevel = std::get<9>(row); - std::optional remoteTraceTarget = std::get<10>(row); - std::optional revision = std::get<11>(row); - std::optional rules = std::get<12>(row); - std::optional tags = std::get<13>(row); - std::optional v4AssignMode = std::get<14>(row); - std::optional v6AssignMode = std::get<15>(row); - std::optional ssoEnabled = std::get<16>(row); - std::optional clientId = std::get<17>(row); - std::optional authorizationEndpoint = std::get<18>(row); - std::optional ssoProvider = std::get<19>(row); - std::optional dnsDomain = std::get<20>(row); - std::optional dnsServers = std::get<21>(row); - std::string assignmentPoolString = std::get<22>(row); - std::string routesString = std::get<23>(row); - - config["id"] = nwid; - config["nwid"] = nwid; - config["creationTime"] = creationTime.value_or(0); - config["capabilities"] = json::parse(capabilities.value_or("[]")); - config["enableBroadcast"] = enableBroadcast.value_or(false); - config["lastModified"] = lastModified.value_or(0); - config["mtu"] = mtu.value_or(2800); - config["multicastLimit"] = multicastLimit.value_or(64); - config["name"] = name.value_or(""); - config["private"] = isPrivate; - config["remoteTraceLevel"] = remoteTraceLevel.value_or(0); - config["remoteTraceTarget"] = remoteTraceTarget.value_or(""); - config["revision"] = revision.value_or(0); - config["rules"] = json::parse(rules.value_or("[]")); - config["tags"] = json::parse(tags.value_or("[]")); - config["v4AssignMode"] = json::parse(v4AssignMode.value_or("{}")); - config["v6AssignMode"] = json::parse(v6AssignMode.value_or("{}")); - config["ssoEnabled"] = ssoEnabled.value_or(false); - config["objtype"] = "network"; - config["ipAssignmentPools"] = json::array(); - config["routes"] = json::array(); - config["clientId"] = clientId.value_or(""); - config["authorizationEndpoint"] = authorizationEndpoint.value_or(""); - config["provider"] = ssoProvider.value_or(""); - - networkSet.insert(nwid); - - if (dnsDomain.has_value()) { - std::string serverList = dnsServers.value(); - json obj; - auto servers = json::array(); - if (serverList.rfind("{", 0) != std::string::npos) { - serverList = serverList.substr(1, serverList.size() - 2); - std::stringstream ss(serverList); - while (ss.good()) { - std::string server; - std::getline(ss, server, ','); - servers.push_back(server); - } - } - obj["domain"] = dnsDomain.value(); - obj["servers"] = servers; - config["dns"] = obj; - } - - config["ipAssignmentPools"] = json::array(); - if (assignmentPoolString != "{}") { - std::string tmp = assignmentPoolString.substr(1, assignmentPoolString.size() - 2); - std::vector assignmentPools = split(tmp, ','); - for (auto it = assignmentPools.begin(); it != assignmentPools.end(); ++it) { - std::vector r = split(*it, '|'); - json ip; - ip["ipRangeStart"] = r[0]; - ip["ipRangeEnd"] = r[1]; - config["ipAssignmentPools"].push_back(ip); - } - } - - config["routes"] = json::array(); - if (routesString != "{}") { - std::string tmp = routesString.substr(1, routesString.size() - 2); - std::vector routes = split(tmp, ','); - for (auto it = routes.begin(); it != routes.end(); ++it) { - std::vector r = split(*it, '|'); - json route; - route["target"] = r[0]; - route["via"] = ((route["via"] == "NULL") ? nullptr : r[1]); - config["routes"].push_back(route); - } - } - - Metrics::network_count++; - - _networkChanged(empty, config, false); - - auto end = std::chrono::high_resolution_clock::now(); - auto dur = std::chrono::duration_cast(end - start); - ; - total += dur.count(); - ++count; - if (count > 0 && count % 10000 == 0) { - fprintf(stderr, "Averaging %llu us per network\n", (total / count)); - } - } - - if (count > 0) { - fprintf(stderr, "Took %llu us per network to load\n", (total / count)); - } - stream.complete(); - - w.commit(); - _pool->unborrow(c2); - _pool->unborrow(c); - fprintf(stderr, "done.\n"); - - if (! networkSet.empty()) { - if (_redisMemberStatus) { - fprintf(stderr, "adding networks to redis...\n"); - if (_rc->clusterMode) { - auto tx = _cluster->transaction(_myAddressStr, true, false); - uint64_t count = 0; - for (std::string nwid : networkSet) { - tx.sadd(setKey, nwid); - if (++count % 30000 == 0) { - tx.exec(); - tx = _cluster->transaction(_myAddressStr, true, false); - } - } - tx.exec(); - } - else { - auto tx = _redis->transaction(true, false); - uint64_t count = 0; - for (std::string nwid : networkSet) { - tx.sadd(setKey, nwid); - if (++count % 30000 == 0) { - tx.exec(); - tx = _redis->transaction(true, false); - } - } - tx.exec(); - } - fprintf(stderr, "done.\n"); - } - } - - if (++this->_ready == 2) { - if (_waitNoticePrinted) { - fprintf(stderr, "[%s] NOTICE: %.10llx controller PostgreSQL data download complete." ZT_EOL_S, _timestr(), (unsigned long long)_myAddress.toInt()); - } - _readyLock.unlock(); - } - fprintf(stderr, "network init done.\n"); - } - catch (sw::redis::Error& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "ERROR: Error initializing networks in Redis: %s\n", e.what()); - std::this_thread::sleep_for(std::chrono::milliseconds(5000)); - exit(-1); - } - catch (std::exception& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "ERROR: Error initializing networks: %s\n", e.what()); - std::this_thread::sleep_for(std::chrono::milliseconds(5000)); - exit(-1); - } -} - -void CV1::initializeMembers() -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::initializeMembers"); - auto scope = tracer->WithActiveSpan(span); - - std::string memberId; - std::string networkId; - try { - std::unordered_map networkMembers; - fprintf(stderr, "Initializing Members...\n"); - - std::string setKeyBase = "network-nodes-all:{" + _myAddressStr + "}:"; - - if (_redisMemberStatus) { - fprintf(stderr, "Initialize Redis for members...\n"); - std::unique_lock l(_networks_l); - std::unordered_set deletes; - for (auto it : _networks) { - uint64_t nwid_i = it.first; - char nwidTmp[64] = { 0 }; - OSUtils::ztsnprintf(nwidTmp, sizeof(nwidTmp), "%.16llx", nwid_i); - std::string nwid(nwidTmp); - std::string key = setKeyBase + nwid; - deletes.insert(key); - } - - if (! deletes.empty()) { - try { - if (_rc->clusterMode) { - auto tx = _cluster->transaction(_myAddressStr, true, false); - for (std::string k : deletes) { - tx.del(k); - } - tx.exec(); - } - else { - auto tx = _redis->transaction(true, false); - for (std::string k : deletes) { - tx.del(k); - } - tx.exec(); - } - } - catch (sw::redis::Error& e) { - // ignore - } - } - } - - char qbuf[2048]; - sprintf( - qbuf, - "SELECT m.id, m.network_id, m.active_bridge, m.authorized, m.capabilities, " - "(EXTRACT(EPOCH FROM m.creation_time AT TIME ZONE 'UTC')*1000)::bigint, m.identity, " - "(EXTRACT(EPOCH FROM m.last_authorized_time AT TIME ZONE 'UTC')*1000)::bigint, " - "(EXTRACT(EPOCH FROM m.last_deauthorized_time AT TIME ZONE 'UTC')*1000)::bigint, " - "m.remote_trace_level, m.remote_trace_target, m.tags, m.v_major, m.v_minor, m.v_rev, m.v_proto, " - "m.no_auto_assign_ips, m.revision, m.sso_exempt, " - "(CASE WHEN n.sso_enabled = TRUE AND m.sso_exempt = FALSE THEN " - " ( " - " SELECT (EXTRACT(EPOCH FROM e.authentication_expiry_time)*1000)::bigint " - " FROM ztc_sso_expiry e " - " INNER JOIN ztc_network n1 " - " ON n1.id = e.network_id AND n1.deleted = TRUE " - " WHERE e.network_id = m.network_id AND e.member_id = m.id AND n.sso_enabled = TRUE AND e.authentication_expiry_time IS NOT NULL " - " ORDER BY e.authentication_expiry_time DESC LIMIT 1 " - " ) " - " ELSE NULL " - " END) AS authentication_expiry_time, " - "ARRAY(SELECT DISTINCT address FROM ztc_member_ip_assignment WHERE member_id = m.id AND network_id = m.network_id) AS assigned_addresses " - "FROM ztc_member m " - "INNER JOIN ztc_network n " - " ON n.id = m.network_id " - "WHERE n.controller_id = '%s' AND n.deleted = FALSE AND m.deleted = FALSE", - _myAddressStr.c_str()); - auto c = _pool->borrow(); - auto c2 = _pool->borrow(); - pqxx::work w { *c->c }; - - fprintf(stderr, "Load members from psql...\n"); - auto stream = pqxx::stream_from::query(w, qbuf); - - std::tuple< - std::string // memberId - , - std::string // memberId - , - std::optional // activeBridge - , - std::optional // authorized - , - std::optional // capabilities - , - std::optional // creationTime - , - std::optional // identity - , - std::optional // lastAuthorizedTime - , - std::optional // lastDeauthorizedTime - , - std::optional // remoteTraceLevel - , - std::optional // remoteTraceTarget - , - std::optional // tags - , - std::optional // vMajor - , - std::optional // vMinor - , - std::optional // vRev - , - std::optional // vProto - , - std::optional // noAutoAssignIps - , - std::optional // revision - , - std::optional // ssoExempt - , - std::optional // authenticationExpiryTime - , - std::string // assignedAddresses - > - row; - - uint64_t count = 0; - auto tmp = std::chrono::high_resolution_clock::now(); - uint64_t total = 0; - while (stream >> row) { - auto start = std::chrono::high_resolution_clock::now(); - json empty; - json config; - - initMember(config); - - memberId = std::get<0>(row); - networkId = std::get<1>(row); - std::optional activeBridge = std::get<2>(row); - std::optional authorized = std::get<3>(row); - std::optional capabilities = std::get<4>(row); - std::optional creationTime = std::get<5>(row); - std::optional identity = std::get<6>(row); - std::optional lastAuthorizedTime = std::get<7>(row); - std::optional lastDeauthorizedTime = std::get<8>(row); - std::optional remoteTraceLevel = std::get<9>(row); - std::optional remoteTraceTarget = std::get<10>(row); - std::optional tags = std::get<11>(row); - std::optional vMajor = std::get<12>(row); - std::optional vMinor = std::get<13>(row); - std::optional vRev = std::get<14>(row); - std::optional vProto = std::get<15>(row); - std::optional noAutoAssignIps = std::get<16>(row); - std::optional revision = std::get<17>(row); - std::optional ssoExempt = std::get<18>(row); - std::optional authenticationExpiryTime = std::get<19>(row); - std::string assignedAddresses = std::get<20>(row); - - networkMembers.insert(std::pair(setKeyBase + networkId, memberId)); - - config["id"] = memberId; - config["address"] = memberId; - config["nwid"] = networkId; - config["activeBridge"] = activeBridge.value_or(false); - config["authorized"] = authorized.value_or(false); - config["capabilities"] = json::parse(capabilities.value_or("[]")); - config["creationTime"] = creationTime.value_or(0); - config["identity"] = identity.value_or(""); - config["lastAuthorizedTime"] = lastAuthorizedTime.value_or(0); - config["lastDeauthorizedTime"] = lastDeauthorizedTime.value_or(0); - config["remoteTraceLevel"] = remoteTraceLevel.value_or(0); - config["remoteTraceTarget"] = remoteTraceTarget.value_or(""); - config["tags"] = json::parse(tags.value_or("[]")); - config["vMajor"] = vMajor.value_or(-1); - config["vMinor"] = vMinor.value_or(-1); - config["vRev"] = vRev.value_or(-1); - config["vProto"] = vProto.value_or(-1); - config["noAutoAssignIps"] = noAutoAssignIps.value_or(false); - config["revision"] = revision.value_or(0); - config["ssoExempt"] = ssoExempt.value_or(false); - config["authenticationExpiryTime"] = authenticationExpiryTime.value_or(0); - config["objtype"] = "member"; - config["ipAssignments"] = json::array(); - - if (assignedAddresses != "{}") { - std::string tmp = assignedAddresses.substr(1, assignedAddresses.size() - 2); - std::vector addrs = split(tmp, ','); - for (auto it = addrs.begin(); it != addrs.end(); ++it) { - config["ipAssignments"].push_back(*it); - } - } - - Metrics::member_count++; - - _memberChanged(empty, config, false); - - memberId = ""; - networkId = ""; - - auto end = std::chrono::high_resolution_clock::now(); - auto dur = std::chrono::duration_cast(end - start); - total += dur.count(); - ++count; - if (count > 0 && count % 10000 == 0) { - fprintf(stderr, "Averaging %llu us per member\n", (total / count)); - } - } - if (count > 0) { - fprintf(stderr, "Took %llu us per member to load\n", (total / count)); - } - - stream.complete(); - - w.commit(); - _pool->unborrow(c2); - _pool->unborrow(c); - fprintf(stderr, "done.\n"); - - if (! networkMembers.empty()) { - if (_redisMemberStatus) { - fprintf(stderr, "Load member data into redis...\n"); - if (_rc->clusterMode) { - auto tx = _cluster->transaction(_myAddressStr, true, false); - uint64_t count = 0; - for (auto it : networkMembers) { - tx.sadd(it.first, it.second); - if (++count % 30000 == 0) { - tx.exec(); - tx = _cluster->transaction(_myAddressStr, true, false); - } - } - tx.exec(); - } - else { - auto tx = _redis->transaction(true, false); - uint64_t count = 0; - for (auto it : networkMembers) { - tx.sadd(it.first, it.second); - if (++count % 30000 == 0) { - tx.exec(); - tx = _redis->transaction(true, false); - } - } - tx.exec(); - } - fprintf(stderr, "done.\n"); - } - } - - fprintf(stderr, "Done loading members...\n"); - - if (++this->_ready == 2) { - if (_waitNoticePrinted) { - fprintf(stderr, "[%s] NOTICE: %.10llx controller PostgreSQL data download complete." ZT_EOL_S, _timestr(), (unsigned long long)_myAddress.toInt()); - } - _readyLock.unlock(); - } - } - catch (sw::redis::Error& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "ERROR: Error initializing members (redis): %s\n", e.what()); - exit(-1); - } - catch (std::exception& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "ERROR: Error initializing member: %s-%s %s\n", networkId.c_str(), memberId.c_str(), e.what()); - exit(-1); - } -} - -void CV1::heartbeat() -{ - char publicId[1024]; - char hostnameTmp[1024]; - _myId.toString(false, publicId); - if (gethostname(hostnameTmp, sizeof(hostnameTmp)) != 0) { - hostnameTmp[0] = (char)0; - } - else { - for (int i = 0; i < (int)sizeof(hostnameTmp); ++i) { - if ((hostnameTmp[i] == '.') || (hostnameTmp[i] == 0)) { - hostnameTmp[i] = (char)0; - break; - } - } - } - const char* controllerId = _myAddressStr.c_str(); - const char* publicIdentity = publicId; - const char* hostname = hostnameTmp; - - while (_run == 1) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::heartbeat"); - auto scope = tracer->WithActiveSpan(span); - - // fprintf(stderr, "%s: heartbeat\n", controllerId); - auto c = _pool->borrow(); - int64_t ts = OSUtils::now(); - - if (c->c) { - std::string major = std::to_string(ZEROTIER_ONE_VERSION_MAJOR); - std::string minor = std::to_string(ZEROTIER_ONE_VERSION_MINOR); - std::string rev = std::to_string(ZEROTIER_ONE_VERSION_REVISION); - std::string build = std::to_string(ZEROTIER_ONE_VERSION_BUILD); - std::string now = std::to_string(ts); - std::string host_port = std::to_string(_listenPort); - std::string use_redis = (_rc != NULL) ? "true" : "false"; - std::string redis_mem_status = (_redisMemberStatus) ? "true" : "false"; - - try { - pqxx::work w { *c->c }; - - pqxx::result res = w.exec0( - "INSERT INTO ztc_controller (id, cluster_host, last_alive, public_identity, v_major, v_minor, v_rev, v_build, host_port, use_redis, redis_member_status) " - "VALUES (" - + w.quote(controllerId) + ", " + w.quote(hostname) + ", TO_TIMESTAMP(" + now + "::double precision/1000), " + w.quote(publicIdentity) + ", " + major + ", " + minor + ", " + rev + ", " + build + ", " + host_port + ", " - + use_redis + ", " + redis_mem_status - + ") " - "ON CONFLICT (id) DO UPDATE SET cluster_host = EXCLUDED.cluster_host, last_alive = EXCLUDED.last_alive, " - "public_identity = EXCLUDED.public_identity, v_major = EXCLUDED.v_major, v_minor = EXCLUDED.v_minor, " - "v_rev = EXCLUDED.v_rev, v_build = EXCLUDED.v_rev, host_port = EXCLUDED.host_port, " - "use_redis = EXCLUDED.use_redis, redis_member_status = EXCLUDED.redis_member_status"); - w.commit(); - } - catch (std::exception& e) { - fprintf(stderr, "%s: Heartbeat update failed: %s\n", controllerId, e.what()); - span->End(); - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - continue; - } - } - _pool->unborrow(c); - - try { - if (_redisMemberStatus) { - if (_rc->clusterMode) { - _cluster->zadd("controllers", "controllerId", ts); - } - else { - _redis->zadd("controllers", "controllerId", ts); - } - } - } - catch (sw::redis::Error& e) { - fprintf(stderr, "ERROR: Redis error in heartbeat thread: %s\n", e.what()); - } - - span->End(); - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - } - fprintf(stderr, "Exited heartbeat thread\n"); -} - -void CV1::membersDbWatcher() -{ - if (_rc) { - _membersWatcher_Redis(); - } - else { - _membersWatcher_Postgres(); - } - - if (_run == 1) { - fprintf(stderr, "ERROR: %s membersDbWatcher should still be running! Exiting Controller.\n", _myAddressStr.c_str()); - exit(9); - } - fprintf(stderr, "Exited membersDbWatcher\n"); -} - -void CV1::_membersWatcher_Postgres() -{ - auto c = _pool->borrow(); - - std::string stream = "member_" + _myAddressStr; - - fprintf(stderr, "Listening to member stream: %s\n", stream.c_str()); - MemberNotificationReceiver m(this, *c->c, stream); - - while (_run == 1) { - c->c->await_notification(5, 0); - } - - _pool->unborrow(c); -} - -void CV1::_membersWatcher_Redis() -{ - char buf[11] = { 0 }; - std::string key = "member-stream:{" + std::string(_myAddress.toString(buf)) + "}"; - std::string lastID = "0"; - fprintf(stderr, "Listening to member stream: %s\n", key.c_str()); - while (_run == 1) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::_membersWatcher_Redis"); - auto scope = tracer->WithActiveSpan(span); - - try { - json tmp; - std::unordered_map result; - if (_rc->clusterMode) { - _cluster->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end())); - } - else { - _redis->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end())); - } - if (! result.empty()) { - for (auto element : result) { -#ifdef REDIS_TRACE - fprintf(stdout, "Received notification from: %s\n", element.first.c_str()); -#endif - for (auto rec : element.second) { - std::string id = rec.first; - auto attrs = rec.second; -#ifdef REDIS_TRACE - fprintf(stdout, "Record ID: %s\n", id.c_str()); - fprintf(stdout, "attrs len: %lu\n", attrs.size()); -#endif - for (auto a : attrs) { -#ifdef REDIS_TRACE - fprintf(stdout, "key: %s\nvalue: %s\n", a.first.c_str(), a.second.c_str()); -#endif - try { - tmp = json::parse(a.second); - json& ov = tmp["old_val"]; - json& nv = tmp["new_val"]; - json oldConfig, newConfig; - if (ov.is_object()) - oldConfig = ov; - if (nv.is_object()) - newConfig = nv; - if (oldConfig.is_object() || newConfig.is_object()) { - _memberChanged(oldConfig, newConfig, (this->_ready >= 2)); - } - } - catch (...) { - fprintf(stderr, "json parse error in _membersWatcher_Redis: %s\n", a.second.c_str()); - } - } - if (_rc->clusterMode) { - _cluster->xdel(key, id); - } - else { - _redis->xdel(key, id); - } - lastID = id; - Metrics::redis_mem_notification++; - } - } - } - } - catch (sw::redis::Error& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "Error in Redis members watcher: %s\n", e.what()); - } - } - fprintf(stderr, "membersWatcher ended\n"); -} - -void CV1::networksDbWatcher() -{ - if (_rc) { - _networksWatcher_Redis(); - } - else { - _networksWatcher_Postgres(); - } - - if (_run == 1) { - fprintf(stderr, "ERROR: %s networksDbWatcher should still be running! Exiting Controller.\n", _myAddressStr.c_str()); - exit(8); - } - fprintf(stderr, "Exited networksDbWatcher\n"); -} - -void CV1::_networksWatcher_Postgres() -{ - std::string stream = "network_" + _myAddressStr; - - fprintf(stderr, "Listening to member stream: %s\n", stream.c_str()); - - auto c = _pool->borrow(); - - NetworkNotificationReceiver n(this, *c->c, stream); - - while (_run == 1) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::_networksWatcher_Postgres"); - auto scope = tracer->WithActiveSpan(span); - - c->c->await_notification(5, 0); - } -} - -void CV1::_networksWatcher_Redis() -{ - char buf[11] = { 0 }; - std::string key = "network-stream:{" + std::string(_myAddress.toString(buf)) + "}"; - std::string lastID = "0"; - while (_run == 1) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::_networksWatcher_Redis"); - auto scope = tracer->WithActiveSpan(span); - - try { - json tmp; - std::unordered_map result; - if (_rc->clusterMode) { - _cluster->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end())); - } - else { - _redis->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end())); - } - - if (! result.empty()) { - for (auto element : result) { -#ifdef REDIS_TRACE - fprintf(stdout, "Received notification from: %s\n", element.first.c_str()); -#endif - for (auto rec : element.second) { - std::string id = rec.first; - auto attrs = rec.second; -#ifdef REDIS_TRACE - fprintf(stdout, "Record ID: %s\n", id.c_str()); - fprintf(stdout, "attrs len: %lu\n", attrs.size()); -#endif - for (auto a : attrs) { -#ifdef REDIS_TRACE - fprintf(stdout, "key: %s\nvalue: %s\n", a.first.c_str(), a.second.c_str()); -#endif - try { - tmp = json::parse(a.second); - json& ov = tmp["old_val"]; - json& nv = tmp["new_val"]; - json oldConfig, newConfig; - if (ov.is_object()) - oldConfig = ov; - if (nv.is_object()) - newConfig = nv; - if (oldConfig.is_object() || newConfig.is_object()) { - _networkChanged(oldConfig, newConfig, (this->_ready >= 2)); - } - } - catch (std::exception& e) { - fprintf(stderr, "json parse error in networkWatcher_Redis: what: %s json: %s\n", e.what(), a.second.c_str()); - } - } - if (_rc->clusterMode) { - _cluster->xdel(key, id); - } - else { - _redis->xdel(key, id); - } - lastID = id; - } - Metrics::redis_net_notification++; - } - } - } - catch (sw::redis::Error& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "Error in Redis networks watcher: %s\n", e.what()); - } - } - fprintf(stderr, "networksWatcher ended\n"); -} - -void CV1::commitThread() -{ - fprintf(stderr, "%s: commitThread start\n", _myAddressStr.c_str()); - std::pair qitem; - while (_commitQueue.get(qitem) & (_run == 1)) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::commitThread"); - auto scope = tracer->WithActiveSpan(span); - - // fprintf(stderr, "commitThread tick\n"); - if (! qitem.first.is_object()) { - fprintf(stderr, "not an object\n"); - continue; - } - - std::shared_ptr c; - try { - c = _pool->borrow(); - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: %s\n", e.what()); - continue; - } - - if (! c) { - fprintf(stderr, "Error getting database connection\n"); - continue; - } - - Metrics::pgsql_commit_ticks++; - try { - nlohmann::json& config = (qitem.first); - const std::string objtype = config["objtype"]; - if (objtype == "member") { - auto mspan = tracer->StartSpan("cv1::commitThread::member"); - auto mscope = tracer->WithActiveSpan(mspan); - - // fprintf(stderr, "%s: commitThread: member\n", _myAddressStr.c_str()); - std::string memberId; - std::string networkId; - try { - pqxx::work w(*c->c); - - memberId = config["id"]; - networkId = config["nwid"]; - - std::string target = "NULL"; - if (! config["remoteTraceTarget"].is_null()) { - target = config["remoteTraceTarget"]; - } - - pqxx::row nwrow = w.exec_params1("SELECT COUNT(id) FROM ztc_network WHERE id = $1", networkId); - int nwcount = nwrow[0].as(); - - if (nwcount != 1) { - fprintf(stderr, "network %s does not exist. skipping member upsert\n", networkId.c_str()); - w.abort(); - _pool->unborrow(c); - continue; - } - - pqxx::row mrow = w.exec_params1("SELECT COUNT(id) FROM ztc_member WHERE id = $1 AND network_id = $2", memberId, networkId); - int membercount = mrow[0].as(); - - bool isNewMember = false; - if (membercount == 0) { - // new member - isNewMember = true; - pqxx::result res = w.exec_params0( - "INSERT INTO ztc_member (id, network_id, active_bridge, authorized, capabilities, " - "identity, last_authorized_time, last_deauthorized_time, no_auto_assign_ips, " - "remote_trace_level, remote_trace_target, revision, tags, v_major, v_minor, v_rev, v_proto) " - "VALUES ($1, $2, $3, $4, $5, $6, " - "TO_TIMESTAMP($7::double precision/1000), TO_TIMESTAMP($8::double precision/1000), " - "$9, $10, $11, $12, $13, $14, $15, $16, $17)", - memberId, - networkId, - (bool)config["activeBridge"], - (bool)config["authorized"], - OSUtils::jsonDump(config["capabilities"], -1), - OSUtils::jsonString(config["identity"], ""), - (uint64_t)config["lastAuthorizedTime"], - (uint64_t)config["lastDeauthorizedTime"], - (bool)config["noAutoAssignIps"], - (int)config["remoteTraceLevel"], - target, - (uint64_t)config["revision"], - OSUtils::jsonDump(config["tags"], -1), - (int)config["vMajor"], - (int)config["vMinor"], - (int)config["vRev"], - (int)config["vProto"]); - } - else { - // existing member - pqxx::result res = w.exec_params0( - "UPDATE ztc_member " - "SET active_bridge = $3, authorized = $4, capabilities = $5, identity = $6, " - "last_authorized_time = TO_TIMESTAMP($7::double precision/1000), " - "last_deauthorized_time = TO_TIMESTAMP($8::double precision/1000), " - "no_auto_assign_ips = $9, remote_trace_level = $10, remote_trace_target= $11, " - "revision = $12, tags = $13, v_major = $14, v_minor = $15, v_rev = $16, v_proto = $17 " - "WHERE id = $1 AND network_id = $2", - memberId, - networkId, - (bool)config["activeBridge"], - (bool)config["authorized"], - OSUtils::jsonDump(config["capabilities"], -1), - OSUtils::jsonString(config["identity"], ""), - (uint64_t)config["lastAuthorizedTime"], - (uint64_t)config["lastDeauthorizedTime"], - (bool)config["noAutoAssignIps"], - (int)config["remoteTraceLevel"], - target, - (uint64_t)config["revision"], - OSUtils::jsonDump(config["tags"], -1), - (int)config["vMajor"], - (int)config["vMinor"], - (int)config["vRev"], - (int)config["vProto"]); - } - - if (! isNewMember) { - pqxx::result res = w.exec_params0("DELETE FROM ztc_member_ip_assignment WHERE member_id = $1 AND network_id = $2", memberId, networkId); - } - - std::vector assignments; - bool ipAssignError = false; - for (auto i = config["ipAssignments"].begin(); i != config["ipAssignments"].end(); ++i) { - std::string addr = *i; - - if (std::find(assignments.begin(), assignments.end(), addr) != assignments.end()) { - continue; - } - - pqxx::result res = w.exec_params0("INSERT INTO ztc_member_ip_assignment (member_id, network_id, address) VALUES ($1, $2, $3) ON CONFLICT (network_id, member_id, address) DO NOTHING", memberId, networkId, addr); - - assignments.push_back(addr); - } - if (ipAssignError) { - fprintf(stderr, "%s: ipAssignError\n", _myAddressStr.c_str()); - w.abort(); - _pool->unborrow(c); - c.reset(); - continue; - } - - w.commit(); - - if (_smee != NULL && isNewMember) { - pqxx::row row = w.exec_params1( - "SELECT " - " count(h.hook_id) " - "FROM " - " ztc_hook h " - " INNER JOIN ztc_org o ON o.org_id = h.org_id " - " INNER JOIN ztc_network n ON n.owner_id = o.owner_id " - " WHERE " - "n.id = $1 ", - networkId); - int64_t hookCount = row[0].as(); - if (hookCount > 0) { - notifyNewMember(networkId, memberId); - } - } - - const uint64_t nwidInt = OSUtils::jsonIntHex(config["nwid"], 0ULL); - const uint64_t memberidInt = OSUtils::jsonIntHex(config["id"], 0ULL); - if (nwidInt && memberidInt) { - nlohmann::json nwOrig; - nlohmann::json memOrig; - - nlohmann::json memNew(config); - - get(nwidInt, nwOrig, memberidInt, memOrig); - - _memberChanged(memOrig, memNew, qitem.second); - } - else { - fprintf(stderr, "%s: Can't notify of change. Error parsing nwid or memberid: %llu-%llu\n", _myAddressStr.c_str(), (unsigned long long)nwidInt, (unsigned long long)memberidInt); - } - } - catch (std::exception& e) { - fprintf(stderr, "%s ERROR: Error updating member %s-%s: %s\n", _myAddressStr.c_str(), networkId.c_str(), memberId.c_str(), e.what()); - mspan->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - } - } - else if (objtype == "network") { - auto nspan = tracer->StartSpan("cv1::commitThread::network"); - auto nscope = tracer->WithActiveSpan(nspan); - - try { - // fprintf(stderr, "%s: commitThread: network\n", _myAddressStr.c_str()); - pqxx::work w(*c->c); - - std::string id = config["id"]; - std::string remoteTraceTarget = ""; - if (! config["remoteTraceTarget"].is_null()) { - remoteTraceTarget = config["remoteTraceTarget"]; - } - std::string rulesSource = ""; - if (config["rulesSource"].is_string()) { - rulesSource = config["rulesSource"]; - } - - // This ugly query exists because when we want to mirror networks to/from - // another data store (e.g. FileDB or LFDB) it is possible to get a network - // that doesn't exist in Central's database. This does an upsert and sets - // the owner_id to the "first" global admin in the user DB if the record - // did not previously exist. If the record already exists owner_id is left - // unchanged, so owner_id should be left out of the update clause. - pqxx::result res = w.exec_params0( - "INSERT INTO ztc_network (id, creation_time, owner_id, controller_id, capabilities, enable_broadcast, " - "last_modified, mtu, multicast_limit, name, private, " - "remote_trace_level, remote_trace_target, rules, rules_source, " - "tags, v4_assign_mode, v6_assign_mode, sso_enabled) VALUES (" - "$1, TO_TIMESTAMP($5::double precision/1000), " - "(SELECT user_id AS owner_id FROM ztc_global_permissions WHERE authorize = true AND del = true AND modify = true AND read = true LIMIT 1)," - "$2, $3, $4, TO_TIMESTAMP($5::double precision/1000), " - "$6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) " - "ON CONFLICT (id) DO UPDATE set controller_id = EXCLUDED.controller_id, " - "capabilities = EXCLUDED.capabilities, enable_broadcast = EXCLUDED.enable_broadcast, " - "last_modified = EXCLUDED.last_modified, mtu = EXCLUDED.mtu, " - "multicast_limit = EXCLUDED.multicast_limit, name = EXCLUDED.name, " - "private = EXCLUDED.private, remote_trace_level = EXCLUDED.remote_trace_level, " - "remote_trace_target = EXCLUDED.remote_trace_target, rules = EXCLUDED.rules, " - "rules_source = EXCLUDED.rules_source, tags = EXCLUDED.tags, " - "v4_assign_mode = EXCLUDED.v4_assign_mode, v6_assign_mode = EXCLUDED.v6_assign_mode, " - "sso_enabled = EXCLUDED.sso_enabled", - id, - _myAddressStr, - OSUtils::jsonDump(config["capabilities"], -1), - (bool)config["enableBroadcast"], - OSUtils::now(), - (int)config["mtu"], - (int)config["multicastLimit"], - OSUtils::jsonString(config["name"], ""), - (bool)config["private"], - (int)config["remoteTraceLevel"], - remoteTraceTarget, - OSUtils::jsonDump(config["rules"], -1), - rulesSource, - OSUtils::jsonDump(config["tags"], -1), - OSUtils::jsonDump(config["v4AssignMode"], -1), - OSUtils::jsonDump(config["v6AssignMode"], -1), - OSUtils::jsonBool(config["ssoEnabled"], false)); - - res = w.exec_params0("DELETE FROM ztc_network_assignment_pool WHERE network_id = $1", 0); - - auto pool = config["ipAssignmentPools"]; - bool err = false; - for (auto i = pool.begin(); i != pool.end(); ++i) { - std::string start = (*i)["ipRangeStart"]; - std::string end = (*i)["ipRangeEnd"]; - - res = w.exec_params0( - "INSERT INTO ztc_network_assignment_pool (network_id, ip_range_start, ip_range_end) " - "VALUES ($1, $2, $3)", - id, - start, - end); - } - - res = w.exec_params0("DELETE FROM ztc_network_route WHERE network_id = $1", id); - - auto routes = config["routes"]; - err = false; - for (auto i = routes.begin(); i != routes.end(); ++i) { - std::string t = (*i)["target"]; - std::vector target; - std::istringstream f(t); - std::string s; - while (std::getline(f, s, '/')) { - target.push_back(s); - } - if (target.empty() || target.size() != 2) { - continue; - } - std::string targetAddr = target[0]; - std::string targetBits = target[1]; - std::string via = "NULL"; - if (! (*i)["via"].is_null()) { - via = (*i)["via"]; - } - - res = w.exec_params0("INSERT INTO ztc_network_route (network_id, address, bits, via) VALUES ($1, $2, $3, $4)", id, targetAddr, targetBits, (via == "NULL" ? NULL : via.c_str())); - } - if (err) { - fprintf(stderr, "%s: route add error\n", _myAddressStr.c_str()); - w.abort(); - _pool->unborrow(c); - continue; - } - - auto dns = config["dns"]; - std::string domain = dns["domain"]; - std::stringstream servers; - servers << "{"; - for (auto j = dns["servers"].begin(); j < dns["servers"].end(); ++j) { - servers << *j; - if ((j + 1) != dns["servers"].end()) { - servers << ","; - } - } - servers << "}"; - - std::string s = servers.str(); - - res = w.exec_params0("INSERT INTO ztc_network_dns (network_id, domain, servers) VALUES ($1, $2, $3) ON CONFLICT (network_id) DO UPDATE SET domain = EXCLUDED.domain, servers = EXCLUDED.servers", id, domain, s); - - w.commit(); - - const uint64_t nwidInt = OSUtils::jsonIntHex(config["nwid"], 0ULL); - if (nwidInt) { - nlohmann::json nwOrig; - nlohmann::json nwNew(config); - - get(nwidInt, nwOrig); - - _networkChanged(nwOrig, nwNew, qitem.second); - } - else { - fprintf(stderr, "%s: Can't notify network changed: %llu\n", _myAddressStr.c_str(), (unsigned long long)nwidInt); - } - } - catch (std::exception& e) { - nspan->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "%s ERROR: Error updating network: %s\n", _myAddressStr.c_str(), e.what()); - } - if (_redisMemberStatus) { - try { - std::string id = config["id"]; - std::string controllerId = _myAddressStr.c_str(); - std::string key = "networks:{" + controllerId + "}"; - if (_rc->clusterMode) { - _cluster->sadd(key, id); - } - else { - _redis->sadd(key, id); - } - } - catch (sw::redis::Error& e) { - nspan->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "ERROR: Error adding network to Redis: %s\n", e.what()); - } - } - } - else if (objtype == "_delete_network") { - auto dspan = tracer->StartSpan("cv1::commitThread::_delete_network"); - auto dscope = tracer->WithActiveSpan(dspan); - - // fprintf(stderr, "%s: commitThread: delete network\n", _myAddressStr.c_str()); - try { - pqxx::work w(*c->c); - - std::string networkId = config["nwid"]; - - pqxx::result res = w.exec_params0("UPDATE ztc_network SET deleted = true WHERE id = $1", networkId); - - w.commit(); - } - catch (std::exception& e) { - dspan->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "%s ERROR: Error deleting network: %s\n", _myAddressStr.c_str(), e.what()); - } - if (_redisMemberStatus) { - try { - std::string id = config["id"]; - std::string controllerId = _myAddressStr.c_str(); - std::string key = "networks:{" + controllerId + "}"; - if (_rc->clusterMode) { - _cluster->srem(key, id); - _cluster->del("network-nodes-online:{" + controllerId + "}:" + id); - } - else { - _redis->srem(key, id); - _redis->del("network-nodes-online:{" + controllerId + "}:" + id); - } - } - catch (sw::redis::Error& e) { - dspan->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "ERROR: Error adding network to Redis: %s\n", e.what()); - } - } - } - else if (objtype == "_delete_member") { - auto mspan = tracer->StartSpan("cv1::commitThread::_delete_member"); - auto mscope = tracer->WithActiveSpan(mspan); - - // fprintf(stderr, "%s commitThread: delete member\n", _myAddressStr.c_str()); - try { - pqxx::work w(*c->c); - - std::string memberId = config["id"]; - std::string networkId = config["nwid"]; - - pqxx::result res = w.exec_params0("UPDATE ztc_member SET hidden = true, deleted = true WHERE id = $1 AND network_id = $2", memberId, networkId); - - w.commit(); - } - catch (std::exception& e) { - mspan->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "%s ERROR: Error deleting member: %s\n", _myAddressStr.c_str(), e.what()); - } - if (_redisMemberStatus) { - try { - std::string memberId = config["id"]; - std::string networkId = config["nwid"]; - std::string controllerId = _myAddressStr.c_str(); - std::string key = "network-nodes-all:{" + controllerId + "}:" + networkId; - if (_rc->clusterMode) { - _cluster->srem(key, memberId); - _cluster->del("member:{" + controllerId + "}:" + networkId + ":" + memberId); - } - else { - _redis->srem(key, memberId); - _redis->del("member:{" + controllerId + "}:" + networkId + ":" + memberId); - } - } - catch (sw::redis::Error& e) { - mspan->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "ERROR: Error deleting member from Redis: %s\n", e.what()); - } - } - } - else { - fprintf(stderr, "%s ERROR: unknown objtype\n", _myAddressStr.c_str()); - } - } - catch (std::exception& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - fprintf(stderr, "%s ERROR: Error getting objtype: %s\n", _myAddressStr.c_str(), e.what()); - } - _pool->unborrow(c); - c.reset(); - } - - fprintf(stderr, "%s commitThread finished\n", _myAddressStr.c_str()); -} - -void CV1::notifyNewMember(const std::string& networkID, const std::string& memberID) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::notifyNewMember"); - auto scope = tracer->WithActiveSpan(span); - - smeeclient::smee_client_notify_network_joined(_smee, networkID.c_str(), memberID.c_str()); -} - -void CV1::onlineNotificationThread() -{ - waitForReady(); - if (_redisMemberStatus) { - onlineNotification_Redis(); - } - else { - onlineNotification_Postgres(); - } -} - -/** - * ONLY UNCOMMENT FOR TEMPORARY DB MAINTENANCE - * - * This define temporarily turns off writing to the member status table - * so it can be reindexed when the indexes get too large. - */ - -// #define DISABLE_MEMBER_STATUS 1 - -void CV1::onlineNotification_Postgres() -{ - _connected = 1; - - nlohmann::json jtmp1, jtmp2; - while (_run == 1) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::onlineNotification_Postgres"); - auto scope = tracer->WithActiveSpan(span); - - auto c = _pool->borrow(); - auto c2 = _pool->borrow(); - try { - fprintf(stderr, "%s onlineNotification_Postgres\n", _myAddressStr.c_str()); - std::unordered_map, NodeOnlineRecord, _PairHasher> lastOnline; - { - std::lock_guard l(_lastOnline_l); - lastOnline.swap(_lastOnline); - } - -#ifndef DISABLE_MEMBER_STATUS - pqxx::work w(*c->c); - pqxx::work w2(*c2->c); - - fprintf(stderr, "online notification tick\n"); - - bool firstRun = true; - bool memberAdded = false; - int updateCount = 0; - - pqxx::pipeline pipe(w); - - for (auto i = lastOnline.begin(); i != lastOnline.end(); ++i) { - updateCount += 1; - uint64_t nwid_i = i->first.first; - char nwidTmp[64]; - char memTmp[64]; - char ipTmp[64]; - OSUtils::ztsnprintf(nwidTmp, sizeof(nwidTmp), "%.16llx", nwid_i); - OSUtils::ztsnprintf(memTmp, sizeof(memTmp), "%.10llx", i->first.second); - - if (! get(nwid_i, jtmp1, i->first.second, jtmp2)) { - continue; // skip non existent networks/members - } - - std::string networkId(nwidTmp); - std::string memberId(memTmp); - - try { - pqxx::row r = w2.exec_params1("SELECT id, network_id FROM ztc_member WHERE network_id = $1 AND id = $2", networkId, memberId); - } - catch (pqxx::unexpected_rows& e) { - continue; - } - - int64_t ts = i->second.lastSeen; - std::string ipAddr = i->second.physicalAddress.toIpString(ipTmp); - std::string timestamp = std::to_string(ts); - std::string osArch = i->second.osArch; - - std::stringstream memberUpdate; - memberUpdate << "INSERT INTO ztc_member_status (network_id, member_id, address, last_updated) VALUES " - << "('" << networkId << "', '" << memberId << "', "; - if (ipAddr.empty()) { - memberUpdate << "NULL, "; - } - else { - memberUpdate << "'" << ipAddr << "', "; - } - memberUpdate << "TO_TIMESTAMP(" << timestamp << "::double precision/1000)) " - << " ON CONFLICT (network_id, member_id) DO UPDATE SET address = EXCLUDED.address, last_updated = EXCLUDED.last_updated"; - - pipe.insert(memberUpdate.str()); - Metrics::pgsql_node_checkin++; - } - while (! pipe.empty()) { - pipe.retrieve(); - } - - pipe.complete(); - w.commit(); - fprintf(stderr, "%s: Updated online status of %d members\n", _myAddressStr.c_str(), updateCount); -#endif - } - catch (std::exception& e) { - fprintf(stderr, "%s: error in onlinenotification thread: %s\n", _myAddressStr.c_str(), e.what()); - } - _pool->unborrow(c2); - _pool->unborrow(c); - - ConnectionPoolStats stats = _pool->get_stats(); - fprintf(stderr, "%s pool stats: in use size: %llu, available size: %llu, total: %llu\n", _myAddressStr.c_str(), stats.borrowed_size, stats.pool_size, (stats.borrowed_size + stats.pool_size)); - - span->End(); - - std::this_thread::sleep_for(std::chrono::seconds(10)); - } - fprintf(stderr, "%s: Fell out of run loop in onlineNotificationThread\n", _myAddressStr.c_str()); - if (_run == 1) { - fprintf(stderr, "ERROR: %s onlineNotificationThread should still be running! Exiting Controller.\n", _myAddressStr.c_str()); - exit(6); - } -} - -void CV1::onlineNotification_Redis() -{ - _connected = 1; - - char buf[11] = { 0 }; - std::string controllerId = std::string(_myAddress.toString(buf)); - - while (_run == 1) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::onlineNotification_Redis"); - auto scope = tracer->WithActiveSpan(span); - - fprintf(stderr, "onlineNotification tick\n"); - auto start = std::chrono::high_resolution_clock::now(); - uint64_t count = 0; - - std::unordered_map, NodeOnlineRecord, _PairHasher> lastOnline; - { - std::lock_guard l(_lastOnline_l); - lastOnline.swap(_lastOnline); - } - try { - if (! lastOnline.empty()) { - if (_rc->clusterMode) { - auto tx = _cluster->transaction(controllerId, true, false); - count = _doRedisUpdate(tx, controllerId, lastOnline); - } - else { - auto tx = _redis->transaction(true, false); - count = _doRedisUpdate(tx, controllerId, lastOnline); - } - } - } - catch (sw::redis::Error& e) { - fprintf(stderr, "Error in online notification thread (redis): %s\n", e.what()); - } - - auto end = std::chrono::high_resolution_clock::now(); - auto dur = std::chrono::duration_cast(end - start); - auto total = dur.count(); - - fprintf(stderr, "onlineNotification ran in %llu ms\n", total); - span->End(); - - std::this_thread::sleep_for(std::chrono::seconds(5)); - } -} - -uint64_t CV1::_doRedisUpdate(sw::redis::Transaction& tx, std::string& controllerId, std::unordered_map, NodeOnlineRecord, _PairHasher>& lastOnline) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv1"); - auto span = tracer->StartSpan("cv1::_doRedisUpdate"); - auto scope = tracer->WithActiveSpan(span); - - nlohmann::json jtmp1, jtmp2; - uint64_t count = 0; - for (auto i = lastOnline.begin(); i != lastOnline.end(); ++i) { - uint64_t nwid_i = i->first.first; - uint64_t memberid_i = i->first.second; - char nwidTmp[64]; - char memTmp[64]; - char ipTmp[64]; - OSUtils::ztsnprintf(nwidTmp, sizeof(nwidTmp), "%.16llx", nwid_i); - OSUtils::ztsnprintf(memTmp, sizeof(memTmp), "%.10llx", memberid_i); - - if (! get(nwid_i, jtmp1, memberid_i, jtmp2)) { - continue; // skip non existent members/networks - } - - std::string networkId(nwidTmp); - std::string memberId(memTmp); - - int64_t ts = i->second.lastSeen; - std::string ipAddr = i->second.physicalAddress.toIpString(ipTmp); - std::string timestamp = std::to_string(ts); - std::string osArch = i->second.osArch; - - std::unordered_map record = { { "id", memberId }, { "address", ipAddr }, { "last_updated", std::to_string(ts) } }; - tx.zadd("nodes-online:{" + controllerId + "}", memberId, ts) - .zadd("nodes-online2:{" + controllerId + "}", networkId + "-" + memberId, ts) - .zadd("network-nodes-online:{" + controllerId + "}:" + networkId, memberId, ts) - .zadd("active-networks:{" + controllerId + "}", networkId, ts) - .sadd("network-nodes-all:{" + controllerId + "}:" + networkId, memberId) - .hmset("member:{" + controllerId + "}:" + networkId + ":" + memberId, record.begin(), record.end()); - ++count; - Metrics::redis_node_checkin++; - } - - // expire records from all-nodes and network-nodes member list - uint64_t expireOld = OSUtils::now() - 300000; - - tx.zremrangebyscore("nodes-online:{" + controllerId + "}", sw::redis::RightBoundedInterval(expireOld, sw::redis::BoundType::LEFT_OPEN)); - tx.zremrangebyscore("nodes-online2:{" + controllerId + "}", sw::redis::RightBoundedInterval(expireOld, sw::redis::BoundType::LEFT_OPEN)); - tx.zremrangebyscore("active-networks:{" + controllerId + "}", sw::redis::RightBoundedInterval(expireOld, sw::redis::BoundType::LEFT_OPEN)); - { - std::shared_lock l(_networks_l); - for (const auto& it : _networks) { - uint64_t nwid_i = it.first; - char nwidTmp[64]; - OSUtils::ztsnprintf(nwidTmp, sizeof(nwidTmp), "%.16llx", nwid_i); - tx.zremrangebyscore("network-nodes-online:{" + controllerId + "}:" + nwidTmp, sw::redis::RightBoundedInterval(expireOld, sw::redis::BoundType::LEFT_OPEN)); - } - } - tx.exec(); - fprintf(stderr, "%s: Updated online status of %d members\n", _myAddressStr.c_str(), count); - - return count; -} - -#endif // ZT_CONTROLLER_USE_LIBPQ diff --git a/controller/CV1.hpp b/controller/CV1.hpp deleted file mode 100644 index b1a362798..000000000 --- a/controller/CV1.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "DB.hpp" - -#ifdef ZT_CONTROLLER_USE_LIBPQ - -#ifndef ZT_CONTROLLER_CV1_HPP -#define ZT_CONTROLLER_CV1_HPP - -#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 - -#include "../node/Metrics.hpp" -#include "ConnectionPool.hpp" -#include "PostgreSQL.hpp" - -#include -#include -#include - -namespace smeeclient { -struct SmeeClient; -} - -namespace ZeroTier { - -struct RedisConfig; - -/** - * A controller database driver that talks to PostgreSQL - * - * This is for use with ZeroTier Central. Others are free to build and use it - * but be aware that we might change it at any time. - */ -class CV1 : public DB { - friend class MemberNotificationReceiver; - friend class NetworkNotificationReceiver; - - public: - CV1(const Identity& myId, const char* path, int listenPort, RedisConfig* rc); - virtual ~CV1(); - - virtual bool waitForReady(); - virtual bool isReady(); - virtual bool save(nlohmann::json& record, bool notifyListeners); - virtual void eraseNetwork(const uint64_t networkId); - virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); - virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL); - - virtual bool ready() - { - return _ready == 2; - } - - protected: - struct _PairHasher { - inline std::size_t operator()(const std::pair& p) const - { - return (std::size_t)(p.first ^ p.second); - } - }; - virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners) - { - DB::_memberChanged(old, memberConfig, notifyListeners); - } - - virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners) - { - DB::_networkChanged(old, networkConfig, notifyListeners); - } - - private: - void initializeNetworks(); - void initializeMembers(); - void heartbeat(); - void membersDbWatcher(); - void _membersWatcher_Postgres(); - void networksDbWatcher(); - void _networksWatcher_Postgres(); - - void _membersWatcher_Redis(); - void _networksWatcher_Redis(); - - void commitThread(); - void onlineNotificationThread(); - void onlineNotification_Postgres(); - void onlineNotification_Redis(); - uint64_t _doRedisUpdate(sw::redis::Transaction& tx, std::string& controllerId, std::unordered_map, NodeOnlineRecord, _PairHasher>& lastOnline); - - void configureSmee(); - void notifyNewMember(const std::string& networkID, const std::string& memberID); - - enum OverrideMode { ALLOW_PGBOUNCER_OVERRIDE = 0, NO_OVERRIDE = 1 }; - - std::shared_ptr > _pool; - - const Identity _myId; - const Address _myAddress; - std::string _myAddressStr; - std::string _connString; - - BlockingQueue > _commitQueue; - - std::thread _heartbeatThread; - std::thread _membersDbWatcher; - std::thread _networksDbWatcher; - std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS]; - std::thread _onlineNotificationThread; - - std::unordered_map, NodeOnlineRecord, _PairHasher> _lastOnline; - - mutable std::mutex _lastOnline_l; - mutable std::mutex _readyLock; - std::atomic _ready, _connected, _run; - mutable volatile bool _waitNoticePrinted; - - int _listenPort; - uint8_t _ssoPsk[48]; - - RedisConfig* _rc; - std::shared_ptr _redis; - std::shared_ptr _cluster; - bool _redisMemberStatus; - - smeeclient::SmeeClient* _smee; -}; - -} // namespace ZeroTier - -#endif // ZT_CONTROLLER_CV1_HPP - -#endif // ZT_CONTROLLER_USE_LIBPQ diff --git a/controller/CV2.cpp b/controller/CV2.cpp deleted file mode 100644 index db9effb3c..000000000 --- a/controller/CV2.cpp +++ /dev/null @@ -1,1244 +0,0 @@ -/* - * Copyright (c)2025 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "CV2.hpp" - -#ifdef ZT_CONTROLLER_USE_LIBPQ - -#include "../node/Constants.hpp" -#include "../node/SHA512.hpp" -#include "../version.h" -#include "CtlUtil.hpp" -#include "EmbeddedNetworkController.hpp" -#include "opentelemetry/trace/provider.h" - -#include -#include -#include -#include -#include - -using json = nlohmann::json; - -namespace { - -} - -using namespace ZeroTier; - -CV2::CV2(const Identity& myId, const char* path, int listenPort) : DB(), _pool(), _myId(myId), _myAddress(myId.address()), _ready(0), _connected(1), _run(1), _waitNoticePrinted(false), _listenPort(listenPort) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::CV2"); - auto scope = tracer->WithActiveSpan(span); - - fprintf(stderr, "CV2::CV2\n"); - char myAddress[64]; - _myAddressStr = myId.address().toString(myAddress); - - _connString = std::string(path); - - auto f = std::make_shared(_connString); - _pool = std::make_shared >(15, 5, std::static_pointer_cast(f)); - - memset(_ssoPsk, 0, sizeof(_ssoPsk)); - char* const ssoPskHex = getenv("ZT_SSO_PSK"); -#ifdef ZT_TRACE - fprintf(stderr, "ZT_SSO_PSK: %s\n", ssoPskHex); -#endif - if (ssoPskHex) { - // SECURITY: note that ssoPskHex will always be null-terminated if libc actually - // returns something non-NULL. If the hex encodes something shorter than 48 bytes, - // it will be padded at the end with zeroes. If longer, it'll be truncated. - Utils::unhex(ssoPskHex, _ssoPsk, sizeof(_ssoPsk)); - } - - _readyLock.lock(); - - fprintf(stderr, "[%s] NOTICE: %.10llx controller PostgreSQL waiting for initial data download..." ZT_EOL_S, ::_timestr(), (unsigned long long)_myAddress.toInt()); - _waitNoticePrinted = true; - - initializeNetworks(); - initializeMembers(); - - _heartbeatThread = std::thread(&CV2::heartbeat, this); - _membersDbWatcher = std::thread(&CV2::membersDbWatcher, this); - _networksDbWatcher = std::thread(&CV2::networksDbWatcher, this); - for (int i = 0; i < ZT_CENTRAL_CONTROLLER_COMMIT_THREADS; ++i) { - _commitThread[i] = std::thread(&CV2::commitThread, this); - } - _onlineNotificationThread = std::thread(&CV2::onlineNotificationThread, this); -} - -CV2::~CV2() -{ - _run = 0; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - _heartbeatThread.join(); - _membersDbWatcher.join(); - _networksDbWatcher.join(); - _commitQueue.stop(); - for (int i = 0; i < ZT_CENTRAL_CONTROLLER_COMMIT_THREADS; ++i) { - _commitThread[i].join(); - } - _onlineNotificationThread.join(); -} - -bool CV2::waitForReady() -{ - while (_ready < 2) { - _readyLock.lock(); - _readyLock.unlock(); - } - return true; -} - -bool CV2::isReady() -{ - return (_ready == 2) && _connected; -} - -void CV2::_memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners) -{ - DB::_memberChanged(old, memberConfig, notifyListeners); -} - -void CV2::_networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners) -{ - DB::_networkChanged(old, networkConfig, notifyListeners); -} - -bool CV2::save(nlohmann::json& record, bool notifyListeners) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::save"); - auto scope = tracer->WithActiveSpan(span); - - bool modified = false; - try { - if (! record.is_object()) { - fprintf(stderr, "record is not an object?!?\n"); - return false; - } - const std::string objtype = record["objtype"]; - if (objtype == "network") { - auto nspan = tracer->StartSpan("cv2::save::network"); - auto nscope = tracer->WithActiveSpan(nspan); - - // fprintf(stderr, "network save\n"); - const uint64_t nwid = OSUtils::jsonIntHex(record["id"], 0ULL); - if (nwid) { - nlohmann::json old; - get(nwid, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - _commitQueue.post(std::pair(record, notifyListeners)); - modified = true; - } - } - } - else if (objtype == "member") { - auto mspan = tracer->StartSpan("cv2::save::member"); - auto mscope = tracer->WithActiveSpan(mspan); - - std::string networkId = record["nwid"]; - std::string memberId = record["id"]; - const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"], 0ULL); - const uint64_t id = OSUtils::jsonIntHex(record["id"], 0ULL); - // fprintf(stderr, "member save %s-%s\n", networkId.c_str(), memberId.c_str()); - if ((id) && (nwid)) { - nlohmann::json network, old; - get(nwid, network, id, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - // fprintf(stderr, "commit queue post\n"); - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - _commitQueue.post(std::pair(record, notifyListeners)); - modified = true; - } - else { - // fprintf(stderr, "no change\n"); - } - } - } - else { - fprintf(stderr, "uhh waaat\n"); - } - } - catch (std::exception& e) { - fprintf(stderr, "Error on PostgreSQL::save: %s\n", e.what()); - } - catch (...) { - fprintf(stderr, "Unknown error on PostgreSQL::save\n"); - } - return modified; -} - -void CV2::eraseNetwork(const uint64_t networkId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::eraseNetwork"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - std::string nwid = Utils::hex(networkId, networkIdStr); - span->SetAttribute("network_id", nwid); - - fprintf(stderr, "CV2::eraseNetwork\n"); - waitForReady(); - std::pair tmp; - tmp.first["id"] = nwid; - tmp.first["objtype"] = "_delete_network"; - tmp.second = true; - _commitQueue.post(tmp); - // nlohmann::json nullJson; - //_networkChanged(tmp.first, nullJson, isReady()); -} - -void CV2::eraseMember(const uint64_t networkId, const uint64_t memberId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::eraseMember"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - - fprintf(stderr, "PostgreSQL::eraseMember\n"); - char tmp2[24]; - waitForReady(); - std::pair tmp, nw; - Utils::hex(networkId, tmp2); - tmp.first["nwid"] = tmp2; - Utils::hex(memberId, tmp2); - tmp.first["id"] = tmp2; - tmp.first["objtype"] = "_delete_member"; - tmp.second = true; - _commitQueue.post(tmp); - // nlohmann::json nullJson; - //_memberChanged(tmp.first, nullJson, isReady()); -} - -void CV2::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::nodeIsOnline"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - char ipAddressStr[INET6_ADDRSTRLEN]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - span->SetAttribute("physical_address", ipAddressStr); - span->SetAttribute("os_arch", osArch); - - std::lock_guard l(_lastOnline_l); - NodeOnlineRecord& i = _lastOnline[std::pair(networkId, memberId)]; - i.lastSeen = OSUtils::now(); - if (physicalAddress) { - i.physicalAddress = physicalAddress; - } - i.osArch = std::string(osArch); -} - -void CV2::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) -{ - this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown"); -} - -AuthInfo CV2::getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL) -{ - // TODO: Redo this for CV2 - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::getSSOAuthInfo"); - auto scope = tracer->WithActiveSpan(span); - - Metrics::db_get_sso_info++; - // NONCE is just a random character string. no semantic meaning - // state = HMAC SHA384 of Nonce based on shared sso key - // - // need nonce timeout in database? make sure it's used within X time - // X is 5 minutes for now. Make configurable later? - // - // how do we tell when a nonce is used? if auth_expiration_time is set - std::string networkId = member["nwid"]; - std::string memberId = member["id"]; - - char authenticationURL[4096] = { 0 }; - AuthInfo info; - info.enabled = true; - - // if (memberId == "a10dccea52" && networkId == "8056c2e21c24673d") { - // fprintf(stderr, "invalid authinfo for grant's machine\n"); - // info.version=1; - // return info; - // } - // fprintf(stderr, "PostgreSQL::updateMemberOnLoad: %s-%s\n", networkId.c_str(), memberId.c_str()); - std::shared_ptr c; - try { - // c = _pool->borrow(); - // pqxx::work w(*c->c); - - // char nonceBytes[16] = {0}; - // std::string nonce = ""; - - // // check if the member exists first. - // pqxx::row count = w.exec_params1("SELECT count(id) FROM ztc_member WHERE id = $1 AND network_id = $2 AND deleted = false", memberId, networkId); - // if (count[0].as() == 1) { - // // get active nonce, if exists. - // pqxx::result r = w.exec_params("SELECT nonce FROM ztc_sso_expiry " - // "WHERE network_id = $1 AND member_id = $2 " - // "AND ((NOW() AT TIME ZONE 'UTC') <= authentication_expiry_time) AND ((NOW() AT TIME ZONE 'UTC') <= nonce_expiration)", - // networkId, memberId); - - // if (r.size() == 0) { - // // no active nonce. - // // find an unused nonce, if one exists. - // pqxx::result r = w.exec_params("SELECT nonce FROM ztc_sso_expiry " - // "WHERE network_id = $1 AND member_id = $2 " - // "AND authentication_expiry_time IS NULL AND ((NOW() AT TIME ZONE 'UTC') <= nonce_expiration)", - // networkId, memberId); - - // if (r.size() == 1) { - // // we have an existing nonce. Use it - // nonce = r.at(0)[0].as(); - // Utils::unhex(nonce.c_str(), nonceBytes, sizeof(nonceBytes)); - // } else if (r.empty()) { - // // create a nonce - // Utils::getSecureRandom(nonceBytes, 16); - // char nonceBuf[64] = {0}; - // Utils::hex(nonceBytes, sizeof(nonceBytes), nonceBuf); - // nonce = std::string(nonceBuf); - - // pqxx::result ir = w.exec_params0("INSERT INTO ztc_sso_expiry " - // "(nonce, nonce_expiration, network_id, member_id) VALUES " - // "($1, TO_TIMESTAMP($2::double precision/1000), $3, $4)", - // nonce, OSUtils::now() + 300000, networkId, memberId); - - // w.commit(); - // } else { - // // > 1 ?!? Thats an error! - // fprintf(stderr, "> 1 unused nonce!\n"); - // exit(6); - // } - // } else if (r.size() == 1) { - // nonce = r.at(0)[0].as(); - // Utils::unhex(nonce.c_str(), nonceBytes, sizeof(nonceBytes)); - // } else { - // // more than 1 nonce in use? Uhhh... - // fprintf(stderr, "> 1 nonce in use for network member?!?\n"); - // exit(7); - // } - - // r = w.exec_params( - // "SELECT oc.client_id, oc.authorization_endpoint, oc.issuer, oc.provider, oc.sso_impl_version " - // "FROM ztc_network AS n " - // "INNER JOIN ztc_org o " - // " ON o.owner_id = n.owner_id " - // "LEFT OUTER JOIN ztc_network_oidc_config noc " - // " ON noc.network_id = n.id " - // "LEFT OUTER JOIN ztc_oidc_config oc " - // " ON noc.client_id = oc.client_id AND oc.org_id = o.org_id " - // "WHERE n.id = $1 AND n.sso_enabled = true", networkId); - - // std::string client_id = ""; - // std::string authorization_endpoint = ""; - // std::string issuer = ""; - // std::string provider = ""; - // uint64_t sso_version = 0; - - // if (r.size() == 1) { - // client_id = r.at(0)[0].as>().value_or(""); - // authorization_endpoint = r.at(0)[1].as>().value_or(""); - // issuer = r.at(0)[2].as>().value_or(""); - // provider = r.at(0)[3].as>().value_or(""); - // sso_version = r.at(0)[4].as>().value_or(1); - // } else if (r.size() > 1) { - // fprintf(stderr, "ERROR: More than one auth endpoint for an organization?!?!? NetworkID: %s\n", networkId.c_str()); - // } else { - // fprintf(stderr, "No client or auth endpoint?!?\n"); - // } - - // info.version = sso_version; - - // // no catch all else because we don't actually care if no records exist here. just continue as normal. - // if ((!client_id.empty())&&(!authorization_endpoint.empty())) { - - // uint8_t state[48]; - // HMACSHA384(_ssoPsk, nonceBytes, sizeof(nonceBytes), state); - // char state_hex[256]; - // Utils::hex(state, 48, state_hex); - - // if (info.version == 0) { - // char url[2048] = {0}; - // OSUtils::ztsnprintf(url, sizeof(authenticationURL), - // "%s?response_type=id_token&response_mode=form_post&scope=openid+email+profile&redirect_uri=%s&nonce=%s&state=%s&client_id=%s", - // authorization_endpoint.c_str(), - // url_encode(redirectURL).c_str(), - // nonce.c_str(), - // state_hex, - // client_id.c_str()); - // info.authenticationURL = std::string(url); - // } else if (info.version == 1) { - // info.ssoClientID = client_id; - // info.issuerURL = issuer; - // info.ssoProvider = provider; - // info.ssoNonce = nonce; - // info.ssoState = std::string(state_hex) + "_" +networkId; - // info.centralAuthURL = redirectURL; - // #ifdef ZT_DEBUG - // fprintf( - // stderr, - // "ssoClientID: %s\nissuerURL: %s\nssoNonce: %s\nssoState: %s\ncentralAuthURL: %s\nprovider: %s\n", - // info.ssoClientID.c_str(), - // info.issuerURL.c_str(), - // info.ssoNonce.c_str(), - // info.ssoState.c_str(), - // info.centralAuthURL.c_str(), - // provider.c_str()); - // #endif - // } - // } else { - // fprintf(stderr, "client_id: %s\nauthorization_endpoint: %s\n", client_id.c_str(), authorization_endpoint.c_str()); - // } - // } - - // _pool->unborrow(c); - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: Error updating member on load for network %s: %s\n", networkId.c_str(), e.what()); - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - } - - return info; // std::string(authenticationURL); -} - -void CV2::initializeNetworks() -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::initializeNetworks"); - auto scope = tracer->WithActiveSpan(span); - - fprintf(stderr, "Initializing networks...\n"); - - try { - char qbuf[2048]; - sprintf( - qbuf, - "SELECT id, name, configuration , (EXTRACT(EPOCH FROM creation_time AT TIME ZONE 'UTC')*1000)::bigint, " - "(EXTRACT(EPOCH FROM last_modified AT TIME ZONE 'UTC')*1000)::bigint, revision " - "FROM networks_ctl WHERE controller_id = '%s'", - _myAddressStr.c_str()); - - auto c = _pool->borrow(); - pqxx::work w(*c->c); - - fprintf(stderr, "Load networks from psql...\n"); - auto stream = pqxx::stream_from::query(w, qbuf); - std::tuple< - std::string // network ID - , - std::optional // name - , - std::string // configuration - , - std::optional // creation_time - , - std::optional // last_modified - , - std::optional // revision - > - row; - uint64_t count = 0; - uint64_t total = 0; - while (stream >> row) { - auto start = std::chrono::high_resolution_clock::now(); - - json empty; - json config; - - initNetwork(config); - - std::string nwid = std::get<0>(row); - std::string name = std::get<1>(row).value_or(""); - json cfgtmp = json::parse(std::get<2>(row)); - std::optional created_at = std::get<3>(row); - std::optional last_modified = std::get<4>(row); - std::optional revision = std::get<5>(row); - - config["id"] = nwid; - config["name"] = name; - config["creationTime"] = created_at.value_or(0); - config["lastModified"] = last_modified.value_or(0); - config["revision"] = revision.value_or(0); - config["capabilities"] = cfgtmp["capabilities"].is_array() ? cfgtmp["capabilities"] : json::array(); - config["enableBroadcast"] = cfgtmp["enableBroadcast"].is_boolean() ? cfgtmp["enableBroadcast"].get() : false; - config["mtu"] = cfgtmp["mtu"].is_number() ? cfgtmp["mtu"].get() : 2800; - config["multicastLimit"] = cfgtmp["multicastLimit"].is_number() ? cfgtmp["multicastLimit"].get() : 64; - config["private"] = cfgtmp["private"].is_boolean() ? cfgtmp["private"].get() : true; - config["remoteTraceLevel"] = cfgtmp["remoteTraceLevel"].is_number() ? cfgtmp["remoteTraceLevel"].get() : 0; - config["remoteTraceTarget"] = cfgtmp["remoteTraceTarget"].is_string() ? cfgtmp["remoteTraceTarget"].get() : ""; - config["revision"] = revision.value_or(0); - config["rules"] = cfgtmp["rules"].is_array() ? cfgtmp["rules"] : json::array(); - config["tags"] = cfgtmp["tags"].is_array() ? cfgtmp["tags"] : json::array(); - if (cfgtmp["v4AssignMode"].is_object()) { - config["v4AssignMode"] = cfgtmp["v4AssignMode"]; - } - else { - config["v4AssignMode"] = json::object(); - config["v4AssignMode"]["zt"] = true; - } - if (cfgtmp["v6AssignMode"].is_object()) { - config["v6AssignMode"] = cfgtmp["v6AssignMode"]; - } - else { - config["v6AssignMode"] = json::object(); - config["v6AssignMode"]["zt"] = true; - config["v6AssignMode"]["6plane"] = true; - config["v6AssignMode"]["rfc4193"] = false; - } - config["ssoEnabled"] = cfgtmp["ssoEnabled"].is_boolean() ? cfgtmp["ssoEnabled"].get() : false; - config["objtype"] = "network"; - config["routes"] = cfgtmp["routes"].is_array() ? cfgtmp["routes"] : json::array(); - config["clientId"] = cfgtmp["clientId"].is_string() ? cfgtmp["clientId"].get() : ""; - config["authorizationEndpoint"] = cfgtmp["authorizationEndpoint"].is_string() ? cfgtmp["authorizationEndpoint"].get() : nullptr; - config["provider"] = cfgtmp["ssoProvider"].is_string() ? cfgtmp["ssoProvider"].get() : ""; - if (! cfgtmp["dns"].is_object()) { - cfgtmp["dns"] = json::object(); - cfgtmp["dns"]["domain"] = ""; - cfgtmp["dns"]["servers"] = json::array(); - } - else { - config["dns"] = cfgtmp["dns"]; - } - config["ipAssignmentPools"] = cfgtmp["ipAssignmentPools"].is_array() ? cfgtmp["ipAssignmentPools"] : json::array(); - - Metrics::network_count++; - - _networkChanged(empty, config, false); - - auto end = std::chrono::high_resolution_clock::now(); - auto dur = std::chrono::duration_cast(end - start); - ; - total += dur.count(); - ++count; - if (count > 0 && count % 10000 == 0) { - fprintf(stderr, "Averaging %lu us per network\n", (total / count)); - } - } - - w.commit(); - _pool->unborrow(c); - fprintf(stderr, "done.\n"); - - if (++this->_ready == 2) { - if (_waitNoticePrinted) { - fprintf(stderr, "[%s] NOTICE: %.10llx controller PostgreSQL data download complete." ZT_EOL_S, _timestr(), (unsigned long long)_myAddress.toInt()); - } - _readyLock.unlock(); - } - fprintf(stderr, "network init done\n"); - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: Error initializing networks: %s\n", e.what()); - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - std::this_thread::sleep_for(std::chrono::milliseconds(5000)); - exit(-1); - } -} - -void CV2::initializeMembers() -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::initializeMembers"); - auto scope = tracer->WithActiveSpan(span); - - std::string memberId; - std::string networkId; - try { - char qbuf[2048]; - sprintf( - qbuf, - "SELECT nm.device_id, nm.network_id, nm.authorized, nm.active_bridge, nm.ip_assignments, nm.no_auto_assign_ips, " - "nm.sso_exempt, (EXTRACT(EPOCH FROM nm.authentication_expiry_time AT TIME ZONE 'UTC')*1000)::bigint, " - "(EXTRACT(EPOCH FROM nm.creation_time AT TIME ZONE 'UTC')*1000)::bigint, nm.identity, " - "(EXTRACT(EPOCH FROM nm.last_authorized_time AT TIME ZONE 'UTC')*1000)::bigint, " - "(EXTRACT(EPOCH FROM nm.last_deauthorized_time AT TIME ZONE 'UTC')*1000)::bigint, " - "nm.remote_trace_level, nm.remote_trace_target, nm.revision, nm.capabilities, nm.tags " - "FROM network_memberships_ctl nm " - "INNER JOIN networks_ctl n " - " ON nm.network_id = n.id " - "WHERE n.controller_id = '%s'", - _myAddressStr.c_str()); - - auto c = _pool->borrow(); - pqxx::work w(*c->c); - fprintf(stderr, "Load members from psql...\n"); - auto stream = pqxx::stream_from::query(w, qbuf); - std::tuple< - std::string // device ID - , - std::string // network ID - , - bool // authorized - , - std::optional // active_bridge - , - std::optional // ip_assignments - , - std::optional // no_auto_assign_ips - , - std::optional // sso_exempt - , - std::optional // authentication_expiry_time - , - std::optional // creation_time - , - std::optional // identity - , - std::optional // last_authorized_time - , - std::optional // last_deauthorized_time - , - std::optional // remote_trace_level - , - std::optional // remote_trace_target - , - std::optional // revision - , - std::optional // capabilities - , - std::optional // tags - > - row; - - uint64_t count = 0; - uint64_t total = 0; - while (stream >> row) { - auto start = std::chrono::high_resolution_clock::now(); - json empty; - json config; - - initMember(config); - - memberId = std::get<0>(row); - networkId = std::get<1>(row); - bool authorized = std::get<2>(row); - std::optional active_bridge = std::get<3>(row); - std::string ip_assignments = std::get<4>(row).value_or(""); - std::optional no_auto_assign_ips = std::get<5>(row); - std::optional sso_exempt = std::get<6>(row); - std::optional authentication_expiry_time = std::get<7>(row); - std::optional creation_time = std::get<8>(row); - std::optional identity = std::get<9>(row); - std::optional last_authorized_time = std::get<10>(row); - std::optional last_deauthorized_time = std::get<11>(row); - std::optional remote_trace_level = std::get<12>(row); - std::optional remote_trace_target = std::get<13>(row); - std::optional revision = std::get<14>(row); - std::optional capabilities = std::get<15>(row); - std::optional tags = std::get<16>(row); - - config["objtype"] = "member"; - config["id"] = memberId; - config["address"] = identity.value_or(""); - config["nwid"] = networkId; - config["authorized"] = authorized; - config["activeBridge"] = active_bridge.value_or(false); - config["ipAssignments"] = json::array(); - if (ip_assignments != "{}") { - std::string tmp = ip_assignments.substr(1, ip_assignments.length() - 2); - std::vector addrs = split(tmp, ','); - for (auto it = addrs.begin(); it != addrs.end(); ++it) { - config["ipAssignments"].push_back(*it); - } - } - config["capabilities"] = json::parse(capabilities.value_or("[]")); - config["creationTime"] = creation_time.value_or(0); - config["lastAuthorizedTime"] = last_authorized_time.value_or(0); - config["lastDeauthorizedTime"] = last_deauthorized_time.value_or(0); - config["noAutoAssignIPs"] = no_auto_assign_ips.value_or(false); - config["remoteTraceLevel"] = remote_trace_level.value_or(0); - config["remoteTraceTarget"] = remote_trace_target.value_or(nullptr); - config["revision"] = revision.value_or(0); - config["ssoExempt"] = sso_exempt.value_or(false); - config["authenticationExpiryTime"] = authentication_expiry_time.value_or(0); - config["tags"] = json::parse(tags.value_or("[]")); - - Metrics::member_count++; - - _memberChanged(empty, config, false); - - memberId = ""; - networkId = ""; - - auto end = std::chrono::high_resolution_clock::now(); - auto dur = std::chrono::duration_cast(end - start); - total += dur.count(); - ++count; - if (count > 0 && count % 10000 == 0) { - fprintf(stderr, "Averaging %lu us per member\n", (total / count)); - } - } - if (count > 0) { - fprintf(stderr, "Took %lu us per member to load\n", (total / count)); - } - - stream.complete(); - w.commit(); - _pool->unborrow(c); - fprintf(stderr, "done.\n"); - - if (++this->_ready == 2) { - if (_waitNoticePrinted) { - fprintf(stderr, "[%s] NOTICE: %.10llx controller PostgreSQL data download complete." ZT_EOL_S, _timestr(), (unsigned long long)_myAddress.toInt()); - } - _readyLock.unlock(); - } - fprintf(stderr, "member init done\n"); - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: Error initializing member: %s-%s %s\n", networkId.c_str(), memberId.c_str(), e.what()); - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - exit(-1); - } -} - -void CV2::heartbeat() -{ - char publicId[1024]; - char hostnameTmp[1024]; - _myId.toString(false, publicId); - if (gethostname(hostnameTmp, sizeof(hostnameTmp)) != 0) { - hostnameTmp[0] = (char)0; - } - else { - for (int i = 0; i < (int)sizeof(hostnameTmp); ++i) { - if ((hostnameTmp[i] == '.') || (hostnameTmp[i] == 0)) { - hostnameTmp[i] = (char)0; - break; - } - } - } - const char* controllerId = _myAddressStr.c_str(); - const char* publicIdentity = publicId; - const char* hostname = hostnameTmp; - - while (_run == 1) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::heartbeat"); - auto scope = tracer->WithActiveSpan(span); - - auto c = _pool->borrow(); - int64_t ts = OSUtils::now(); - - if (c->c) { - std::string major = std::to_string(ZEROTIER_ONE_VERSION_MAJOR); - std::string minor = std::to_string(ZEROTIER_ONE_VERSION_MINOR); - std::string rev = std::to_string(ZEROTIER_ONE_VERSION_REVISION); - std::string version = major + "." + minor + "." + rev; - std::string versionStr = "v" + version; - - try { - pqxx::work w { *c->c }; - w.exec_params0( - "INSERT INTO controllers_ctl (id, hostname, last_heartbeat, public_identity, version) VALUES " - "($1, $2, TO_TIMESTAMP($3::double precision/1000), $4, $5) " - "ON CONFLICT (id) DO UPDATE SET hostname = EXCLUDED.hostname, last_heartbeat = EXCLUDED.last_heartbeat, " - "public_identity = EXCLUDED.public_identity, version = EXCLUDED.version", - controllerId, - hostname, - ts, - publicIdentity, - versionStr); - w.commit(); - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: Error in heartbeat: %s\n", e.what()); - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - continue; - } - catch (...) { - fprintf(stderr, "ERROR: Unknown error in heartbeat\n"); - span->SetStatus(opentelemetry::trace::StatusCode::kError, "Unknown error in heartbeat"); - continue; - } - } - - _pool->unborrow(c); - span->End(); - - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - fprintf(stderr, "Exited heartbeat thread\n"); -} - -void CV2::membersDbWatcher() -{ - auto c = _pool->borrow(); - - std::string stream = "member_" + _myAddressStr; - - fprintf(stderr, "Listening to member stream: %s\n", stream.c_str()); - MemberNotificationReceiver m(this, *c->c, stream); - - while (_run == 1) { - c->c->await_notification(5, 0); - } - - _pool->unborrow(c); - - fprintf(stderr, "Exited membersDbWatcher\n"); -} - -void CV2::networksDbWatcher() -{ - std::string stream = "network_" + _myAddressStr; - - fprintf(stderr, "Listening to member stream: %s\n", stream.c_str()); - - auto c = _pool->borrow(); - - NetworkNotificationReceiver n(this, *c->c, stream); - - while (_run == 1) { - c->c->await_notification(5, 0); - } - - _pool->unborrow(c); - fprintf(stderr, "Exited networksDbWatcher\n"); -} - -void CV2::commitThread() -{ - fprintf(stderr, "%s: commitThread start\n", _myAddressStr.c_str()); - std::pair qitem; - while (_commitQueue.get(qitem) && (_run == 1)) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::commitThread"); - auto scope = tracer->WithActiveSpan(span); - - // fprintf(stderr, "commitThread tick\n"); - if (! qitem.first.is_object()) { - fprintf(stderr, "not an object\n"); - continue; - } - - std::shared_ptr c; - try { - c = _pool->borrow(); - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: %s\n", e.what()); - continue; - } - - if (! c) { - fprintf(stderr, "Error getting database connection\n"); - continue; - } - - Metrics::pgsql_commit_ticks++; - try { - nlohmann::json& config = (qitem.first); - const std::string objtype = config["objtype"]; - if (objtype == "member") { - auto mspan = tracer->StartSpan("cv2::commitThread::member"); - auto mscope = tracer->WithActiveSpan(span); - - // fprintf(stderr, "%s: commitThread: member\n", _myAddressStr.c_str()); - std::string memberId; - std::string networkId; - try { - pqxx::work w(*c->c); - - memberId = config["id"]; - networkId = config["nwid"]; - - std::string target = "NULL"; - if (! config["remoteTraceTarget"].is_null()) { - target = config["remoteTraceTarget"]; - } - - pqxx::row nwrow = w.exec_params1("SELECT COUNT(id) FROM networks WHERE id = $1", networkId); - int nwcount = nwrow[0].as(); - - if (nwcount != 1) { - fprintf(stderr, "network %s does not exist. skipping member upsert\n", networkId.c_str()); - w.abort(); - _pool->unborrow(c); - continue; - } - - // only needed for hooks, and no hooks for now - // pqxx::row mrow = w.exec_params1("SELECT COUNT(id) FROM device_networks WHERE device_id = $1 AND network_id = $2", memberId, networkId); - // int membercount = mrow[0].as(); - // bool isNewMember = (membercount == 0); - - pqxx::result res = w.exec_params0( - "INSERT INTO network_memberships_ctl (device_id, network_id, authorized, active_bridge, ip_assignments, " - "no_auto_assign_ips, sso_exempt, authentication_expiry_time, capabilities, creation_time, " - "identity, last_authorized_time, last_deauthorized_time, " - "remote_trace_level, remote_trace_target, revision, tags, version_major, version_minor, " - "version_revision, version_protocol) " - "VALUES ($1, $2, $3, $4, $5, $6, $7, TO_TIMESTAMP($8::double precision/1000), $9, " - "TO_TIMESTAMP($10::double precision/1000), $11, TO_TIMESTAMP($12::double precision/1000), " - "TO_TIMESTAMP($13::double precision/1000), $14, $15, $16, $17, $18, $19, $20, $21) " - "ON CONFLICT (device_id, network_id) DO UPDATE SET " - "authorized = EXCLUDED.authorized, active_bridge = EXCLUDED.active_bridge, " - "ip_assignments = EXCLUDED.ip_assignments, no_auto_assign_ips = EXCLUDED.no_auto_assign_ips, " - "sso_exempt = EXCLUDED.sso_exempt, authentication_expiry_time = EXCLUDED.authentication_expiry_time, " - "capabilities = EXCLUDED.capabilities, creation_time = EXCLUDED.creation_time, " - "identity = EXCLUDED.identity, last_authorized_time = EXCLUDED.last_authorized_time, " - "last_deauthorized_time = EXCLUDED.last_deauthorized_time, " - "remote_trace_level = EXCLUDED.remote_trace_level, remote_trace_target = EXCLUDED.remote_trace_target, " - "revision = EXCLUDED.revision, tags = EXCLUDED.tags, version_major = EXCLUDED.version_major, " - "version_minor = EXCLUDED.version_minor, version_revision = EXCLUDED.version_revision, " - "version_protocol = EXCLUDED.version_protocol", - memberId, - networkId, - (bool)config["authorized"], - (bool)config["activeBridge"], - config["ipAssignments"].get >(), - (bool)config["noAutoAssignIps"], - (bool)config["ssoExempt"], - (uint64_t)config["authenticationExpiryTime"], - OSUtils::jsonDump(config["capabilities"], -1), - (uint64_t)config["creationTime"], - OSUtils::jsonString(config["identity"], ""), - (uint64_t)config["lastAuthorizedTime"], - (uint64_t)config["lastDeauthorizedTime"], - (int)config["remoteTraceLevel"], - target, - (uint64_t)config["revision"], - OSUtils::jsonDump(config["tags"], -1), - (int)config["vMajor"], - (int)config["vMinor"], - (int)config["vRev"], - (int)config["vProto"]); - - w.commit(); - - // No hooks for now - // if (_smee != NULL && isNewMember) { - // pqxx::row row = w.exec_params1( - // "SELECT " - // " count(h.hook_id) " - // "FROM " - // " ztc_hook h " - // " INNER JOIN ztc_org o ON o.org_id = h.org_id " - // " INNER JOIN ztc_network n ON n.owner_id = o.owner_id " - // " WHERE " - // "n.id = $1 ", - // networkId - // ); - // int64_t hookCount = row[0].as(); - // if (hookCount > 0) { - // notifyNewMember(networkId, memberId); - // } - // } - - const uint64_t nwidInt = OSUtils::jsonIntHex(config["nwid"], 0ULL); - const uint64_t memberidInt = OSUtils::jsonIntHex(config["id"], 0ULL); - if (nwidInt && memberidInt) { - nlohmann::json nwOrig; - nlohmann::json memOrig; - - nlohmann::json memNew(config); - - get(nwidInt, nwOrig, memberidInt, memOrig); - - _memberChanged(memOrig, memNew, qitem.second); - } - else { - fprintf(stderr, "%s: Can't notify of change. Error parsing nwid or memberid: %llu-%llu\n", _myAddressStr.c_str(), (unsigned long long)nwidInt, (unsigned long long)memberidInt); - } - } - catch (pqxx::data_exception& e) { - std::string cfgDump = OSUtils::jsonDump(config, 2); - fprintf(stderr, "Member save %s-%s: %s\n", networkId.c_str(), memberId.c_str(), cfgDump.c_str()); - - const pqxx::sql_error* s = dynamic_cast(&e); - fprintf(stderr, "%s ERROR: Error updating member: %s\n", _myAddressStr.c_str(), e.what()); - if (s) { - fprintf(stderr, "%s ERROR: SQL error: %s\n", _myAddressStr.c_str(), s->query().c_str()); - } - mspan->SetStatus(opentelemetry::trace::StatusCode::kError, "pqxx::data_exception"); - mspan->SetAttribute("error", e.what()); - mspan->SetAttribute("config", cfgDump); - } - catch (std::exception& e) { - std::string cfgDump = OSUtils::jsonDump(config, 2); - fprintf(stderr, "%s ERROR: Error updating member %s-%s: %s\njsonDump: %s\n", _myAddressStr.c_str(), networkId.c_str(), memberId.c_str(), e.what(), cfgDump.c_str()); - mspan->SetStatus(opentelemetry::trace::StatusCode::kError, "std::exception"); - mspan->SetAttribute("error", e.what()); - mspan->SetAttribute("config", cfgDump); - } - } - else if (objtype == "network") { - auto nspan = tracer->StartSpan("cv2::commitThread::network"); - auto nscope = tracer->WithActiveSpan(span); - - try { - // fprintf(stderr, "%s: commitThread: network\n", _myAddressStr.c_str()); - pqxx::work w(*c->c); - - std::string id = config["id"]; - - // network must already exist - pqxx::result res = w.exec_params0( - "INSERT INTO networks_ctl (id, name, configuration, controller_id, revision) " - "VALUES ($1, $2, $3, $4, $5) " - "ON CONFLICT (id) DO UPDATE SET " - "name = EXCLUDED.name, configuration = EXCLUDED.configuration, revision = EXCLUDED.revision+1", - id, - OSUtils::jsonString(config["name"], ""), - OSUtils::jsonDump(config, -1), - _myAddressStr, - ((uint64_t)config["revision"])); - - w.commit(); - - const uint64_t nwidInt = OSUtils::jsonIntHex(config["nwid"], 0ULL); - if (nwidInt) { - nlohmann::json nwOrig; - nlohmann::json nwNew(config); - - get(nwidInt, nwOrig); - - _networkChanged(nwOrig, nwNew, qitem.second); - } - else { - fprintf(stderr, "%s: Can't notify network changed: %llu\n", _myAddressStr.c_str(), (unsigned long long)nwidInt); - } - } - catch (pqxx::data_exception& e) { - const pqxx::sql_error* s = dynamic_cast(&e); - fprintf(stderr, "%s ERROR: Error updating network: %s\n", _myAddressStr.c_str(), e.what()); - if (s) { - fprintf(stderr, "%s ERROR: SQL error: %s\n", _myAddressStr.c_str(), s->query().c_str()); - } - nspan->SetStatus(opentelemetry::trace::StatusCode::kError, "pqxx::data_exception"); - nspan->SetAttribute("error", e.what()); - nspan->SetAttribute("config", OSUtils::jsonDump(config, 2)); - } - catch (std::exception& e) { - fprintf(stderr, "%s ERROR: Error updating network: %s\n", _myAddressStr.c_str(), e.what()); - nspan->SetStatus(opentelemetry::trace::StatusCode::kError, "std::exception"); - nspan->SetAttribute("error", e.what()); - nspan->SetAttribute("config", OSUtils::jsonDump(config, 2)); - } - } - else if (objtype == "_delete_network") { - auto dspan = tracer->StartSpan("cv2::commitThread::delete_network"); - auto dscope = tracer->WithActiveSpan(span); - - // fprintf(stderr, "%s: commitThread: delete network\n", _myAddressStr.c_str()); - try { - pqxx::work w(*c->c); - std::string networkId = config["id"]; - fprintf(stderr, "Deleting network %s\n", networkId.c_str()); - w.exec_params0("DELETE FROM network_memberships_ctl WHERE network_id = $1", networkId); - w.exec_params0("DELETE FROM networks_ctl WHERE id = $1", networkId); - - w.commit(); - - uint64_t nwidInt = OSUtils::jsonIntHex(config["nwid"], 0ULL); - json oldConfig; - get(nwidInt, oldConfig); - json empty; - _networkChanged(oldConfig, empty, qitem.second); - } - catch (std::exception& e) { - fprintf(stderr, "%s ERROR: Error deleting network: %s\n", _myAddressStr.c_str(), e.what()); - dspan->SetStatus(opentelemetry::trace::StatusCode::kError, "std::exception"); - dspan->SetAttribute("error", e.what()); - dspan->SetAttribute("config", OSUtils::jsonDump(config, 2)); - } - } - else if (objtype == "_delete_member") { - auto dspan = tracer->StartSpan("cv2::commitThread::delete_member"); - auto dscope = tracer->WithActiveSpan(span); - - // fprintf(stderr, "%s commitThread: delete member\n", _myAddressStr.c_str()); - try { - pqxx::work w(*c->c); - - std::string memberId = config["id"]; - std::string networkId = config["nwid"]; - - pqxx::result res = w.exec_params0("DELETE FROM network_memberships_ctl WHERE device_id = $1 AND network_id = $2", memberId, networkId); - - w.commit(); - - uint64_t nwidInt = OSUtils::jsonIntHex(config["nwid"], 0ULL); - uint64_t memberidInt = OSUtils::jsonIntHex(config["id"], 0ULL); - - nlohmann::json networkConfig; - nlohmann::json oldConfig; - - get(nwidInt, networkConfig, memberidInt, oldConfig); - json empty; - _memberChanged(oldConfig, empty, qitem.second); - } - catch (std::exception& e) { - fprintf(stderr, "%s ERROR: Error deleting member: %s\n", _myAddressStr.c_str(), e.what()); - dspan->SetStatus(opentelemetry::trace::StatusCode::kError, "std::exception"); - dspan->SetAttribute("error", e.what()); - dspan->SetAttribute("config", OSUtils::jsonDump(config, 2)); - } - } - else { - fprintf(stderr, "%s ERROR: unknown objtype\n", _myAddressStr.c_str()); - } - } - catch (std::exception& e) { - fprintf(stderr, "%s ERROR: Error getting objtype: %s\n", _myAddressStr.c_str(), e.what()); - span->SetStatus(opentelemetry::trace::StatusCode::kError, "std::exception"); - span->SetAttribute("error", e.what()); - } - _pool->unborrow(c); - c.reset(); - } - - fprintf(stderr, "%s commitThread finished\n", _myAddressStr.c_str()); -} - -void CV2::onlineNotificationThread() -{ - waitForReady(); - - _connected = 1; - - nlohmann::json jtmp1, jtmp2; - while (_run == 1) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("cv2"); - auto span = tracer->StartSpan("cv2::onlineNotificationThread"); - auto scope = tracer->WithActiveSpan(span); - - auto c = _pool->borrow(); - auto c2 = _pool->borrow(); - - try { - fprintf(stderr, "%s onlineNotificationThread\n", _myAddressStr.c_str()); - - std::unordered_map, NodeOnlineRecord, _PairHasher> lastOnline; - { - std::lock_guard l(_lastOnline_l); - lastOnline.swap(_lastOnline); - } - - pqxx::work w(*c->c); - pqxx::work w2(*c2->c); - - bool firstRun = true; - bool memberAdded = false; - uint64_t updateCount = 0; - - pqxx::pipeline pipe(w); - - for (auto i = lastOnline.begin(); i != lastOnline.end(); ++i) { - updateCount++; - - uint64_t nwid_i = i->first.first; - char nwidTmp[64]; - char memTmp[64]; - char ipTmp[64]; - - OSUtils::ztsnprintf(nwidTmp, sizeof(nwidTmp), "%.16llx", nwid_i); - OSUtils::ztsnprintf(memTmp, sizeof(memTmp), "%.10llx", i->first.second); - - if (! get(nwid_i, jtmp1, i->first.second, jtmp2)) { - continue; // skip non existent networks/members - } - - std::string networkId(nwidTmp); - std::string memberId(memTmp); - - try { - pqxx::row r = w2.exec_params1("SELECT device_id, network_id FROM network_memberships_ctl WHERE network_id = $1 AND device_id = $2", networkId, memberId); - } - catch (pqxx::unexpected_rows& e) { - continue; - } - - int64_t ts = i->second.lastSeen; - std::string ipAddr = i->second.physicalAddress.toIpString(ipTmp); - std::string timestamp = std::to_string(ts); - std::string osArch = i->second.osArch; - std::vector osArchSplit = split(osArch, '/'); - std::string os = osArchSplit[0]; - std::string arch = osArchSplit[1]; - - if (ipAddr.empty()) { - ipAddr = "relayed"; - } - - json record = { - { ipAddr, ts }, - }; - - std::string device_network_insert = "INSERT INTO network_memberships_ctl (device_id, network_id, last_seen, os, arch) " - "VALUES ('" - + w2.esc(memberId) + "', '" + w2.esc(networkId) + "', '" + w2.esc(record.dump()) - + "'::JSONB, " - "'" - + w2.esc(os) + "', '" + w2.esc(arch) - + "') " - "ON CONFLICT (device_id, network_id) DO UPDATE SET os = EXCLUDED.os, arch = EXCLUDED.arch, " - "last_seen = network_memberships_ctl.last_seen || EXCLUDED.last_seen"; - pipe.insert(device_network_insert); - - Metrics::pgsql_node_checkin++; - } - - pipe.complete(); - ; - w2.commit(); - w.commit(); - fprintf(stderr, "%s: Updated online status of %lu members\n", _myAddressStr.c_str(), updateCount); - } - catch (std::exception& e) { - fprintf(stderr, "%s ERROR: Error in onlineNotificationThread: %s\n", _myAddressStr.c_str(), e.what()); - span->SetStatus(opentelemetry::trace::StatusCode::kError, "std::exception"); - span->SetAttribute("error", e.what()); - } - catch (...) { - fprintf(stderr, "%s ERROR: Unknown error in onlineNotificationThread\n", _myAddressStr.c_str()); - span->SetStatus(opentelemetry::trace::StatusCode::kError, "unknown"); - } - _pool->unborrow(c2); - _pool->unborrow(c); - span->End(); - - std::this_thread::sleep_for(std::chrono::seconds(10)); - } - - fprintf(stderr, "%s: Fell out of run loop in onlineNotificationThread\n", _myAddressStr.c_str()); - if (_run == 1) { - fprintf(stderr, "ERROR: %s onlineNotificationThread should still be running! Exiting Controller.\n", _myAddressStr.c_str()); - exit(6); - } -} -#endif // ZT_CONTROLLER_USE_LIBPQ \ No newline at end of file diff --git a/controller/CV2.hpp b/controller/CV2.hpp deleted file mode 100644 index 09501e021..000000000 --- a/controller/CV2.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c)2025 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "DB.hpp" - -#ifdef ZT_CONTROLLER_USE_LIBPQ - -#ifndef ZT_CONTROLLER_CV2_HPP -#define ZT_CONTROLLER_CV2_HPP - -#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 - -#include "../node/Metrics.hpp" -#include "ConnectionPool.hpp" -#include "PostgreSQL.hpp" - -#include -#include -#include - -namespace ZeroTier { - -class CV2 : public DB { - friend class MemberNotificationReceiver; - friend class NetworkNotificationReceiver; - - public: - CV2(const Identity& myId, const char* path, int listenPort); - virtual ~CV2(); - - virtual bool waitForReady(); - virtual bool isReady(); - virtual bool save(nlohmann::json& record, bool notifyListeners); - virtual void eraseNetwork(const uint64_t networkId); - virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); - virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL); - - virtual bool ready() - { - return _ready == 2; - } - - protected: - struct _PairHasher { - inline std::size_t operator()(const std::pair& p) const - { - return (std::size_t)(p.first ^ p.second); - } - }; - virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners); - - virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners); - - private: - void initializeNetworks(); - void initializeMembers(); - void heartbeat(); - void membersDbWatcher(); - void networksDbWatcher(); - - void commitThread(); - void onlineNotificationThread(); - - // void notifyNewMember(const std::string &networkID, const std::string &memberID); - - enum OverrideMode { ALLOW_PGBOUNCER_OVERRIDE = 0, NO_OVERRIDE = 1 }; - - std::shared_ptr > _pool; - - const Identity _myId; - const Address _myAddress; - std::string _myAddressStr; - std::string _connString; - - BlockingQueue > _commitQueue; - - std::thread _heartbeatThread; - std::thread _membersDbWatcher; - std::thread _networksDbWatcher; - std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS]; - std::thread _onlineNotificationThread; - - std::unordered_map, NodeOnlineRecord, _PairHasher> _lastOnline; - - mutable std::mutex _lastOnline_l; - mutable std::mutex _readyLock; - std::atomic _ready, _connected, _run; - mutable volatile bool _waitNoticePrinted; - - int _listenPort; - uint8_t _ssoPsk[48]; -}; - -} // namespace ZeroTier - -#endif // ZT_CONTROLLER_CV2_HPP -#endif // ZT_CONTROLLER_USE_LIBPQ \ No newline at end of file diff --git a/controller/ConnectionPool.hpp b/controller/ConnectionPool.hpp deleted file mode 100644 index 75690fab4..000000000 --- a/controller/ConnectionPool.hpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c)2021 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_CONNECTION_POOL_H_ -#define ZT_CONNECTION_POOL_H_ - -#ifndef _DEBUG -#define _DEBUG(x) -#endif - -#include "../node/Metrics.hpp" -#include "opentelemetry/trace/provider.h" - -#include -#include -#include -#include -#include -#include - -namespace ZeroTier { - -struct ConnectionUnavailable : std::exception { - char const* what() const throw() - { - return "Unable to allocate connection"; - }; -}; - -class Connection { - public: - virtual ~Connection() {}; -}; - -class ConnectionFactory { - public: - virtual ~ConnectionFactory() {}; - virtual std::shared_ptr create() = 0; -}; - -struct ConnectionPoolStats { - size_t pool_size; - size_t borrowed_size; -}; - -template class ConnectionPool { - public: - ConnectionPool(size_t max_pool_size, size_t min_pool_size, std::shared_ptr factory) : m_maxPoolSize(max_pool_size), m_minPoolSize(min_pool_size), m_factory(factory) - { - Metrics::max_pool_size += max_pool_size; - Metrics::min_pool_size += min_pool_size; - while (m_pool.size() < m_minPoolSize) { - m_pool.push_back(m_factory->create()); - Metrics::pool_avail++; - } - }; - - ConnectionPoolStats get_stats() - { - std::unique_lock lock(m_poolMutex); - - ConnectionPoolStats stats; - stats.pool_size = m_pool.size(); - stats.borrowed_size = m_borrowed.size(); - - return stats; - }; - - ~ConnectionPool() {}; - - /** - * Borrow - * - * Borrow a connection for temporary use - * - * When done, either (a) call unborrow() to return it, or (b) (if it's bad) just let it go out of scope. This will cause it to automatically be replaced. - * @retval a shared_ptr to the connection object - */ - std::shared_ptr borrow() - { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("connection_pool"); - auto span = tracer->StartSpan("connection_pool::borrow"); - auto scope = tracer->WithActiveSpan(span); - - std::unique_lock l(m_poolMutex); - - while ((m_pool.size() + m_borrowed.size()) < m_minPoolSize) { - std::shared_ptr conn = m_factory->create(); - m_pool.push_back(conn); - Metrics::pool_avail++; - } - - if (m_pool.size() == 0) { - if ((m_pool.size() + m_borrowed.size()) < m_maxPoolSize) { - try { - std::shared_ptr conn = m_factory->create(); - m_borrowed.insert(conn); - Metrics::pool_in_use++; - return std::static_pointer_cast(conn); - } - catch (std::exception& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - Metrics::pool_errors++; - throw ConnectionUnavailable(); - } - } - else { - for (auto it = m_borrowed.begin(); it != m_borrowed.end(); ++it) { - if ((*it).unique()) { - // This connection has been abandoned! Destroy it and create a new connection - try { - // If we are able to create a new connection, return it - _DEBUG("Creating new connection to replace discarded connection"); - std::shared_ptr conn = m_factory->create(); - m_borrowed.erase(it); - m_borrowed.insert(conn); - return std::static_pointer_cast(conn); - } - catch (std::exception& e) { - span->SetStatus(opentelemetry::trace::StatusCode::kError, e.what()); - // Error creating a replacement connection - Metrics::pool_errors++; - throw ConnectionUnavailable(); - } - } - } - - span->SetStatus(opentelemetry::trace::StatusCode::kError, "No available connections in pool"); - // Nothing available - Metrics::pool_errors++; - throw ConnectionUnavailable(); - } - } - - // Take one off the front - std::shared_ptr conn = m_pool.front(); - m_pool.pop_front(); - Metrics::pool_avail--; - // Add it to the borrowed list - m_borrowed.insert(conn); - Metrics::pool_in_use++; - return std::static_pointer_cast(conn); - }; - - /** - * Unborrow a connection - * - * Only call this if you are returning a working connection. If the connection was bad, just let it go out of scope (so the connection manager can replace it). - * @param the connection - */ - void unborrow(std::shared_ptr conn) - { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("connection_pool"); - auto span = tracer->StartSpan("connection_pool::unborrow"); - auto scope = tracer->WithActiveSpan(span); - - // Lock - std::unique_lock lock(m_poolMutex); - m_borrowed.erase(conn); - Metrics::pool_in_use--; - if ((m_pool.size() + m_borrowed.size()) < m_maxPoolSize) { - Metrics::pool_avail++; - m_pool.push_back(conn); - } - }; - - protected: - size_t m_maxPoolSize; - size_t m_minPoolSize; - std::shared_ptr m_factory; - std::deque > m_pool; - std::set > m_borrowed; - std::mutex m_poolMutex; -}; - -} // namespace ZeroTier - -#endif diff --git a/controller/CtlUtil.cpp b/controller/CtlUtil.cpp deleted file mode 100644 index e1e82f7a3..000000000 --- a/controller/CtlUtil.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "CtlUtil.hpp" - -#ifdef ZT_CONTROLLER_USE_LIBPQ - -#include -#include - -namespace ZeroTier { - -const char* _timestr() -{ - time_t t = time(0); - char* ts = ctime(&t); - char* p = ts; - if (! p) - return ""; - while (*p) { - if (*p == '\n') { - *p = (char)0; - break; - } - ++p; - } - return ts; -} - -std::vector split(std::string str, char delim) -{ - std::istringstream iss(str); - std::vector tokens; - std::string item; - while (std::getline(iss, item, delim)) { - tokens.push_back(item); - } - return tokens; -} - -std::string url_encode(const std::string& value) -{ - std::ostringstream escaped; - escaped.fill('0'); - escaped << std::hex; - - for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) { - std::string::value_type c = (*i); - - // Keep alphanumeric and other accepted characters intact - if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { - escaped << c; - continue; - } - - // Any other characters are percent-encoded - escaped << std::uppercase; - escaped << '%' << std::setw(2) << int((unsigned char)c); - escaped << std::nouppercase; - } - - return escaped.str(); -} - -} // namespace ZeroTier - -#endif \ No newline at end of file diff --git a/controller/CtlUtil.hpp b/controller/CtlUtil.hpp deleted file mode 100644 index 0ba665af3..000000000 --- a/controller/CtlUtil.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef ZT_CTLUTIL_HPP -#define ZT_CTLUTIL_HPP - -#include -#include - -namespace ZeroTier { - -const char* _timestr(); - -std::vector split(std::string str, char delim); - -std::string url_encode(const std::string& value); -} // namespace ZeroTier - -#endif // namespace ZeroTier \ No newline at end of file diff --git a/controller/DB.cpp b/controller/DB.cpp deleted file mode 100644 index 4cce312ed..000000000 --- a/controller/DB.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "DB.hpp" - -#include "../node/Metrics.hpp" -#include "EmbeddedNetworkController.hpp" -#include "opentelemetry/trace/provider.h" - -#include -#include -#include - -using json = nlohmann::json; - -namespace ZeroTier { - -void DB::initNetwork(nlohmann::json& network) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::initNetwork"); - auto scope = tracer->WithActiveSpan(span); - - if (! network.count("private")) - network["private"] = true; - if (! network.count("creationTime")) - network["creationTime"] = OSUtils::now(); - if (! network.count("name")) - network["name"] = ""; - if (! network.count("multicastLimit")) - network["multicastLimit"] = (uint64_t)32; - if (! network.count("enableBroadcast")) - network["enableBroadcast"] = true; - if (! network.count("v4AssignMode")) - network["v4AssignMode"] = { { "zt", false } }; - if (! network.count("v6AssignMode")) - network["v6AssignMode"] = { { "rfc4193", false }, { "zt", false }, { "6plane", false } }; - if (! network.count("authTokens")) - network["authTokens"] = { {} }; - if (! network.count("capabilities")) - network["capabilities"] = nlohmann::json::array(); - if (! network.count("tags")) - network["tags"] = nlohmann::json::array(); - if (! network.count("routes")) - network["routes"] = nlohmann::json::array(); - if (! network.count("ipAssignmentPools")) - network["ipAssignmentPools"] = nlohmann::json::array(); - if (! network.count("mtu")) - network["mtu"] = ZT_DEFAULT_MTU; - if (! network.count("remoteTraceTarget")) - network["remoteTraceTarget"] = nlohmann::json(); - if (! network.count("removeTraceLevel")) - network["remoteTraceLevel"] = 0; - if (! network.count("rulesSource")) - network["rulesSource"] = ""; - if (! network.count("rules")) { - // If unspecified, rules are set to allow anything and behave like a flat L2 segment - network["rules"] = { { { "not", false }, { "or", false }, { "type", "ACTION_ACCEPT" } } }; - } - if (! network.count("dns")) - network["dns"] = nlohmann::json::array(); - if (! network.count("ssoEnabled")) - network["ssoEnabled"] = false; - if (! network.count("clientId")) - network["clientId"] = ""; - if (! network.count("authorizationEndpoint")) - network["authorizationEndpoint"] = ""; - - network["objtype"] = "network"; -} - -void DB::initMember(nlohmann::json& member) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::initMember"); - auto scope = tracer->WithActiveSpan(span); - - if (! member.count("authorized")) - member["authorized"] = false; - if (! member.count("ssoExempt")) - member["ssoExempt"] = false; - if (! member.count("ipAssignments")) - member["ipAssignments"] = nlohmann::json::array(); - if (! member.count("activeBridge")) - member["activeBridge"] = false; - if (! member.count("tags")) - member["tags"] = nlohmann::json::array(); - if (! member.count("capabilities")) - member["capabilities"] = nlohmann::json::array(); - if (! member.count("creationTime")) - member["creationTime"] = OSUtils::now(); - if (! member.count("noAutoAssignIps")) - member["noAutoAssignIps"] = false; - if (! member.count("revision")) - member["revision"] = 0ULL; - if (! member.count("lastDeauthorizedTime")) - member["lastDeauthorizedTime"] = 0ULL; - if (! member.count("lastAuthorizedTime")) - member["lastAuthorizedTime"] = 0ULL; - if (! member.count("lastAuthorizedCredentialType")) - member["lastAuthorizedCredentialType"] = nlohmann::json(); - if (! member.count("lastAuthorizedCredential")) - member["lastAuthorizedCredential"] = nlohmann::json(); - if (! member.count("authenticationExpiryTime")) - member["authenticationExpiryTime"] = 0LL; - if (! member.count("vMajor")) - member["vMajor"] = -1; - if (! member.count("vMinor")) - member["vMinor"] = -1; - if (! member.count("vRev")) - member["vRev"] = -1; - if (! member.count("vProto")) - member["vProto"] = -1; - if (! member.count("remoteTraceTarget")) - member["remoteTraceTarget"] = nlohmann::json(); - if (! member.count("removeTraceLevel")) - member["remoteTraceLevel"] = 0; - member["objtype"] = "member"; -} - -void DB::cleanNetwork(nlohmann::json& network) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::cleanNetwork"); - auto scope = tracer->WithActiveSpan(span); - - network.erase("clock"); - network.erase("authorizedMemberCount"); - network.erase("activeMemberCount"); - network.erase("totalMemberCount"); - network.erase("lastModified"); -} - -void DB::cleanMember(nlohmann::json& member) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::cleanMember"); - auto scope = tracer->WithActiveSpan(span); - - member.erase("clock"); - member.erase("physicalAddr"); - member.erase("recentLog"); - member.erase("lastModified"); - member.erase("lastRequestMetaData"); - member.erase("authenticationURL"); // computed - member.erase("authenticationClientID"); // computed -} - -DB::DB() -{ -} -DB::~DB() -{ -} - -bool DB::get(const uint64_t networkId, nlohmann::json& network) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::getNetwork"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - - waitForReady(); - Metrics::db_get_network++; - std::shared_ptr<_Network> nw; - { - std::shared_lock l(_networks_l); - auto nwi = _networks.find(networkId); - if (nwi == _networks.end()) - return false; - nw = nwi->second; - } - { - std::shared_lock l2(nw->lock); - network = nw->config; - } - return true; -} - -bool DB::get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::getNetworkAndMember"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex(networkId, memberIdStr)); - - waitForReady(); - Metrics::db_get_network_and_member++; - std::shared_ptr<_Network> nw; - { - std::shared_lock l(_networks_l); - auto nwi = _networks.find(networkId); - if (nwi == _networks.end()) - return false; - nw = nwi->second; - } - { - std::shared_lock l2(nw->lock); - network = nw->config; - auto m = nw->members.find(memberId); - if (m == nw->members.end()) - return false; - member = m->second; - } - return true; -} - -bool DB::get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member, NetworkSummaryInfo& info) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::getNetworkAndMemberAndSummary"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex(memberId, memberIdStr)); - - waitForReady(); - Metrics::db_get_network_and_member_and_summary++; - std::shared_ptr<_Network> nw; - { - std::shared_lock l(_networks_l); - auto nwi = _networks.find(networkId); - if (nwi == _networks.end()) - return false; - nw = nwi->second; - } - { - std::shared_lock l2(nw->lock); - network = nw->config; - _fillSummaryInfo(nw, info); - auto m = nw->members.find(memberId); - if (m == nw->members.end()) - return false; - member = m->second; - } - - return true; -} - -bool DB::get(const uint64_t networkId, nlohmann::json& network, std::vector& members) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::getNetworkAndMembers"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - - waitForReady(); - Metrics::db_get_member_list++; - std::shared_ptr<_Network> nw; - { - std::shared_lock l(_networks_l); - auto nwi = _networks.find(networkId); - if (nwi == _networks.end()) - return false; - nw = nwi->second; - } - { - std::shared_lock l2(nw->lock); - network = nw->config; - for (auto m = nw->members.begin(); m != nw->members.end(); ++m) { - members.push_back(m->second); - } - } - return true; -} - -void DB::networks(std::set& networks) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::networks"); - auto scope = tracer->WithActiveSpan(span); - - waitForReady(); - Metrics::db_get_network_list++; - std::shared_lock l(_networks_l); - for (auto n = _networks.begin(); n != _networks.end(); ++n) - networks.insert(n->first); -} - -void DB::_memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::_memberChanged"); - auto scope = tracer->WithActiveSpan(span); - - Metrics::db_member_change++; - uint64_t memberId = 0; - uint64_t networkId = 0; - bool isAuth = false; - bool wasAuth = false; - std::shared_ptr<_Network> nw; - - if (old.is_object()) { - memberId = OSUtils::jsonIntHex(old["id"], 0ULL); - networkId = OSUtils::jsonIntHex(old["nwid"], 0ULL); - if ((memberId) && (networkId)) { - { - std::unique_lock l(_networks_l); - auto nw2 = _networks.find(networkId); - if (nw2 != _networks.end()) { - nw = nw2->second; - } - } - if (nw) { - std::unique_lock l(nw->lock); - if (OSUtils::jsonBool(old["activeBridge"], false)) { - nw->activeBridgeMembers.erase(memberId); - } - wasAuth = OSUtils::jsonBool(old["authorized"], false); - if (wasAuth) { - nw->authorizedMembers.erase(memberId); - } - json& ips = old["ipAssignments"]; - if (ips.is_array()) { - for (unsigned long i = 0; i < ips.size(); ++i) { - json& ipj = ips[i]; - if (ipj.is_string()) { - const std::string ips = ipj; - InetAddress ipa(ips.c_str()); - ipa.setPort(0); - nw->allocatedIps.erase(ipa); - } - } - } - } - } - } - - if (memberConfig.is_object()) { - if (! nw) { - memberId = OSUtils::jsonIntHex(memberConfig["id"], 0ULL); - networkId = OSUtils::jsonIntHex(memberConfig["nwid"], 0ULL); - if ((! memberId) || (! networkId)) - return; - std::unique_lock l(_networks_l); - std::shared_ptr<_Network>& nw2 = _networks[networkId]; - if (! nw2) - nw2.reset(new _Network); - nw = nw2; - } - - { - std::unique_lock l(nw->lock); - - nw->members[memberId] = memberConfig; - - if (OSUtils::jsonBool(memberConfig["activeBridge"], false)) { - nw->activeBridgeMembers.insert(memberId); - } - isAuth = OSUtils::jsonBool(memberConfig["authorized"], false); - if (isAuth) { - Metrics::member_auths++; - nw->authorizedMembers.insert(memberId); - } - json& ips = memberConfig["ipAssignments"]; - if (ips.is_array()) { - for (unsigned long i = 0; i < ips.size(); ++i) { - json& ipj = ips[i]; - if (ipj.is_string()) { - const std::string ips = ipj; - InetAddress ipa(ips.c_str()); - ipa.setPort(0); - nw->allocatedIps.insert(ipa); - } - } - } - - if (! isAuth) { - const int64_t ldt = (int64_t)OSUtils::jsonInt(memberConfig["lastDeauthorizedTime"], 0ULL); - if (ldt > nw->mostRecentDeauthTime) - nw->mostRecentDeauthTime = ldt; - } - } - - if (notifyListeners) { - std::unique_lock ll(_changeListeners_l); - for (auto i = _changeListeners.begin(); i != _changeListeners.end(); ++i) { - (*i)->onNetworkMemberUpdate(this, networkId, memberId, memberConfig); - } - } - } - else if (memberId) { - if (nw) { - std::unique_lock l(nw->lock); - nw->members.erase(memberId); - } - if (networkId) { - std::unique_lock l(_networks_l); - auto er = _networkByMember.equal_range(memberId); - for (auto i = er.first; i != er.second; ++i) { - if (i->second == networkId) { - _networkByMember.erase(i); - break; - } - } - } - } - - if (notifyListeners) { - if (networkId != 0 && memberId != 0 && old.is_object() && ! memberConfig.is_object()) { - // member delete - Metrics::member_count--; - } - else if (networkId != 0 && memberId != 0 && ! old.is_object() && memberConfig.is_object()) { - // new member - Metrics::member_count++; - } - - if (! wasAuth && isAuth) { - Metrics::member_auths++; - } - else if (wasAuth && ! isAuth) { - Metrics::member_deauths++; - } - else { - Metrics::member_changes++; - } - } - - if ((notifyListeners) && ((wasAuth) && (! isAuth) && (networkId) && (memberId))) { - std::unique_lock ll(_changeListeners_l); - for (auto i = _changeListeners.begin(); i != _changeListeners.end(); ++i) { - (*i)->onNetworkMemberDeauthorize(this, networkId, memberId); - } - } -} - -void DB::_networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::_networkChanged"); - span->SetAttribute("old_network_config", old.dump()); - span->SetAttribute("network_config", networkConfig.dump()); - span->SetAttribute("notify_listeners", notifyListeners); - auto scope = tracer->WithActiveSpan(span); - - Metrics::db_network_change++; - if (notifyListeners) { - if (old.is_object() && old.contains("id") && networkConfig.is_object() && networkConfig.contains("id")) { - Metrics::network_changes++; - } - else if (! old.is_object() && networkConfig.is_object() && networkConfig.contains("id")) { - Metrics::network_count++; - } - else if (old.is_object() && old.contains("id") && ! networkConfig.is_object()) { - Metrics::network_count--; - } - } - - if (networkConfig.is_object()) { - const std::string ids = networkConfig["id"]; - const uint64_t networkId = Utils::hexStrToU64(ids.c_str()); - if (networkId) { - std::shared_ptr<_Network> nw; - { - std::unique_lock l(_networks_l); - std::shared_ptr<_Network>& nw2 = _networks[networkId]; - if (! nw2) - nw2.reset(new _Network); - nw = nw2; - } - { - std::unique_lock l2(nw->lock); - nw->config = networkConfig; - } - if (notifyListeners) { - std::unique_lock ll(_changeListeners_l); - for (auto i = _changeListeners.begin(); i != _changeListeners.end(); ++i) { - (*i)->onNetworkUpdate(this, networkId, networkConfig); - } - } - } - } - else if (old.is_object()) { - const std::string ids = old["id"]; - const uint64_t networkId = Utils::hexStrToU64(ids.c_str()); - if (networkId) { - try { - // deauth all members on the network - nlohmann::json network; - std::vector members; - this->get(networkId, network, members); - for (auto i = members.begin(); i != members.end(); ++i) { - const std::string nodeID = (*i)["id"]; - const uint64_t memberId = Utils::hexStrToU64(nodeID.c_str()); - std::unique_lock ll(_changeListeners_l); - for (auto j = _changeListeners.begin(); j != _changeListeners.end(); ++j) { - (*j)->onNetworkMemberDeauthorize(this, networkId, memberId); - } - } - } - catch (std::exception& e) { - std::cerr << "Error deauthorizing members on network delete: " << e.what() << std::endl; - } - - // delete the network - std::unique_lock l(_networks_l); - _networks.erase(networkId); - } - } -} - -void DB::_fillSummaryInfo(const std::shared_ptr<_Network>& nw, NetworkSummaryInfo& info) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db"); - auto span = tracer->StartSpan("db::_fillSummaryInfo"); - auto scope = tracer->WithActiveSpan(span); - - for (auto ab = nw->activeBridgeMembers.begin(); ab != nw->activeBridgeMembers.end(); ++ab) - info.activeBridges.push_back(Address(*ab)); - std::sort(info.activeBridges.begin(), info.activeBridges.end()); - for (auto ip = nw->allocatedIps.begin(); ip != nw->allocatedIps.end(); ++ip) - info.allocatedIps.push_back(*ip); - std::sort(info.allocatedIps.begin(), info.allocatedIps.end()); - info.authorizedMemberCount = (unsigned long)nw->authorizedMembers.size(); - info.totalMemberCount = (unsigned long)nw->members.size(); - info.mostRecentDeauthTime = nw->mostRecentDeauthTime; -} - -} // namespace ZeroTier diff --git a/controller/DB.hpp b/controller/DB.hpp deleted file mode 100644 index 01b6f1266..000000000 --- a/controller/DB.hpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_CONTROLLER_DB_HPP -#define ZT_CONTROLLER_DB_HPP - -// #define ZT_CONTROLLER_USE_LIBPQ - -#include "../node/Constants.hpp" -#include "../node/Identity.hpp" -#include "../node/InetAddress.hpp" -#include "../osdep/BlockingQueue.hpp" -#include "../osdep/OSUtils.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ZT_MEMBER_AUTH_TIMEOUT_NOTIFY_BEFORE 25000 - -namespace ZeroTier { - -struct AuthInfo { - public: - AuthInfo() : enabled(false), version(0), authenticationURL(), authenticationExpiryTime(0), issuerURL(), centralAuthURL(), ssoNonce(), ssoState(), ssoClientID(), ssoProvider("default") - { - } - - bool enabled; - uint64_t version; - std::string authenticationURL; - uint64_t authenticationExpiryTime; - std::string issuerURL; - std::string centralAuthURL; - std::string ssoNonce; - std::string ssoState; - std::string ssoClientID; - std::string ssoProvider; -}; - -/** - * Base class with common infrastructure for all controller DB implementations - */ -class DB { - public: - class ChangeListener { - public: - ChangeListener() - { - } - virtual ~ChangeListener() - { - } - virtual void onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network) - { - } - virtual void onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member) - { - } - virtual void onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId) - { - } - }; - - struct NetworkSummaryInfo { - NetworkSummaryInfo() : authorizedMemberCount(0), totalMemberCount(0), mostRecentDeauthTime(0) - { - } - std::vector
activeBridges; - std::vector allocatedIps; - unsigned long authorizedMemberCount; - unsigned long totalMemberCount; - int64_t mostRecentDeauthTime; - }; - - static void initNetwork(nlohmann::json& network); - static void initMember(nlohmann::json& member); - static void cleanNetwork(nlohmann::json& network); - static void cleanMember(nlohmann::json& member); - - DB(); - virtual ~DB(); - - virtual bool waitForReady() = 0; - virtual bool isReady() = 0; - - inline bool hasNetwork(const uint64_t networkId) const - { - std::shared_lock l(_networks_l); - return (_networks.find(networkId) != _networks.end()); - } - - bool get(const uint64_t networkId, nlohmann::json& network); - bool get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member); - bool get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member, NetworkSummaryInfo& info); - bool get(const uint64_t networkId, nlohmann::json& network, std::vector& members); - - void networks(std::set& networks); - - template inline void each(F f) - { - nlohmann::json nullJson; - std::unique_lock lck(_networks_l); - for (auto nw = _networks.begin(); nw != _networks.end(); ++nw) { - f(nw->first, nw->second->config, 0, nullJson); // first provide network with 0 for member ID - for (auto m = nw->second->members.begin(); m != nw->second->members.end(); ++m) { - f(nw->first, nw->second->config, m->first, m->second); - } - } - } - - virtual bool save(nlohmann::json& record, bool notifyListeners) = 0; - virtual void eraseNetwork(const uint64_t networkId) = 0; - virtual void eraseMember(const uint64_t networkId, const uint64_t memberId) = 0; - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) = 0; - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) = 0; - - virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL) - { - return AuthInfo(); - } - - inline void addListener(DB::ChangeListener* const listener) - { - std::unique_lock l(_changeListeners_l); - _changeListeners.push_back(listener); - } - - protected: - static inline bool _compareRecords(const nlohmann::json& a, const nlohmann::json& b) - { - if (a.is_object() == b.is_object()) { - if (a.is_object()) { - if (a.size() != b.size()) - return false; - auto amap = a.get(); - auto bmap = b.get(); - for (auto ai = amap.begin(); ai != amap.end(); ++ai) { - if (ai->first != "revision") { // ignore revision, compare only non-revision-counter fields - auto bi = bmap.find(ai->first); - if ((bi == bmap.end()) || (bi->second != ai->second)) - return false; - } - } - return true; - } - return (a == b); - } - return false; - } - - struct _Network { - _Network() : mostRecentDeauthTime(0) - { - } - nlohmann::json config; - std::unordered_map members; - std::unordered_set activeBridgeMembers; - std::unordered_set authorizedMembers; - std::unordered_set allocatedIps; - int64_t mostRecentDeauthTime; - std::shared_mutex lock; - }; - - virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners); - virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners); - void _fillSummaryInfo(const std::shared_ptr<_Network>& nw, NetworkSummaryInfo& info); - - std::vector _changeListeners; - std::unordered_map > _networks; - std::unordered_multimap _networkByMember; - mutable std::shared_mutex _changeListeners_l; - mutable std::shared_mutex _networks_l; -}; - -} // namespace ZeroTier - -#endif diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp deleted file mode 100644 index f8c6f0366..000000000 --- a/controller/DBMirrorSet.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "DBMirrorSet.hpp" - -#include "opentelemetry/trace/provider.h" - -namespace ZeroTier { - -DBMirrorSet::DBMirrorSet(DB::ChangeListener* listener) : _listener(listener), _running(true), _syncCheckerThread(), _dbs(), _dbs_l() -{ - _syncCheckerThread = std::thread([this]() { - for (;;) { - for (int i = 0; i < 120; ++i) { // 1 minute delay between checks - if (! _running) - return; - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } - - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db::syncChecker"); - auto scope = tracer->WithActiveSpan(span); - - std::vector > dbs; - { - std::unique_lock l(_dbs_l); - if (_dbs.size() <= 1) - continue; // no need to do this if there's only one DB, so skip the iteration - dbs = _dbs; - } - - for (auto db = dbs.begin(); db != dbs.end(); ++db) { - (*db)->each([&dbs, &db](uint64_t networkId, const nlohmann::json& network, uint64_t memberId, const nlohmann::json& member) { - try { - if (network.is_object()) { - if (memberId == 0) { - for (auto db2 = dbs.begin(); db2 != dbs.end(); ++db2) { - if (db->get() != db2->get()) { - nlohmann::json nw2; - if ((! (*db2)->get(networkId, nw2)) || ((nw2.is_object()) && (OSUtils::jsonInt(nw2["revision"], 0) < OSUtils::jsonInt(network["revision"], 0)))) { - nw2 = network; - (*db2)->save(nw2, false); - } - } - } - } - else if (member.is_object()) { - for (auto db2 = dbs.begin(); db2 != dbs.end(); ++db2) { - if (db->get() != db2->get()) { - nlohmann::json nw2, m2; - if ((! (*db2)->get(networkId, nw2, memberId, m2)) || ((m2.is_object()) && (OSUtils::jsonInt(m2["revision"], 0) < OSUtils::jsonInt(member["revision"], 0)))) { - m2 = member; - (*db2)->save(m2, false); - } - } - } - } - } - } - catch (...) { - } // skip entries that generate JSON errors - }); - } - } - }); -} - -DBMirrorSet::~DBMirrorSet() -{ - _running = false; - _syncCheckerThread.join(); -} - -bool DBMirrorSet::hasNetwork(const uint64_t networkId) const -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::hasNetwork"); - auto scope = tracer->WithActiveSpan(span); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - if ((*d)->hasNetwork(networkId)) - return true; - } - return false; -} - -bool DBMirrorSet::get(const uint64_t networkId, nlohmann::json& network) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::getNetwork"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - if ((*d)->get(networkId, network)) { - return true; - } - } - return false; -} - -bool DBMirrorSet::get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::getNetworkAndMember"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - if ((*d)->get(networkId, network, memberId, member)) - return true; - } - return false; -} - -bool DBMirrorSet::get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member, DB::NetworkSummaryInfo& info) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::getNetworkAndMemberWithSummary"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - if ((*d)->get(networkId, network, memberId, member, info)) - return true; - } - return false; -} - -bool DBMirrorSet::get(const uint64_t networkId, nlohmann::json& network, std::vector& members) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::getNetworkAndMembers"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - if ((*d)->get(networkId, network, members)) - return true; - } - return false; -} - -AuthInfo DBMirrorSet::getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::getSSOAuthInfo"); - auto scope = tracer->WithActiveSpan(span); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - AuthInfo info = (*d)->getSSOAuthInfo(member, redirectURL); - if (info.enabled) { - return info; - } - } - return AuthInfo(); -} - -void DBMirrorSet::networks(std::set& networks) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::networks"); - auto scope = tracer->WithActiveSpan(span); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - (*d)->networks(networks); - } -} - -bool DBMirrorSet::waitForReady() -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::waitForReady"); - auto scope = tracer->WithActiveSpan(span); - - bool r = false; - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - r |= (*d)->waitForReady(); - } - return r; -} - -bool DBMirrorSet::isReady() -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::isReady"); - auto scope = tracer->WithActiveSpan(span); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - if (! (*d)->isReady()) - return false; - } - return true; -} - -bool DBMirrorSet::save(nlohmann::json& record, bool notifyListeners) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::save"); - auto scope = tracer->WithActiveSpan(span); - - std::vector > dbs; - { - std::unique_lock l(_dbs_l); - dbs = _dbs; - } - if (notifyListeners) { - for (auto d = dbs.begin(); d != dbs.end(); ++d) { - if ((*d)->save(record, true)) - return true; - } - return false; - } - else { - bool modified = false; - for (auto d = dbs.begin(); d != dbs.end(); ++d) { - modified |= (*d)->save(record, false); - } - return modified; - } -} - -void DBMirrorSet::eraseNetwork(const uint64_t networkId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::eraseNetwork"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - - std::unique_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - (*d)->eraseNetwork(networkId); - } -} - -void DBMirrorSet::eraseMember(const uint64_t networkId, const uint64_t memberId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::eraseMember"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - - std::unique_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - (*d)->eraseMember(networkId, memberId); - } -} - -void DBMirrorSet::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::nodeIsOnline"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - char phyAddressStr[INET6_ADDRSTRLEN]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - span->SetAttribute("physical_address", physicalAddress.toString(phyAddressStr)); - span->SetAttribute("os_arch", osArch); - - std::shared_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - (*d)->nodeIsOnline(networkId, memberId, physicalAddress, osArch); - } -} - -void DBMirrorSet::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) -{ - this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown"); -} - -void DBMirrorSet::onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::onNetworkUpdate"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - - nlohmann::json record(network); - std::unique_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - if (d->get() != db) { - (*d)->save(record, false); - } - } - _listener->onNetworkUpdate(this, networkId, network); -} - -void DBMirrorSet::onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::onNetworkMemberUpdate"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - - nlohmann::json record(member); - std::unique_lock l(_dbs_l); - for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { - if (d->get() != db) { - (*d)->save(record, false); - } - } - _listener->onNetworkMemberUpdate(this, networkId, memberId, member); -} - -void DBMirrorSet::onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_mirror_set"); - auto span = tracer->StartSpan("db_mirror_set::onNetworkMemberDeauthorize"); - auto scope = tracer->WithActiveSpan(span); - char networkIdStr[17]; - char memberIdStr[11]; - span->SetAttribute("network_id", Utils::hex(networkId, networkIdStr)); - span->SetAttribute("member_id", Utils::hex10(memberId, memberIdStr)); - - _listener->onNetworkMemberDeauthorize(this, networkId, memberId); -} - -} // namespace ZeroTier diff --git a/controller/DBMirrorSet.hpp b/controller/DBMirrorSet.hpp deleted file mode 100644 index 50230c545..000000000 --- a/controller/DBMirrorSet.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_DBMIRRORSET_HPP -#define ZT_DBMIRRORSET_HPP - -#include "DB.hpp" - -#include -#include -#include -#include -#include - -namespace ZeroTier { - -class DBMirrorSet : public DB::ChangeListener { - public: - DBMirrorSet(DB::ChangeListener* listener); - virtual ~DBMirrorSet(); - - bool hasNetwork(const uint64_t networkId) const; - - bool get(const uint64_t networkId, nlohmann::json& network); - bool get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member); - bool get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member, DB::NetworkSummaryInfo& info); - bool get(const uint64_t networkId, nlohmann::json& network, std::vector& members); - - void networks(std::set& networks); - - bool waitForReady(); - bool isReady(); - bool save(nlohmann::json& record, bool notifyListeners); - void eraseNetwork(const uint64_t networkId); - void eraseMember(const uint64_t networkId, const uint64_t memberId); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); - - // These are called by various DB instances when changes occur. - virtual void onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network); - virtual void onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member); - virtual void onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId); - - AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL); - - inline void addDB(const std::shared_ptr& db) - { - db->addListener(this); - std::unique_lock l(_dbs_l); - _dbs.push_back(db); - } - - private: - DB::ChangeListener* const _listener; - std::atomic_bool _running; - std::thread _syncCheckerThread; - std::vector > _dbs; - mutable std::shared_mutex _dbs_l; -}; - -} // namespace ZeroTier - -#endif diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp deleted file mode 100644 index b7ba04299..000000000 --- a/controller/EmbeddedNetworkController.cpp +++ /dev/null @@ -1,2396 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include -#include -#include -#include -#include -#include - -#ifndef _WIN32 -#include -#endif -#include "../include/ZeroTierOne.h" -#include "../version.h" -#include "EmbeddedNetworkController.hpp" -#include "FileDB.hpp" -#include "LFDB.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef ZT_CONTROLLER_USE_LIBPQ -#include "CV1.hpp" -#include "CV2.hpp" -#endif - -#include "../node/CertificateOfMembership.hpp" -#include "../node/Dictionary.hpp" -#include "../node/MAC.hpp" -#include "../node/NetworkConfig.hpp" -#include "../node/Node.hpp" -#include "opentelemetry/trace/provider.h" - -using json = nlohmann::json; - -// API version reported via JSON control plane -#define ZT_NETCONF_CONTROLLER_API_VERSION 4 - -// Min duration between requests for an address/nwid combo to prevent floods -#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000 - -// Global maximum size of arrays in JSON objects -#define ZT_CONTROLLER_MAX_ARRAY_SIZE 16384 - -namespace ZeroTier { - -namespace { - -static json _renderRule(ZT_VirtualNetworkRule& rule) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::renderRule"); - auto scope = tracer->WithActiveSpan(span); - - char tmp[128]; - json r = json::object(); - const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rule.t & 0x3f); - - switch (rt) { - case ZT_NETWORK_RULE_ACTION_DROP: - r["type"] = "ACTION_DROP"; - break; - case ZT_NETWORK_RULE_ACTION_ACCEPT: - r["type"] = "ACTION_ACCEPT"; - break; - case ZT_NETWORK_RULE_ACTION_TEE: - r["type"] = "ACTION_TEE"; - r["address"] = Address(rule.v.fwd.address).toString(tmp); - r["flags"] = (unsigned int)rule.v.fwd.flags; - r["length"] = (unsigned int)rule.v.fwd.length; - break; - case ZT_NETWORK_RULE_ACTION_WATCH: - r["type"] = "ACTION_WATCH"; - r["address"] = Address(rule.v.fwd.address).toString(tmp); - r["flags"] = (unsigned int)rule.v.fwd.flags; - r["length"] = (unsigned int)rule.v.fwd.length; - break; - case ZT_NETWORK_RULE_ACTION_REDIRECT: - r["type"] = "ACTION_REDIRECT"; - r["address"] = Address(rule.v.fwd.address).toString(tmp); - r["flags"] = (unsigned int)rule.v.fwd.flags; - break; - case ZT_NETWORK_RULE_ACTION_BREAK: - r["type"] = "ACTION_BREAK"; - break; - default: - break; - } - - if (r.empty()) { - switch (rt) { - case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: - r["type"] = "MATCH_SOURCE_ZEROTIER_ADDRESS"; - r["zt"] = Address(rule.v.zt).toString(tmp); - break; - case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: - r["type"] = "MATCH_DEST_ZEROTIER_ADDRESS"; - r["zt"] = Address(rule.v.zt).toString(tmp); - break; - case ZT_NETWORK_RULE_MATCH_VLAN_ID: - r["type"] = "MATCH_VLAN_ID"; - r["vlanId"] = (unsigned int)rule.v.vlanId; - break; - case ZT_NETWORK_RULE_MATCH_VLAN_PCP: - r["type"] = "MATCH_VLAN_PCP"; - r["vlanPcp"] = (unsigned int)rule.v.vlanPcp; - break; - case ZT_NETWORK_RULE_MATCH_VLAN_DEI: - r["type"] = "MATCH_VLAN_DEI"; - r["vlanDei"] = (unsigned int)rule.v.vlanDei; - break; - case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: - r["type"] = "MATCH_MAC_SOURCE"; - OSUtils::ztsnprintf( - tmp, - sizeof(tmp), - "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", - (unsigned int)rule.v.mac[0], - (unsigned int)rule.v.mac[1], - (unsigned int)rule.v.mac[2], - (unsigned int)rule.v.mac[3], - (unsigned int)rule.v.mac[4], - (unsigned int)rule.v.mac[5]); - r["mac"] = tmp; - break; - case ZT_NETWORK_RULE_MATCH_MAC_DEST: - r["type"] = "MATCH_MAC_DEST"; - OSUtils::ztsnprintf( - tmp, - sizeof(tmp), - "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", - (unsigned int)rule.v.mac[0], - (unsigned int)rule.v.mac[1], - (unsigned int)rule.v.mac[2], - (unsigned int)rule.v.mac[3], - (unsigned int)rule.v.mac[4], - (unsigned int)rule.v.mac[5]); - r["mac"] = tmp; - break; - case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: - r["type"] = "MATCH_IPV4_SOURCE"; - r["ip"] = InetAddress(&(rule.v.ipv4.ip), 4, (unsigned int)rule.v.ipv4.mask).toString(tmp); - break; - case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - r["type"] = "MATCH_IPV4_DEST"; - r["ip"] = InetAddress(&(rule.v.ipv4.ip), 4, (unsigned int)rule.v.ipv4.mask).toString(tmp); - break; - case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: - r["type"] = "MATCH_IPV6_SOURCE"; - r["ip"] = InetAddress(rule.v.ipv6.ip, 16, (unsigned int)rule.v.ipv6.mask).toString(tmp); - break; - case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - r["type"] = "MATCH_IPV6_DEST"; - r["ip"] = InetAddress(rule.v.ipv6.ip, 16, (unsigned int)rule.v.ipv6.mask).toString(tmp); - break; - case ZT_NETWORK_RULE_MATCH_IP_TOS: - r["type"] = "MATCH_IP_TOS"; - r["mask"] = (unsigned int)rule.v.ipTos.mask; - r["start"] = (unsigned int)rule.v.ipTos.value[0]; - r["end"] = (unsigned int)rule.v.ipTos.value[1]; - break; - case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: - r["type"] = "MATCH_IP_PROTOCOL"; - r["ipProtocol"] = (unsigned int)rule.v.ipProtocol; - break; - case ZT_NETWORK_RULE_MATCH_ETHERTYPE: - r["type"] = "MATCH_ETHERTYPE"; - r["etherType"] = (unsigned int)rule.v.etherType; - break; - case ZT_NETWORK_RULE_MATCH_ICMP: - r["type"] = "MATCH_ICMP"; - r["icmpType"] = (unsigned int)rule.v.icmp.type; - if ((rule.v.icmp.flags & 0x01) != 0) - r["icmpCode"] = (unsigned int)rule.v.icmp.code; - else - r["icmpCode"] = json(); - break; - case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: - r["type"] = "MATCH_IP_SOURCE_PORT_RANGE"; - r["start"] = (unsigned int)rule.v.port[0]; - r["end"] = (unsigned int)rule.v.port[1]; - break; - case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: - r["type"] = "MATCH_IP_DEST_PORT_RANGE"; - r["start"] = (unsigned int)rule.v.port[0]; - r["end"] = (unsigned int)rule.v.port[1]; - break; - case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: - r["type"] = "MATCH_CHARACTERISTICS"; - OSUtils::ztsnprintf(tmp, sizeof(tmp), "%.16llx", rule.v.characteristics); - r["mask"] = tmp; - break; - case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: - r["type"] = "MATCH_FRAME_SIZE_RANGE"; - r["start"] = (unsigned int)rule.v.frameSize[0]; - r["end"] = (unsigned int)rule.v.frameSize[1]; - break; - case ZT_NETWORK_RULE_MATCH_RANDOM: - r["type"] = "MATCH_RANDOM"; - r["probability"] = (unsigned long)rule.v.randomProbability; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE: - r["type"] = "MATCH_TAGS_DIFFERENCE"; - r["id"] = rule.v.tag.id; - r["value"] = rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND: - r["type"] = "MATCH_TAGS_BITWISE_AND"; - r["id"] = rule.v.tag.id; - r["value"] = rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR: - r["type"] = "MATCH_TAGS_BITWISE_OR"; - r["id"] = rule.v.tag.id; - r["value"] = rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR: - r["type"] = "MATCH_TAGS_BITWISE_XOR"; - r["id"] = rule.v.tag.id; - r["value"] = rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL: - r["type"] = "MATCH_TAGS_EQUAL"; - r["id"] = rule.v.tag.id; - r["value"] = rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAG_SENDER: - r["type"] = "MATCH_TAG_SENDER"; - r["id"] = rule.v.tag.id; - r["value"] = rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER: - r["type"] = "MATCH_TAG_RECEIVER"; - r["id"] = rule.v.tag.id; - r["value"] = rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE: - r["type"] = "INTEGER_RANGE"; - OSUtils::ztsnprintf(tmp, sizeof(tmp), "%.16llx", rule.v.intRange.start); - r["start"] = tmp; - OSUtils::ztsnprintf(tmp, sizeof(tmp), "%.16llx", rule.v.intRange.start + (uint64_t)rule.v.intRange.end); - r["end"] = tmp; - r["idx"] = rule.v.intRange.idx; - r["little"] = ((rule.v.intRange.format & 0x80) != 0); - r["bits"] = (rule.v.intRange.format & 63) + 1; - break; - default: - break; - } - - if (! r.empty()) { - r["not"] = ((rule.t & 0x80) != 0); - r["or"] = ((rule.t & 0x40) != 0); - } - } - - return r; -} - -static bool _parseRule(json& r, ZT_VirtualNetworkRule& rule) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::parseRule"); - auto scope = tracer->WithActiveSpan(span); - - if (! r.is_object()) - return false; - - const std::string t(OSUtils::jsonString(r["type"], "")); - memset(&rule, 0, sizeof(ZT_VirtualNetworkRule)); - - if (OSUtils::jsonBool(r["not"], false)) - rule.t = 0x80; - else - rule.t = 0x00; - if (OSUtils::jsonBool(r["or"], false)) - rule.t |= 0x40; - - bool tag = false; - if (t == "ACTION_DROP") { - rule.t |= ZT_NETWORK_RULE_ACTION_DROP; - return true; - } - else if (t == "ACTION_ACCEPT") { - rule.t |= ZT_NETWORK_RULE_ACTION_ACCEPT; - return true; - } - else if (t == "ACTION_TEE") { - rule.t |= ZT_NETWORK_RULE_ACTION_TEE; - rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"], "0").c_str()) & 0xffffffffffULL; - rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"], 0ULL) & 0xffffffffULL); - rule.v.fwd.length = (uint16_t)(OSUtils::jsonInt(r["length"], 0ULL) & 0xffffULL); - return true; - } - else if (t == "ACTION_WATCH") { - rule.t |= ZT_NETWORK_RULE_ACTION_WATCH; - rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"], "0").c_str()) & 0xffffffffffULL; - rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"], 0ULL) & 0xffffffffULL); - rule.v.fwd.length = (uint16_t)(OSUtils::jsonInt(r["length"], 0ULL) & 0xffffULL); - return true; - } - else if (t == "ACTION_REDIRECT") { - rule.t |= ZT_NETWORK_RULE_ACTION_REDIRECT; - rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"], "0").c_str()) & 0xffffffffffULL; - rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"], 0ULL) & 0xffffffffULL); - return true; - } - else if (t == "ACTION_BREAK") { - rule.t |= ZT_NETWORK_RULE_ACTION_BREAK; - return true; - } - else if (t == "MATCH_SOURCE_ZEROTIER_ADDRESS") { - rule.t |= ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS; - rule.v.zt = Utils::hexStrToU64(OSUtils::jsonString(r["zt"], "0").c_str()) & 0xffffffffffULL; - return true; - } - else if (t == "MATCH_DEST_ZEROTIER_ADDRESS") { - rule.t |= ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS; - rule.v.zt = Utils::hexStrToU64(OSUtils::jsonString(r["zt"], "0").c_str()) & 0xffffffffffULL; - return true; - } - else if (t == "MATCH_VLAN_ID") { - rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_ID; - rule.v.vlanId = (uint16_t)(OSUtils::jsonInt(r["vlanId"], 0ULL) & 0xffffULL); - return true; - } - else if (t == "MATCH_VLAN_PCP") { - rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_PCP; - rule.v.vlanPcp = (uint8_t)(OSUtils::jsonInt(r["vlanPcp"], 0ULL) & 0xffULL); - return true; - } - else if (t == "MATCH_VLAN_DEI") { - rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI; - rule.v.vlanDei = (uint8_t)(OSUtils::jsonInt(r["vlanDei"], 0ULL) & 0xffULL); - return true; - } - else if (t == "MATCH_MAC_SOURCE") { - rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE; - std::string mac(OSUtils::jsonString(r["mac"], "0")); - Utils::cleanMac(mac); - Utils::unhex(mac.c_str(), (unsigned int)mac.length(), rule.v.mac, 6); - return true; - } - else if (t == "MATCH_MAC_DEST") { - rule.t |= ZT_NETWORK_RULE_MATCH_MAC_DEST; - std::string mac(OSUtils::jsonString(r["mac"], "0")); - Utils::cleanMac(mac); - Utils::unhex(mac.c_str(), (unsigned int)mac.length(), rule.v.mac, 6); - return true; - } - else if (t == "MATCH_IPV4_SOURCE") { - rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_SOURCE; - InetAddress ip(OSUtils::jsonString(r["ip"], "0.0.0.0").c_str()); - rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; - rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; - if (rule.v.ipv4.mask > 32) - rule.v.ipv4.mask = 32; - return true; - } - else if (t == "MATCH_IPV4_DEST") { - rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_DEST; - InetAddress ip(OSUtils::jsonString(r["ip"], "0.0.0.0").c_str()); - rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; - rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; - if (rule.v.ipv4.mask > 32) - rule.v.ipv4.mask = 32; - return true; - } - else if (t == "MATCH_IPV6_SOURCE") { - rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; - InetAddress ip(OSUtils::jsonString(r["ip"], "::0").c_str()); - memcpy(rule.v.ipv6.ip, reinterpret_cast(&ip)->sin6_addr.s6_addr, 16); - rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; - if (rule.v.ipv6.mask > 128) - rule.v.ipv6.mask = 128; - return true; - } - else if (t == "MATCH_IPV6_DEST") { - rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; - InetAddress ip(OSUtils::jsonString(r["ip"], "::0").c_str()); - memcpy(rule.v.ipv6.ip, reinterpret_cast(&ip)->sin6_addr.s6_addr, 16); - rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; - if (rule.v.ipv6.mask > 128) - rule.v.ipv6.mask = 128; - return true; - } - else if (t == "MATCH_IP_TOS") { - rule.t |= ZT_NETWORK_RULE_MATCH_IP_TOS; - rule.v.ipTos.mask = (uint8_t)(OSUtils::jsonInt(r["mask"], 0ULL) & 0xffULL); - rule.v.ipTos.value[0] = (uint8_t)(OSUtils::jsonInt(r["start"], 0ULL) & 0xffULL); - rule.v.ipTos.value[1] = (uint8_t)(OSUtils::jsonInt(r["end"], 0ULL) & 0xffULL); - return true; - } - else if (t == "MATCH_IP_PROTOCOL") { - rule.t |= ZT_NETWORK_RULE_MATCH_IP_PROTOCOL; - rule.v.ipProtocol = (uint8_t)(OSUtils::jsonInt(r["ipProtocol"], 0ULL) & 0xffULL); - return true; - } - else if (t == "MATCH_ETHERTYPE") { - rule.t |= ZT_NETWORK_RULE_MATCH_ETHERTYPE; - rule.v.etherType = (uint16_t)(OSUtils::jsonInt(r["etherType"], 0ULL) & 0xffffULL); - return true; - } - else if (t == "MATCH_ICMP") { - rule.t |= ZT_NETWORK_RULE_MATCH_ICMP; - rule.v.icmp.type = (uint8_t)(OSUtils::jsonInt(r["icmpType"], 0ULL) & 0xffULL); - json& code = r["icmpCode"]; - if (code.is_null()) { - rule.v.icmp.code = 0; - rule.v.icmp.flags = 0x00; - } - else { - rule.v.icmp.code = (uint8_t)(OSUtils::jsonInt(code, 0ULL) & 0xffULL); - rule.v.icmp.flags = 0x01; - } - return true; - } - else if (t == "MATCH_IP_SOURCE_PORT_RANGE") { - rule.t |= ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE; - rule.v.port[0] = (uint16_t)(OSUtils::jsonInt(r["start"], 0ULL) & 0xffffULL); - rule.v.port[1] = (uint16_t)(OSUtils::jsonInt(r["end"], (uint64_t)rule.v.port[0]) & 0xffffULL); - return true; - } - else if (t == "MATCH_IP_DEST_PORT_RANGE") { - rule.t |= ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE; - rule.v.port[0] = (uint16_t)(OSUtils::jsonInt(r["start"], 0ULL) & 0xffffULL); - rule.v.port[1] = (uint16_t)(OSUtils::jsonInt(r["end"], (uint64_t)rule.v.port[0]) & 0xffffULL); - return true; - } - else if (t == "MATCH_CHARACTERISTICS") { - rule.t |= ZT_NETWORK_RULE_MATCH_CHARACTERISTICS; - if (r.count("mask")) { - json& v = r["mask"]; - if (v.is_number()) { - rule.v.characteristics = v; - } - else { - std::string tmp = v; - rule.v.characteristics = Utils::hexStrToU64(tmp.c_str()); - } - } - return true; - } - else if (t == "MATCH_FRAME_SIZE_RANGE") { - rule.t |= ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE; - rule.v.frameSize[0] = (uint16_t)(OSUtils::jsonInt(r["start"], 0ULL) & 0xffffULL); - rule.v.frameSize[1] = (uint16_t)(OSUtils::jsonInt(r["end"], (uint64_t)rule.v.frameSize[0]) & 0xffffULL); - return true; - } - else if (t == "MATCH_RANDOM") { - rule.t |= ZT_NETWORK_RULE_MATCH_RANDOM; - rule.v.randomProbability = (uint32_t)(OSUtils::jsonInt(r["probability"], 0ULL) & 0xffffffffULL); - return true; - } - else if (t == "MATCH_TAGS_DIFFERENCE") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE; - tag = true; - } - else if (t == "MATCH_TAGS_BITWISE_AND") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND; - tag = true; - } - else if (t == "MATCH_TAGS_BITWISE_OR") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR; - tag = true; - } - else if (t == "MATCH_TAGS_BITWISE_XOR") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR; - tag = true; - } - else if (t == "MATCH_TAGS_EQUAL") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_EQUAL; - tag = true; - } - else if (t == "MATCH_TAG_SENDER") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAG_SENDER; - tag = true; - } - else if (t == "MATCH_TAG_RECEIVER") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAG_RECEIVER; - tag = true; - } - else if (t == "INTEGER_RANGE") { - json& s = r["start"]; - if (s.is_string()) { - std::string tmp = s; - rule.v.intRange.start = Utils::hexStrToU64(tmp.c_str()); - } - else { - rule.v.intRange.start = OSUtils::jsonInt(s, 0ULL); - } - json& e = r["end"]; - if (e.is_string()) { - std::string tmp = e; - rule.v.intRange.end = (uint32_t)(Utils::hexStrToU64(tmp.c_str()) - rule.v.intRange.start); - } - else { - rule.v.intRange.end = (uint32_t)(OSUtils::jsonInt(e, 0ULL) - rule.v.intRange.start); - } - rule.v.intRange.idx = (uint16_t)OSUtils::jsonInt(r["idx"], 0ULL); - rule.v.intRange.format = (OSUtils::jsonBool(r["little"], false)) ? 0x80 : 0x00; - rule.v.intRange.format |= (uint8_t)((OSUtils::jsonInt(r["bits"], 1ULL) - 1) & 63); - } - - if (tag) { - rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"], 0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"], 0ULL) & 0xffffffffULL); - return true; - } - - return false; -} - -} // anonymous namespace - -EmbeddedNetworkController::EmbeddedNetworkController(Node* node, const char* ztPath, const char* dbPath, int listenPort, RedisConfig* rc) - : _startTime(OSUtils::now()) - , _listenPort(listenPort) - , _node(node) - , _ztPath(ztPath) - , _path(dbPath) - , _signingId() - , _signingIdAddressString() - , _sender((NetworkController::Sender*)0) - , _db(this) - , _queue() - , _threads() - , _threads_l() - , _memberStatus() - , _memberStatus_l() - , _expiringSoon() - , _expiringSoon_l() - , _rc(rc) - , _ssoExpiryRunning(true) - , _ssoExpiry(std::thread(&EmbeddedNetworkController::_ssoExpiryThread, this)) - -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - , _member_status_lookup { "nc_member_status_lookup", "" } - , _member_status_lookup_count { "nc_member_status_lookup_count", "" } - , _node_is_online { "nc_node_is_online", "" } - , _node_is_online_count { "nc_node_is_online_count", "" } - , _get_and_init_member { "nc_get_and_init_member", "" } - , _get_and_init_member_count { "nc_get_and_init_member_count", "" } - , _have_identity { "nc_have_identity", "" } - , _have_identity_count { "nc_have_identity_count", "" } - , _determine_auth { "nc_determine_auth", "" } - , _determine_auth_count { "nc_determine_auth_count", "" } - , _sso_check { "nc_sso_check", "" } - , _sso_check_count { "nc_sso_check_count", "" } - , _auth_check { "nc_auth_check", "" } - , _auth_check_count { "nc_auth_check_count", "" } - , _json_schlep { "nc_json_schlep", "" } - , _json_schlep_count { "nc_json_schlep_count", "" } - , _issue_certificate { "nc_issue_certificate", "" } - , _issue_certificate_count { "nc_issue_certificate_count", "" } - , _save_member { "nc_save_member", "" } - , _save_member_count { "nc_save_member_count", "" } - , _send_netconf { "nc_send_netconf2", "" } - , _send_netconf_count { "nc_send_netconf2_count", "" } -#endif -{ -} - -EmbeddedNetworkController::~EmbeddedNetworkController() -{ - std::lock_guard l(_threads_l); - _queue.stop(); - for (auto t = _threads.begin(); t != _threads.end(); ++t) { - t->join(); - } - _ssoExpiryRunning = false; - _ssoExpiry.join(); -} - -void EmbeddedNetworkController::setSSORedirectURL(const std::string& url) -{ - _ssoRedirectURL = url; -} - -void EmbeddedNetworkController::init(const Identity& signingId, Sender* sender) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::init"); - auto scope = tracer->WithActiveSpan(span); - - char tmp[64]; - _signingId = signingId; - _sender = sender; - _signingIdAddressString = signingId.address().toString(tmp); - -#ifdef ZT_CONTROLLER_USE_LIBPQ - if ((_path.length() > 9) && (_path.substr(0, 9) == "postgres:")) { - fprintf(stderr, "CV1\n"); - _db.addDB(std::shared_ptr(new CV1(_signingId, _path.substr(9).c_str(), _listenPort, _rc))); - } - else if ((_path.length() > 4) && (_path.substr(0, 4) == "cv2:")) { - fprintf(stderr, "CV2\n"); - _db.addDB(std::shared_ptr(new CV2(_signingId, _path.substr(4).c_str(), _listenPort))); - } - else { - fprintf(stderr, "FileDB\n"); -#endif - _db.addDB(std::shared_ptr(new FileDB(_path.c_str()))); -#ifdef ZT_CONTROLLER_USE_LIBPQ - } -#endif - - std::string lfJSON; - OSUtils::readFile((_ztPath + ZT_PATH_SEPARATOR_S "local.conf").c_str(), lfJSON); - if (lfJSON.length() > 0) { - nlohmann::json lfConfig(OSUtils::jsonParse(lfJSON)); - nlohmann::json& settings = lfConfig["settings"]; - if (settings.is_object()) { - nlohmann::json& controllerDb = settings["controllerDb"]; - if (controllerDb.is_object()) { - std::string type = controllerDb["type"]; - if (type == "lf") { - std::string lfOwner = controllerDb["owner"]; - std::string lfHost = controllerDb["host"]; - int lfPort = controllerDb["port"]; - bool storeOnlineState = controllerDb["storeOnlineState"]; - if ((lfOwner.length()) && (lfHost.length()) && (lfPort > 0) && (lfPort < 65536)) { - std::size_t pubHdrLoc = lfOwner.find("Public: "); - if ((pubHdrLoc > 0) && ((pubHdrLoc + 8) < lfOwner.length())) { - std::string lfOwnerPublic = lfOwner.substr(pubHdrLoc + 8); - std::size_t pubHdrEnd = lfOwnerPublic.find_first_of("\n\r\t "); - if (pubHdrEnd != std::string::npos) { - lfOwnerPublic = lfOwnerPublic.substr(0, pubHdrEnd); - _db.addDB(std::shared_ptr(new LFDB(_signingId, _path.c_str(), lfOwner.c_str(), lfOwnerPublic.c_str(), lfHost.c_str(), lfPort, storeOnlineState))); - } - } - } - } - } - } - } - - _db.waitForReady(); -} - -void EmbeddedNetworkController::request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary& metaData) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::request"); - auto scope = tracer->WithActiveSpan(span); - - if (((! _signingId) || (! _signingId.hasPrivate())) || (_signingId.address().toInt() != (nwid >> 24)) || (! _sender)) - return; - _startThreads(); - - const int64_t now = OSUtils::now(); - - if (requestPacketId) { - std::lock_guard l(_memberStatus_l); - _MemberStatus& ms = _memberStatus[_MemberStatusKey(nwid, identity.address().toInt())]; - if ((now - ms.lastRequestTime) <= ZT_NETCONF_MIN_REQUEST_PERIOD) { - return; - } - ms.lastRequestTime = now; - } - - _RQEntry* qe = new _RQEntry; - qe->nwid = nwid; - qe->requestPacketId = requestPacketId; - qe->fromAddr = fromAddr; - qe->identity = identity; - qe->metaData = metaData; - qe->type = _RQEntry::RQENTRY_TYPE_REQUEST; - _queue.post(qe); -} - -std::string EmbeddedNetworkController::networkUpdateFromPostData(uint64_t networkID, const std::string& body) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::networkUpdateFromPostData"); - auto scope = tracer->WithActiveSpan(span); - - json b = OSUtils::jsonParse(body); - - char nwids[24]; - OSUtils::ztsnprintf(nwids, sizeof(nwids), "%.16llx", networkID); - - json network; - _db.get(networkID, network); - DB::initNetwork(network); - if (b.count("name")) - network["name"] = OSUtils::jsonString(b["name"], ""); - if (b.count("private")) - network["private"] = OSUtils::jsonBool(b["private"], true); - if (b.count("enableBroadcast")) - network["enableBroadcast"] = OSUtils::jsonBool(b["enableBroadcast"], false); - if (b.count("multicastLimit")) - network["multicastLimit"] = OSUtils::jsonInt(b["multicastLimit"], 32ULL); - if (b.count("mtu")) - network["mtu"] = std::max(std::min((unsigned int)OSUtils::jsonInt(b["mtu"], ZT_DEFAULT_MTU), (unsigned int)ZT_MAX_MTU), (unsigned int)ZT_MIN_MTU); - - if (b.count("remoteTraceTarget")) { - const std::string rtt(OSUtils::jsonString(b["remoteTraceTarget"], "")); - if (rtt.length() == 10) { - network["remoteTraceTarget"] = rtt; - } - else { - network["remoteTraceTarget"] = json(); - } - } - if (b.count("remoteTraceLevel")) - network["remoteTraceLevel"] = OSUtils::jsonInt(b["remoteTraceLevel"], 0ULL); - - if (b.count("v4AssignMode")) { - json nv4m; - json& v4m = b["v4AssignMode"]; - if (v4m.is_string()) { // backward compatibility - nv4m["zt"] = (OSUtils::jsonString(v4m, "") == "zt"); - } - else if (v4m.is_object()) { - nv4m["zt"] = OSUtils::jsonBool(v4m["zt"], false); - } - else - nv4m["zt"] = false; - network["v4AssignMode"] = nv4m; - } - - if (b.count("v6AssignMode")) { - json nv6m; - json& v6m = b["v6AssignMode"]; - if (! nv6m.is_object()) - nv6m = json::object(); - if (v6m.is_string()) { // backward compatibility - std::vector v6ms(OSUtils::split(OSUtils::jsonString(v6m, "").c_str(), ",", "", "")); - std::sort(v6ms.begin(), v6ms.end()); - v6ms.erase(std::unique(v6ms.begin(), v6ms.end()), v6ms.end()); - nv6m["rfc4193"] = false; - nv6m["zt"] = false; - nv6m["6plane"] = false; - for (std::vector::iterator i(v6ms.begin()); i != v6ms.end(); ++i) { - if (*i == "rfc4193") - nv6m["rfc4193"] = true; - else if (*i == "zt") - nv6m["zt"] = true; - else if (*i == "6plane") - nv6m["6plane"] = true; - } - } - else if (v6m.is_object()) { - if (v6m.count("rfc4193")) - nv6m["rfc4193"] = OSUtils::jsonBool(v6m["rfc4193"], false); - if (v6m.count("zt")) - nv6m["zt"] = OSUtils::jsonBool(v6m["zt"], false); - if (v6m.count("6plane")) - nv6m["6plane"] = OSUtils::jsonBool(v6m["6plane"], false); - } - else { - nv6m["rfc4193"] = false; - nv6m["zt"] = false; - nv6m["6plane"] = false; - } - network["v6AssignMode"] = nv6m; - } - - if (b.count("routes")) { - json& rts = b["routes"]; - if (rts.is_array()) { - json nrts = json::array(); - for (unsigned long i = 0; i < rts.size(); ++i) { - json& rt = rts[i]; - if (rt.is_object()) { - json& target = rt["target"]; - json& via = rt["via"]; - if (target.is_string()) { - InetAddress t(target.get().c_str()); - InetAddress v; - if (via.is_string()) - v.fromString(via.get().c_str()); - if (((t.ss_family == AF_INET) || (t.ss_family == AF_INET6)) && (t.netmaskBitsValid())) { - json tmp; - char tmp2[64]; - tmp["target"] = t.toString(tmp2); - if (v.ss_family == t.ss_family) - tmp["via"] = v.toIpString(tmp2); - else - tmp["via"] = json(); - nrts.push_back(tmp); - if (nrts.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - } - } - } - network["routes"] = nrts; - } - } - - if (b.count("ipAssignmentPools")) { - json& ipp = b["ipAssignmentPools"]; - if (ipp.is_array()) { - json nipp = json::array(); - for (unsigned long i = 0; i < ipp.size(); ++i) { - json& ip = ipp[i]; - if ((ip.is_object()) && (ip.count("ipRangeStart")) && (ip.count("ipRangeEnd"))) { - InetAddress f(OSUtils::jsonString(ip["ipRangeStart"], "").c_str()); - InetAddress t(OSUtils::jsonString(ip["ipRangeEnd"], "").c_str()); - if (((f.ss_family == AF_INET) || (f.ss_family == AF_INET6)) && (f.ss_family == t.ss_family)) { - json tmp = json::object(); - char tmp2[64]; - tmp["ipRangeStart"] = f.toIpString(tmp2); - tmp["ipRangeEnd"] = t.toIpString(tmp2); - nipp.push_back(tmp); - if (nipp.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - } - } - network["ipAssignmentPools"] = nipp; - } - } - - if (b.count("rules")) { - json& rules = b["rules"]; - if (rules.is_array()) { - json nrules = json::array(); - for (unsigned long i = 0; i < rules.size(); ++i) { - json& rule = rules[i]; - if (rule.is_object()) { - ZT_VirtualNetworkRule ztr; - if (_parseRule(rule, ztr)) { - nrules.push_back(_renderRule(ztr)); - if (nrules.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - } - } - network["rules"] = nrules; - } - } - - if (b.count("authTokens")) { - json& authTokens = b["authTokens"]; - if (authTokens.is_object()) { - json nat; - for (json::iterator t(authTokens.begin()); t != authTokens.end(); ++t) { - if ((t.value().is_number()) && (t.value() >= 0)) - nat[t.key()] = t.value(); - } - network["authTokens"] = nat; - } - else { - network["authTokens"] = { {} }; - } - } - - if (b.count("capabilities")) { - json& capabilities = b["capabilities"]; - if (capabilities.is_array()) { - std::map ncaps; - for (unsigned long i = 0; i < capabilities.size(); ++i) { - json& cap = capabilities[i]; - if (cap.is_object()) { - json ncap = json::object(); - const uint64_t capId = OSUtils::jsonInt(cap["id"], 0ULL); - ncap["id"] = capId; - ncap["default"] = OSUtils::jsonBool(cap["default"], false); - - json& rules = cap["rules"]; - json nrules = json::array(); - if (rules.is_array()) { - for (unsigned long i = 0; i < rules.size(); ++i) { - json& rule = rules[i]; - if (rule.is_object()) { - ZT_VirtualNetworkRule ztr; - if (_parseRule(rule, ztr)) { - nrules.push_back(_renderRule(ztr)); - if (nrules.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - } - } - } - ncap["rules"] = nrules; - - ncaps[capId] = ncap; - } - } - - json ncapsa = json::array(); - for (std::map::iterator c(ncaps.begin()); c != ncaps.end(); ++c) { - ncapsa.push_back(c->second); - if (ncapsa.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - network["capabilities"] = ncapsa; - } - } - - if (b.count("tags")) { - json& tags = b["tags"]; - if (tags.is_array()) { - std::map ntags; - for (unsigned long i = 0; i < tags.size(); ++i) { - json& tag = tags[i]; - if (tag.is_object()) { - json ntag = json::object(); - const uint64_t tagId = OSUtils::jsonInt(tag["id"], 0ULL); - ntag["id"] = tagId; - json& dfl = tag["default"]; - if (dfl.is_null()) - ntag["default"] = dfl; - else - ntag["default"] = OSUtils::jsonInt(dfl, 0ULL); - ntags[tagId] = ntag; - } - } - - json ntagsa = json::array(); - for (std::map::iterator t(ntags.begin()); t != ntags.end(); ++t) { - ntagsa.push_back(t->second); - if (ntagsa.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - network["tags"] = ntagsa; - } - } - - if (b.count("dns")) { - json& dns = b["dns"]; - if (dns.is_object()) { - json nd; - - nd["domain"] = dns["domain"]; - - json& srv = dns["servers"]; - if (srv.is_array()) { - json ns = json::array(); - for (unsigned int i = 0; i < srv.size(); ++i) { - ns.push_back(srv[i]); - } - nd["servers"] = ns; - } - - network["dns"] = nd; - } - } - - network["id"] = nwids; - network["nwid"] = nwids; - - DB::cleanNetwork(network); - _db.save(network, true); - - return network.dump(); -} - -void EmbeddedNetworkController::configureHTTPControlPlane(httplib::Server& s, httplib::Server& sv6, const std::function setContent) -{ - // Control plane Endpoints - std::string controllerPath = "/controller"; - std::string networkListPath = "/controller/network"; - std::string networkListPath2 = "/unstable/controller/network"; - std::string networkPath = "/controller/network/([0-9a-fA-F]{16})"; - std::string oldAndBustedNetworkCreatePath = "/controller/network/([0-9a-fA-F]{10})______"; - std::string memberListPath = "/controller/network/([0-9a-fA-F]{16})/member"; - std::string memberListPath2 = "/unstable/controller/network/([0-9a-fA-F]{16})/member"; - std::string memberPath = "/controller/network/([0-9a-fA-F]{16})/member/([0-9a-fA-F]{10})"; - - auto controllerGet = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::controllerGet"); - auto scope = tracer->WithActiveSpan(span); - - char tmp[4096]; - const bool dbOk = _db.isReady(); - OSUtils::ztsnprintf( - tmp, - sizeof(tmp), - "{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu,\n\t\"databaseReady\": %s\n}\n", - ZT_NETCONF_CONTROLLER_API_VERSION, - (unsigned long long)OSUtils::now(), - dbOk ? "true" : "false"); - - if (! dbOk) { - res.status = 503; - } - - setContent(req, res, tmp); - }; - s.Get(controllerPath, controllerGet); - sv6.Get(controllerPath, controllerGet); - - auto networkListGet = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::networkListGet"); - auto scope = tracer->WithActiveSpan(span); - - std::set networkIds; - _db.networks(networkIds); - char tmp[64]; - - auto out = json::array(); - for (std::set::const_iterator i(networkIds.begin()); i != networkIds.end(); ++i) { - OSUtils::ztsnprintf(tmp, sizeof(tmp), "%.16llx", *i); - out.push_back(tmp); - } - - setContent(req, res, out.dump()); - }; - s.Get(networkListPath, networkListGet); - sv6.Get(networkListPath, networkListGet); - - auto networkListGet2 = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::networkListGet2"); - auto scope = tracer->WithActiveSpan(span); - - std::set networkIds; - _db.networks(networkIds); - - auto meta = json::object(); - auto data = json::array(); - uint64_t networkCount = 0; - - for (std::set::const_iterator nwid(networkIds.begin()); nwid != networkIds.end(); ++nwid) { - json network; - if (! _db.get(*nwid, network)) { - continue; - } - - std::vector memTmp; - if (_db.get(*nwid, network, memTmp)) { - if (! network.is_null()) { - uint64_t authorizedCount = 0; - uint64_t totalCount = memTmp.size(); - networkCount++; - - for (auto m = memTmp.begin(); m != memTmp.end(); ++m) { - bool a = OSUtils::jsonBool((*m)["authorized"], 0); - if (a) { - authorizedCount++; - } - } - - auto nwMeta = json::object(); - nwMeta["totalMemberCount"] = totalCount; - nwMeta["authorizedMemberCount"] = authorizedCount; - network["meta"] = nwMeta; - - data.push_back(network); - } - } - } - meta["networkCount"] = networkCount; - - auto out = json::object(); - out["data"] = data; - out["meta"] = meta; - - setContent(req, res, out.dump()); - }; - s.Get(networkListPath2, networkListGet2); - sv6.Get(networkListPath2, networkListGet2); - - auto networkGet = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::networkGet"); - auto scope = tracer->WithActiveSpan(span); - - auto networkID = req.matches[1]; - uint64_t nwid = Utils::hexStrToU64(networkID.str().c_str()); - json network; - if (! _db.get(nwid, network)) { - res.status = 404; - return; - } - - setContent(req, res, network.dump()); - }; - s.Get(networkPath, networkGet); - sv6.Get(networkPath, networkGet); - - auto createNewNetwork = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::createNewNetwork"); - auto scope = tracer->WithActiveSpan(span); - - // fprintf(stderr, "creating new network (new style)\n"); - uint64_t nwid = 0; - uint64_t nwidPrefix = (Utils::hexStrToU64(_signingIdAddressString.c_str()) << 24) & 0xffffffffff000000ULL; - uint64_t nwidPostfix = 0; - for (unsigned long k = 0; k < 100000; ++k) { // sanity limit on trials - Utils::getSecureRandom(&nwidPostfix, sizeof(nwidPostfix)); - uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL); - if ((tryNwid & 0xffffffULL) == 0ULL) - tryNwid |= 1ULL; - if (! _db.hasNetwork(tryNwid)) { - nwid = tryNwid; - break; - } - } - if (! nwid) { - res.status = 503; - return; - } - - setContent(req, res, networkUpdateFromPostData(nwid, req.body)); - }; - s.Put(networkListPath, createNewNetwork); - s.Post(networkListPath, createNewNetwork); - sv6.Put(networkListPath, createNewNetwork); - sv6.Post(networkListPath, createNewNetwork); - - auto createNewNetworkOldAndBusted = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::createNewNetworkOldAndBusted"); - auto scope = tracer->WithActiveSpan(span); - - auto inID = req.matches[1].str(); - - if (inID != _signingIdAddressString) { - res.status = 400; - return; - } - - uint64_t nwid = 0; - uint64_t nwidPrefix = (Utils::hexStrToU64(inID.c_str()) << 24) & 0xffffffffff000000ULL; - uint64_t nwidPostfix = 0; - for (unsigned long k = 0; k < 100000; ++k) { // sanity limit on trials - Utils::getSecureRandom(&nwidPostfix, sizeof(nwidPostfix)); - uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL); - if ((tryNwid & 0xffffffULL) == 0ULL) - tryNwid |= 1ULL; - if (! _db.hasNetwork(tryNwid)) { - nwid = tryNwid; - break; - } - } - if (! nwid) { - res.status = 503; - return; - } - setContent(req, res, networkUpdateFromPostData(nwid, req.body)); - }; - s.Put(oldAndBustedNetworkCreatePath, createNewNetworkOldAndBusted); - s.Post(oldAndBustedNetworkCreatePath, createNewNetworkOldAndBusted); - sv6.Put(oldAndBustedNetworkCreatePath, createNewNetworkOldAndBusted); - sv6.Post(oldAndBustedNetworkCreatePath, createNewNetworkOldAndBusted); - - auto networkPost = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::networkPost"); - auto scope = tracer->WithActiveSpan(span); - - auto networkID = req.matches[1].str(); - uint64_t nwid = Utils::hexStrToU64(networkID.c_str()); - - res.status = 200; - setContent(req, res, networkUpdateFromPostData(nwid, req.body)); - }; - s.Put(networkPath, networkPost); - s.Post(networkPath, networkPost); - sv6.Put(networkPath, networkPost); - sv6.Post(networkPath, networkPost); - - auto networkDelete = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::networkDelete"); - auto scope = tracer->WithActiveSpan(span); - - auto networkID = req.matches[1].str(); - uint64_t nwid = Utils::hexStrToU64(networkID.c_str()); - - json network; - if (! _db.get(nwid, network)) { - res.status = 404; - return; - } - - _db.eraseNetwork(nwid); - setContent(req, res, network.dump()); - }; - s.Delete(networkPath, networkDelete); - sv6.Delete(networkPath, networkDelete); - - auto memberListGet = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::memberListGet"); - auto scope = tracer->WithActiveSpan(span); - - auto networkID = req.matches[1]; - uint64_t nwid = Utils::hexStrToU64(networkID.str().c_str()); - json network; - if (! _db.get(nwid, network)) { - res.status = 404; - return; - } - - json out = json::object(); - std::vector memTmp; - if (_db.get(nwid, network, memTmp)) { - for (auto m = memTmp.begin(); m != memTmp.end(); ++m) { - int revision = OSUtils::jsonInt((*m)["revision"], 0); - std::string id = OSUtils::jsonString((*m)["id"], ""); - if (id.length() == 10) { - out[id] = revision; - } - } - } - - setContent(req, res, out.dump()); - }; - s.Get(memberListPath, memberListGet); - sv6.Get(memberListPath, memberListGet); - - auto memberListGet2 = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::memberListGet2"); - auto scope = tracer->WithActiveSpan(span); - - auto networkID = req.matches[1]; - uint64_t nwid = Utils::hexStrToU64(networkID.str().c_str()); - json network; - if (! _db.get(nwid, network)) { - res.status = 404; - return; - } - - auto out = nlohmann::json::object(); - auto meta = nlohmann::json::object(); - std::vector memTmp; - if (_db.get(nwid, network, memTmp)) { - uint64_t authorizedCount = 0; - uint64_t totalCount = memTmp.size(); - for (auto m = memTmp.begin(); m != memTmp.end(); ++m) { - bool a = OSUtils::jsonBool((*m)["authorized"], 0); - if (a) { - authorizedCount++; - } - } - - meta["totalCount"] = totalCount; - meta["authorizedCount"] = authorizedCount; - - out["data"] = memTmp; - out["meta"] = meta; - - setContent(req, res, out.dump()); - } - else { - res.status = 404; - return; - } - }; - s.Get(memberListPath2, memberListGet2); - sv6.Get(memberListPath2, memberListGet2); - - auto memberGet = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::memberGet"); - auto scope = tracer->WithActiveSpan(span); - - auto networkID = req.matches[1]; - auto memberID = req.matches[2]; - uint64_t nwid = Utils::hexStrToU64(networkID.str().c_str()); - uint64_t memid = Utils::hexStrToU64(memberID.str().c_str()); - json network; - json member; - if (! _db.get(nwid, network, memid, member)) { - res.status = 404; - return; - } - - setContent(req, res, member.dump()); - }; - s.Get(memberPath, memberGet); - sv6.Get(memberPath, memberGet); - - auto memberPost = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::memberPost"); - auto scope = tracer->WithActiveSpan(span); - - auto networkID = req.matches[1].str(); - auto memberID = req.matches[2].str(); - uint64_t nwid = Utils::hexStrToU64(networkID.c_str()); - uint64_t memid = Utils::hexStrToU64(memberID.c_str()); - - if (! _db.hasNetwork(nwid)) { - res.status = 404; - return; - } - - json network; - json member; - _db.get(nwid, network, memid, member); - DB::initMember(member); - - json b = OSUtils::jsonParse(req.body); - - if (b.count("activeBridge")) - member["activeBridge"] = OSUtils::jsonBool(b["activeBridge"], false); - if (b.count("noAutoAssignIps")) - member["noAutoAssignIps"] = OSUtils::jsonBool(b["noAutoAssignIps"], false); - if (b.count("authenticationExpiryTime")) - member["authenticationExpiryTime"] = (uint64_t)OSUtils::jsonInt(b["authenticationExpiryTime"], 0ULL); - if (b.count("authenticationURL")) - member["authenticationURL"] = OSUtils::jsonString(b["authenticationURL"], ""); - if (b.count("name")) - member["name"] = OSUtils::jsonString(b["name"], ""); - - if (b.count("remoteTraceTarget")) { - const std::string rtt(OSUtils::jsonString(b["remoteTraceTarget"], "")); - if (rtt.length() == 10) { - member["remoteTraceTarget"] = rtt; - } - else { - member["remoteTraceTarget"] = json(); - } - } - if (b.count("remoteTraceLevel")) - member["remoteTraceLevel"] = OSUtils::jsonInt(b["remoteTraceLevel"], 0ULL); - - if (b.count("authorized")) { - const bool newAuth = OSUtils::jsonBool(b["authorized"], false); - if (newAuth != OSUtils::jsonBool(member["authorized"], false)) { - member["authorized"] = newAuth; - member[((newAuth) ? "lastAuthorizedTime" : "lastDeauthorizedTime")] = OSUtils::now(); - if (newAuth) { - member["lastAuthorizedCredentialType"] = "api"; - member["lastAuthorizedCredential"] = json(); - } - } - } - - if (b.count("ipAssignments")) { - json& ipa = b["ipAssignments"]; - if (ipa.is_array()) { - json mipa(json::array()); - for (unsigned long i = 0; i < ipa.size(); ++i) { - std::string ips = ipa[i]; - InetAddress ip(ips.c_str()); - if ((ip.ss_family == AF_INET) || (ip.ss_family == AF_INET6)) { - char tmpip[64]; - mipa.push_back(ip.toIpString(tmpip)); - if (mipa.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - } - member["ipAssignments"] = mipa; - } - } - - if (b.count("tags")) { - json& tags = b["tags"]; - if (tags.is_array()) { - std::map mtags; - for (unsigned long i = 0; i < tags.size(); ++i) { - json& tag = tags[i]; - if ((tag.is_array()) && (tag.size() == 2)) - mtags[OSUtils::jsonInt(tag[0], 0ULL) & 0xffffffffULL] = OSUtils::jsonInt(tag[1], 0ULL) & 0xffffffffULL; - } - json mtagsa = json::array(); - for (std::map::iterator t(mtags.begin()); t != mtags.end(); ++t) { - json ta = json::array(); - ta.push_back(t->first); - ta.push_back(t->second); - mtagsa.push_back(ta); - if (mtagsa.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - member["tags"] = mtagsa; - } - } - - if (b.count("capabilities")) { - json& capabilities = b["capabilities"]; - if (capabilities.is_array()) { - json mcaps = json::array(); - for (unsigned long i = 0; i < capabilities.size(); ++i) { - mcaps.push_back(OSUtils::jsonInt(capabilities[i], 0ULL)); - if (mcaps.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE) - break; - } - std::sort(mcaps.begin(), mcaps.end()); - mcaps.erase(std::unique(mcaps.begin(), mcaps.end()), mcaps.end()); - member["capabilities"] = mcaps; - } - } - - member["id"] = memberID; - member["address"] = memberID; - member["nwid"] = networkID; - - DB::cleanMember(member); - _db.save(member, true); - - setContent(req, res, member.dump()); - }; - s.Put(memberPath, memberPost); - s.Post(memberPath, memberPost); - sv6.Put(memberPath, memberPost); - sv6.Post(memberPath, memberPost); - - auto memberDelete = [&, setContent](const httplib::Request& req, httplib::Response& res) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::memberDelete"); - auto scope = tracer->WithActiveSpan(span); - - auto networkID = req.matches[1].str(); - auto memberID = req.matches[2].str(); - - uint64_t nwid = Utils::hexStrToU64(networkID.c_str()); - uint64_t address = Utils::hexStrToU64(memberID.c_str()); - json network, member; - - if (! _db.get(nwid, network, address, member)) { - res.status = 404; - return; - } - - if (! member.size()) { - res.status = 404; - return; - } - - _db.eraseMember(nwid, address); - - setContent(req, res, member.dump()); - }; - s.Delete(memberPath, memberDelete); - sv6.Delete(memberPath, memberDelete); -} - -void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace& rt) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::handleRemoteTrace"); - auto scope = tracer->WithActiveSpan(span); - - static volatile unsigned long idCounter = 0; - char id[128], tmp[128]; - std::string k, v; - - try { - // Convert Dictionary into JSON object - json d; - char* saveptr = (char*)0; - for (char* l = Utils::stok(rt.data, "\n", &saveptr); (l); l = Utils::stok((char*)0, "\n", &saveptr)) { - char* eq = strchr(l, '='); - if (eq > l) { - k.assign(l, (unsigned long)(eq - l)); - v.clear(); - ++eq; - while (*eq) { - if (*eq == '\\') { - ++eq; - if (*eq) { - switch (*eq) { - case 'r': - v.push_back('\r'); - break; - case 'n': - v.push_back('\n'); - break; - case '0': - v.push_back((char)0); - break; - case 'e': - v.push_back('='); - break; - default: - v.push_back(*eq); - break; - } - ++eq; - } - } - else { - v.push_back(*(eq++)); - } - } - if ((k.length() > 0) && (v.length() > 0)) - d[k] = v; - } - } - - const int64_t now = OSUtils::now(); - OSUtils::ztsnprintf(id, sizeof(id), "%.10llx-%.16llx-%.10llx-%.4x", _signingId.address().toInt(), now, rt.origin, (unsigned int)(idCounter++ & 0xffff)); - d["id"] = id; - d["objtype"] = "trace"; - d["ts"] = now; - d["nodeId"] = Utils::hex10(rt.origin, tmp); - _db.save(d, true); - } - catch (...) { - // drop invalid trace messages if an error occurs - } -} - -void EmbeddedNetworkController::onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::onNetworkUpdate"); - auto scope = tracer->WithActiveSpan(span); - - // Send an update to all members of the network that are online - const int64_t now = OSUtils::now(); - std::lock_guard l(_memberStatus_l); - for (auto i = _memberStatus.begin(); i != _memberStatus.end(); ++i) { - if ((i->first.networkId == networkId) && (i->second.online(now)) && (i->second.lastRequestMetaData)) - request(networkId, InetAddress(), 0, i->second.identity, i->second.lastRequestMetaData); - } -} - -void EmbeddedNetworkController::onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::onNetworkMemberUpdate"); - auto scope = tracer->WithActiveSpan(span); - - // Push update to member if online - try { - std::lock_guard l(_memberStatus_l); - _MemberStatus& ms = _memberStatus[_MemberStatusKey(networkId, memberId)]; - if ((ms.online(OSUtils::now())) && (ms.lastRequestMetaData)) - request(networkId, InetAddress(), 0, ms.identity, ms.lastRequestMetaData); - } - catch (...) { - } -} - -void EmbeddedNetworkController::onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::onNetworkMemberDeauthorize"); - auto scope = tracer->WithActiveSpan(span); - - const int64_t now = OSUtils::now(); - Revocation rev((uint32_t)_node->prng(), networkId, 0, now, ZT_REVOCATION_FLAG_FAST_PROPAGATE, Address(memberId), Revocation::CREDENTIAL_TYPE_COM); - rev.sign(_signingId); - { - std::lock_guard l(_memberStatus_l); - for (auto i = _memberStatus.begin(); i != _memberStatus.end(); ++i) { - if ((i->first.networkId == networkId) && (i->second.online(now))) - _node->ncSendRevocation(Address(i->first.nodeId), rev); - } - } -} - -void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary& metaData) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_controller"); - auto span = tracer->StartSpan("embedded_controller::_request"); - auto scope = tracer->WithActiveSpan(span); - - Metrics::network_config_request++; - auto tid = std::this_thread::get_id(); - std::stringstream ss; - ss << tid; - std::string threadID = ss.str(); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - auto b1 = _member_status_lookup.Add({ { "thread", threadID } }); - auto c1 = _member_status_lookup_count.Add({ { "thread", threadID } }); - c1++; - b1.start(); -#endif - - char nwids[24]; - DB::NetworkSummaryInfo ns; - json network, member; - - if (((! _signingId) || (! _signingId.hasPrivate())) || (_signingId.address().toInt() != (nwid >> 24)) || (! _sender)) { - return; - } - - const int64_t now = OSUtils::now(); - -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b1.stop(); - auto b2 = _node_is_online.Add({ { "thread", threadID } }); - auto c2 = _node_is_online_count.Add({ { "thread", threadID } }); - c2++; - b2.start(); -#endif - char osArch[256]; - metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_OS_ARCH, osArch, sizeof(osArch)); - // fprintf(stderr, "Network Config Request: nwid=%.16llx, nodeid=%.10llx, osArch=%s\n", - // nwid, identity.address().toInt(), osArch); - _db.nodeIsOnline(nwid, identity.address().toInt(), fromAddr, osArch); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b2.stop(); - - auto b3 = _get_and_init_member.Add({ { "thread", threadID } }); - auto c3 = _get_and_init_member_count.Add({ { "thread", threadID } }); - c3++; - b3.start(); -#endif - Utils::hex(nwid, nwids); - _db.get(nwid, network, identity.address().toInt(), member, ns); - if ((! network.is_object()) || (network.empty())) { - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_OBJECT_NOT_FOUND, nullptr, 0); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b3.stop(); -#endif - return; - } - const bool newMember = ((! member.is_object()) || (member.empty())); - DB::initMember(member); - _MemberStatusKey msk(nwid, identity.address().toInt()); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b3.stop(); -#endif - - { -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - auto b4 = _have_identity.Add({ { "thread", threadID } }); - auto c4 = _have_identity_count.Add({ { "thread", threadID } }); - c4++; - b4.start(); -#endif - const std::string haveIdStr(OSUtils::jsonString(member["identity"], "")); - if (haveIdStr.length() > 0) { - // If we already know this member's identity perform a full compare. This prevents - // a "collision" from being able to auth onto our network in place of an already - // known member. - try { - if (Identity(haveIdStr.c_str()) != identity) { - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b4.stop(); -#endif - return; - } - } - catch (...) { - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b4.stop(); -#endif - return; - } - } - else { - // If we do not yet know this member's identity, learn it. - char idtmp[1024]; - member["identity"] = identity.toString(false, idtmp); - } -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b4.stop(); -#endif - } - - // These are always the same, but make sure they are set - { - char tmpid[128]; - const std::string addrs(identity.address().toString(tmpid)); - member["id"] = addrs; - member["address"] = addrs; - member["nwid"] = nwids; - } - - // Determine whether and how member is authorized -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - auto b5 = _determine_auth.Add({ { "thread", threadID } }); - auto c5 = _determine_auth_count.Add({ { "thread", threadID } }); - c5++; - b5.start(); -#endif - bool authorized = false; - bool autoAuthorized = false; - json autoAuthCredentialType, autoAuthCredential; - if (OSUtils::jsonBool(member["authorized"], false)) { - authorized = true; - } - else if (! OSUtils::jsonBool(network["private"], true)) { - authorized = true; - autoAuthorized = true; - autoAuthCredentialType = "public"; - } - else { - char presentedAuth[512]; - if (metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH, presentedAuth, sizeof(presentedAuth)) > 0) { - presentedAuth[511] = (char)0; // sanity check - if ((strlen(presentedAuth) > 6) && (! strncmp(presentedAuth, "token:", 6))) { - const char* const presentedToken = presentedAuth + 6; - json authTokens(network["authTokens"]); - json& tokenExpires = authTokens[presentedToken]; - if (tokenExpires.is_number()) { - if ((tokenExpires == 0) || (tokenExpires > now)) { - authorized = true; - autoAuthorized = true; - autoAuthCredentialType = "token"; - autoAuthCredential = presentedToken; - } - } - } - } - } - - // If we auto-authorized, update member record - if ((autoAuthorized) && (authorized)) { - member["authorized"] = true; - member["lastAuthorizedTime"] = now; - member["lastAuthorizedCredentialType"] = autoAuthCredentialType; - member["lastAuthorizedCredential"] = autoAuthCredential; - } -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b5.stop(); -#endif - - // Should we check SSO Stuff? - // If network is configured with SSO, and the member is not marked exempt: yes - // Otherwise no, we use standard auth logic. -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - auto b6 = _sso_check.Add({ { "thread", threadID } }); - auto c6 = _sso_check_count.Add({ { "thread", threadID } }); - c6++; - b6.start(); -#endif - AuthInfo info; - int64_t authenticationExpiryTime = -1; - bool networkSSOEnabled = OSUtils::jsonBool(network["ssoEnabled"], false); - bool memberSSOExempt = OSUtils::jsonBool(member["ssoExempt"], false); - if (networkSSOEnabled && ! memberSSOExempt) { - authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0); - info = _db.getSSOAuthInfo(member, _ssoRedirectURL); - assert(info.enabled == networkSSOEnabled); - if (authenticationExpiryTime <= now) { - if (info.version == 0) { - Dictionary<4096> authInfo; - authInfo.add(ZT_AUTHINFO_DICT_KEY_VERSION, (uint64_t)0ULL); - authInfo.add(ZT_AUTHINFO_DICT_KEY_AUTHENTICATION_URL, info.authenticationURL.c_str()); - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes()); - } - else if (info.version == 1) { - Dictionary<8192> authInfo; - authInfo.add(ZT_AUTHINFO_DICT_KEY_VERSION, info.version); - authInfo.add(ZT_AUTHINFO_DICT_KEY_ISSUER_URL, info.issuerURL.c_str()); - authInfo.add(ZT_AUTHINFO_DICT_KEY_CENTRAL_ENDPOINT_URL, info.centralAuthURL.c_str()); - authInfo.add(ZT_AUTHINFO_DICT_KEY_NONCE, info.ssoNonce.c_str()); - authInfo.add(ZT_AUTHINFO_DICT_KEY_STATE, info.ssoState.c_str()); - authInfo.add(ZT_AUTHINFO_DICT_KEY_CLIENT_ID, info.ssoClientID.c_str()); - authInfo.add(ZT_AUTHINFO_DICT_KEY_SSO_PROVIDER, info.ssoProvider.c_str()); - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes()); - } - DB::cleanMember(member); - _db.save(member, true); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b6.stop(); -#endif - return; - } - } -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b6.stop(); - - auto b7 = _auth_check.Add({ { "thread", threadID } }); - auto c7 = _auth_check_count.Add({ { "thread", threadID } }); - c7++; - b7.start(); -#endif - if (authorized) { - // Update version info and meta-data if authorized and if this is a genuine request - if (requestPacketId) { - const uint64_t vMajor = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION, 0); - const uint64_t vMinor = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION, 0); - const uint64_t vRev = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION, 0); - const uint64_t vProto = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION, 0); - - member["vMajor"] = vMajor; - member["vMinor"] = vMinor; - member["vRev"] = vRev; - member["vProto"] = vProto; - - { - std::lock_guard l(_memberStatus_l); - _MemberStatus& ms = _memberStatus[msk]; - ms.authenticationExpiryTime = authenticationExpiryTime; - ms.vMajor = (int)vMajor; - ms.vMinor = (int)vMinor; - ms.vRev = (int)vRev; - ms.vProto = (int)vProto; - ms.lastRequestMetaData = metaData; - ms.identity = identity; - } - - if (authenticationExpiryTime > 0) { - std::lock_guard l(_expiringSoon_l); - _expiringSoon.insert(std::pair(authenticationExpiryTime, msk)); - } - } - } - else { - // If they are not authorized, STOP! - DB::cleanMember(member); - _db.save(member, true); - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b7.stop(); -#endif - return; - } -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b7.stop(); -#endif - - // ------------------------------------------------------------------------- - // If we made it this far, they are authorized (and authenticated). - // ------------------------------------------------------------------------- - - // Default timeout: 15 minutes. Maximum: two hours. Can be specified by an optional field in the network config - // if something longer than 15 minutes is desired. Minimum is 5 minutes since shorter than that would be flaky. -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - auto b8 = _json_schlep.Add({ { "thread", threadID } }); - auto c8 = _json_schlep_count.Add({ { "thread", threadID } }); - c8++; - b8.start(); -#endif - int64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_DFL_MAX_DELTA; - if (network.contains("certificateTimeoutWindowSize")) { - credentialtmd = (int64_t)network["certificateTimeoutWindowSize"]; - } - credentialtmd = std::max(std::min(credentialtmd, ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA), ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA); - - std::unique_ptr nc(new NetworkConfig()); - - nc->networkId = nwid; - nc->type = OSUtils::jsonBool(network["private"], true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC; - nc->timestamp = now; - nc->credentialTimeMaxDelta = credentialtmd; - nc->revision = OSUtils::jsonInt(network["revision"], 0ULL); - nc->issuedTo = identity.address(); - if (OSUtils::jsonBool(network["enableBroadcast"], true)) - nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; - Utils::scopy(nc->name, sizeof(nc->name), OSUtils::jsonString(network["name"], "").c_str()); - nc->mtu = std::max(std::min((unsigned int)OSUtils::jsonInt(network["mtu"], ZT_DEFAULT_MTU), (unsigned int)ZT_MAX_MTU), (unsigned int)ZT_MIN_MTU); - nc->multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"], 32ULL); - - nc->ssoEnabled = networkSSOEnabled; // OSUtils::jsonBool(network["ssoEnabled"], false); - nc->ssoVersion = info.version; - - if (info.version == 0) { - nc->authenticationExpiryTime = OSUtils::jsonInt(member["authenticationExpiryTime"], 0LL); - if (! info.authenticationURL.empty()) { - Utils::scopy(nc->authenticationURL, sizeof(nc->authenticationURL), info.authenticationURL.c_str()); - } - } - else if (info.version == 1) { - nc->authenticationExpiryTime = OSUtils::jsonInt(member["authenticationExpiryTime"], 0LL); - if (! info.authenticationURL.empty()) { - Utils::scopy(nc->authenticationURL, sizeof(nc->authenticationURL), info.authenticationURL.c_str()); - } - if (! info.centralAuthURL.empty()) { - Utils::scopy(nc->centralAuthURL, sizeof(nc->centralAuthURL), info.centralAuthURL.c_str()); - } - if (! info.issuerURL.empty()) { -#ifdef ZT_DEBUG - fprintf(stderr, "copying issuerURL to nc: %s\n", info.issuerURL.c_str()); -#endif - Utils::scopy(nc->issuerURL, sizeof(nc->issuerURL), info.issuerURL.c_str()); - } - if (! info.ssoNonce.empty()) { - Utils::scopy(nc->ssoNonce, sizeof(nc->ssoNonce), info.ssoNonce.c_str()); - } - if (! info.ssoState.empty()) { - Utils::scopy(nc->ssoState, sizeof(nc->ssoState), info.ssoState.c_str()); - } - if (! info.ssoClientID.empty()) { - Utils::scopy(nc->ssoClientID, sizeof(nc->ssoClientID), info.ssoClientID.c_str()); - } - } - - std::string rtt(OSUtils::jsonString(member["remoteTraceTarget"], "")); - if (rtt.length() == 10) { - nc->remoteTraceTarget = Address(Utils::hexStrToU64(rtt.c_str())); - nc->remoteTraceLevel = (Trace::Level)OSUtils::jsonInt(member["remoteTraceLevel"], 0ULL); - } - else { - rtt = OSUtils::jsonString(network["remoteTraceTarget"], ""); - if (rtt.length() == 10) { - nc->remoteTraceTarget = Address(Utils::hexStrToU64(rtt.c_str())); - } - else { - nc->remoteTraceTarget.zero(); - } - nc->remoteTraceLevel = (Trace::Level)OSUtils::jsonInt(network["remoteTraceLevel"], 0ULL); - } - - for (std::vector
::const_iterator ab(ns.activeBridges.begin()); ab != ns.activeBridges.end(); ++ab) { - nc->addSpecialist(*ab, ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE); - } - - json& v4AssignMode = network["v4AssignMode"]; - json& v6AssignMode = network["v6AssignMode"]; - json& ipAssignmentPools = network["ipAssignmentPools"]; - json& routes = network["routes"]; - json& rules = network["rules"]; - json& capabilities = network["capabilities"]; - json& tags = network["tags"]; - json& memberCapabilities = member["capabilities"]; - json& memberTags = member["tags"]; - json& dns = network["dns"]; - - // fprintf(stderr, "IP Assignment Pools for Network %s: %s\n", nwids, OSUtils::jsonDump(ipAssignmentPools, 2).c_str()); - - if (metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV, 0) <= 0) { - // Old versions with no rules engine support get an allow everything rule. - // Since rules are enforced bidirectionally, newer versions *will* still - // enforce rules on the inbound side. - nc->ruleCount = 1; - nc->rules[0].t = ZT_NETWORK_RULE_ACTION_ACCEPT; - } - else { - if (rules.is_array()) { - for (unsigned long i = 0; i < rules.size(); ++i) { - if (nc->ruleCount >= ZT_MAX_NETWORK_RULES) - break; - if (_parseRule(rules[i], nc->rules[nc->ruleCount])) - ++nc->ruleCount; - } - } - - std::map capsById; - if (! memberCapabilities.is_array()) - memberCapabilities = json::array(); - if (capabilities.is_array()) { - for (unsigned long i = 0; i < capabilities.size(); ++i) { - json& cap = capabilities[i]; - if (cap.is_object()) { - const uint64_t id = OSUtils::jsonInt(cap["id"], 0ULL) & 0xffffffffULL; - capsById[id] = ∩ - if ((newMember) && (OSUtils::jsonBool(cap["default"], false))) { - bool have = false; - for (unsigned long i = 0; i < memberCapabilities.size(); ++i) { - if (id == (OSUtils::jsonInt(memberCapabilities[i], 0ULL) & 0xffffffffULL)) { - have = true; - break; - } - } - if (! have) - memberCapabilities.push_back(id); - } - } - } - } - for (unsigned long i = 0; i < memberCapabilities.size(); ++i) { - const uint64_t capId = OSUtils::jsonInt(memberCapabilities[i], 0ULL) & 0xffffffffULL; - std::map::const_iterator ctmp = capsById.find(capId); - if (ctmp != capsById.end()) { - json* cap = ctmp->second; - if ((cap) && (cap->is_object()) && (! cap->empty())) { - ZT_VirtualNetworkRule capr[ZT_MAX_CAPABILITY_RULES]; - unsigned int caprc = 0; - json& caprj = (*cap)["rules"]; - if ((caprj.is_array()) && (! caprj.empty())) { - for (unsigned long j = 0; j < caprj.size(); ++j) { - if (caprc >= ZT_MAX_CAPABILITY_RULES) - break; - if (_parseRule(caprj[j], capr[caprc])) - ++caprc; - } - } - nc->capabilities[nc->capabilityCount] = Capability((uint32_t)capId, nwid, now, 1, capr, caprc); - if (nc->capabilities[nc->capabilityCount].sign(_signingId, identity.address())) - ++nc->capabilityCount; - if (nc->capabilityCount >= ZT_MAX_NETWORK_CAPABILITIES) - break; - } - } - } - - std::map memberTagsById; - if (memberTags.is_array()) { - for (unsigned long i = 0; i < memberTags.size(); ++i) { - json& t = memberTags[i]; - if ((t.is_array()) && (t.size() == 2)) - memberTagsById[(uint32_t)(OSUtils::jsonInt(t[0], 0ULL) & 0xffffffffULL)] = (uint32_t)(OSUtils::jsonInt(t[1], 0ULL) & 0xffffffffULL); - } - } - if (tags.is_array()) { // check network tags array for defaults that are not present in member tags - for (unsigned long i = 0; i < tags.size(); ++i) { - json& t = tags[i]; - if (t.is_object()) { - const uint32_t id = (uint32_t)(OSUtils::jsonInt(t["id"], 0) & 0xffffffffULL); - json& dfl = t["default"]; - if ((dfl.is_number()) && (memberTagsById.find(id) == memberTagsById.end())) { - memberTagsById[id] = (uint32_t)(OSUtils::jsonInt(dfl, 0) & 0xffffffffULL); - json mt = json::array(); - mt.push_back(id); - mt.push_back(dfl); - memberTags.push_back(mt); // add default to member tags if not present - } - } - } - } - for (std::map::const_iterator t(memberTagsById.begin()); t != memberTagsById.end(); ++t) { - if (nc->tagCount >= ZT_MAX_NETWORK_TAGS) - break; - nc->tags[nc->tagCount] = Tag(nwid, now, identity.address(), t->first, t->second); - if (nc->tags[nc->tagCount].sign(_signingId)) - ++nc->tagCount; - } - } - - if (routes.is_array()) { - for (unsigned long i = 0; i < routes.size(); ++i) { - if (nc->routeCount >= ZT_MAX_NETWORK_ROUTES) - break; - json& route = routes[i]; - json& target = route["target"]; - json& via = route["via"]; - if (target.is_string()) { - const InetAddress t(target.get().c_str()); - InetAddress v; - if (via.is_string()) - v.fromString(via.get().c_str()); - if ((t.ss_family == AF_INET) || (t.ss_family == AF_INET6)) { - ZT_VirtualNetworkRoute* r = &(nc->routes[nc->routeCount]); - *(reinterpret_cast(&(r->target))) = t; - if (v.ss_family == t.ss_family) - *(reinterpret_cast(&(r->via))) = v; - ++nc->routeCount; - } - } - } - } - - const bool noAutoAssignIps = OSUtils::jsonBool(member["noAutoAssignIps"], false); - - if ((v6AssignMode.is_object()) && (! noAutoAssignIps)) { - if ((OSUtils::jsonBool(v6AssignMode["rfc4193"], false)) && (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { - nc->staticIps[nc->staticIpCount++] = InetAddress::makeIpv6rfc4193(nwid, identity.address().toInt()); - nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; - } - if ((OSUtils::jsonBool(v6AssignMode["6plane"], false)) && (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { - nc->staticIps[nc->staticIpCount++] = InetAddress::makeIpv66plane(nwid, identity.address().toInt()); - nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; - } - } - - bool haveManagedIpv4AutoAssignment = false; - bool haveManagedIpv6AutoAssignment = false; // "special" NDP-emulated address types do not count - json ipAssignments = member["ipAssignments"]; // we want to make a copy - if (ipAssignments.is_array()) { - for (unsigned long i = 0; i < ipAssignments.size(); ++i) { - if (ipAssignments[i].is_string()) { - const std::string ips = ipAssignments[i]; - InetAddress ip(ips.c_str()); - - int routedNetmaskBits = -1; - for (unsigned int rk = 0; rk < nc->routeCount; ++rk) { - if (reinterpret_cast(&(nc->routes[rk].target))->containsAddress(ip)) { - const int nb = (int)(reinterpret_cast(&(nc->routes[rk].target))->netmaskBits()); - if (nb > routedNetmaskBits) - routedNetmaskBits = nb; - } - } - - if (routedNetmaskBits >= 0) { - if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { - ip.setPort(routedNetmaskBits); - nc->staticIps[nc->staticIpCount++] = ip; - } - if (ip.ss_family == AF_INET) - haveManagedIpv4AutoAssignment = true; - else if (ip.ss_family == AF_INET6) - haveManagedIpv6AutoAssignment = true; - } - } - } - } - else { - ipAssignments = json::array(); - } - - if ((ipAssignmentPools.is_array()) && ((v6AssignMode.is_object()) && (OSUtils::jsonBool(v6AssignMode["zt"], false))) && (! haveManagedIpv6AutoAssignment) && (! noAutoAssignIps)) { - for (unsigned long p = 0; ((p < ipAssignmentPools.size()) && (! haveManagedIpv6AutoAssignment)); ++p) { - json& pool = ipAssignmentPools[p]; - if (pool.is_object()) { - InetAddress ipRangeStart(OSUtils::jsonString(pool["ipRangeStart"], "").c_str()); - InetAddress ipRangeEnd(OSUtils::jsonString(pool["ipRangeEnd"], "").c_str()); - if ((ipRangeStart.ss_family == AF_INET6) && (ipRangeEnd.ss_family == AF_INET6)) { - uint64_t s[2], e[2], x[2], xx[2]; - memcpy(s, ipRangeStart.rawIpData(), 16); - memcpy(e, ipRangeEnd.rawIpData(), 16); - s[0] = Utils::ntoh(s[0]); - s[1] = Utils::ntoh(s[1]); - e[0] = Utils::ntoh(e[0]); - e[1] = Utils::ntoh(e[1]); - x[0] = s[0]; - x[1] = s[1]; - - for (unsigned int trialCount = 0; trialCount < 1000; ++trialCount) { - if ((trialCount == 0) && (e[1] > s[1]) && ((e[1] - s[1]) >= 0xffffffffffULL)) { - // First see if we can just cram a ZeroTier ID into the higher 64 bits. If so do that. - xx[0] = Utils::hton(x[0]); - xx[1] = Utils::hton(x[1] + identity.address().toInt()); - } - else { - // Otherwise pick random addresses -- this technically doesn't explore the whole range if the lower 64 bit range is >= 1 but that won't matter since that would be huge anyway - Utils::getSecureRandom((void*)xx, 16); - if ((e[0] > s[0])) - xx[0] %= (e[0] - s[0]); - else - xx[0] = 0; - if ((e[1] > s[1])) - xx[1] %= (e[1] - s[1]); - else - xx[1] = 0; - xx[0] = Utils::hton(x[0] + xx[0]); - xx[1] = Utils::hton(x[1] + xx[1]); - } - - InetAddress ip6((const void*)xx, 16, 0); - - // Check if this IP is within a local-to-Ethernet routed network - int routedNetmaskBits = 0; - for (unsigned int rk = 0; rk < nc->routeCount; ++rk) { - if ((! nc->routes[rk].via.ss_family) && (nc->routes[rk].target.ss_family == AF_INET6) && (reinterpret_cast(&(nc->routes[rk].target))->containsAddress(ip6))) - routedNetmaskBits = reinterpret_cast(&(nc->routes[rk].target))->netmaskBits(); - } - - // If it's routed, then try to claim and assign it and if successful end loop - if ((routedNetmaskBits > 0) && (! std::binary_search(ns.allocatedIps.begin(), ns.allocatedIps.end(), ip6))) { - char tmpip[64]; - const std::string ipStr(ip6.toIpString(tmpip)); - if (std::find(ipAssignments.begin(), ipAssignments.end(), ipStr) == ipAssignments.end()) { - ipAssignments.push_back(ipStr); - member["ipAssignments"] = ipAssignments; - ip6.setPort((unsigned int)routedNetmaskBits); - if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) - nc->staticIps[nc->staticIpCount++] = ip6; - haveManagedIpv6AutoAssignment = true; - break; - } - } - } - } - } - } - } - - if ((ipAssignmentPools.is_array()) && ((v4AssignMode.is_object()) && (OSUtils::jsonBool(v4AssignMode["zt"], false))) && (! haveManagedIpv4AutoAssignment) && (! noAutoAssignIps)) { - for (unsigned long p = 0; ((p < ipAssignmentPools.size()) && (! haveManagedIpv4AutoAssignment)); ++p) { - json& pool = ipAssignmentPools[p]; - if (pool.is_object()) { - InetAddress ipRangeStartIA(OSUtils::jsonString(pool["ipRangeStart"], "").c_str()); - InetAddress ipRangeEndIA(OSUtils::jsonString(pool["ipRangeEnd"], "").c_str()); - if ((ipRangeStartIA.ss_family == AF_INET) && (ipRangeEndIA.ss_family == AF_INET)) { - uint32_t ipRangeStart = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeStartIA)->sin_addr.s_addr)); - uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEndIA)->sin_addr.s_addr)); - - if ((ipRangeEnd < ipRangeStart) || (ipRangeStart == 0)) - continue; - uint32_t ipRangeLen = ipRangeEnd - ipRangeStart; - - // Start with the LSB of the member's address - uint32_t ipTrialCounter = (uint32_t)(identity.address().toInt() & 0xffffffff); - - for (uint32_t k = ipRangeStart, trialCount = 0; ((k <= ipRangeEnd) && (trialCount < 1000)); ++k, ++trialCount) { - uint32_t ip = (ipRangeLen > 0) ? (ipRangeStart + (ipTrialCounter % ipRangeLen)) : ipRangeStart; - ++ipTrialCounter; - if ((ip & 0x000000ff) == 0x000000ff) { - continue; // don't allow addresses that end in .255 - } - - // Check if this IP is within a local-to-Ethernet routed network - int routedNetmaskBits = -1; - for (unsigned int rk = 0; rk < nc->routeCount; ++rk) { - if (nc->routes[rk].target.ss_family == AF_INET) { - uint32_t targetIp = Utils::ntoh((uint32_t)(reinterpret_cast(&(nc->routes[rk].target))->sin_addr.s_addr)); - int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast(&(nc->routes[rk].target))->sin_port)); - if ((ip & (0xffffffff << (32 - targetBits))) == targetIp) { - routedNetmaskBits = targetBits; - break; - } - } - } - - // If it's routed, then try to claim and assign it and if successful end loop - const InetAddress ip4(Utils::hton(ip), 0); - if ((routedNetmaskBits > 0) && (! std::binary_search(ns.allocatedIps.begin(), ns.allocatedIps.end(), ip4))) { - char tmpip[64]; - const std::string ipStr(ip4.toIpString(tmpip)); - if (std::find(ipAssignments.begin(), ipAssignments.end(), ipStr) == ipAssignments.end()) { - ipAssignments.push_back(ipStr); - member["ipAssignments"] = ipAssignments; - if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { - struct sockaddr_in* const v4ip = reinterpret_cast(&(nc->staticIps[nc->staticIpCount++])); - v4ip->sin_family = AF_INET; - v4ip->sin_port = Utils::hton((uint16_t)routedNetmaskBits); - v4ip->sin_addr.s_addr = Utils::hton(ip); - } - haveManagedIpv4AutoAssignment = true; - break; - } - } - } - } - } - } - } - - if (dns.is_object()) { - std::string domain = OSUtils::jsonString(dns["domain"], ""); - memcpy(nc->dns.domain, domain.c_str(), domain.size()); - json& addrArray = dns["servers"]; - if (addrArray.is_array()) { - for (unsigned int j = 0; j < addrArray.size() && j < ZT_MAX_DNS_SERVERS; ++j) { - json& addr = addrArray[j]; - nc->dns.server_addr[j] = InetAddress(OSUtils::jsonString(addr, "").c_str()); - } - } - } - else { - dns = json::object(); - } -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b8.stop(); -#endif - - // Issue a certificate of ownership for all static IPs -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - auto b9 = _issue_certificate.Add({ { "thread", threadID } }); - auto c9 = _issue_certificate_count.Add({ { "thread", threadID } }); - c9++; - b9.start(); -#endif - if (nc->staticIpCount) { - nc->certificatesOfOwnership[0] = CertificateOfOwnership(nwid, now, identity.address(), 1); - for (unsigned int i = 0; i < nc->staticIpCount; ++i) { - nc->certificatesOfOwnership[0].addThing(nc->staticIps[i]); - } - nc->certificatesOfOwnership[0].sign(_signingId); - nc->certificateOfOwnershipCount = 1; - } - - CertificateOfMembership com(now, credentialtmd, nwid, identity); - if (com.sign(_signingId)) { - nc->com = com; - } - else { - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR, nullptr, 0); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b9.stop(); -#endif - return; - } -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b9.stop(); - - auto b10 = _save_member.Add({ { "thread", threadID } }); - auto c10 = _save_member_count.Add({ { "thread", threadID } }); - c10++; - b10.start(); -#endif - DB::cleanMember(member); - _db.save(member, true); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b10.stop(); - - auto b11 = _send_netconf.Add({ { "thread", threadID } }); - auto c11 = _send_netconf_count.Add({ { "thread", threadID } }); - c11++; - b11.start(); -#endif - _sender->ncSendConfig(nwid, requestPacketId, identity.address(), *(nc.get()), metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION, 0) < 6); -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - b11.stop(); -#endif -} - -void EmbeddedNetworkController::_startThreads() -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_network_controller"); - auto span = tracer->StartSpan("embedded_network_controller::_startThreads"); - auto scope = tracer->WithActiveSpan(span); - - std::lock_guard l(_threads_l); - if (! _threads.empty()) { - return; - } - const long hwc = std::max((long)std::thread::hardware_concurrency(), (long)1); - for (long t = 0; t < hwc; ++t) { - _threads.emplace_back([this]() { - Metrics::network_config_request_threads++; - for (;;) { - _RQEntry* qe = (_RQEntry*)0; - Metrics::network_config_request_queue_size = _queue.size(); - auto timedWaitResult = _queue.get(qe, 1000); - if (timedWaitResult == BlockingQueue<_RQEntry*>::STOP) { - break; - } - else if (timedWaitResult == BlockingQueue<_RQEntry*>::OK) { - if (qe) { - try { - _request(qe->nwid, qe->fromAddr, qe->requestPacketId, qe->identity, qe->metaData); - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: exception in controller request handling thread: %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: exception in controller request handling thread: unknown exception" ZT_EOL_S); - } - delete qe; - qe = nullptr; - } - } - } - Metrics::network_config_request_threads--; - }); - } -} - -void EmbeddedNetworkController::_ssoExpiryThread() -{ - while (_ssoExpiryRunning) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("embedded_network_controller"); - auto span = tracer->StartSpan("embedded_network_controller::_ssoExpiryThread"); - auto scope = tracer->WithActiveSpan(span); - - std::vector<_MemberStatusKey> expired; - nlohmann::json network, member; - int64_t now = OSUtils::now(); - { - std::lock_guard l(_expiringSoon_l); - for (auto s = _expiringSoon.begin(); s != _expiringSoon.end();) { - Metrics::sso_expiration_checks++; - const int64_t when = s->first; - if (when <= now) { - // The user may have re-authorized, so we must actually look it up and check. - network.clear(); - member.clear(); - if (_db.get(s->second.networkId, network, s->second.nodeId, member)) { - int64_t authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0); - if (authenticationExpiryTime <= now) { - expired.push_back(s->second); - } - } - s = _expiringSoon.erase(s); - } - else { - // Don't bother going further into the future than necessary. - break; - } - } - } - for (auto e = expired.begin(); e != expired.end(); ++e) { - Metrics::sso_member_deauth++; - onNetworkMemberDeauthorize(nullptr, e->networkId, e->nodeId); - } - span->End(); - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } -} - -} // namespace ZeroTier diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp deleted file mode 100644 index 111417bfb..000000000 --- a/controller/EmbeddedNetworkController.hpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_SQLITENETWORKCONTROLLER_HPP -#define ZT_SQLITENETWORKCONTROLLER_HPP - -#include "../node/Address.hpp" -#include "../node/Constants.hpp" -#include "../node/InetAddress.hpp" -#include "../node/NetworkController.hpp" -#include "../node/Utils.hpp" -#include "../osdep/BlockingQueue.hpp" -#include "../osdep/OSUtils.hpp" -#include "../osdep/Thread.hpp" -#include "DB.hpp" -#include "DBMirrorSet.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ZeroTier { - -class Node; -struct RedisConfig; - -class EmbeddedNetworkController - : public NetworkController - , public DB::ChangeListener { - public: - /** - * @param node Parent node - * @param dbPath Database path (file path or database credentials) - */ - EmbeddedNetworkController(Node* node, const char* ztPath, const char* dbPath, int listenPort, RedisConfig* rc); - virtual ~EmbeddedNetworkController(); - - virtual void init(const Identity& signingId, Sender* sender); - - void setSSORedirectURL(const std::string& url); - - virtual void request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary& metaData); - - void configureHTTPControlPlane(httplib::Server& s, httplib::Server& sV6, const std::function); - - void handleRemoteTrace(const ZT_RemoteTrace& rt); - - virtual void onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network); - virtual void onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member); - virtual void onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId); - - private: - void _request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary& metaData); - void _startThreads(); - void _ssoExpiryThread(); - - std::string networkUpdateFromPostData(uint64_t networkID, const std::string& body); - - struct _RQEntry { - uint64_t nwid; - uint64_t requestPacketId; - InetAddress fromAddr; - Identity identity; - Dictionary metaData; - enum { RQENTRY_TYPE_REQUEST = 0 } type; - }; - - struct _MemberStatusKey { - _MemberStatusKey() : networkId(0), nodeId(0) - { - } - _MemberStatusKey(const uint64_t nwid, const uint64_t nid) : networkId(nwid), nodeId(nid) - { - } - uint64_t networkId; - uint64_t nodeId; - inline bool operator==(const _MemberStatusKey& k) const - { - return ((k.networkId == networkId) && (k.nodeId == nodeId)); - } - inline bool operator<(const _MemberStatusKey& k) const - { - return (k.networkId < networkId) || ((k.networkId == networkId) && (k.nodeId < nodeId)); - } - }; - struct _MemberStatus { - _MemberStatus() : lastRequestTime(0), authenticationExpiryTime(-1), vMajor(-1), vMinor(-1), vRev(-1), vProto(-1) - { - } - int64_t lastRequestTime; - int64_t authenticationExpiryTime; - int vMajor, vMinor, vRev, vProto; - Dictionary lastRequestMetaData; - Identity identity; - inline bool online(const int64_t now) const - { - return ((now - lastRequestTime) < (ZT_NETWORK_AUTOCONF_DELAY * 2)); - } - }; - struct _MemberStatusHash { - inline std::size_t operator()(const _MemberStatusKey& networkIdNodeId) const - { - return (std::size_t)(networkIdNodeId.networkId + networkIdNodeId.nodeId); - } - }; - - const int64_t _startTime; - int _listenPort; - Node* const _node; - std::string _ztPath; - std::string _path; - Identity _signingId; - std::string _signingIdAddressString; - NetworkController::Sender* _sender; - - DBMirrorSet _db; - BlockingQueue<_RQEntry*> _queue; - - std::vector _threads; - std::mutex _threads_l; - - std::unordered_map<_MemberStatusKey, _MemberStatus, _MemberStatusHash> _memberStatus; - std::mutex _memberStatus_l; - - std::set > _expiringSoon; - std::mutex _expiringSoon_l; - - RedisConfig* _rc; - std::string _ssoRedirectURL; - - bool _ssoExpiryRunning; - std::thread _ssoExpiry; - -#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK - prometheus::simpleapi::benchmark_family_t _member_status_lookup; - prometheus::simpleapi::counter_family_t _member_status_lookup_count; - prometheus::simpleapi::benchmark_family_t _node_is_online; - prometheus::simpleapi::counter_family_t _node_is_online_count; - prometheus::simpleapi::benchmark_family_t _get_and_init_member; - prometheus::simpleapi::counter_family_t _get_and_init_member_count; - prometheus::simpleapi::benchmark_family_t _have_identity; - prometheus::simpleapi::counter_family_t _have_identity_count; - prometheus::simpleapi::benchmark_family_t _determine_auth; - prometheus::simpleapi::counter_family_t _determine_auth_count; - prometheus::simpleapi::benchmark_family_t _sso_check; - prometheus::simpleapi::counter_family_t _sso_check_count; - prometheus::simpleapi::benchmark_family_t _auth_check; - prometheus::simpleapi::counter_family_t _auth_check_count; - prometheus::simpleapi::benchmark_family_t _json_schlep; - prometheus::simpleapi::counter_family_t _json_schlep_count; - prometheus::simpleapi::benchmark_family_t _issue_certificate; - prometheus::simpleapi::counter_family_t _issue_certificate_count; - prometheus::simpleapi::benchmark_family_t _save_member; - prometheus::simpleapi::counter_family_t _save_member_count; - prometheus::simpleapi::benchmark_family_t _send_netconf; - prometheus::simpleapi::counter_family_t _send_netconf_count; -#endif -}; - -} // namespace ZeroTier - -#endif diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp deleted file mode 100644 index 6472022e2..000000000 --- a/controller/FileDB.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "FileDB.hpp" - -#include "../node/Metrics.hpp" -#include "opentelemetry/trace/provider.h" - -namespace ZeroTier { - -FileDB::FileDB(const char* path) : DB(), _path(path), _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), _running(true) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("filedb"); - auto span = tracer->StartSpan("filedb::FileDB"); - auto scope = tracer->WithActiveSpan(span); - - OSUtils::mkdir(_path.c_str()); - OSUtils::lockDownFile(_path.c_str(), true); - OSUtils::mkdir(_networksPath.c_str()); - OSUtils::mkdir(_tracePath.c_str()); - - std::vector networks(OSUtils::listDirectory(_networksPath.c_str(), false)); - std::string buf; - for (auto n = networks.begin(); n != networks.end(); ++n) { - buf.clear(); - if ((n->length() == 21) && (OSUtils::readFile((_networksPath + ZT_PATH_SEPARATOR_S + *n).c_str(), buf))) { - try { - nlohmann::json network(OSUtils::jsonParse(buf)); - const std::string nwids = network["id"]; - if (nwids.length() == 16) { - nlohmann::json nullJson; - _networkChanged(nullJson, network, false); - Metrics::network_count++; - std::string membersPath(_networksPath + ZT_PATH_SEPARATOR_S + nwids + ZT_PATH_SEPARATOR_S "member"); - std::vector members(OSUtils::listDirectory(membersPath.c_str(), false)); - for (auto m = members.begin(); m != members.end(); ++m) { - buf.clear(); - if ((m->length() == 15) && (OSUtils::readFile((membersPath + ZT_PATH_SEPARATOR_S + *m).c_str(), buf))) { - try { - nlohmann::json member(OSUtils::jsonParse(buf)); - const std::string addrs = member["id"]; - if (addrs.length() == 10) { - nlohmann::json nullJson2; - _memberChanged(nullJson2, member, false); - Metrics::member_count++; - } - } - catch (...) { - } - } - } - } - } - catch (...) { - } - } - } -} - -FileDB::~FileDB() -{ - try { - _online_l.lock(); - _running = false; - _online_l.unlock(); - _onlineUpdateThread.join(); - } - catch (...) { - } -} - -bool FileDB::waitForReady() -{ - return true; -} -bool FileDB::isReady() -{ - return true; -} - -bool FileDB::save(nlohmann::json& record, bool notifyListeners) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("filedb"); - auto span = tracer->StartSpan("filedb::save"); - auto scope = tracer->WithActiveSpan(span); - - char p1[4096], p2[4096], pb[4096]; - bool modified = false; - try { - const std::string objtype = record["objtype"]; - if (objtype == "network") { - auto span = tracer->StartSpan("filedb::save::network"); - auto scope = tracer->WithActiveSpan(span); - - const uint64_t nwid = OSUtils::jsonIntHex(record["id"], 0ULL); - if (nwid) { - nlohmann::json old; - get(nwid, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - OSUtils::ztsnprintf(p1, sizeof(p1), "%s" ZT_PATH_SEPARATOR_S "%.16llx.json", _networksPath.c_str(), nwid); - if (! OSUtils::writeFile(p1, OSUtils::jsonDump(record, -1))) { - fprintf(stderr, "WARNING: controller unable to write to path: %s" ZT_EOL_S, p1); - } - _networkChanged(old, record, notifyListeners); - modified = true; - } - } - } - else if (objtype == "member") { - auto span = tracer->StartSpan("filedb::save::member"); - auto scope = tracer->WithActiveSpan(span); - - const uint64_t id = OSUtils::jsonIntHex(record["id"], 0ULL); - const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"], 0ULL); - if ((id) && (nwid)) { - nlohmann::json network, old; - get(nwid, network, id, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - OSUtils::ztsnprintf(pb, sizeof(pb), "%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member", _networksPath.c_str(), (unsigned long long)nwid); - OSUtils::ztsnprintf(p1, sizeof(p1), "%s" ZT_PATH_SEPARATOR_S "%.10llx.json", pb, (unsigned long long)id); - if (! OSUtils::writeFile(p1, OSUtils::jsonDump(record, -1))) { - OSUtils::ztsnprintf(p2, sizeof(p2), "%s" ZT_PATH_SEPARATOR_S "%.16llx", _networksPath.c_str(), (unsigned long long)nwid); - OSUtils::mkdir(p2); - OSUtils::mkdir(pb); - if (! OSUtils::writeFile(p1, OSUtils::jsonDump(record, -1))) { - fprintf(stderr, "WARNING: controller unable to write to path: %s" ZT_EOL_S, p1); - } - } - _memberChanged(old, record, notifyListeners); - modified = true; - } - } - } - } - catch (...) { - } // drop invalid records missing fields - return modified; -} - -void FileDB::eraseNetwork(const uint64_t networkId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("filedb"); - auto span = tracer->StartSpan("filedb::eraseNetwork"); - auto scope = tracer->WithActiveSpan(span); - - nlohmann::json network, nullJson; - get(networkId, network); - char p[16384]; - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx.json", _networksPath.c_str(), networkId); - OSUtils::rm(p); - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx", _networksPath.c_str(), (unsigned long long)networkId); - OSUtils::rmDashRf(p); - _networkChanged(network, nullJson, true); - std::lock_guard l(this->_online_l); - this->_online.erase(networkId); -} - -void FileDB::eraseMember(const uint64_t networkId, const uint64_t memberId) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("filedb"); - auto span = tracer->StartSpan("filedb::eraseMember"); - auto scope = tracer->WithActiveSpan(span); - - nlohmann::json network, member, nullJson; - get(networkId, network, memberId, member); - char p[4096]; - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member" ZT_PATH_SEPARATOR_S "%.10llx.json", _networksPath.c_str(), networkId, memberId); - OSUtils::rm(p); - _memberChanged(member, nullJson, true); - std::lock_guard l(this->_online_l); - this->_online[networkId].erase(memberId); -} - -void FileDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) -{ - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("filedb"); - auto span = tracer->StartSpan("filedb::nodeIsOnline"); - auto scope = tracer->WithActiveSpan(span); - - char mid[32], atmp[64]; - OSUtils::ztsnprintf(mid, sizeof(mid), "%.10llx", (unsigned long long)memberId); - physicalAddress.toString(atmp); - std::lock_guard l(this->_online_l); - this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; -} - -void FileDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) -{ - this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown"); -} - -} // namespace ZeroTier diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp deleted file mode 100644 index e10753223..000000000 --- a/controller/FileDB.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_CONTROLLER_FILEDB_HPP -#define ZT_CONTROLLER_FILEDB_HPP - -#include "DB.hpp" - -namespace ZeroTier { - -class FileDB : public DB { - public: - FileDB(const char* path); - virtual ~FileDB(); - - virtual bool waitForReady(); - virtual bool isReady(); - virtual bool save(nlohmann::json& record, bool notifyListeners); - virtual void eraseNetwork(const uint64_t networkId); - virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); - - protected: - std::string _path; - std::string _networksPath; - std::string _tracePath; - std::thread _onlineUpdateThread; - std::map > > _online; - std::mutex _online_l; - bool _running; -}; - -} // namespace ZeroTier - -#endif diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp deleted file mode 100644 index 77fa8ffe1..000000000 --- a/controller/LFDB.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "LFDB.hpp" - -#include "../ext/cpp-httplib/httplib.h" -#include "../osdep/OSUtils.hpp" - -#include -#include -#include -#include - -namespace ZeroTier { - -LFDB::LFDB(const Identity& myId, const char* path, const char* lfOwnerPrivate, const char* lfOwnerPublic, const char* lfNodeHost, int lfNodePort, bool storeOnlineState) - : DB() - , _myId(myId) - , _lfOwnerPrivate((lfOwnerPrivate) ? lfOwnerPrivate : "") - , _lfOwnerPublic((lfOwnerPublic) ? lfOwnerPublic : "") - , _lfNodeHost((lfNodeHost) ? lfNodeHost : "127.0.0.1") - , _lfNodePort(((lfNodePort > 0) && (lfNodePort < 65536)) ? lfNodePort : 9980) - , _running(true) - , _ready(false) - , _storeOnlineState(storeOnlineState) -{ - _syncThread = std::thread([this]() { - char controllerAddress[24]; - const uint64_t controllerAddressInt = _myId.address().toInt(); - _myId.address().toString(controllerAddress); - std::string networksSelectorName("com.zerotier.controller.lfdb:"); - networksSelectorName.append(controllerAddress); - networksSelectorName.append("/network"); - - // LF record masking key is the first 32 bytes of SHA512(controller private key) in hex, - // hiding record values from anything but the controller or someone who has its key. - uint8_t sha512pk[64]; - _myId.sha512PrivateKey(sha512pk); - char maskingKey[128]; - Utils::hex(sha512pk, 32, maskingKey); - - httplib::Client htcli(_lfNodeHost.c_str(), _lfNodePort); - int64_t timeRangeStart = 0; - while (_running.load()) { - { - std::lock_guard sl(_state_l); - for (auto ns = _state.begin(); ns != _state.end(); ++ns) { - if (ns->second.dirty) { - nlohmann::json network; - if (get(ns->first, network)) { - nlohmann::json newrec, selector0; - selector0["Name"] = networksSelectorName; - selector0["Ordinal"] = ns->first; - newrec["Selectors"].push_back(selector0); - newrec["Value"] = network.dump(); - newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = maskingKey; - newrec["PulseIfUnchanged"] = true; - try { - auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json"); - if (resp) { - if (resp->status == 200) { - ns->second.dirty = false; - // printf("SET network %.16llx %s\n",ns->first,resp->body.c_str()); - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update network): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update network): unknown exception" ZT_EOL_S); - } - } - } - - for (auto ms = ns->second.members.begin(); ms != ns->second.members.end(); ++ms) { - if ((_storeOnlineState) && (ms->second.lastOnlineDirty) && (ms->second.lastOnlineAddress)) { - nlohmann::json newrec, selector0, selector1, selectors, ip; - char tmp[1024], tmp2[128]; - OSUtils::ztsnprintf(tmp, sizeof(tmp), "com.zerotier.controller.lfdb:%s/network/%.16llx/online", controllerAddress, (unsigned long long)ns->first); - ms->second.lastOnlineAddress.toIpString(tmp2); - selector0["Name"] = tmp; - selector0["Ordinal"] = ms->first; - selector1["Name"] = tmp2; - selector1["Ordinal"] = 0; - selectors.push_back(selector0); - selectors.push_back(selector1); - newrec["Selectors"] = selectors; - const uint8_t* const rawip = (const uint8_t*)ms->second.lastOnlineAddress.rawIpData(); - switch (ms->second.lastOnlineAddress.ss_family) { - case AF_INET: - for (int j = 0; j < 4; ++j) - ip.push_back((unsigned int)rawip[j]); - break; - case AF_INET6: - for (int j = 0; j < 16; ++j) - ip.push_back((unsigned int)rawip[j]); - break; - default: - ip = tmp2; // should never happen since only IP transport is currently supported - break; - } - newrec["Value"] = ip; - newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = maskingKey; - newrec["Timestamp"] = ms->second.lastOnlineTime; - newrec["PulseIfUnchanged"] = true; - try { - auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json"); - if (resp) { - if (resp->status == 200) { - ms->second.lastOnlineDirty = false; - // printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (create/update member online status): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member online status): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member online status): unknown exception" ZT_EOL_S); - } - } - - if (ms->second.dirty) { - nlohmann::json network, member; - if (get(ns->first, network, ms->first, member)) { - nlohmann::json newrec, selector0, selector1, selectors; - selector0["Name"] = networksSelectorName; - selector0["Ordinal"] = ns->first; - selector1["Name"] = "member"; - selector1["Ordinal"] = ms->first; - selectors.push_back(selector0); - selectors.push_back(selector1); - newrec["Selectors"] = selectors; - newrec["Value"] = member.dump(); - newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = maskingKey; - newrec["PulseIfUnchanged"] = true; - try { - auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json"); - if (resp) { - if (resp->status == 200) { - ms->second.dirty = false; - // printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member): unknown exception" ZT_EOL_S); - } - } - } - } - } - } - - try { - std::ostringstream query; - query << "{" - "\"Ranges\":[{" - "\"Name\":\"" - << networksSelectorName - << "\"," - "\"Range\":[0,18446744073709551615]" - "}]," - "\"TimeRange\":[" - << timeRangeStart - << ",9223372036854775807]," - "\"MaskingKey\":\"" - << maskingKey - << "\"," - "\"Owners\":[\"" - << _lfOwnerPublic - << "\"]" - "}"; - auto resp = htcli.Post("/query", query.str(), "application/json"); - if (resp) { - if (resp->status == 200) { - nlohmann::json results(OSUtils::jsonParse(resp->body)); - if ((results.is_array()) && (! results.empty())) { - for (std::size_t ri = 0; ri < results.size(); ++ri) { - nlohmann::json& rset = results[ri]; - if ((rset.is_array()) && (! rset.empty())) { - nlohmann::json& result = rset[0]; - if (result.is_object()) { - nlohmann::json& record = result["Record"]; - if (record.is_object()) { - const std::string recordValue = result["Value"]; - // printf("GET network %s\n",recordValue.c_str()); - nlohmann::json network(OSUtils::jsonParse(recordValue)); - if (network.is_object()) { - const std::string idstr = network["id"]; - const uint64_t id = Utils::hexStrToU64(idstr.c_str()); - if ((id >> 24) == controllerAddressInt) { // sanity check - - nlohmann::json oldNetwork; - if ((timeRangeStart > 0) && (get(id, oldNetwork))) { - const uint64_t revision = network["revision"]; - const uint64_t prevRevision = oldNetwork["revision"]; - if (prevRevision < revision) { - _networkChanged(oldNetwork, network, timeRangeStart > 0); - } - } - else { - nlohmann::json nullJson; - _networkChanged(nullJson, network, timeRangeStart > 0); - } - } - } - } - } - } - } - } - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (check for network updates): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for network updates): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for network updates): unknown exception" ZT_EOL_S); - } - - try { - std::ostringstream query; - query << "{" - "\"Ranges\":[{" - "\"Name\":\"" - << networksSelectorName - << "\"," - "\"Range\":[0,18446744073709551615]" - "},{" - "\"Name\":\"member\"," - "\"Range\":[0,18446744073709551615]" - "}]," - "\"TimeRange\":[" - << timeRangeStart - << ",9223372036854775807]," - "\"MaskingKey\":\"" - << maskingKey - << "\"," - "\"Owners\":[\"" - << _lfOwnerPublic - << "\"]" - "}"; - auto resp = htcli.Post("/query", query.str(), "application/json"); - if (resp) { - if (resp->status == 200) { - nlohmann::json results(OSUtils::jsonParse(resp->body)); - if ((results.is_array()) && (! results.empty())) { - for (std::size_t ri = 0; ri < results.size(); ++ri) { - nlohmann::json& rset = results[ri]; - if ((rset.is_array()) && (! rset.empty())) { - nlohmann::json& result = rset[0]; - if (result.is_object()) { - nlohmann::json& record = result["Record"]; - if (record.is_object()) { - const std::string recordValue = result["Value"]; - // printf("GET member %s\n",recordValue.c_str()); - nlohmann::json member(OSUtils::jsonParse(recordValue)); - if (member.is_object()) { - const std::string nwidstr = member["nwid"]; - const std::string idstr = member["id"]; - const uint64_t nwid = Utils::hexStrToU64(nwidstr.c_str()); - const uint64_t id = Utils::hexStrToU64(idstr.c_str()); - if ((id) && ((nwid >> 24) == controllerAddressInt)) { // sanity check - - nlohmann::json network, oldMember; - if ((timeRangeStart > 0) && (get(nwid, network, id, oldMember))) { - const uint64_t revision = member["revision"]; - const uint64_t prevRevision = oldMember["revision"]; - if (prevRevision < revision) - _memberChanged(oldMember, member, timeRangeStart > 0); - } - else if (hasNetwork(nwid)) { - nlohmann::json nullJson; - _memberChanged(nullJson, member, timeRangeStart > 0); - } - } - } - } - } - } - } - } - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (check for member updates): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for member updates): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for member updates): unknown exception" ZT_EOL_S); - } - - timeRangeStart = time(nullptr) - 120; // start next query 2m before now to avoid losing updates - _ready.store(true); - - for (int k = 0; k < 4; ++k) { // 2s delay between queries for remotely modified networks or members - if (! _running.load()) - return; - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } - } - }); -} - -LFDB::~LFDB() -{ - _running.store(false); - _syncThread.join(); -} - -bool LFDB::waitForReady() -{ - while (! _ready.load()) { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } - return true; -} - -bool LFDB::isReady() -{ - return (_ready.load()); -} - -bool LFDB::save(nlohmann::json& record, bool notifyListeners) -{ - bool modified = false; - const std::string objtype = record["objtype"]; - if (objtype == "network") { - const uint64_t nwid = OSUtils::jsonIntHex(record["id"], 0ULL); - if (nwid) { - nlohmann::json old; - get(nwid, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - _networkChanged(old, record, notifyListeners); - { - std::lock_guard l(_state_l); - _state[nwid].dirty = true; - } - modified = true; - } - } - } - else if (objtype == "member") { - const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"], 0ULL); - const uint64_t id = OSUtils::jsonIntHex(record["id"], 0ULL); - if ((id) && (nwid)) { - nlohmann::json network, old; - get(nwid, network, id, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - _memberChanged(old, record, notifyListeners); - { - std::lock_guard l(_state_l); - _state[nwid].members[id].dirty = true; - } - modified = true; - } - } - } - return modified; -} - -void LFDB::eraseNetwork(const uint64_t networkId) -{ - // TODO -} - -void LFDB::eraseMember(const uint64_t networkId, const uint64_t memberId) -{ - // TODO -} - -void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) -{ - std::lock_guard l(_state_l); - auto nw = _state.find(networkId); - if (nw != _state.end()) { - auto m = nw->second.members.find(memberId); - if (m != nw->second.members.end()) { - m->second.lastOnlineTime = OSUtils::now(); - if (physicalAddress) - m->second.lastOnlineAddress = physicalAddress; - m->second.lastOnlineDirty = true; - } - } -} - -void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) -{ - this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown"); -} - -} // namespace ZeroTier diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp deleted file mode 100644 index 3632e483f..000000000 --- a/controller/LFDB.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_CONTROLLER_LFDB_HPP -#define ZT_CONTROLLER_LFDB_HPP - -#include "DB.hpp" - -#include -#include -#include -#include - -namespace ZeroTier { - -/** - * DB implementation for controller that stores data in LF - */ -class LFDB : public DB { - public: - /** - * @param myId This controller's identity - * @param path Base path for ZeroTier node itself - * @param lfOwnerPrivate LF owner private in PEM format - * @param lfOwnerPublic LF owner public in @base62 format - * @param lfNodeHost LF node host - * @param lfNodePort LF node http (not https) port - * @param storeOnlineState If true, store online/offline state and IP info in LF (a lot of data, only for private networks!) - */ - LFDB(const Identity& myId, const char* path, const char* lfOwnerPrivate, const char* lfOwnerPublic, const char* lfNodeHost, int lfNodePort, bool storeOnlineState); - virtual ~LFDB(); - - virtual bool waitForReady(); - virtual bool isReady(); - virtual bool save(nlohmann::json& record, bool notifyListeners); - virtual void eraseNetwork(const uint64_t networkId); - virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); - - protected: - const Identity _myId; - - std::string _lfOwnerPrivate, _lfOwnerPublic; - std::string _lfNodeHost; - int _lfNodePort; - - struct _MemberState { - _MemberState() : lastOnlineAddress(), lastOnlineTime(0), dirty(false), lastOnlineDirty(false) - { - } - InetAddress lastOnlineAddress; - int64_t lastOnlineTime; - bool dirty; - bool lastOnlineDirty; - }; - struct _NetworkState { - _NetworkState() : members(), dirty(false) - { - } - std::unordered_map members; - bool dirty; - }; - std::unordered_map _state; - std::mutex _state_l; - - std::atomic_bool _running; - std::atomic_bool _ready; - std::thread _syncThread; - bool _storeOnlineState; -}; - -} // namespace ZeroTier - -#endif diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp deleted file mode 100644 index 3bc864601..000000000 --- a/controller/PostgreSQL.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifdef ZT_CONTROLLER_USE_LIBPQ - -#include "PostgreSQL.hpp" - -#include - -using namespace nlohmann; - -using namespace ZeroTier; - -#endif \ No newline at end of file diff --git a/controller/PostgreSQL.hpp b/controller/PostgreSQL.hpp deleted file mode 100644 index 41f36e3c5..000000000 --- a/controller/PostgreSQL.hpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c)2025 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifdef ZT_CONTROLLER_USE_LIBPQ - -#ifndef ZT_CONTROLLER_POSTGRESQL_HPP -#define ZT_CONTROLLER_POSTGRESQL_HPP - -#include "ConnectionPool.hpp" -#include "DB.hpp" -#include "opentelemetry/trace/provider.h" - -#include -#include -#include - -namespace ZeroTier { - -extern "C" { -typedef struct pg_conn PGconn; -} - -class PostgresConnection : public Connection { - public: - virtual ~PostgresConnection() - { - } - - std::shared_ptr c; - int a; -}; - -class PostgresConnFactory : public ConnectionFactory { - public: - PostgresConnFactory(std::string& connString) : m_connString(connString) - { - } - - virtual std::shared_ptr create() - { - Metrics::conn_counter++; - auto c = std::shared_ptr(new PostgresConnection()); - c->c = std::make_shared(m_connString); - return std::static_pointer_cast(c); - } - - private: - std::string m_connString; -}; - -template class MemberNotificationReceiver : public pqxx::notification_receiver { - public: - MemberNotificationReceiver(T* p, pqxx::connection& c, const std::string& channel) : pqxx::notification_receiver(c, channel), _psql(p) - { - fprintf(stderr, "initialize MemberNotificationReceiver\n"); - } - - virtual ~MemberNotificationReceiver() - { - fprintf(stderr, "MemberNotificationReceiver destroyed\n"); - } - - virtual void operator()(const std::string& payload, int backendPid) - { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_member_notification"); - auto span = tracer->StartSpan("db_member_notification::operator()"); - auto scope = tracer->WithActiveSpan(span); - span->SetAttribute("payload", payload); - span->SetAttribute("psqlReady", _psql->isReady()); - - fprintf(stderr, "Member Notification received: %s\n", payload.c_str()); - Metrics::pgsql_mem_notification++; - nlohmann::json tmp(nlohmann::json::parse(payload)); - nlohmann::json& ov = tmp["old_val"]; - nlohmann::json& nv = tmp["new_val"]; - nlohmann::json oldConfig, newConfig; - if (ov.is_object()) - oldConfig = ov; - if (nv.is_object()) - newConfig = nv; - - if (oldConfig.is_object() && newConfig.is_object()) { - _psql->save(newConfig, _psql->isReady()); - fprintf(stderr, "payload sent\n"); - } - else if (newConfig.is_object() && ! oldConfig.is_object()) { - // new member - Metrics::member_count++; - _psql->save(newConfig, _psql->isReady()); - fprintf(stderr, "new member payload sent\n"); - } - else if (! newConfig.is_object() && oldConfig.is_object()) { - // member delete - uint64_t networkId = OSUtils::jsonIntHex(oldConfig["nwid"], 0ULL); - uint64_t memberId = OSUtils::jsonIntHex(oldConfig["id"], 0ULL); - if (memberId && networkId) { - _psql->eraseMember(networkId, memberId); - fprintf(stderr, "member delete payload sent\n"); - } - } - } - - private: - T* _psql; -}; - -template class NetworkNotificationReceiver : public pqxx::notification_receiver { - public: - NetworkNotificationReceiver(T* p, pqxx::connection& c, const std::string& channel) : pqxx::notification_receiver(c, channel), _psql(p) - { - fprintf(stderr, "initialize NetworkrNotificationReceiver\n"); - } - - virtual ~NetworkNotificationReceiver() - { - fprintf(stderr, "NetworkNotificationReceiver destroyed\n"); - }; - - virtual void operator()(const std::string& payload, int packend_pid) - { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("db_network_notification"); - auto span = tracer->StartSpan("db_network_notification::operator()"); - auto scope = tracer->WithActiveSpan(span); - span->SetAttribute("payload", payload); - span->SetAttribute("psqlReady", _psql->isReady()); - - fprintf(stderr, "Network Notification received: %s\n", payload.c_str()); - Metrics::pgsql_net_notification++; - nlohmann::json tmp(nlohmann::json::parse(payload)); - - nlohmann::json& ov = tmp["old_val"]; - nlohmann::json& nv = tmp["new_val"]; - nlohmann::json oldConfig, newConfig; - - if (ov.is_object()) - oldConfig = ov; - if (nv.is_object()) - newConfig = nv; - - if (oldConfig.is_object() && newConfig.is_object()) { - std::string nwid = oldConfig["id"]; - span->SetAttribute("action", "network_change"); - span->SetAttribute("network_id", nwid); - _psql->save(newConfig, _psql->isReady()); - fprintf(stderr, "payload sent\n"); - } - else if (newConfig.is_object() && ! oldConfig.is_object()) { - std::string nwid = newConfig["id"]; - span->SetAttribute("network_id", nwid); - span->SetAttribute("action", "new_network"); - // new network - _psql->save(newConfig, _psql->isReady()); - fprintf(stderr, "new network payload sent\n"); - } - else if (! newConfig.is_object() && oldConfig.is_object()) { - // network delete - span->SetAttribute("action", "delete_network"); - std::string nwid = oldConfig["id"]; - span->SetAttribute("network_id", nwid); - uint64_t networkId = Utils::hexStrToU64(nwid.c_str()); - span->SetAttribute("network_id_int", networkId); - if (networkId) { - _psql->eraseNetwork(networkId); - fprintf(stderr, "network delete payload sent\n"); - } - } - } - - private: - T* _psql; -}; - -struct NodeOnlineRecord { - uint64_t lastSeen; - InetAddress physicalAddress; - std::string osArch; -}; - -} // namespace ZeroTier - -#endif // ZT_CONTROLLER_POSTGRESQL_HPP - -#endif // ZT_CONTROLLER_USE_LIBPQ \ No newline at end of file diff --git a/controller/README.md b/controller/README.md index 41cfd3ff3..6989e98d9 100644 --- a/controller/README.md +++ b/controller/README.md @@ -1,55 +1,32 @@ -Network Controller Microservice +Network Controller Implementation ====== -Every ZeroTier virtual network has a *network controller* responsible for admitting members to the network, issuing certificates, and issuing default configuration information. +This folder contains code implementing the node/NetworkController.hpp interface to allow ZeroTier nodes to create and manage virtual networks. -This is our reference controller implementation and is almost the same as the one we use to power our own hosted services at [my.zerotier.com](https://my.zerotier.com/). The only difference is the database backend used. +### Building -Controller data is stored in JSON format under `controller.d` in the ZeroTier working directory. It can be copied, rsync'd, placed in `git`, etc. The files under `controller.d` should not be modified in place while the controller is running or data loss may result, and if they are edited directly take care not to save corrupt JSON since that can also lead to data loss when the controller is restarted. Going through the API is strongly preferred to directly modifying these files. +By default this code is not built or included in the client. To build on Linux, BSD, or Mac add ZT_\ENABLE_\NETWORK_\CONTROLLER=1 to the make command line. You'll need the development headers for Sqlite3 installed. They ship as part of OSX and Xcode. On Linux or BSD you'll probably need to install a package. -See the API section below for information about controlling the controller. +### Running -### Scalability and Reliability +When started, a controller-enabled build of ZeroTier One will automatically create and initialize a *controller.db* in its home folder. This is where all the controller's data and persistent state lives. -Controllers can in theory host up to 2^24 networks and serve many millions of devices (or more), but we recommend spreading large numbers of networks across many controllers for load balancing and fault tolerance reasons. Since the controller uses the filesystem as its data store we recommend fast filesystems and fast SSD drives for heavily loaded controllers. +Since Sqlite3 supports multiple processes attached to the same database, it is safe to back up a running database with the command line *sqlite3* utility: -Since ZeroTier nodes are mobile and do not need static IPs, implementing high availability fail-over for controllers is easy. Just replicate their working directories from master to backup and have something automatically fire up the backup if the master goes down. Modern orchestration tools like Nomad and Kubernetes can be of help here. + sqlite3 /path/to/controller.db .dump -### Dockerizing Controllers +In production ZeroTier runs this frequently and keeps many timestamped copies going back about a week. These are also backed up (encrypted) to Amazon S3 along with the rest of our data. -ZeroTier network controllers can easily be run in Docker or other container systems. Since containers do not need to actually join networks, extra privilege options like "--device=/dev/net/tun --privileged" are not needed. You'll just need to map the local JSON API port of the running controller and allow it to access the Internet (over UDP/9993 at a minimum) so things can reach and query it. +### Administrating -### Upgrading from Older (1.1.14 or earlier) Versions +See service/README.md for documentation on the JSON API presented by this network controller implementation. Also see *nodejs-zt1-client* for a NodeJS JavaScript interface. -Older versions of this code used a SQLite database instead of in-filesystem JSON. A migration utility called `migrate-sqlite` is included here and *must* be used to migrate this data to the new format. If the controller is started with an old `controller.db` in its working directory it will terminate after printing an error to *stderr*. This is done to prevent "surprises" for those running DIY controllers using the old code. +### Reliability -The migration tool is written in nodeJS and can be used like this: +Network controllers can go offline without affecting already-configured members of running networks. You just won't be able to change anything and new members will not be able to join. - cd migrate-sqlite - npm install - node migrate.js +High-availability can be implemented through fail-over. A simple method involves making a frequent backup of the SQLite database (use the SQLite command line client to do this safely) and the network configuration master's working directory. Then, if the master goes down, another instance of it can rapidly be provisioned elsewhere. Since ZeroTier addresses are mobile, the new instance will quickly (usually no more than 30s) take over for the old one and service requests. -### Network Controller API +### Limits -The controller API is hosted via the same JSON API endpoint that ZeroTier One uses for local control (usually at 127.0.0.1 port 9993). All controller options are routed under the `/controller` base path. - -The controller microservice itself does not implement any fine-grained access control. Access control is via the ZeroTier control interface itself and `authtoken.secret`. This can be sent as the `X-ZT1-Auth` HTTP header field or appended to the URL as `?auth=`. Take care when doing the latter that request URLs are not being logged. - -While networks with any valid ID can be added to the controller's database, it will only actually work to control networks whose first 10 hex digits correspond with the network controller's ZeroTier ID. See [section 2.2.1 of the ZeroTier manual](https://zerotier.com/manual.shtml#2_2_1). - -The controller JSON API is *very* sensitive about types. Integers must be integers and strings strings, etc. Incorrect types may be ignored, set to default values, or set to undefined values. - -Full documentation of the Controller API can be found on our [documentation site](https://docs.zerotier.com/service/v1#tag/controller) - -### Prometheus Metrics - -Controller specific metrics are available from the `/metrics` endpoint. - -| Metric Name | Type | Description | -| --- | --- | --- | -| controller_network_count | Gauge | number of networks the controller is serving | -| controller_member_count | Gauge | number of network members the controller is serving | -| controller_network_change_count | Counter | number of times a network configuration is changed | -| controller_member_change_count | Counter | number of times a network member configuration is changed | -| controller_member_auth_count | Counter | number of network member auths | -| controller_member_deauth_count | Counter | number of network member deauths| +A single network configuration master can administrate up to 2^24 (~16m) networks as per the ZeroTier protocol limit. There is no hard limit on the number of clients, though millions or more would impose significant CPU demands on a server. Optimizations could be implemented such as memoization/caching to reduce this. diff --git a/controller/Redis.hpp b/controller/Redis.hpp deleted file mode 100644 index c6845d517..000000000 --- a/controller/Redis.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef ZT_CONTROLLER_REDIS_HPP -#define ZT_CONTROLLER_REDIS_HPP - -#include - -namespace ZeroTier { -struct RedisConfig { - std::string hostname; - int port; - std::string password; - bool clusterMode; -}; -} // namespace ZeroTier - -#endif \ No newline at end of file diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp new file mode 100644 index 000000000..bef9cfc16 --- /dev/null +++ b/controller/SqliteNetworkController.cpp @@ -0,0 +1,2159 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../include/ZeroTierOne.h" +#include "../node/Constants.hpp" + +#include "../ext/json-parser/json.h" + +#include "SqliteNetworkController.hpp" + +#include "../node/Node.hpp" +#include "../node/Utils.hpp" +#include "../node/CertificateOfMembership.hpp" +#include "../node/NetworkConfig.hpp" +#include "../node/InetAddress.hpp" +#include "../node/MAC.hpp" +#include "../node/Address.hpp" + +#include "../osdep/OSUtils.hpp" + +// Include ZT_NETCONF_SCHEMA_SQL constant to init database +#include "schema.sql.c" + +// Stored in database as schemaVersion key in Config. +// If not present, database is assumed to be empty and at the current schema version +// and this key/value is added automatically. +#define ZT_NETCONF_SQLITE_SCHEMA_VERSION 2 +#define ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR "2" + +// API version reported via JSON control plane +#define ZT_NETCONF_CONTROLLER_API_VERSION 1 + +// Min duration between requests for an address/nwid combo to prevent floods +#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000 + +// Delay between backups in milliseconds +#define ZT_NETCONF_BACKUP_PERIOD 300000 + +// Number of NodeHistory entries to maintain per node and network (can be changed) +#define ZT_NETCONF_NODE_HISTORY_LENGTH 64 + +// Nodes are considered active if they've queried in less than this long +#define ZT_NETCONF_NODE_ACTIVE_THRESHOLD ((ZT_NETWORK_AUTOCONF_DELAY * 2) + 5000) + +namespace ZeroTier { + +namespace { + +static std::string _jsonEscape(const char *s) +{ + if (!s) + return std::string(); + std::string buf; + for(const char *p=s;(*p);++p) { + switch(*p) { + case '\t': buf.append("\\t"); break; + case '\b': buf.append("\\b"); break; + case '\r': buf.append("\\r"); break; + case '\n': buf.append("\\n"); break; + case '\f': buf.append("\\f"); break; + case '"': buf.append("\\\""); break; + case '\\': buf.append("\\\\"); break; + case '/': buf.append("\\/"); break; + default: buf.push_back(*p); break; + } + } + return buf; +} +static std::string _jsonEscape(const std::string &s) { return _jsonEscape(s.c_str()); } + +struct MemberRecord { + int64_t rowid; + char nodeId[16]; + bool authorized; + bool activeBridge; +}; + +struct NetworkRecord { + char id[24]; + const char *name; + const char *v4AssignMode; + const char *v6AssignMode; + bool isPrivate; + bool enableBroadcast; + bool allowPassiveBridging; + int multicastLimit; + uint64_t creationTime; + uint64_t revision; + uint64_t memberRevisionCounter; +}; + +} // anonymous namespace + +SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,const char *circuitTestPath) : + _node(node), + _backupThreadRun(true), + _dbPath(dbPath), + _circuitTestPath(circuitTestPath), + _db((sqlite3 *)0) +{ + if (sqlite3_open_v2(dbPath,&_db,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,(const char *)0) != SQLITE_OK) + throw std::runtime_error("SqliteNetworkController cannot open database file"); + sqlite3_busy_timeout(_db,10000); + + sqlite3_exec(_db,"PRAGMA synchronous = OFF",0,0,0); + sqlite3_exec(_db,"PRAGMA journal_mode = MEMORY",0,0,0); + + sqlite3_stmt *s = (sqlite3_stmt *)0; + if ((sqlite3_prepare_v2(_db,"SELECT v FROM Config WHERE k = 'schemaVersion';",-1,&s,(const char **)0) == SQLITE_OK)&&(s)) { + int schemaVersion = -1234; + if (sqlite3_step(s) == SQLITE_ROW) { + schemaVersion = sqlite3_column_int(s,0); + } + + sqlite3_finalize(s); + + if (schemaVersion == -1234) { + sqlite3_close(_db); + throw std::runtime_error("SqliteNetworkController schemaVersion not found in Config table (init failure?)"); + } else if (schemaVersion == 1) { + // Create NodeHistory table to upgrade from version 1 to version 2 + if (sqlite3_exec(_db, + "CREATE TABLE NodeHistory (\n" + " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n" + " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" + " networkVisitCounter INTEGER NOT NULL DEFAULT(0),\n" + " networkRequestAuthorized INTEGER NOT NULL DEFAULT(0),\n" + " requestTime INTEGER NOT NULL DEFAULT(0),\n" + " clientMajorVersion INTEGER NOT NULL DEFAULT(0),\n" + " clientMinorVersion INTEGER NOT NULL DEFAULT(0),\n" + " clientRevision INTEGER NOT NULL DEFAULT(0),\n" + " networkRequestMetaData VARCHAR(1024),\n" + " fromAddress VARCHAR(128)\n" + ");\n" + "\n" + "CREATE INDEX NodeHistory_nodeId ON NodeHistory (nodeId);\n" + "CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);\n" + "CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);\n" + "\n" + "UPDATE \"Config\" SET \"v\" = 2 WHERE \"k\" = 'schemaVersion';\n" + ,0,0,0) != SQLITE_OK) { + char err[1024]; + Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 2: %s",sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } + } else if (schemaVersion != ZT_NETCONF_SQLITE_SCHEMA_VERSION) { + sqlite3_close(_db); + throw std::runtime_error("SqliteNetworkController database schema version mismatch"); + } + } else { + // Prepare statement will fail if Config table doesn't exist, which means our DB + // needs to be initialized. + if (sqlite3_exec(_db,ZT_NETCONF_SCHEMA_SQL"INSERT INTO Config (k,v) VALUES ('schemaVersion',"ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR");",0,0,0) != SQLITE_OK) { + char err[1024]; + Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot initialize database and/or insert schemaVersion into Config table: %s",sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } + } + + if ( + + /* Network */ + (sqlite3_prepare_v2(_db,"SELECT name,private,enableBroadcast,allowPassiveBridging,v4AssignMode,v6AssignMode,multicastLimit,creationTime,revision,memberRevisionCounter,(SELECT COUNT(1) FROM Member WHERE Member.networkId = Network.id AND Member.authorized > 0) FROM Network WHERE id = ?",-1,&_sGetNetworkById,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT id FROM Network ORDER BY id ASC",-1,&_sListNetworks,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Network SET memberRevisionCounter = (memberRevisionCounter + 1) WHERE id = ?",-1,&_sIncrementMemberRevisionCounter,(const char **)0) != SQLITE_OK) + + /* Node */ + ||(sqlite3_prepare_v2(_db,"SELECT identity FROM Node WHERE id = ?",-1,&_sGetNodeIdentity,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO Node (id,identity) VALUES (?,?)",-1,&_sCreateOrReplaceNode,(const char **)0) != SQLITE_OK) + + /* NodeHistory */ + ||(sqlite3_prepare_v2(_db,"SELECT IFNULL(MAX(networkVisitCounter),0) FROM NodeHistory WHERE networkId = ? AND nodeId = ?",-1,&_sGetMaxNodeHistoryNetworkVisitCounter,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO NodeHistory (nodeId,networkId,networkVisitCounter,networkRequestAuthorized,requestTime,clientMajorVersion,clientMinorVersion,clientRevision,networkRequestMetaData,fromAddress) VALUES (?,?,?,?,?,?,?,?,?,?)",-1,&_sAddNodeHistoryEntry,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM NodeHistory WHERE networkId = ? AND nodeId = ? AND networkVisitCounter <= ?",-1,&_sDeleteOldNodeHistoryEntries,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT nodeId,requestTime,clientMajorVersion,clientMinorVersion,clientRevision,fromAddress,networkRequestAuthorized FROM NodeHistory WHERE networkId = ? AND requestTime IN (SELECT MAX(requestTime) FROM NodeHistory WHERE networkId = ? AND requestTime >= ? GROUP BY nodeId) ORDER BY nodeId ASC,requestTime DESC",-1,&_sGetActiveNodesOnNetwork,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT networkVisitCounter,networkRequestAuthorized,requestTime,clientMajorVersion,clientMinorVersion,clientRevision,networkRequestMetaData,fromAddress FROM NodeHistory WHERE networkId = ? AND nodeId = ? ORDER BY requestTime DESC",-1,&_sGetNodeHistory,(const char **)0) != SQLITE_OK) + + /* Rule */ + ||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleNo,nodeId,sourcePort,destPort,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,flags,invFlags,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,sourcePort,destPort,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleNo ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK) + + /* IpAssignmentPool */ + ||(sqlite3_prepare_v2(_db,"SELECT ipRangeStart,ipRangeEnd FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT ipRangeStart,ipRangeEnd,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipRangeStart ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipRangeStart,ipRangeEnd,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignmentPool WHERE networkId = ?",-1,&_sDeleteIpAssignmentPoolsForNetwork,(const char **)0) != SQLITE_OK) + + /* IpAssignment */ + ||(sqlite3_prepare_v2(_db,"SELECT \"type\",ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND (nodeId = ? OR nodeId IS NULL) AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = ? ORDER BY ip ASC",-1,&_sGetIpAssignmentsForNode2,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId IS NULL AND \"type\" = ?",-1,&_sGetLocalRoutes,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT 1 FROM IpAssignment WHERE networkId = ? AND ip = ? AND ipVersion = ? AND \"type\" = ?",-1,&_sCheckIfIpIsAllocated,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignment (networkId,nodeId,\"type\",ip,ipNetmaskBits,ipVersion) VALUES (?,?,?,?,?,?)",-1,&_sAllocateIp,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = ?",-1,&_sDeleteIpAllocations,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId IS NULL AND \"type\" = ?",-1,&_sDeleteLocalRoutes,(const char **)0) != SQLITE_OK) + + /* Relay */ + ||(sqlite3_prepare_v2(_db,"SELECT \"address\",\"phyAddress\" FROM Relay WHERE \"networkId\" = ? ORDER BY \"address\" ASC",-1,&_sGetRelays,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Relay WHERE networkId = ?",-1,&_sDeleteRelaysForNetwork,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Relay (\"networkId\",\"address\",\"phyAddress\") VALUES (?,?,?)",-1,&_sCreateRelay,(const char **)0) != SQLITE_OK) + + /* Member */ + ||(sqlite3_prepare_v2(_db,"SELECT rowid,authorized,activeBridge FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sGetMember,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,m.memberRevision,n.identity FROM Member AS m LEFT OUTER JOIN Node AS n ON n.id = m.nodeId WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Member (networkId,nodeId,authorized,activeBridge,memberRevision) VALUES (?,?,?,0,(SELECT memberRevisionCounter FROM Network WHERE id = ?))",-1,&_sCreateMember,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT m.nodeId,m.memberRevision FROM Member AS m WHERE m.networkId = ? ORDER BY m.nodeId ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ?",-1,&_sDeleteAllNetworkMembers,(const char **)0) != SQLITE_OK) + + /* Gateway */ + ||(sqlite3_prepare_v2(_db,"SELECT \"ip\",ipVersion,metric FROM Gateway WHERE networkId = ? ORDER BY metric ASC",-1,&_sGetGateways,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Gateway WHERE networkId = ?",-1,&_sDeleteGateways,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Gateway (networkId,\"ip\",ipVersion,metric) VALUES (?,?,?,?)",-1,&_sCreateGateway,(const char **)0) != SQLITE_OK) + + /* Config */ + ||(sqlite3_prepare_v2(_db,"SELECT \"v\" FROM \"Config\" WHERE \"k\" = ?",-1,&_sGetConfig,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO \"Config\" (\"k\",\"v\") VALUES (?,?)",-1,&_sSetConfig,(const char **)0) != SQLITE_OK) + + ) { + std::string err(std::string("SqliteNetworkController unable to initialize one or more prepared statements: ") + sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } + + /* Generate a 128-bit / 32-character "instance ID" if one isn't already + * defined. Clients can use this to determine if this is the same controller + * database they know and love. */ + sqlite3_reset(_sGetConfig); + sqlite3_bind_text(_sGetConfig,1,"instanceId",10,SQLITE_STATIC); + if (sqlite3_step(_sGetConfig) != SQLITE_ROW) { + unsigned char sr[32]; + Utils::getSecureRandom(sr,32); + for(unsigned int i=0;i<32;++i) + _instanceId.push_back("0123456789abcdef"[(unsigned int)sr[i] & 0xf]); + + sqlite3_reset(_sSetConfig); + sqlite3_bind_text(_sSetConfig,1,"instanceId",10,SQLITE_STATIC); + sqlite3_bind_text(_sSetConfig,2,_instanceId.c_str(),-1,SQLITE_STATIC); + if (sqlite3_step(_sSetConfig) != SQLITE_DONE) + throw std::runtime_error("SqliteNetworkController unable to read or initialize instanceId"); + } else { + const char *iid = reinterpret_cast(sqlite3_column_text(_sGetConfig,0)); + if (!iid) + throw std::runtime_error("SqliteNetworkController unable to read instanceId (it's NULL)"); + _instanceId = iid; + } + + _backupThread = Thread::start(this); +} + +SqliteNetworkController::~SqliteNetworkController() +{ + _backupThreadRun = false; + Thread::join(_backupThread); + + Mutex::Lock _l(_lock); + if (_db) { + sqlite3_finalize(_sGetNetworkById); + sqlite3_finalize(_sGetMember); + sqlite3_finalize(_sCreateMember); + sqlite3_finalize(_sGetNodeIdentity); + sqlite3_finalize(_sCreateOrReplaceNode); + sqlite3_finalize(_sGetMaxNodeHistoryNetworkVisitCounter); + sqlite3_finalize(_sAddNodeHistoryEntry); + sqlite3_finalize(_sDeleteOldNodeHistoryEntries); + sqlite3_finalize(_sGetActiveNodesOnNetwork); + sqlite3_finalize(_sGetNodeHistory); + sqlite3_finalize(_sGetEtherTypesFromRuleTable); + sqlite3_finalize(_sGetActiveBridges); + sqlite3_finalize(_sGetIpAssignmentsForNode); + sqlite3_finalize(_sGetIpAssignmentPools); + sqlite3_finalize(_sGetLocalRoutes); + sqlite3_finalize(_sCheckIfIpIsAllocated); + sqlite3_finalize(_sAllocateIp); + sqlite3_finalize(_sDeleteIpAllocations); + sqlite3_finalize(_sDeleteLocalRoutes); + sqlite3_finalize(_sGetRelays); + sqlite3_finalize(_sListNetworks); + sqlite3_finalize(_sListNetworkMembers); + sqlite3_finalize(_sGetMember2); + sqlite3_finalize(_sGetIpAssignmentPools2); + sqlite3_finalize(_sListRules); + sqlite3_finalize(_sCreateRule); + sqlite3_finalize(_sCreateNetwork); + sqlite3_finalize(_sGetNetworkRevision); + sqlite3_finalize(_sSetNetworkRevision); + sqlite3_finalize(_sGetIpAssignmentsForNode2); + sqlite3_finalize(_sDeleteRelaysForNetwork); + sqlite3_finalize(_sCreateRelay); + sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork); + sqlite3_finalize(_sDeleteRulesForNetwork); + sqlite3_finalize(_sCreateIpAssignmentPool); + sqlite3_finalize(_sUpdateMemberAuthorized); + sqlite3_finalize(_sUpdateMemberActiveBridge); + sqlite3_finalize(_sDeleteMember); + sqlite3_finalize(_sDeleteAllNetworkMembers); + sqlite3_finalize(_sDeleteNetwork); + sqlite3_finalize(_sGetGateways); + sqlite3_finalize(_sDeleteGateways); + sqlite3_finalize(_sCreateGateway); + sqlite3_finalize(_sIncrementMemberRevisionCounter); + sqlite3_finalize(_sGetConfig); + sqlite3_finalize(_sSetConfig); + sqlite3_close(_db); + } +} + +NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(const InetAddress &fromAddr,const Identity &signingId,const Identity &identity,uint64_t nwid,const Dictionary &metaData,Dictionary &netconf) +{ + Mutex::Lock _l(_lock); + return _doNetworkConfigRequest(fromAddr,signingId,identity,nwid,metaData,netconf); +} + +unsigned int SqliteNetworkController::handleControlPlaneHttpGET( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType) +{ + Mutex::Lock _l(_lock); + return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType); +} + +unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType) +{ + if (path.empty()) + return 404; + Mutex::Lock _l(_lock); + + if (path[0] == "network") { + + if ((path.size() >= 2)&&(path[1].length() == 16)) { + uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); + char nwids[24]; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + + int64_t revision = 0; + sqlite3_reset(_sGetNetworkRevision); + sqlite3_bind_text(_sGetNetworkRevision,1,nwids,16,SQLITE_STATIC); + bool networkExists = false; + if (sqlite3_step(_sGetNetworkRevision) == SQLITE_ROW) { + networkExists = true; + revision = sqlite3_column_int64(_sGetNetworkRevision,0); + } + + if (path.size() >= 3) { + + if (!networkExists) + return 404; + + if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { + uint64_t address = Utils::hexStrToU64(path[3].c_str()); + char addrs[24]; + Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address); + + int64_t addToNetworkRevision = 0; + + int64_t memberRowId = 0; + sqlite3_reset(_sGetMember); + sqlite3_bind_text(_sGetMember,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetMember,2,addrs,10,SQLITE_STATIC); + bool memberExists = false; + if (sqlite3_step(_sGetMember) == SQLITE_ROW) { + memberExists = true; + memberRowId = sqlite3_column_int64(_sGetMember,0); + } + + if (!memberExists) { + sqlite3_reset(_sCreateMember); + sqlite3_bind_text(_sCreateMember,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sCreateMember,2,addrs,10,SQLITE_STATIC); + sqlite3_bind_int(_sCreateMember,3,0); + sqlite3_bind_text(_sCreateMember,4,nwids,16,SQLITE_STATIC); + if (sqlite3_step(_sCreateMember) != SQLITE_DONE) + return 500; + memberRowId = (int64_t)sqlite3_last_insert_rowid(_db); + + sqlite3_reset(_sIncrementMemberRevisionCounter); + sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sIncrementMemberRevisionCounter); + addToNetworkRevision = 1; + } + + json_value *j = json_parse(body.c_str(),body.length()); + if (j) { + if (j->type == json_object) { + for(unsigned int k=0;ku.object.length;++k) { + + if (!strcmp(j->u.object.values[k].name,"authorized")) { + if (j->u.object.values[k].value->type == json_boolean) { + sqlite3_reset(_sUpdateMemberAuthorized); + sqlite3_bind_int(_sUpdateMemberAuthorized,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + sqlite3_bind_text(_sUpdateMemberAuthorized,2,nwids,16,SQLITE_STATIC); + sqlite3_bind_int64(_sUpdateMemberAuthorized,3,memberRowId); + if (sqlite3_step(_sUpdateMemberAuthorized) != SQLITE_DONE) + return 500; + + sqlite3_reset(_sIncrementMemberRevisionCounter); + sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sIncrementMemberRevisionCounter); + addToNetworkRevision = 1; + } + } else if (!strcmp(j->u.object.values[k].name,"activeBridge")) { + if (j->u.object.values[k].value->type == json_boolean) { + sqlite3_reset(_sUpdateMemberActiveBridge); + sqlite3_bind_int(_sUpdateMemberActiveBridge,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + sqlite3_bind_text(_sUpdateMemberActiveBridge,2,nwids,16,SQLITE_STATIC); + sqlite3_bind_int64(_sUpdateMemberActiveBridge,3,memberRowId); + if (sqlite3_step(_sUpdateMemberActiveBridge) != SQLITE_DONE) + return 500; + + sqlite3_reset(_sIncrementMemberRevisionCounter); + sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sIncrementMemberRevisionCounter); + addToNetworkRevision = 1; + } + } else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) { + if (j->u.object.values[k].value->type == json_array) { + sqlite3_reset(_sDeleteIpAllocations); + sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC); + sqlite3_bind_int(_sDeleteIpAllocations,3,(int)ZT_IP_ASSIGNMENT_TYPE_ADDRESS); + if (sqlite3_step(_sDeleteIpAllocations) != SQLITE_DONE) + return 500; + for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { + json_value *ipalloc = j->u.object.values[k].value->u.array.values[kk]; + if (ipalloc->type == json_string) { + InetAddress a(ipalloc->u.string.ptr); + char ipBlob[16]; + int ipVersion = 0; + switch(a.ss_family) { + case AF_INET: + if ((a.netmaskBits() > 0)&&(a.netmaskBits() <= 32)) { + memset(ipBlob,0,12); + memcpy(ipBlob + 12,a.rawIpData(),4); + ipVersion = 4; + } + break; + case AF_INET6: + if ((a.netmaskBits() > 0)&&(a.netmaskBits() <= 128)) { + memcpy(ipBlob,a.rawIpData(),16); + ipVersion = 6; + } + break; + } + if (ipVersion > 0) { + sqlite3_reset(_sAllocateIp); + sqlite3_bind_text(_sAllocateIp,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sAllocateIp,2,addrs,10,SQLITE_STATIC); + sqlite3_bind_int(_sAllocateIp,3,(int)ZT_IP_ASSIGNMENT_TYPE_ADDRESS); + sqlite3_bind_blob(_sAllocateIp,4,(const void *)ipBlob,16,SQLITE_STATIC); + sqlite3_bind_int(_sAllocateIp,5,(int)a.netmaskBits()); + sqlite3_bind_int(_sAllocateIp,6,ipVersion); + if (sqlite3_step(_sAllocateIp) != SQLITE_DONE) + return 500; + } + } + } + addToNetworkRevision = 1; + } + } else if (!strcmp(j->u.object.values[k].name,"identity")) { + // Identity is technically an immutable field, but if the member's Node has + // no identity we allow it to be populated. This is primarily for migrating + // node data from another controller. + json_value *idstr = j->u.object.values[k].value; + if (idstr->type == json_string) { + bool alreadyHaveIdentity = false; + + sqlite3_reset(_sGetNodeIdentity); + sqlite3_bind_text(_sGetNodeIdentity,1,addrs,10,SQLITE_STATIC); + if (sqlite3_step(_sGetNodeIdentity) == SQLITE_ROW) { + const char *tmp2 = (const char *)sqlite3_column_text(_sGetNodeIdentity,0); + if ((tmp2)&&(tmp2[0])) + alreadyHaveIdentity = true; + } + + if (!alreadyHaveIdentity) { + try { + Identity id2(idstr->u.string.ptr); + if (id2) { + std::string idstr2(id2.toString(false)); // object must persist until after sqlite3_step() for SQLITE_STATIC + sqlite3_reset(_sCreateOrReplaceNode); + sqlite3_bind_text(_sCreateOrReplaceNode,1,addrs,10,SQLITE_STATIC); + sqlite3_bind_text(_sCreateOrReplaceNode,2,idstr2.c_str(),-1,SQLITE_STATIC); + sqlite3_step(_sCreateOrReplaceNode); + } + } catch ( ... ) {} // ignore invalid identities + } + } + } + + } + } + json_value_free(j); + } + + if ((addToNetworkRevision > 0)&&(revision > 0)) { + sqlite3_reset(_sSetNetworkRevision); + sqlite3_bind_int64(_sSetNetworkRevision,1,revision + addToNetworkRevision); + sqlite3_bind_text(_sSetNetworkRevision,2,nwids,16,SQLITE_STATIC); + sqlite3_step(_sSetNetworkRevision); + } + + return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType); + } else if ((path.size() == 3)&&(path[2] == "test")) { + ZT_CircuitTest *test = (ZT_CircuitTest *)malloc(sizeof(ZT_CircuitTest)); + memset(test,0,sizeof(ZT_CircuitTest)); + + Utils::getSecureRandom(&(test->testId),sizeof(test->testId)); + test->credentialNetworkId = nwid; + test->ptr = (void *)this; + + json_value *j = json_parse(body.c_str(),body.length()); + if (j) { + if (j->type == json_object) { + for(unsigned int k=0;ku.object.length;++k) { + + if (!strcmp(j->u.object.values[k].name,"hops")) { + if (j->u.object.values[k].value->type == json_array) { + for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { + json_value *hop = j->u.object.values[k].value->u.array.values[kk]; + if (hop->type == json_array) { + for(unsigned int kkk=0;kkku.array.length;++kkk) { + if (hop->u.array.values[kkk]->type == json_string) { + test->hops[test->hopCount].addresses[test->hops[test->hopCount].breadth++] = Utils::hexStrToU64(hop->u.array.values[kkk]->u.string.ptr) & 0xffffffffffULL; + } + } + ++test->hopCount; + } + } + } + } else if (!strcmp(j->u.object.values[k].name,"reportAtEveryHop")) { + if (j->u.object.values[k].value->type == json_boolean) + test->reportAtEveryHop = (j->u.object.values[k].value->u.boolean == 0) ? 0 : 1; + } + + } + } + json_value_free(j); + } + + if (!test->hopCount) { + ::free((void *)test); + return 500; + } + + test->timestamp = OSUtils::now(); + + _CircuitTestEntry &te = _circuitTests[test->testId]; + te.test = test; + te.jsonResults = ""; + + _node->circuitTestBegin(test,&(SqliteNetworkController::_circuitTestCallback)); + + char json[1024]; + Utils::snprintf(json,sizeof(json),"{\"testId\":\"%.16llx\"}",test->testId); + responseBody = json; + responseContentType = "application/json"; + + return 200; + } // else 404 + + } else { + std::vector path_copy(path); + + if (!networkExists) { + if (path[1].substr(10) == "______") { + // A special POST /network/##########______ feature lets users create a network + // with an arbitrary unused network number at this controller. + nwid = 0; + + uint64_t nwidPrefix = (Utils::hexStrToU64(path[1].substr(0,10).c_str()) << 24) & 0xffffffffff000000ULL; + uint64_t nwidPostfix = 0; + Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix)); + uint64_t nwidOriginalPostfix = nwidPostfix; + do { + uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL); + if (!nwidPostfix) + tryNwid |= 1; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid); + + sqlite3_reset(_sGetNetworkRevision); + sqlite3_bind_text(_sGetNetworkRevision,1,nwids,16,SQLITE_STATIC); + if (sqlite3_step(_sGetNetworkRevision) != SQLITE_ROW) { + nwid = tryNwid; + break; + } + + ++nwidPostfix; + } while (nwidPostfix != nwidOriginalPostfix); + + // 503 means we have no more free IDs for this prefix. You shouldn't host anywhere + // near 16 million networks on the same controller, so shouldn't happen. + if (!nwid) + return 503; + } + + sqlite3_reset(_sCreateNetwork); + sqlite3_bind_text(_sCreateNetwork,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sCreateNetwork,2,"",0,SQLITE_STATIC); + sqlite3_bind_int64(_sCreateNetwork,3,(long long)OSUtils::now()); + if (sqlite3_step(_sCreateNetwork) != SQLITE_DONE) + return 500; + path_copy[1].assign(nwids); + } + + json_value *j = json_parse(body.c_str(),body.length()); + if (j) { + if (j->type == json_object) { + for(unsigned int k=0;ku.object.length;++k) { + sqlite3_stmt *stmt = (sqlite3_stmt *)0; + + if (!strcmp(j->u.object.values[k].name,"name")) { + if ((j->u.object.values[k].value->type == json_string)&&(j->u.object.values[k].value->u.string.ptr[0])) { + if (sqlite3_prepare_v2(_db,"UPDATE Network SET \"name\" = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) + sqlite3_bind_text(stmt,1,j->u.object.values[k].value->u.string.ptr,-1,SQLITE_STATIC); + } + } else if (!strcmp(j->u.object.values[k].name,"private")) { + if (j->u.object.values[k].value->type == json_boolean) { + if (sqlite3_prepare_v2(_db,"UPDATE Network SET \"private\" = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) + sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + } + } else if (!strcmp(j->u.object.values[k].name,"enableBroadcast")) { + if (j->u.object.values[k].value->type == json_boolean) { + if (sqlite3_prepare_v2(_db,"UPDATE Network SET enableBroadcast = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) + sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + } + } else if (!strcmp(j->u.object.values[k].name,"allowPassiveBridging")) { + if (j->u.object.values[k].value->type == json_boolean) { + if (sqlite3_prepare_v2(_db,"UPDATE Network SET allowPassiveBridging = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) + sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + } + } else if (!strcmp(j->u.object.values[k].name,"v4AssignMode")) { + if (j->u.object.values[k].value->type == json_string) { + if (sqlite3_prepare_v2(_db,"UPDATE Network SET v4AssignMode = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) + sqlite3_bind_text(stmt,1,j->u.object.values[k].value->u.string.ptr,-1,SQLITE_STATIC); + } + } else if (!strcmp(j->u.object.values[k].name,"v6AssignMode")) { + if (j->u.object.values[k].value->type == json_string) { + if (sqlite3_prepare_v2(_db,"UPDATE Network SET v6AssignMode = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) + sqlite3_bind_text(stmt,1,j->u.object.values[k].value->u.string.ptr,-1,SQLITE_STATIC); + } + } else if (!strcmp(j->u.object.values[k].name,"multicastLimit")) { + if (j->u.object.values[k].value->type == json_integer) { + if (sqlite3_prepare_v2(_db,"UPDATE Network SET multicastLimit = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) + sqlite3_bind_int(stmt,1,(int)j->u.object.values[k].value->u.integer); + } + } else if (!strcmp(j->u.object.values[k].name,"relays")) { + if (j->u.object.values[k].value->type == json_array) { + std::map nodeIdToPhyAddress; + for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { + json_value *relay = j->u.object.values[k].value->u.array.values[kk]; + const char *address = (const char *)0; + const char *phyAddress = (const char *)0; + if ((relay)&&(relay->type == json_object)) { + for(unsigned int rk=0;rku.object.length;++rk) { + if ((!strcmp(relay->u.object.values[rk].name,"address"))&&(relay->u.object.values[rk].value->type == json_string)) + address = relay->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(relay->u.object.values[rk].name,"phyAddress"))&&(relay->u.object.values[rk].value->type == json_string)) + phyAddress = relay->u.object.values[rk].value->u.string.ptr; + } + } + if ((address)&&(phyAddress)) + nodeIdToPhyAddress[Address(address)] = InetAddress(phyAddress); + } + + sqlite3_reset(_sDeleteRelaysForNetwork); + sqlite3_bind_text(_sDeleteRelaysForNetwork,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sDeleteRelaysForNetwork); + + for(std::map::iterator rl(nodeIdToPhyAddress.begin());rl!=nodeIdToPhyAddress.end();++rl) { + sqlite3_reset(_sCreateRelay); + sqlite3_bind_text(_sCreateRelay,1,nwids,16,SQLITE_STATIC); + std::string a(rl->first.toString()),b(rl->second.toString()); // don't destroy strings until sqlite3_step() + sqlite3_bind_text(_sCreateRelay,2,a.c_str(),-1,SQLITE_STATIC); + sqlite3_bind_text(_sCreateRelay,3,b.c_str(),-1,SQLITE_STATIC); + sqlite3_step(_sCreateRelay); + } + } + } else if (!strcmp(j->u.object.values[k].name,"gateways")) { + sqlite3_reset(_sDeleteGateways); + sqlite3_bind_text(_sDeleteGateways,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sDeleteGateways); + if (j->u.object.values[k].value->type == json_array) { + for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { + json_value *gateway = j->u.object.values[k].value->u.array.values[kk]; + if ((gateway)&&(gateway->type == json_string)) { + InetAddress gwip(gateway->u.string.ptr); + sqlite3_reset(_sCreateGateway); + sqlite3_bind_text(_sCreateGateway,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_int(_sCreateGateway,4,(int)gwip.metric()); + if (gwip.ss_family == AF_INET) { + char ipBlob[16]; + memset(ipBlob,0,12); + memcpy(ipBlob + 12,gwip.rawIpData(),4); + sqlite3_bind_blob(_sCreateGateway,2,(const void *)ipBlob,16,SQLITE_STATIC); + sqlite3_bind_int(_sCreateGateway,3,4); + sqlite3_step(_sCreateGateway); + } else if (gwip.ss_family == AF_INET6) { + sqlite3_bind_blob(_sCreateGateway,2,gwip.rawIpData(),16,SQLITE_STATIC); + sqlite3_bind_int(_sCreateGateway,3,6); + sqlite3_step(_sCreateGateway); + } + } + } + } + } else if (!strcmp(j->u.object.values[k].name,"ipLocalRoutes")) { + sqlite3_reset(_sDeleteLocalRoutes); + sqlite3_bind_text(_sDeleteLocalRoutes,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_int(_sDeleteLocalRoutes,2,(int)ZT_IP_ASSIGNMENT_TYPE_NETWORK); + sqlite3_step(_sDeleteLocalRoutes); + if (j->u.object.values[k].value->type == json_array) { + for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { + json_value *localRoute = j->u.object.values[k].value->u.array.values[kk]; + if ((localRoute)&&(localRoute->type == json_string)) { + InetAddress lr(localRoute->u.string.ptr); + if (lr.ss_family == AF_INET) { + char ipBlob[16]; + memset(ipBlob,0,12); + memcpy(ipBlob + 12,lr.rawIpData(),4); + sqlite3_reset(_sAllocateIp); + sqlite3_bind_text(_sAllocateIp,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_null(_sAllocateIp,2); + sqlite3_bind_int(_sAllocateIp,3,(int)ZT_IP_ASSIGNMENT_TYPE_NETWORK); + sqlite3_bind_blob(_sAllocateIp,4,(const void *)ipBlob,16,SQLITE_STATIC); + sqlite3_bind_int(_sAllocateIp,5,lr.netmaskBits()); + sqlite3_bind_int(_sAllocateIp,6,4); + sqlite3_step(_sAllocateIp); + } else if (lr.ss_family == AF_INET6) { + sqlite3_reset(_sAllocateIp); + sqlite3_bind_text(_sAllocateIp,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_null(_sAllocateIp,2); + sqlite3_bind_int(_sAllocateIp,3,(int)ZT_IP_ASSIGNMENT_TYPE_NETWORK); + sqlite3_bind_blob(_sAllocateIp,4,lr.rawIpData(),16,SQLITE_STATIC); + sqlite3_bind_int(_sAllocateIp,5,lr.netmaskBits()); + sqlite3_bind_int(_sAllocateIp,6,6); + sqlite3_step(_sAllocateIp); + } + } + } + } + } else if (!strcmp(j->u.object.values[k].name,"ipAssignmentPools")) { + if (j->u.object.values[k].value->type == json_array) { + std::vector< std::pair > pools; + for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { + json_value *pool = j->u.object.values[k].value->u.array.values[kk]; + const char *iprs = (const char *)0; + const char *ipre = (const char *)0; + if ((pool)&&(pool->type == json_object)) { + for(unsigned int rk=0;rku.object.length;++rk) { + if ((!strcmp(pool->u.object.values[rk].name,"ipRangeStart"))&&(pool->u.object.values[rk].value->type == json_string)) + iprs = pool->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(pool->u.object.values[rk].name,"ipRangeEnd"))&&(pool->u.object.values[rk].value->type == json_string)) + ipre = pool->u.object.values[rk].value->u.string.ptr; + } + } + if ((iprs)&&(ipre)) { + InetAddress iprs2(iprs); + InetAddress ipre2(ipre); + if (iprs2.ss_family == ipre2.ss_family) { + iprs2.setPort(0); + ipre2.setPort(0); + pools.push_back(std::pair(iprs2,ipre2)); + } + } + } + std::sort(pools.begin(),pools.end()); + pools.erase(std::unique(pools.begin(),pools.end()),pools.end()); + + sqlite3_reset(_sDeleteIpAssignmentPoolsForNetwork); + sqlite3_bind_text(_sDeleteIpAssignmentPoolsForNetwork,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sDeleteIpAssignmentPoolsForNetwork); + + for(std::vector< std::pair >::const_iterator p(pools.begin());p!=pools.end();++p) { + char ipBlob1[16],ipBlob2[16]; + sqlite3_reset(_sCreateIpAssignmentPool); + sqlite3_bind_text(_sCreateIpAssignmentPool,1,nwids,16,SQLITE_STATIC); + if (p->first.ss_family == AF_INET) { + memset(ipBlob1,0,12); + memcpy(ipBlob1 + 12,p->first.rawIpData(),4); + memset(ipBlob2,0,12); + memcpy(ipBlob2 + 12,p->second.rawIpData(),4); + sqlite3_bind_blob(_sCreateIpAssignmentPool,2,(const void *)ipBlob1,16,SQLITE_STATIC); + sqlite3_bind_blob(_sCreateIpAssignmentPool,3,(const void *)ipBlob2,16,SQLITE_STATIC); + sqlite3_bind_int(_sCreateIpAssignmentPool,4,4); + } else if (p->first.ss_family == AF_INET6) { + sqlite3_bind_blob(_sCreateIpAssignmentPool,2,p->first.rawIpData(),16,SQLITE_STATIC); + sqlite3_bind_blob(_sCreateIpAssignmentPool,3,p->second.rawIpData(),16,SQLITE_STATIC); + sqlite3_bind_int(_sCreateIpAssignmentPool,4,6); + } else continue; + sqlite3_step(_sCreateIpAssignmentPool); + } + } + } else if (!strcmp(j->u.object.values[k].name,"rules")) { + if (j->u.object.values[k].value->type == json_array) { + sqlite3_reset(_sDeleteRulesForNetwork); + sqlite3_bind_text(_sDeleteRulesForNetwork,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sDeleteRulesForNetwork); + + for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { + json_value *rj = j->u.object.values[k].value->u.array.values[kk]; + if ((rj)&&(rj->type == json_object)) { + struct { // NULL pointers indicate missing or NULL -- wildcards + const json_int_t *ruleNo; + const char *nodeId; + const char *sourcePort; + const char *destPort; + const json_int_t *vlanId; + const json_int_t *vlanPcp; + const json_int_t *etherType; + const char *macSource; + const char *macDest; + const char *ipSource; + const char *ipDest; + const json_int_t *ipTos; + const json_int_t *ipProtocol; + const json_int_t *ipSourcePort; + const json_int_t *ipDestPort; + const json_int_t *flags; + const json_int_t *invFlags; + const char *action; + } rule; + memset(&rule,0,sizeof(rule)); + + for(unsigned int rk=0;rku.object.length;++rk) { + if ((!strcmp(rj->u.object.values[rk].name,"ruleNo"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.ruleNo = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"nodeId"))&&(rj->u.object.values[rk].value->type == json_string)) + rule.nodeId = rj->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(rj->u.object.values[rk].name,"sourcePort"))&&(rj->u.object.values[rk].value->type == json_string)) + rule.sourcePort = rj->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(rj->u.object.values[rk].name,"destPort"))&&(rj->u.object.values[rk].value->type == json_string)) + rule.destPort = rj->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(rj->u.object.values[rk].name,"vlanId"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.vlanId = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"vlanPcp"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.vlanPcp = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"etherType"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.etherType = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"macSource"))&&(rj->u.object.values[rk].value->type == json_string)) + rule.macSource = rj->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(rj->u.object.values[rk].name,"macDest"))&&(rj->u.object.values[rk].value->type == json_string)) + rule.macDest = rj->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(rj->u.object.values[rk].name,"ipSource"))&&(rj->u.object.values[rk].value->type == json_string)) + rule.ipSource = rj->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(rj->u.object.values[rk].name,"ipDest"))&&(rj->u.object.values[rk].value->type == json_string)) + rule.ipDest = rj->u.object.values[rk].value->u.string.ptr; + else if ((!strcmp(rj->u.object.values[rk].name,"ipTos"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.ipTos = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"ipProtocol"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.ipProtocol = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"ipSourcePort"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.ipSourcePort = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"ipDestPort"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.ipDestPort = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"flags"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.flags = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"invFlags"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.invFlags = &(rj->u.object.values[rk].value->u.integer); + else if ((!strcmp(rj->u.object.values[rk].name,"action"))&&(rj->u.object.values[rk].value->type == json_string)) + rule.action = rj->u.object.values[rk].value->u.string.ptr; + } + + if ((rule.ruleNo)&&(rule.action)&&(rule.action[0])) { + char mactmp1[16],mactmp2[16]; + sqlite3_reset(_sCreateRule); + sqlite3_bind_text(_sCreateRule,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_int64(_sCreateRule,2,*rule.ruleNo); + + // Optional values: null by default + for(int i=3;i<=18;++i) + sqlite3_bind_null(_sCreateRule,i); + if ((rule.nodeId)&&(strlen(rule.nodeId) == 10)) sqlite3_bind_text(_sCreateRule,3,rule.nodeId,10,SQLITE_STATIC); + if ((rule.sourcePort)&&(strlen(rule.sourcePort) == 10)) sqlite3_bind_text(_sCreateRule,4,rule.sourcePort,10,SQLITE_STATIC); + if ((rule.destPort)&&(strlen(rule.destPort) == 10)) sqlite3_bind_text(_sCreateRule,5,rule.destPort,10,SQLITE_STATIC); + if (rule.vlanId) sqlite3_bind_int(_sCreateRule,6,(int)*rule.vlanId); + if (rule.vlanPcp) sqlite3_bind_int(_sCreateRule,7,(int)*rule.vlanPcp); + if (rule.etherType) sqlite3_bind_int(_sCreateRule,8,(int)*rule.etherType & (int)0xffff); + if (rule.macSource) { + MAC m(rule.macSource); + Utils::snprintf(mactmp1,sizeof(mactmp1),"%.12llx",(unsigned long long)m.toInt()); + sqlite3_bind_text(_sCreateRule,9,mactmp1,-1,SQLITE_STATIC); + } + if (rule.macDest) { + MAC m(rule.macDest); + Utils::snprintf(mactmp2,sizeof(mactmp2),"%.12llx",(unsigned long long)m.toInt()); + sqlite3_bind_text(_sCreateRule,10,mactmp2,-1,SQLITE_STATIC); + } + if (rule.ipSource) sqlite3_bind_text(_sCreateRule,11,rule.ipSource,-1,SQLITE_STATIC); + if (rule.ipDest) sqlite3_bind_text(_sCreateRule,12,rule.ipDest,-1,SQLITE_STATIC); + if (rule.ipTos) sqlite3_bind_int(_sCreateRule,13,(int)*rule.ipTos); + if (rule.ipProtocol) sqlite3_bind_int(_sCreateRule,14,(int)*rule.ipProtocol); + if (rule.ipSourcePort) sqlite3_bind_int(_sCreateRule,15,(int)*rule.ipSourcePort & (int)0xffff); + if (rule.ipDestPort) sqlite3_bind_int(_sCreateRule,16,(int)*rule.ipDestPort & (int)0xffff); + if (rule.flags) sqlite3_bind_int64(_sCreateRule,17,(int64_t)*rule.flags); + if (rule.invFlags) sqlite3_bind_int64(_sCreateRule,18,(int64_t)*rule.invFlags); + + sqlite3_bind_text(_sCreateRule,19,rule.action,-1,SQLITE_STATIC); + sqlite3_step(_sCreateRule); + } + } + } + } + } + + if (stmt) { + sqlite3_bind_text(stmt,2,nwids,16,SQLITE_STATIC); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + } + } + } + json_value_free(j); + } + + sqlite3_reset(_sSetNetworkRevision); + sqlite3_bind_int64(_sSetNetworkRevision,1,revision += 1); + sqlite3_bind_text(_sSetNetworkRevision,2,nwids,16,SQLITE_STATIC); + sqlite3_step(_sSetNetworkRevision); + + return _doCPGet(path_copy,urlArgs,headers,body,responseBody,responseContentType); + } + + } // else 404 + + } // else 404 + + return 404; +} + +unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType) +{ + if (path.empty()) + return 404; + Mutex::Lock _l(_lock); + + if (path[0] == "network") { + + if ((path.size() >= 2)&&(path[1].length() == 16)) { + uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); + char nwids[24]; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + + sqlite3_reset(_sGetNetworkById); + sqlite3_bind_text(_sGetNetworkById,1,nwids,16,SQLITE_STATIC); + if (sqlite3_step(_sGetNetworkById) != SQLITE_ROW) + return 404; + + if (path.size() >= 3) { + + if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { + uint64_t address = Utils::hexStrToU64(path[3].c_str()); + char addrs[24]; + Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address); + + sqlite3_reset(_sGetMember); + sqlite3_bind_text(_sGetMember,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetMember,2,addrs,10,SQLITE_STATIC); + if (sqlite3_step(_sGetMember) != SQLITE_ROW) + return 404; + + sqlite3_reset(_sDeleteIpAllocations); + sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC); + sqlite3_bind_int(_sDeleteIpAllocations,3,(int)ZT_IP_ASSIGNMENT_TYPE_ADDRESS); + if (sqlite3_step(_sDeleteIpAllocations) == SQLITE_DONE) { + sqlite3_reset(_sDeleteMember); + sqlite3_bind_text(_sDeleteMember,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sDeleteMember,2,addrs,10,SQLITE_STATIC); + if (sqlite3_step(_sDeleteMember) != SQLITE_DONE) + return 500; + } else return 500; + + return 200; + } + + } else { + + sqlite3_reset(_sDeleteNetwork); + sqlite3_bind_text(_sDeleteNetwork,1,nwids,16,SQLITE_STATIC); + if (sqlite3_step(_sDeleteNetwork) == SQLITE_DONE) { + sqlite3_reset(_sDeleteAllNetworkMembers); + sqlite3_bind_text(_sDeleteAllNetworkMembers,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sDeleteAllNetworkMembers); + return 200; + } else return 500; + + } + } // else 404 + + } // else 404 + + return 404; +} + +void SqliteNetworkController::threadMain() + throw() +{ + uint64_t lastBackupTime = OSUtils::now(); + uint64_t lastCleanupTime = OSUtils::now(); + + while (_backupThreadRun) { + if ((OSUtils::now() - lastCleanupTime) >= 5000) { + const uint64_t now = OSUtils::now(); + lastCleanupTime = now; + + Mutex::Lock _l(_lock); + + // Clean out really old circuit tests to prevent memory build-up + for(std::map< uint64_t,_CircuitTestEntry >::iterator ct(_circuitTests.begin());ct!=_circuitTests.end();) { + if (!ct->second.test) { + _circuitTests.erase(ct++); + } else if ((now - ct->second.test->timestamp) >= ZT_SQLITENETWORKCONTROLLER_CIRCUIT_TEST_TIMEOUT) { + _node->circuitTestEnd(ct->second.test); + ::free((void *)ct->second.test); + _circuitTests.erase(ct++); + } else ++ct; + } + } + + if ((OSUtils::now() - lastBackupTime) >= ZT_NETCONF_BACKUP_PERIOD) { + lastBackupTime = OSUtils::now(); + + char backupPath[4096],backupPath2[4096]; + Utils::snprintf(backupPath,sizeof(backupPath),"%s.backupInProgress",_dbPath.c_str()); + Utils::snprintf(backupPath2,sizeof(backupPath),"%s.backup",_dbPath.c_str()); + OSUtils::rm(backupPath); // delete any unfinished backups + + sqlite3 *bakdb = (sqlite3 *)0; + sqlite3_backup *bak = (sqlite3_backup *)0; + if (sqlite3_open_v2(backupPath,&bakdb,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,(const char *)0) != SQLITE_OK) { + fprintf(stderr,"SqliteNetworkController: CRITICAL: backup failed on sqlite3_open_v2()"ZT_EOL_S); + continue; + } + bak = sqlite3_backup_init(bakdb,"main",_db,"main"); + if (!bak) { + sqlite3_close(bakdb); + OSUtils::rm(backupPath); // delete any unfinished backups + fprintf(stderr,"SqliteNetworkController: CRITICAL: backup failed on sqlite3_backup_init()"ZT_EOL_S); + continue; + } + + int rc = SQLITE_OK; + for(;;) { + if (!_backupThreadRun) { + sqlite3_backup_finish(bak); + sqlite3_close(bakdb); + OSUtils::rm(backupPath); + return; + } + _lock.lock(); + rc = sqlite3_backup_step(bak,64); + _lock.unlock(); + if ((rc == SQLITE_OK)||(rc == SQLITE_LOCKED)||(rc == SQLITE_BUSY)) + Thread::sleep(50); + else break; + } + + sqlite3_backup_finish(bak); + sqlite3_close(bakdb); + + OSUtils::rm(backupPath2); + ::rename(backupPath,backupPath2); + } + + Thread::sleep(250); + } +} + +unsigned int SqliteNetworkController::_doCPGet( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType) +{ + // Assumes _lock is locked + char json[65536]; + + if ((path.size() > 0)&&(path[0] == "network")) { + + if ((path.size() >= 2)&&(path[1].length() == 16)) { + uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); + char nwids[24]; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + + if (path.size() >= 3) { + // /network//... + + if (path[2] == "member") { + + if (path.size() >= 4) { + // Get specific member info + + uint64_t address = Utils::hexStrToU64(path[3].c_str()); + char addrs[24]; + Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address); + + sqlite3_reset(_sGetMember2); + sqlite3_bind_text(_sGetMember2,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetMember2,2,addrs,10,SQLITE_STATIC); + if (sqlite3_step(_sGetMember2) == SQLITE_ROW) { + const char *memberIdStr = (const char *)sqlite3_column_text(_sGetMember2,3); + + // If testSingingId is included in the URL or X-ZT1-TestSigningId in the headers + // and if it contains an identity with a secret portion, the resturned JSON + // will contain an extra field called _testConf. This will contain several + // fields that report the result of doNetworkConfigRequest() for this member. + std::string testFields; + { + Identity testOutputSigningId; + std::map::const_iterator sid(urlArgs.find("testSigningId")); + if (sid != urlArgs.end()) { + testOutputSigningId.fromString(sid->second.c_str()); + } else { + sid = headers.find("x-zt1-testsigningid"); + if (sid != headers.end()) + testOutputSigningId.fromString(sid->second.c_str()); + } + + if ((testOutputSigningId.hasPrivate())&&(memberIdStr)) { + Dictionary testNetconf; + NetworkController::ResultCode rc = this->_doNetworkConfigRequest( + InetAddress(), + testOutputSigningId, + Identity(memberIdStr), + nwid, + Dictionary(), // TODO: allow passing of meta-data for testing + testNetconf); + char rcs[16]; + Utils::snprintf(rcs,sizeof(rcs),"%d,\n",(int)rc); + testFields.append("\t\"_test\": {\n"); + testFields.append("\t\t\"resultCode\": "); testFields.append(rcs); + testFields.append("\t\t\"result\": \""); testFields.append(_jsonEscape(testNetconf.toString().c_str()).c_str()); testFields.append("\",\n"); + testFields.append("\t\t\"resultJson\": {\n"); + for(Dictionary::const_iterator i(testNetconf.begin());i!=testNetconf.end();++i) { + if (i != testNetconf.begin()) + testFields.append(",\n"); + testFields.append("\t\t\t\""); + testFields.append(i->first); + testFields.append("\": \""); + testFields.append(_jsonEscape(i->second.c_str())); + testFields.push_back('"'); + } + testFields.append("\n\t\t}\n"); + testFields.append("\t},\n"); + } + } + + Utils::snprintf(json,sizeof(json), + "{\n%s" + "\t\"nwid\": \"%s\",\n" + "\t\"address\": \"%s\",\n" + "\t\"controllerInstanceId\": \"%s\",\n" + "\t\"authorized\": %s,\n" + "\t\"activeBridge\": %s,\n" + "\t\"memberRevision\": %llu,\n" + "\t\"clock\": %llu,\n" + "\t\"identity\": \"%s\",\n" + "\t\"ipAssignments\": [", + testFields.c_str(), + nwids, + addrs, + _instanceId.c_str(), + (sqlite3_column_int(_sGetMember2,0) > 0) ? "true" : "false", + (sqlite3_column_int(_sGetMember2,1) > 0) ? "true" : "false", + (unsigned long long)sqlite3_column_int64(_sGetMember2,2), + (unsigned long long)OSUtils::now(), + _jsonEscape(memberIdStr).c_str()); + responseBody = json; + + sqlite3_reset(_sGetIpAssignmentsForNode2); + sqlite3_bind_text(_sGetIpAssignmentsForNode2,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetIpAssignmentsForNode2,2,addrs,10,SQLITE_STATIC); + sqlite3_bind_int(_sGetIpAssignmentsForNode2,3,(int)ZT_IP_ASSIGNMENT_TYPE_ADDRESS); + bool firstIp = true; + while (sqlite3_step(_sGetIpAssignmentsForNode2) == SQLITE_ROW) { + int ipversion = sqlite3_column_int(_sGetIpAssignmentsForNode2,2); + char ipBlob[16]; + memcpy(ipBlob,(const void *)sqlite3_column_blob(_sGetIpAssignmentsForNode2,0),16); + InetAddress ip( + (const void *)(ipversion == 6 ? ipBlob : &ipBlob[12]), + (ipversion == 6 ? 16 : 4), + (unsigned int)sqlite3_column_int(_sGetIpAssignmentsForNode2,1) + ); + responseBody.append(firstIp ? "\"" : ",\""); + responseBody.append(_jsonEscape(ip.toString())); + responseBody.push_back('"'); + firstIp = false; + } + + responseBody.append("],\n\t\"recentLog\": ["); + + sqlite3_reset(_sGetNodeHistory); + sqlite3_bind_text(_sGetNodeHistory,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetNodeHistory,2,addrs,10,SQLITE_STATIC); + bool firstHistory = true; + while (sqlite3_step(_sGetNodeHistory) == SQLITE_ROW) { + responseBody.append(firstHistory ? "{" : ",{"); + responseBody.append("\"ts\":"); + responseBody.append((const char *)sqlite3_column_text(_sGetNodeHistory,2)); + responseBody.append((sqlite3_column_int(_sGetNodeHistory,1) == 0) ? ",\"authorized\":false,\"clientMajorVersion\":" : ",\"authorized\":true,\"clientMajorVersion\":"); + responseBody.append((const char *)sqlite3_column_text(_sGetNodeHistory,3)); + responseBody.append(",\"clientMinorVersion\":"); + responseBody.append((const char *)sqlite3_column_text(_sGetNodeHistory,4)); + responseBody.append(",\"clientRevision\":"); + responseBody.append((const char *)sqlite3_column_text(_sGetNodeHistory,5)); + responseBody.append(",\"fromAddr\":"); + const char *fa = (const char *)sqlite3_column_text(_sGetNodeHistory,7); + if (fa) { + responseBody.push_back('"'); + responseBody.append(_jsonEscape(fa)); + responseBody.append("\"}"); + } else responseBody.append("null}"); + firstHistory = false; + } + responseBody.append("]\n}\n"); + + responseContentType = "application/json"; + return 200; + } // else 404 + + } else { + // List members + + sqlite3_reset(_sListNetworkMembers); + sqlite3_bind_text(_sListNetworkMembers,1,nwids,16,SQLITE_STATIC); + responseBody.push_back('{'); + bool firstMember = true; + while (sqlite3_step(_sListNetworkMembers) == SQLITE_ROW) { + responseBody.append(firstMember ? "\"" : ",\""); + firstMember = false; + responseBody.append((const char *)sqlite3_column_text(_sListNetworkMembers,0)); + responseBody.append("\":"); + responseBody.append((const char *)sqlite3_column_text(_sListNetworkMembers,1)); + } + responseBody.push_back('}'); + responseContentType = "application/json"; + return 200; + + } + + } else if ((path[2] == "active")&&(path.size() == 3)) { + + sqlite3_reset(_sGetActiveNodesOnNetwork); + sqlite3_bind_text(_sGetActiveNodesOnNetwork,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetActiveNodesOnNetwork,2,nwids,16,SQLITE_STATIC); + sqlite3_bind_int64(_sGetActiveNodesOnNetwork,3,(int64_t)(OSUtils::now() - ZT_NETCONF_NODE_ACTIVE_THRESHOLD)); + + responseBody.push_back('{'); + bool firstMember = true; + uint64_t lastNodeId = 0; + while (sqlite3_step(_sGetActiveNodesOnNetwork) == SQLITE_ROW) { + const char *nodeId = (const char *)sqlite3_column_text(_sGetActiveNodesOnNetwork,0); + if (nodeId) { + const uint64_t nodeIdInt = Utils::hexStrToU64(nodeId); + if (nodeIdInt == lastNodeId) // technically that SQL query could (rarely) generate a duplicate for a given nodeId, in which case we want the first + continue; + lastNodeId = nodeIdInt; + + responseBody.append(firstMember ? "\"" : ",\""); + firstMember = false; + responseBody.append(nodeId); + responseBody.append("\":{"); + responseBody.append("\"ts\":"); + responseBody.append((const char *)sqlite3_column_text(_sGetActiveNodesOnNetwork,1)); + responseBody.append((sqlite3_column_int(_sGetActiveNodesOnNetwork,6) > 0) ? ",\"authorized\":true" : ",\"authorized\":false"); + responseBody.append(",\"clientMajorVersion\":"); + responseBody.append((const char *)sqlite3_column_text(_sGetActiveNodesOnNetwork,2)); + responseBody.append(",\"clientMinorVersion\":"); + responseBody.append((const char *)sqlite3_column_text(_sGetActiveNodesOnNetwork,3)); + responseBody.append(",\"clientRevision\":"); + responseBody.append((const char *)sqlite3_column_text(_sGetActiveNodesOnNetwork,4)); + const char *fromAddr = (const char *)sqlite3_column_text(_sGetActiveNodesOnNetwork,5); + if ((fromAddr)&&(fromAddr[0])) { + responseBody.append(",\"fromAddr\":\""); + responseBody.append(_jsonEscape(fromAddr)); + responseBody.append("\"}"); + } else { + responseBody.append(",\"fromAddr\":null}"); + } + } + } + responseBody.push_back('}'); + + responseContentType = "application/json"; + return 200; + + } else if ((path[2] == "test")&&(path.size() >= 4)) { + + std::map< uint64_t,_CircuitTestEntry >::iterator cte(_circuitTests.find(Utils::hexStrToU64(path[3].c_str()))); + if ((cte != _circuitTests.end())&&(cte->second.test)) { + + responseBody = "["; + responseBody.append(cte->second.jsonResults); + responseBody.push_back(']'); + responseContentType = "application/json"; + + return 200; + + } // else 404 + + } // else 404 + + } else { + + sqlite3_reset(_sGetNetworkById); + sqlite3_bind_text(_sGetNetworkById,1,nwids,16,SQLITE_STATIC); + if (sqlite3_step(_sGetNetworkById) == SQLITE_ROW) { + Utils::snprintf(json,sizeof(json), + "{\n" + "\t\"nwid\": \"%s\",\n" + "\t\"controllerInstanceId\": \"%s\",\n" + "\t\"clock\": %llu,\n" + "\t\"name\": \"%s\",\n" + "\t\"private\": %s,\n" + "\t\"enableBroadcast\": %s,\n" + "\t\"allowPassiveBridging\": %s,\n" + "\t\"v4AssignMode\": \"%s\",\n" + "\t\"v6AssignMode\": \"%s\",\n" + "\t\"multicastLimit\": %d,\n" + "\t\"creationTime\": %llu,\n" + "\t\"revision\": %llu,\n" + "\t\"memberRevisionCounter\": %llu,\n" + "\t\"authorizedMemberCount\": %llu,\n" + "\t\"relays\": [", + nwids, + _instanceId.c_str(), + (unsigned long long)OSUtils::now(), + _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,0)).c_str(), + (sqlite3_column_int(_sGetNetworkById,1) > 0) ? "true" : "false", + (sqlite3_column_int(_sGetNetworkById,2) > 0) ? "true" : "false", + (sqlite3_column_int(_sGetNetworkById,3) > 0) ? "true" : "false", + _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,4)).c_str(), + _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,5)).c_str(), + sqlite3_column_int(_sGetNetworkById,6), + (unsigned long long)sqlite3_column_int64(_sGetNetworkById,7), + (unsigned long long)sqlite3_column_int64(_sGetNetworkById,8), + (unsigned long long)sqlite3_column_int64(_sGetNetworkById,9), + (unsigned long long)sqlite3_column_int64(_sGetNetworkById,10)); + responseBody = json; + + sqlite3_reset(_sGetRelays); + sqlite3_bind_text(_sGetRelays,1,nwids,16,SQLITE_STATIC); + bool firstRelay = true; + while (sqlite3_step(_sGetRelays) == SQLITE_ROW) { + responseBody.append(firstRelay ? "\n\t\t" : ",\n\t\t"); + firstRelay = false; + responseBody.append("{\"address\":\""); + responseBody.append((const char *)sqlite3_column_text(_sGetRelays,0)); + responseBody.append("\",\"phyAddress\":\""); + responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1))); + responseBody.append("\"}"); + } + + responseBody.append("],\n\t\"gateways\": ["); + + sqlite3_reset(_sGetGateways); + sqlite3_bind_text(_sGetGateways,1,nwids,16,SQLITE_STATIC); + bool firstGateway = true; + while (sqlite3_step(_sGetGateways) == SQLITE_ROW) { + char tmp[128]; + const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0); + switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion + case 4: + Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"", + (firstGateway) ? "\"" : ",\"", + (int)ip[12], + (int)ip[13], + (int)ip[14], + (int)ip[15], + (int)sqlite3_column_int(_sGetGateways,2)); // metric + break; + case 6: + Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d\"", + (firstGateway) ? "\"" : ",\"", + (int)ip[0], + (int)ip[1], + (int)ip[2], + (int)ip[3], + (int)ip[4], + (int)ip[5], + (int)ip[6], + (int)ip[7], + (int)ip[8], + (int)ip[9], + (int)ip[10], + (int)ip[11], + (int)ip[12], + (int)ip[13], + (int)ip[14], + (int)ip[15], + (int)sqlite3_column_int(_sGetGateways,2)); // metric + break; + } + responseBody.append(tmp); + firstGateway = false; + } + + responseBody.append("],\n\t\"ipLocalRoutes\": ["); + + sqlite3_reset(_sGetLocalRoutes); + sqlite3_bind_text(_sGetLocalRoutes,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_int(_sGetLocalRoutes,2,(int)ZT_IP_ASSIGNMENT_TYPE_NETWORK); + bool firstLocalRoute = true; + while (sqlite3_step(_sGetLocalRoutes) == SQLITE_ROW) { + char tmp[128]; + const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetLocalRoutes,0); + switch (sqlite3_column_int(_sGetLocalRoutes,2)) { + case 4: + Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"", + (firstLocalRoute) ? "\"" : ",\"", + (int)ip[12], + (int)ip[13], + (int)ip[14], + (int)ip[15], + (int)sqlite3_column_int(_sGetLocalRoutes,1)); // netmask bits + break; + case 6: + Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d\"", + (firstLocalRoute) ? "\"" : ",\"", + (int)ip[0], + (int)ip[1], + (int)ip[2], + (int)ip[3], + (int)ip[4], + (int)ip[5], + (int)ip[6], + (int)ip[7], + (int)ip[8], + (int)ip[9], + (int)ip[10], + (int)ip[11], + (int)ip[12], + (int)ip[13], + (int)ip[14], + (int)ip[15], + (int)sqlite3_column_int(_sGetLocalRoutes,1)); // netmask bits + break; + } + responseBody.append(tmp); + firstLocalRoute = false; + } + + responseBody.append("],\n\t\"ipAssignmentPools\": ["); + + sqlite3_reset(_sGetIpAssignmentPools2); + sqlite3_bind_text(_sGetIpAssignmentPools2,1,nwids,16,SQLITE_STATIC); + bool firstIpAssignmentPool = true; + while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) { + const char *ipRangeStartB = reinterpret_cast(sqlite3_column_blob(_sGetIpAssignmentPools2,0)); + const char *ipRangeEndB = reinterpret_cast(sqlite3_column_blob(_sGetIpAssignmentPools2,1)); + if ((ipRangeStartB)&&(ipRangeEndB)) { + InetAddress ipps,ippe; + int ipVersion = sqlite3_column_int(_sGetIpAssignmentPools2,2); + if (ipVersion == 4) { + ipps.set((const void *)(ipRangeStartB + 12),4,0); + ippe.set((const void *)(ipRangeEndB + 12),4,0); + } else if (ipVersion == 6) { + ipps.set((const void *)ipRangeStartB,16,0); + ippe.set((const void *)ipRangeEndB,16,0); + } + if (ipps) { + responseBody.append(firstIpAssignmentPool ? "\n\t\t" : ",\n\t\t"); + firstIpAssignmentPool = false; + Utils::snprintf(json,sizeof(json),"{\"ipRangeStart\":\"%s\",\"ipRangeEnd\":\"%s\"}", + _jsonEscape(ipps.toIpString()).c_str(), + _jsonEscape(ippe.toIpString()).c_str()); + responseBody.append(json); + } + } + } + + responseBody.append("],\n\t\"rules\": ["); + + sqlite3_reset(_sListRules); + sqlite3_bind_text(_sListRules,1,nwids,16,SQLITE_STATIC); + bool firstRule = true; + while (sqlite3_step(_sListRules) == SQLITE_ROW) { + responseBody.append(firstRule ? "\n\t{\n" : ",{\n"); + firstRule = false; + Utils::snprintf(json,sizeof(json),"\t\t\"ruleNo\": %lld,\n",sqlite3_column_int64(_sListRules,0)); + responseBody.append(json); + if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"nodeId\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,2) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"sourcePort\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,2)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,3) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"destPort\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,3)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,4) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"vlanId\": %d,\n",sqlite3_column_int(_sListRules,4)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,5) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"vlanPcp\": %d,\n",sqlite3_column_int(_sListRules,5)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,6) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"etherType\": %d,\n",sqlite3_column_int(_sListRules,6)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,7) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"macSource\": \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,7)).toString().c_str()); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,8) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"macDest\": \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,8)).toString().c_str()); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,9) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"ipSource\": \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,9)).c_str()); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,10) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"ipDest\": \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,10)).c_str()); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,11) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"ipTos\": %d,\n",sqlite3_column_int(_sListRules,11)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,12) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"ipProtocol\": %d,\n",sqlite3_column_int(_sListRules,12)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,13) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"ipSourcePort\": %d,\n",sqlite3_column_int(_sListRules,13)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,14) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"ipDestPort\": %d,\n",sqlite3_column_int(_sListRules,14)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,15) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"flags\": %lu,\n",(unsigned long)sqlite3_column_int64(_sListRules,15)); + responseBody.append(json); + } + if (sqlite3_column_type(_sListRules,16) != SQLITE_NULL) { + Utils::snprintf(json,sizeof(json),"\t\t\"invFlags\": %lu,\n",(unsigned long)sqlite3_column_int64(_sListRules,16)); + responseBody.append(json); + } + responseBody.append("\t\t\"action\": \""); + responseBody.append(_jsonEscape( (sqlite3_column_type(_sListRules,17) == SQLITE_NULL) ? "drop" : (const char *)sqlite3_column_text(_sListRules,17) )); + responseBody.append("\"\n\t}"); + } + + responseBody.append("]\n}\n"); + responseContentType = "application/json"; + return 200; + } // else 404 + } + } else if (path.size() == 1) { + // list networks + sqlite3_reset(_sListNetworks); + responseContentType = "application/json"; + responseBody = "["; + bool first = true; + while (sqlite3_step(_sListNetworks) == SQLITE_ROW) { + if (first) { + first = false; + responseBody.push_back('"'); + } else responseBody.append(",\""); + responseBody.append((const char *)sqlite3_column_text(_sListNetworks,0)); + responseBody.push_back('"'); + } + responseBody.push_back(']'); + return 200; + } // else 404 + + } else { + // GET /controller returns status and API version if controller is supported + Utils::snprintf(json,sizeof(json),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu,\n\t\"instanceId\": \"%s\"\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now(),_instanceId.c_str()); + responseBody = json; + responseContentType = "application/json"; + return 200; + } + + return 404; +} + +NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(const InetAddress &fromAddr,const Identity &signingId,const Identity &identity,uint64_t nwid,const Dictionary &metaData,Dictionary &netconf) +{ + // Assumes _lock is locked + + // Decode some stuff from metaData + const unsigned int clientMajorVersion = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0); + const unsigned int clientMinorVersion = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,0); + const unsigned int clientRevision = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,0); + const bool clientIs104 = (Utils::compareVersion(clientMajorVersion,clientMinorVersion,clientRevision,1,0,4) >= 0); + + // Note: we can't reuse prepared statements that return const char * pointers without + // making our own copy in e.g. a std::string first. + + if ((!signingId)||(!signingId.hasPrivate())) { + netconf["error"] = "signing identity invalid or lacks private key"; + return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR; + } + if (signingId.address().toInt() != (nwid >> 24)) { + netconf["error"] = "signing identity address does not match most significant 40 bits of network ID"; + return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR; + } + + const uint64_t now = OSUtils::now(); + + // Check rate limit circuit breaker to prevent flooding + { + uint64_t &lrt = _lastRequestTime[std::pair(identity.address().toInt(),nwid)]; + if ((now - lrt) <= ZT_NETCONF_MIN_REQUEST_PERIOD) + return NetworkController::NETCONF_QUERY_IGNORE; + lrt = now; + } + + NetworkRecord network; + memset(&network,0,sizeof(network)); + Utils::snprintf(network.id,sizeof(network.id),"%.16llx",(unsigned long long)nwid); + + MemberRecord member; + memset(&member,0,sizeof(member)); + Utils::snprintf(member.nodeId,sizeof(member.nodeId),"%.10llx",(unsigned long long)identity.address().toInt()); + + // Create Node record or do full identity check if we already have one + + sqlite3_reset(_sGetNodeIdentity); + sqlite3_bind_text(_sGetNodeIdentity,1,member.nodeId,10,SQLITE_STATIC); + if (sqlite3_step(_sGetNodeIdentity) == SQLITE_ROW) { + try { + Identity alreadyKnownIdentity((const char *)sqlite3_column_text(_sGetNodeIdentity,0)); + if (alreadyKnownIdentity != identity) + return NetworkController::NETCONF_QUERY_ACCESS_DENIED; + } catch ( ... ) { // identity stored in database is not valid or is NULL + return NetworkController::NETCONF_QUERY_ACCESS_DENIED; + } + } else { + std::string idstr(identity.toString(false)); + sqlite3_reset(_sCreateOrReplaceNode); + sqlite3_bind_text(_sCreateOrReplaceNode,1,member.nodeId,10,SQLITE_STATIC); + sqlite3_bind_text(_sCreateOrReplaceNode,2,idstr.c_str(),-1,SQLITE_STATIC); + if (sqlite3_step(_sCreateOrReplaceNode) != SQLITE_DONE) { + netconf["error"] = "unable to create new Node record"; + return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR; + } + } + + // Fetch Network record + + sqlite3_reset(_sGetNetworkById); + sqlite3_bind_text(_sGetNetworkById,1,network.id,16,SQLITE_STATIC); + if (sqlite3_step(_sGetNetworkById) == SQLITE_ROW) { + network.name = (const char *)sqlite3_column_text(_sGetNetworkById,0); + network.isPrivate = (sqlite3_column_int(_sGetNetworkById,1) > 0); + network.enableBroadcast = (sqlite3_column_int(_sGetNetworkById,2) > 0); + network.allowPassiveBridging = (sqlite3_column_int(_sGetNetworkById,3) > 0); + network.v4AssignMode = (const char *)sqlite3_column_text(_sGetNetworkById,4); + network.v6AssignMode = (const char *)sqlite3_column_text(_sGetNetworkById,5); + network.multicastLimit = sqlite3_column_int(_sGetNetworkById,6); + network.creationTime = (uint64_t)sqlite3_column_int64(_sGetNetworkById,7); + network.revision = (uint64_t)sqlite3_column_int64(_sGetNetworkById,8); + network.memberRevisionCounter = (uint64_t)sqlite3_column_int64(_sGetNetworkById,9); + } else { + return NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND; + } + + // Fetch Member record + + bool foundMember = false; + sqlite3_reset(_sGetMember); + sqlite3_bind_text(_sGetMember,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetMember,2,member.nodeId,10,SQLITE_STATIC); + if (sqlite3_step(_sGetMember) == SQLITE_ROW) { + foundMember = true; + member.rowid = (int64_t)sqlite3_column_int64(_sGetMember,0); + member.authorized = (sqlite3_column_int(_sGetMember,1) > 0); + member.activeBridge = (sqlite3_column_int(_sGetMember,2) > 0); + } + + // Create Member record for unknown nodes, auto-authorizing if network is public + + if (!foundMember) { + member.authorized = (network.isPrivate ? false : true); + member.activeBridge = false; + sqlite3_reset(_sCreateMember); + sqlite3_bind_text(_sCreateMember,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_text(_sCreateMember,2,member.nodeId,10,SQLITE_STATIC); + sqlite3_bind_int(_sCreateMember,3,(member.authorized ? 1 : 0)); + sqlite3_bind_text(_sCreateMember,4,network.id,16,SQLITE_STATIC); + if (sqlite3_step(_sCreateMember) != SQLITE_DONE) { + netconf["error"] = "unable to create new member record"; + return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR; + } + member.rowid = (int64_t)sqlite3_last_insert_rowid(_db); + + sqlite3_reset(_sIncrementMemberRevisionCounter); + sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,network.id,16,SQLITE_STATIC); + sqlite3_step(_sIncrementMemberRevisionCounter); + } + + // Update NodeHistory with new log entry and delete expired entries + + { + int64_t nextVC = 1; + sqlite3_reset(_sGetMaxNodeHistoryNetworkVisitCounter); + sqlite3_bind_text(_sGetMaxNodeHistoryNetworkVisitCounter,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetMaxNodeHistoryNetworkVisitCounter,2,member.nodeId,10,SQLITE_STATIC); + if (sqlite3_step(_sGetMaxNodeHistoryNetworkVisitCounter) == SQLITE_ROW) { + nextVC = (int64_t)sqlite3_column_int64(_sGetMaxNodeHistoryNetworkVisitCounter,0) + 1; + } + + std::string mdstr(metaData.toString()); + if (mdstr.length() > 1024) + mdstr = mdstr.substr(0,1024); + std::string fastr; + if (fromAddr) + fastr = fromAddr.toString(); + + sqlite3_reset(_sAddNodeHistoryEntry); + sqlite3_bind_text(_sAddNodeHistoryEntry,1,member.nodeId,10,SQLITE_STATIC); + sqlite3_bind_text(_sAddNodeHistoryEntry,2,network.id,16,SQLITE_STATIC); + sqlite3_bind_int64(_sAddNodeHistoryEntry,3,nextVC); + sqlite3_bind_int(_sAddNodeHistoryEntry,4,(member.authorized ? 1 : 0)); + sqlite3_bind_int64(_sAddNodeHistoryEntry,5,(long long)now); + sqlite3_bind_int(_sAddNodeHistoryEntry,6,(int)clientMajorVersion); + sqlite3_bind_int(_sAddNodeHistoryEntry,7,(int)clientMinorVersion); + sqlite3_bind_int(_sAddNodeHistoryEntry,8,(int)clientRevision); + sqlite3_bind_text(_sAddNodeHistoryEntry,9,mdstr.c_str(),-1,SQLITE_STATIC); + if (fastr.length() > 0) + sqlite3_bind_text(_sAddNodeHistoryEntry,10,fastr.c_str(),-1,SQLITE_STATIC); + else sqlite3_bind_null(_sAddNodeHistoryEntry,10); + sqlite3_step(_sAddNodeHistoryEntry); + + nextVC -= ZT_NETCONF_NODE_HISTORY_LENGTH; + if (nextVC >= 0) { + sqlite3_reset(_sDeleteOldNodeHistoryEntries); + sqlite3_bind_text(_sDeleteOldNodeHistoryEntries,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_text(_sDeleteOldNodeHistoryEntries,2,member.nodeId,10,SQLITE_STATIC); + sqlite3_bind_int64(_sDeleteOldNodeHistoryEntries,3,nextVC); + sqlite3_step(_sDeleteOldNodeHistoryEntries); + } + } + + // Check member authorization + + if (!member.authorized) + return NetworkController::NETCONF_QUERY_ACCESS_DENIED; + + // Create and sign netconf + + netconf.clear(); + { + char tss[24],rs[24]; + Utils::snprintf(tss,sizeof(tss),"%.16llx",(unsigned long long)now); + Utils::snprintf(rs,sizeof(rs),"%.16llx",(unsigned long long)network.revision); + netconf[ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP] = tss; + netconf[ZT_NETWORKCONFIG_DICT_KEY_REVISION] = rs; + netconf[ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID] = network.id; + netconf[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO] = member.nodeId; + netconf[ZT_NETWORKCONFIG_DICT_KEY_PRIVATE] = network.isPrivate ? "1" : "0"; + netconf[ZT_NETWORKCONFIG_DICT_KEY_NAME] = (network.name) ? network.name : ""; + netconf[ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST] = network.enableBroadcast ? "1" : "0"; + netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING] = network.allowPassiveBridging ? "1" : "0"; + + { // TODO: right now only etherTypes are supported in rules + std::vector allowedEtherTypes; + sqlite3_reset(_sGetEtherTypesFromRuleTable); + sqlite3_bind_text(_sGetEtherTypesFromRuleTable,1,network.id,16,SQLITE_STATIC); + while (sqlite3_step(_sGetEtherTypesFromRuleTable) == SQLITE_ROW) { + if (sqlite3_column_type(_sGetEtherTypesFromRuleTable,0) == SQLITE_NULL) { + allowedEtherTypes.clear(); + allowedEtherTypes.push_back(0); // NULL 'allow' matches ANY + break; + } else { + int et = sqlite3_column_int(_sGetEtherTypesFromRuleTable,0); + if ((et >= 0)&&(et <= 0xffff)) + allowedEtherTypes.push_back(et); + } + } + std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end()); + allowedEtherTypes.erase(std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()),allowedEtherTypes.end()); + std::string allowedEtherTypesCsv; + for(std::vector::const_iterator i(allowedEtherTypes.begin());i!=allowedEtherTypes.end();++i) { + if (allowedEtherTypesCsv.length()) + allowedEtherTypesCsv.push_back(','); + char tmp[16]; + Utils::snprintf(tmp,sizeof(tmp),"%.4x",(unsigned int)*i); + allowedEtherTypesCsv.append(tmp); + } + netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = allowedEtherTypesCsv; + } + + if (network.multicastLimit > 0) { + char ml[16]; + Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit); + netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml; + } + + bool amActiveBridge = false; + { + std::string activeBridges; + sqlite3_reset(_sGetActiveBridges); + sqlite3_bind_text(_sGetActiveBridges,1,network.id,16,SQLITE_STATIC); + while (sqlite3_step(_sGetActiveBridges) == SQLITE_ROW) { + const char *ab = (const char *)sqlite3_column_text(_sGetActiveBridges,0); + if ((ab)&&(strlen(ab) == 10)) { + if (activeBridges.length()) + activeBridges.push_back(','); + activeBridges.append(ab); + if (!strcmp(member.nodeId,ab)) + amActiveBridge = true; + } + if (activeBridges.length() > 1024) // sanity check -- you can't have too many active bridges at the moment + break; + } + if (activeBridges.length()) + netconf[ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES] = activeBridges; + } + + // Do not send relays to 1.1.0 since it had a serious bug in using them + // 1.1.0 will still work, it'll just fall back to roots instead of using network preferred relays + if (!((clientMajorVersion == 1)&&(clientMinorVersion == 1)&&(clientRevision == 0))) { + std::string relays; + sqlite3_reset(_sGetRelays); + sqlite3_bind_text(_sGetRelays,1,network.id,16,SQLITE_STATIC); + while (sqlite3_step(_sGetRelays) == SQLITE_ROW) { + const char *n = (const char *)sqlite3_column_text(_sGetRelays,0); + const char *a = (const char *)sqlite3_column_text(_sGetRelays,1); + if ((n)&&(a)) { + Address node(n); + InetAddress addr(a); + if ((node)&&(addr)) { + if (relays.length()) + relays.push_back(','); + relays.append(node.toString()); + relays.push_back(';'); + relays.append(addr.toString()); + } + } + } + if (relays.length()) + netconf[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays; + } + + { + char tmp[128]; + std::string gateways; + sqlite3_reset(_sGetGateways); + sqlite3_bind_text(_sGetGateways,1,network.id,16,SQLITE_STATIC); + while (sqlite3_step(_sGetGateways) == SQLITE_ROW) { + const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0); + switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion + case 4: + Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d", + (gateways.length() > 0) ? "," : "", + (int)ip[12], + (int)ip[13], + (int)ip[14], + (int)ip[15], + (int)sqlite3_column_int(_sGetGateways,2)); // metric + gateways.append(tmp); + break; + case 6: + Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", + (gateways.length() > 0) ? "," : "", + (int)ip[0], + (int)ip[1], + (int)ip[2], + (int)ip[3], + (int)ip[4], + (int)ip[5], + (int)ip[6], + (int)ip[7], + (int)ip[8], + (int)ip[9], + (int)ip[10], + (int)ip[11], + (int)ip[12], + (int)ip[13], + (int)ip[14], + (int)ip[15], + (int)sqlite3_column_int(_sGetGateways,2)); // metric + gateways.append(tmp); + break; + } + } + if (gateways.length()) + netconf[ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS] = gateways; + } + + if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) { + std::string v4s; + + // Get existing IPv4 IP assignments and network routes -- keep routes in a + // vector for use in auto-assign if we need them. + std::vector< std::pair > routedNetworks; + bool haveStaticIpAssignment = false; + sqlite3_reset(_sGetIpAssignmentsForNode); + sqlite3_bind_text(_sGetIpAssignmentsForNode,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetIpAssignmentsForNode,2,member.nodeId,10,SQLITE_STATIC); + sqlite3_bind_int(_sGetIpAssignmentsForNode,3,4); // 4 == IPv4 + while (sqlite3_step(_sGetIpAssignmentsForNode) == SQLITE_ROW) { + const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetIpAssignmentsForNode,1); + if ((!ip)||(sqlite3_column_bytes(_sGetIpAssignmentsForNode,1) != 16)) + continue; + int ipNetmaskBits = sqlite3_column_int(_sGetIpAssignmentsForNode,2); + if ((ipNetmaskBits <= 0)||(ipNetmaskBits > 32)) + continue; + + const IpAssignmentType ipt = (IpAssignmentType)sqlite3_column_int(_sGetIpAssignmentsForNode,0); + switch(ipt) { + case ZT_IP_ASSIGNMENT_TYPE_ADDRESS: + haveStaticIpAssignment = true; + break; + case ZT_IP_ASSIGNMENT_TYPE_NETWORK: + routedNetworks.push_back(std::pair(Utils::ntoh(*(reinterpret_cast(ip + 12))),ipNetmaskBits)); + break; + default: + continue; + } + + // 1.0.4 or newer clients support network routes in addition to IPs. + // Older clients only support IP address / netmask entries. + if ((clientIs104)||(ipt == ZT_IP_ASSIGNMENT_TYPE_ADDRESS)) { + char tmp[32]; + Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[12],(int)ip[13],(int)ip[14],(int)ip[15],ipNetmaskBits); + if (v4s.length()) + v4s.push_back(','); + v4s.append(tmp); + } + } + + if ((!haveStaticIpAssignment)&&(!amActiveBridge)) { + // Attempt to auto-assign an IPv4 address from an available routed pool + sqlite3_reset(_sGetIpAssignmentPools); + sqlite3_bind_text(_sGetIpAssignmentPools,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_int(_sGetIpAssignmentPools,2,4); // 4 == IPv4 + + while (sqlite3_step(_sGetIpAssignmentPools) == SQLITE_ROW) { + const unsigned char *ipRangeStartB = reinterpret_cast(sqlite3_column_blob(_sGetIpAssignmentPools,0)); + const unsigned char *ipRangeEndB = reinterpret_cast(sqlite3_column_blob(_sGetIpAssignmentPools,1)); + if ((!ipRangeStartB)||(!ipRangeEndB)||(sqlite3_column_bytes(_sGetIpAssignmentPools,0) != 16)||(sqlite3_column_bytes(_sGetIpAssignmentPools,1) != 16)) + continue; + + uint32_t ipRangeStart = Utils::ntoh(*(reinterpret_cast(ipRangeStartB + 12))); + uint32_t ipRangeEnd = Utils::ntoh(*(reinterpret_cast(ipRangeEndB + 12))); + if ((ipRangeEnd <= ipRangeStart)||(ipRangeStart == 0)) + continue; + uint32_t ipRangeLen = ipRangeEnd - ipRangeStart; + + // Start with the LSB of the member's address + uint32_t ipTrialCounter = (uint32_t)(identity.address().toInt() & 0xffffffff); + + for(uint32_t k=ipRangeStart,l=0;(k<=ipRangeEnd)&&(l < 1000000);++k,++l) { + uint32_t ip = (ipRangeLen > 0) ? (ipRangeStart + (ipTrialCounter % ipRangeLen)) : ipRangeStart; + ++ipTrialCounter; + if ((ip & 0x000000ff) == 0x000000ff) + continue; // don't allow addresses that end in .255 + + for(std::vector< std::pair >::const_iterator r(routedNetworks.begin());r!=routedNetworks.end();++r) { + if ((ip & (0xffffffff << (32 - r->second))) == r->first) { + // IP is included in a routed network, so check if it's allocated + + uint32_t ipBlob[4]; + ipBlob[0] = 0; ipBlob[1] = 0; ipBlob[2] = 0; ipBlob[3] = Utils::hton(ip); + + sqlite3_reset(_sCheckIfIpIsAllocated); + sqlite3_bind_text(_sCheckIfIpIsAllocated,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_blob(_sCheckIfIpIsAllocated,2,(const void *)ipBlob,16,SQLITE_STATIC); + sqlite3_bind_int(_sCheckIfIpIsAllocated,3,4); // 4 == IPv4 + sqlite3_bind_int(_sCheckIfIpIsAllocated,4,(int)ZT_IP_ASSIGNMENT_TYPE_ADDRESS); + if (sqlite3_step(_sCheckIfIpIsAllocated) != SQLITE_ROW) { + // No rows returned, so the IP is available + sqlite3_reset(_sAllocateIp); + sqlite3_bind_text(_sAllocateIp,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_text(_sAllocateIp,2,member.nodeId,10,SQLITE_STATIC); + sqlite3_bind_int(_sAllocateIp,3,(int)ZT_IP_ASSIGNMENT_TYPE_ADDRESS); + sqlite3_bind_blob(_sAllocateIp,4,(const void *)ipBlob,16,SQLITE_STATIC); + sqlite3_bind_int(_sAllocateIp,5,r->second); // IP netmask bits from matching route + sqlite3_bind_int(_sAllocateIp,6,4); // 4 == IPv4 + if (sqlite3_step(_sAllocateIp) == SQLITE_DONE) { + char tmp[32]; + Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)((ip >> 24) & 0xff),(int)((ip >> 16) & 0xff),(int)((ip >> 8) & 0xff),(int)(ip & 0xff),r->second); + if (v4s.length()) + v4s.push_back(','); + v4s.append(tmp); + haveStaticIpAssignment = true; // break outer loop + } + } + + break; // stop checking routed networks + } + } + + if (haveStaticIpAssignment) + break; + } + } + } + + if (v4s.length()) + netconf[ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC] = v4s; + } + + if ((network.v6AssignMode)&&(!strcmp(network.v6AssignMode,"rfc4193"))) { + InetAddress rfc4193Addr(InetAddress::makeIpv6rfc4193(nwid,identity.address().toInt())); + netconf[ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC] = rfc4193Addr.toString(); + } + + if (network.isPrivate) { + CertificateOfMembership com(now,ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA,nwid,identity.address()); + if (com.sign(signingId)) // basically can't fail unless our identity is invalid + netconf[ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP] = com.toString(); + else { + netconf["error"] = "unable to sign COM"; + return NETCONF_QUERY_INTERNAL_SERVER_ERROR; + } + } + + if (!netconf.sign(signingId,now)) { + netconf["error"] = "unable to sign netconf dictionary"; + return NETCONF_QUERY_INTERNAL_SERVER_ERROR; + } + } + + return NetworkController::NETCONF_QUERY_OK; +} + +void SqliteNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report) +{ + char tmp[65535]; + SqliteNetworkController *const self = reinterpret_cast(test->ptr); + + if (!test) + return; + if (!report) + return; + + Mutex::Lock _l(self->_lock); + std::map< uint64_t,_CircuitTestEntry >::iterator cte(self->_circuitTests.find(test->testId)); + + if (cte == self->_circuitTests.end()) { // sanity check: a circuit test we didn't launch? + self->_node->circuitTestEnd(test); + ::free((void *)test); + return; + } + + Utils::snprintf(tmp,sizeof(tmp), + "%s{\n" + "\t\"timestamp\": %llu,"ZT_EOL_S + "\t\"testId\": \"%.16llx\","ZT_EOL_S + "\t\"upstream\": \"%.10llx\","ZT_EOL_S + "\t\"current\": \"%.10llx\","ZT_EOL_S + "\t\"receivedTimestamp\": %llu,"ZT_EOL_S + "\t\"remoteTimestamp\": %llu,"ZT_EOL_S + "\t\"sourcePacketId\": \"%.16llx\","ZT_EOL_S + "\t\"flags\": %llu,"ZT_EOL_S + "\t\"sourcePacketHopCount\": %u,"ZT_EOL_S + "\t\"errorCode\": %u,"ZT_EOL_S + "\t\"vendor\": %d,"ZT_EOL_S + "\t\"protocolVersion\": %u,"ZT_EOL_S + "\t\"majorVersion\": %u,"ZT_EOL_S + "\t\"minorVersion\": %u,"ZT_EOL_S + "\t\"revision\": %u,"ZT_EOL_S + "\t\"platform\": %d,"ZT_EOL_S + "\t\"architecture\": %d,"ZT_EOL_S + "\t\"receivedOnLocalAddress\": \"%s\","ZT_EOL_S + "\t\"receivedFromRemoteAddress\": \"%s\""ZT_EOL_S + "}", + ((cte->second.jsonResults.length() > 0) ? ",\n" : ""), + (unsigned long long)report->timestamp, + (unsigned long long)test->testId, + (unsigned long long)report->upstream, + (unsigned long long)report->current, + (unsigned long long)OSUtils::now(), + (unsigned long long)report->remoteTimestamp, + (unsigned long long)report->sourcePacketId, + (unsigned long long)report->flags, + report->sourcePacketHopCount, + report->errorCode, + (int)report->vendor, + report->protocolVersion, + report->majorVersion, + report->minorVersion, + report->revision, + (int)report->platform, + (int)report->architecture, + reinterpret_cast(&(report->receivedOnLocalAddress))->toString().c_str(), + reinterpret_cast(&(report->receivedFromRemoteAddress))->toString().c_str()); + + cte->second.jsonResults.append(tmp); +} + +} // namespace ZeroTier diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp new file mode 100644 index 000000000..11be9db47 --- /dev/null +++ b/controller/SqliteNetworkController.hpp @@ -0,0 +1,191 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef ZT_SQLITENETWORKCONTROLLER_HPP +#define ZT_SQLITENETWORKCONTROLLER_HPP + +#include + +#include + +#include +#include +#include + +#include "../node/Constants.hpp" +#include "../node/NetworkController.hpp" +#include "../node/Mutex.hpp" +#include "../osdep/Thread.hpp" + +// Number of in-memory last log entries to maintain per user +#define ZT_SQLITENETWORKCONTROLLER_IN_MEMORY_LOG_SIZE 32 + +// How long do circuit tests last before they're forgotten? +#define ZT_SQLITENETWORKCONTROLLER_CIRCUIT_TEST_TIMEOUT 60000 + +namespace ZeroTier { + +class Node; + +class SqliteNetworkController : public NetworkController +{ +public: + SqliteNetworkController(Node *node,const char *dbPath,const char *circuitTestPath); + virtual ~SqliteNetworkController(); + + virtual NetworkController::ResultCode doNetworkConfigRequest( + const InetAddress &fromAddr, + const Identity &signingId, + const Identity &identity, + uint64_t nwid, + const Dictionary &metaData, + Dictionary &netconf); + + unsigned int handleControlPlaneHttpGET( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType); + unsigned int handleControlPlaneHttpPOST( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType); + unsigned int handleControlPlaneHttpDELETE( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType); + + // threadMain() for backup thread -- do not call directly + void threadMain() + throw(); + +private: + enum IpAssignmentType { + // IP assignment is a static IP address + ZT_IP_ASSIGNMENT_TYPE_ADDRESS = 0, + // IP assignment is a network -- a route via this interface, not an address + ZT_IP_ASSIGNMENT_TYPE_NETWORK = 1 + }; + + unsigned int _doCPGet( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType); + NetworkController::ResultCode _doNetworkConfigRequest( + const InetAddress &fromAddr, + const Identity &signingId, + const Identity &identity, + uint64_t nwid, + const Dictionary &metaData, + Dictionary &netconf); + + static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report); + + Node *_node; + Thread _backupThread; + volatile bool _backupThreadRun; + std::string _dbPath; + std::string _circuitTestPath; + std::string _instanceId; + + // Circuit tests outstanding + struct _CircuitTestEntry + { + ZT_CircuitTest *test; + std::string jsonResults; + }; + std::map< uint64_t,_CircuitTestEntry > _circuitTests; + + // Last request time by address, for rate limitation + std::map< std::pair,uint64_t > _lastRequestTime; + + sqlite3 *_db; + + sqlite3_stmt *_sGetNetworkById; + sqlite3_stmt *_sGetMember; + sqlite3_stmt *_sCreateMember; + sqlite3_stmt *_sGetNodeIdentity; + sqlite3_stmt *_sCreateOrReplaceNode; + sqlite3_stmt *_sGetMaxNodeHistoryNetworkVisitCounter; + sqlite3_stmt *_sAddNodeHistoryEntry; + sqlite3_stmt *_sDeleteOldNodeHistoryEntries; + sqlite3_stmt *_sGetActiveNodesOnNetwork; + sqlite3_stmt *_sGetNodeHistory; + sqlite3_stmt *_sGetEtherTypesFromRuleTable; + sqlite3_stmt *_sGetActiveBridges; + sqlite3_stmt *_sGetIpAssignmentsForNode; + sqlite3_stmt *_sGetIpAssignmentPools; + sqlite3_stmt *_sGetLocalRoutes; + sqlite3_stmt *_sCheckIfIpIsAllocated; + sqlite3_stmt *_sAllocateIp; + sqlite3_stmt *_sDeleteIpAllocations; + sqlite3_stmt *_sDeleteLocalRoutes; + sqlite3_stmt *_sGetRelays; + sqlite3_stmt *_sListNetworks; + sqlite3_stmt *_sListNetworkMembers; + sqlite3_stmt *_sGetMember2; + sqlite3_stmt *_sGetIpAssignmentPools2; + sqlite3_stmt *_sListRules; + sqlite3_stmt *_sCreateRule; + sqlite3_stmt *_sCreateNetwork; + sqlite3_stmt *_sGetNetworkRevision; + sqlite3_stmt *_sSetNetworkRevision; + sqlite3_stmt *_sGetIpAssignmentsForNode2; + sqlite3_stmt *_sDeleteRelaysForNetwork; + sqlite3_stmt *_sCreateRelay; + sqlite3_stmt *_sDeleteIpAssignmentPoolsForNetwork; + sqlite3_stmt *_sDeleteRulesForNetwork; + sqlite3_stmt *_sCreateIpAssignmentPool; + sqlite3_stmt *_sUpdateMemberAuthorized; + sqlite3_stmt *_sUpdateMemberActiveBridge; + sqlite3_stmt *_sDeleteMember; + sqlite3_stmt *_sDeleteAllNetworkMembers; + sqlite3_stmt *_sDeleteNetwork; + sqlite3_stmt *_sGetGateways; + sqlite3_stmt *_sDeleteGateways; + sqlite3_stmt *_sCreateGateway; + sqlite3_stmt *_sIncrementMemberRevisionCounter; + sqlite3_stmt *_sGetConfig; + sqlite3_stmt *_sSetConfig; + + Mutex _lock; +}; + +} // namespace ZeroTier + +#endif diff --git a/controller/schema.sql b/controller/schema.sql new file mode 100644 index 000000000..aff088273 --- /dev/null +++ b/controller/schema.sql @@ -0,0 +1,127 @@ +CREATE TABLE Config ( + k varchar(16) PRIMARY KEY NOT NULL, + v varchar(1024) NOT NULL +); + +CREATE TABLE Network ( + id char(16) PRIMARY KEY NOT NULL, + name varchar(128) NOT NULL, + private integer NOT NULL DEFAULT(1), + enableBroadcast integer NOT NULL DEFAULT(1), + allowPassiveBridging integer NOT NULL DEFAULT(0), + v4AssignMode varchar(8) NOT NULL DEFAULT('none'), + v6AssignMode varchar(8) NOT NULL DEFAULT('none'), + multicastLimit integer NOT NULL DEFAULT(32), + creationTime integer NOT NULL DEFAULT(0), + revision integer NOT NULL DEFAULT(1), + memberRevisionCounter integer NOT NULL DEFAULT(1) +); + +CREATE TABLE AuthToken ( + id integer PRIMARY KEY NOT NULL, + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + authMode integer NOT NULL DEFAULT(1), + useCount integer NOT NULL DEFAULT(0), + maxUses integer NOT NULL DEFAULT(0), + expiresAt integer NOT NULL DEFAULT(0), + token varchar(256) NOT NULL +); + +CREATE INDEX AuthToken_networkId_token ON AuthToken(networkId,token); + +CREATE TABLE Node ( + id char(10) PRIMARY KEY NOT NULL, + identity varchar(4096) NOT NULL +); + +CREATE TABLE NodeHistory ( + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + networkVisitCounter INTEGER NOT NULL DEFAULT(0), + networkRequestAuthorized INTEGER NOT NULL DEFAULT(0), + requestTime INTEGER NOT NULL DEFAULT(0), + clientMajorVersion INTEGER NOT NULL DEFAULT(0), + clientMinorVersion INTEGER NOT NULL DEFAULT(0), + clientRevision INTEGER NOT NULL DEFAULT(0), + networkRequestMetaData VARCHAR(1024), + fromAddress VARCHAR(128) +); + +CREATE INDEX NodeHistory_nodeId ON NodeHistory (nodeId); +CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId); +CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime); + +CREATE TABLE Gateway ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + ip blob(16) NOT NULL, + ipVersion integer NOT NULL DEFAULT(4), + metric integer NOT NULL DEFAULT(0) +); + +CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip); + +CREATE TABLE IpAssignment ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + nodeId char(10) REFERENCES Node(id) ON DELETE CASCADE, + type integer NOT NULL DEFAULT(0), + ip blob(16) NOT NULL, + ipNetmaskBits integer NOT NULL DEFAULT(0), + ipVersion integer NOT NULL DEFAULT(4) +); + +CREATE UNIQUE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip); + +CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId); + +CREATE TABLE IpAssignmentPool ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + ipRangeStart blob(16) NOT NULL, + ipRangeEnd blob(16) NOT NULL, + ipVersion integer NOT NULL DEFAULT(4) +); + +CREATE UNIQUE INDEX IpAssignmentPool_networkId_ipRangeStart ON IpAssignmentPool (networkId,ipRangeStart); + +CREATE TABLE Member ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + authorized integer NOT NULL DEFAULT(0), + activeBridge integer NOT NULL DEFAULT(0), + memberRevision integer NOT NULL DEFAULT(0), + PRIMARY KEY (networkId, nodeId) +); + +CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); +CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision); + +CREATE TABLE Relay ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + address char(10) NOT NULL, + phyAddress varchar(64) NOT NULL +); + +CREATE UNIQUE INDEX Relay_networkId_address ON Relay (networkId,address); + +CREATE TABLE Rule ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + ruleNo integer NOT NULL, + nodeId char(10) REFERENCES Node(id), + sourcePort char(10), + destPort char(10), + vlanId integer, + vlanPcp integer, + etherType integer, + macSource char(12), + macDest char(12), + ipSource varchar(64), + ipDest varchar(64), + ipTos integer, + ipProtocol integer, + ipSourcePort integer, + ipDestPort integer, + flags integer, + invFlags integer, + "action" varchar(4096) NOT NULL DEFAULT('accept') +); + +CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo); diff --git a/controller/schema.sql.c b/controller/schema.sql.c new file mode 100644 index 000000000..4b524547e --- /dev/null +++ b/controller/schema.sql.c @@ -0,0 +1,129 @@ +#define ZT_NETCONF_SCHEMA_SQL \ +"CREATE TABLE Config (\n"\ +" k varchar(16) PRIMARY KEY NOT NULL,\n"\ +" v varchar(1024) NOT NULL\n"\ +");\n"\ +"\n"\ +"CREATE TABLE Network (\n"\ +" id char(16) PRIMARY KEY NOT NULL,\n"\ +" name varchar(128) NOT NULL,\n"\ +" private integer NOT NULL DEFAULT(1),\n"\ +" enableBroadcast integer NOT NULL DEFAULT(1),\n"\ +" allowPassiveBridging integer NOT NULL DEFAULT(0),\n"\ +" v4AssignMode varchar(8) NOT NULL DEFAULT('none'),\n"\ +" v6AssignMode varchar(8) NOT NULL DEFAULT('none'),\n"\ +" multicastLimit integer NOT NULL DEFAULT(32),\n"\ +" creationTime integer NOT NULL DEFAULT(0),\n"\ +" revision integer NOT NULL DEFAULT(1),\n"\ +" memberRevisionCounter integer NOT NULL DEFAULT(1)\n"\ +");\n"\ +"\n"\ +"CREATE TABLE AuthToken (\n"\ +" id integer PRIMARY KEY NOT NULL,\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" authMode integer NOT NULL DEFAULT(1),\n"\ +" useCount integer NOT NULL DEFAULT(0),\n"\ +" maxUses integer NOT NULL DEFAULT(0),\n"\ +" expiresAt integer NOT NULL DEFAULT(0),\n"\ +" token varchar(256) NOT NULL\n"\ +");\n"\ +"\n"\ +"CREATE INDEX AuthToken_networkId_token ON AuthToken(networkId,token);\n"\ +"\n"\ +"CREATE TABLE Node (\n"\ +" id char(10) PRIMARY KEY NOT NULL,\n"\ +" identity varchar(4096) NOT NULL\n"\ +");\n"\ +"\n"\ +"CREATE TABLE NodeHistory (\n"\ +" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" networkVisitCounter INTEGER NOT NULL DEFAULT(0),\n"\ +" networkRequestAuthorized INTEGER NOT NULL DEFAULT(0),\n"\ +" requestTime INTEGER NOT NULL DEFAULT(0),\n"\ +" clientMajorVersion INTEGER NOT NULL DEFAULT(0),\n"\ +" clientMinorVersion INTEGER NOT NULL DEFAULT(0),\n"\ +" clientRevision INTEGER NOT NULL DEFAULT(0),\n"\ +" networkRequestMetaData VARCHAR(1024),\n"\ +" fromAddress VARCHAR(128)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX NodeHistory_nodeId ON NodeHistory (nodeId);\n"\ +"CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);\n"\ +"CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);\n"\ +"\n"\ +"CREATE TABLE Gateway (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" ip blob(16) NOT NULL,\n"\ +" ipVersion integer NOT NULL DEFAULT(4),\n"\ +" metric integer NOT NULL DEFAULT(0)\n"\ +");\n"\ +"\n"\ +"CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);\n"\ +"\n"\ +"CREATE TABLE IpAssignment (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" nodeId char(10) REFERENCES Node(id) ON DELETE CASCADE,\n"\ +" type integer NOT NULL DEFAULT(0),\n"\ +" ip blob(16) NOT NULL,\n"\ +" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\ +" ipVersion integer NOT NULL DEFAULT(4)\n"\ +");\n"\ +"\n"\ +"CREATE UNIQUE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\ +"\n"\ +"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\ +"\n"\ +"CREATE TABLE IpAssignmentPool (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" ipRangeStart blob(16) NOT NULL,\n"\ +" ipRangeEnd blob(16) NOT NULL,\n"\ +" ipVersion integer NOT NULL DEFAULT(4)\n"\ +");\n"\ +"\n"\ +"CREATE UNIQUE INDEX IpAssignmentPool_networkId_ipRangeStart ON IpAssignmentPool (networkId,ipRangeStart);\n"\ +"\n"\ +"CREATE TABLE Member (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ +" authorized integer NOT NULL DEFAULT(0),\n"\ +" activeBridge integer NOT NULL DEFAULT(0),\n"\ +" memberRevision integer NOT NULL DEFAULT(0),\n"\ +" PRIMARY KEY (networkId, nodeId)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ +"CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);\n"\ +"\n"\ +"CREATE TABLE Relay (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" address char(10) NOT NULL,\n"\ +" phyAddress varchar(64) NOT NULL\n"\ +");\n"\ +"\n"\ +"CREATE UNIQUE INDEX Relay_networkId_address ON Relay (networkId,address);\n"\ +"\n"\ +"CREATE TABLE Rule (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" ruleNo integer NOT NULL,\n"\ +" nodeId char(10) REFERENCES Node(id),\n"\ +" sourcePort char(10),\n"\ +" destPort char(10),\n"\ +" vlanId integer,\n"\ +" vlanPcp integer,\n"\ +" etherType integer,\n"\ +" macSource char(12),\n"\ +" macDest char(12),\n"\ +" ipSource varchar(64),\n"\ +" ipDest varchar(64),\n"\ +" ipTos integer,\n"\ +" ipProtocol integer,\n"\ +" ipSourcePort integer,\n"\ +" ipDestPort integer,\n"\ +" flags integer,\n"\ +" invFlags integer,\n"\ +" \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\ +");\n"\ +"\n"\ +"CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"\ +"" diff --git a/controller/schema2c.sh b/controller/schema2c.sh new file mode 100755 index 000000000..4f4f1647c --- /dev/null +++ b/controller/schema2c.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# Run this file to package the .sql file into a .c file whenever the SQL changes. + +rm -f schema.sql.c +echo '#define ZT_NETCONF_SCHEMA_SQL \' >schema.sql.c +cat schema.sql | sed 's/"/\\"/g' | sed 's/^/"/' | sed 's/$/\\n"\\/' >>schema.sql.c +echo '""' >>schema.sql.c diff --git a/cycle_controllers.sh b/cycle_controllers.sh deleted file mode 100755 index 34acacf4e..000000000 --- a/cycle_controllers.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -CONTROLLERS=`kubectl get pods -o=name | grep controller | sed "s/^.\{4\}//"` - -for c in ${CONTROLLERS[@]} -do - kubectl delete pod ${c} - sleep 30 -done diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index fdc85f860..000000000 --- a/debian/changelog +++ /dev/null @@ -1,318 +0,0 @@ -zerotier-one (1.14.2) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Wed, 23 Oct 2024 01:00:00 -0700 - -zerotier-one (1.14.1) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Wed, 11 Sep 2024 01:00:00 -0700 - -zerotier-one (1.14.0) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Tue, 19 Mar 2024 01:00:00 -0700 - -zerotier-one (1.12.2) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Tue, 12 Sep 2023 01:00:00 -0700 - -zerotier-one (1.12.1) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Fri, 25 Aug 2023 01:00:00 -0700 - -zerotier-one (1.12.0) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Thu, 17 Aug 2023 01:00:00 -0700 - -zerotier-one (1.10.6) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Tue, 21 Mar 2023 01:00:00 -0700 - -zerotier-one (1.10.5) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Fri, 10 Mar 2023 01:00:00 -0700 - -zerotier-one (1.10.4) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 06 Mar 2023 01:00:00 -0700 - -zerotier-one (1.10.3) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Sat, 21 Jan 2023 01:00:00 -0700 - -zerotier-one (1.10.2) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Thu, 13 Oct 2022 01:00:00 -0700 - -zerotier-one (1.10.1) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 27 Jun 2022 01:00:00 -0700 - -zerotier-one (1.10.0) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Fri, 03 Jun 2022 01:00:00 -0700 - -zerotier-one (1.8.10) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Tue, 10 May 2022 01:00:00 -0700 - -zerotier-one (1.8.9) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 25 Apr 2022 01:00:00 -0700 - -zerotier-one (1.8.8) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 11 Apr 2022 01:00:00 -0700 - -zerotier-one (1.8.7) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 21 Mar 2022 01:00:00 -0700 - -zerotier-one (1.8.6) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 07 Mar 2022 01:00:00 -0700 - -zerotier-one (1.8.5) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Fri, 17 Dec 2021 01:00:00 -0700 - -zerotier-one (1.8.4) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 23 Nov 2021 01:00:00 -0700 - -zerotier-one (1.8.3) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 15 Nov 2021 01:00:00 -0700 - -zerotier-one (1.8.2) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 08 Nov 2021 01:00:00 -0700 - -zerotier-one (1.8.1) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Wed, 20 Oct 2021 01:00:00 -0700 - -zerotier-one (1.8.0) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Wed, 15 Sep 2021 01:00:00 -0700 - -zerotier-one (1.6.6) unstable; urgency=medium - - * Backport endpoint mitigation against address collision attack. - - -- Adam Ierymenko Tue, 21 Sep 2021 01:00:00 -0700 - -zerotier-one (1.6.5) unstable; urgency=medium - - * Fix path filtering bug that could cause "software laser" effect. - * Fix printf overflow in CLI (not exploitable or security related) - * Fix Windows device enumeration issue. - - -- Adam Ierymenko Tue, 13 Apr 2021 01:00:00 -0700 - -zerotier-one (1.6.4) unstable; urgency=medium - - * REALLY fix a problem causing nodes to go into a "coma" with some network configurations. - - -- Adam Ierymenko Tue, 15 Feb 2021 01:00:00 -0700 - -zerotier-one (1.6.3-1) unstable; urgency=medium - - * Fix a problem causing nodes to go into a "coma" with some network configurations. - - -- Adam Ierymenko Tue, 02 Feb 2021 01:00:00 -0700 - -zerotier-one (1.6.2-2) unstable; urgency=medium - - * This is a minor update to the 1.6.2 package to address issues with - running on ARMv6 CPUs like the Raspberry Pi Zero and original v1 Pi. - - -- Adam Ierymenko Tue, 31 Nov 2020 01:00:00 -0700 - -zerotier-one (1.6.2) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 30 Nov 2020 01:00:00 -0700 - -zerotier-one (1.6.1) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Tue, 24 Nov 2020 01:00:00 -0700 - -zerotier-one (1.6.0) unstable; urgency=medium - - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Thu, 19 Nov 2020 01:00:00 -0700 - -zerotier-one (1.5.0) unstable; urgency=medium - - * Version 1.5.0 is actually 1.6.0-beta1 - * See RELEASE-NOTES.md for release notes. - - -- Adam Ierymenko Mon, 05 Aug 2020 01:00:00 -0700 - -zerotier-one (1.4.6) unstable; urgency=medium - - * Update default root server list - * Fix build flags on "armhf" (32-bit ARM) platforms for better - compatibility with Pi Zero and other devices. - * Fix license text in one.cpp. - * Add a clarification to LICENSE.txt. - - -- Adam Ierymenko Fri, 30 Aug 2019 01:00:00 -0700 - -zerotier-one (1.4.4) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - * License changed to BSL 1.1 - - -- Adam Ierymenko Fri, 23 Aug 2019 01:00:00 -0700 - -zerotier-one (1.4.2-2) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - * This is a new build that fixes a binary build issue with containers and SELinux - - -- Adam Ierymenko Thu, 04 Aug 2019 01:00:00 -0700 - -zerotier-one (1.4.2) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Thu, 04 Aug 2019 01:00:00 -0700 - -zerotier-one (1.4.0) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Thu, 29 Jul 2019 01:00:00 -0700 - -zerotier-one (1.2.12) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Tue, 25 Jul 2018 01:00:00 -0700 - -zerotier-one (1.2.10) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Tue, 08 May 2018 01:00:00 -0700 - -zerotier-one (1.2.8) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Tue, 27 Apr 2018 01:00:00 -0700 - -zerotier-one (1.2.6) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Tue, 17 Apr 2018 01:00:00 -0700 - -zerotier-one (1.2.4) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Mon, 24 Mar 2017 01:00:00 -0700 - -zerotier-one (1.2.2) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Fri, 17 Mar 2017 01:00:00 -0700 - -zerotier-one (1.2.0) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Tue, 14 Mar 2017 09:08:00 -0700 - -zerotier-one (1.1.14) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Tue, 21 Jul 2016 07:14:12 -0700 - -zerotier-one (1.1.12) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Tue, 12 Jul 2016 03:02:22 -0700 - -zerotier-one (1.1.10) unstable; urgency=medium - - * See https://github.com/zerotier/ZeroTierOne for release notes. - * ZeroTier Debian packages no longer depend on http-parser since its ABI is too unstable. - - -- Adam Ierymenko Tue, 12 Jul 2016 12:29:00 -0700 - -zerotier-one (1.1.8) unstable; urgency=low - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Fri, 08 Jul 2016 01:56:00 -0700 - -zerotier-one (1.1.6) unstable; urgency=medium - - * First Debian release on ZeroTier, Inc. private apt repository. - - * See https://github.com/zerotier/ZeroTierOne for release notes. - - -- Adam Ierymenko Fri, 24 Jun 2016 10:00:00 -0700 - -zerotier-one (1.1.5) UNRELEASED; urgency=medium - - * Development package -- first clean Debian packaging test. - - -- Adam Ierymenko Wed, 08 Jun 2016 10:05:01 -0700 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 9a037142a..000000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -10 \ No newline at end of file diff --git a/debian/control b/debian/control deleted file mode 100644 index b0c178ab1..000000000 --- a/debian/control +++ /dev/null @@ -1,19 +0,0 @@ -Source: zerotier-one -Maintainer: Adam Ierymenko -Section: net -Priority: optional -Standards-Version: 3.9.6 -Build-Depends: debhelper -Vcs-Git: git://github.com/zerotier/ZeroTierOne -Vcs-Browser: https://github.com/zerotier/ZeroTierOne -Homepage: https://www.zerotier.com/ - -Package: zerotier-one -Architecture: any -Depends: adduser, libstdc++6 (>= 5), openssl -Homepage: https://www.zerotier.com/ -Description: ZeroTier network virtualization service - ZeroTier One lets you join ZeroTier virtual networks and - have them appear as tun/tap ports on your system. See - https://www.zerotier.com/ for instructions and - documentation. diff --git a/debian/control.wheezy b/debian/control.wheezy deleted file mode 100644 index fbbc40d93..000000000 --- a/debian/control.wheezy +++ /dev/null @@ -1,19 +0,0 @@ -Source: zerotier-one -Maintainer: Adam Ierymenko -Section: net -Priority: optional -Standards-Version: 3.9.4 -Build-Depends: debhelper -Vcs-Git: git://github.com/zerotier/ZeroTierOne -Vcs-Browser: https://github.com/zerotier/ZeroTierOne -Homepage: https://www.zerotier.com/ - -Package: zerotier-one -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libstdc++6 -Homepage: https://www.zerotier.com/ -Description: ZeroTier network virtualization service - ZeroTier One lets you join ZeroTier virtual networks and - have them appear as tun/tap ports on your system. See - https://www.zerotier.com/ for instructions and - documentation. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index da3678d52..000000000 --- a/debian/copyright +++ /dev/null @@ -1,18 +0,0 @@ -Format: http://dep.debian.net/deps/dep5 -Upstream-Name: zerotier-one -Source: https://github.com/zerotier/ZeroTierOne - -Files: * -Copyright: 2011-2016 ZeroTier, Inc. -License: ZeroTier BSL 1.1 - -License: ZeroTier BSL 1.1 - Copyright (c)2019 ZeroTier, Inc. - - Use of this software is governed by the Business Source License included - in the LICENSE.TXT file in the project's root directory. - - Change Date: 2026-01-01 - - On the date above, in accordance with the Business Source License, use - of this software will be governed by version 2.0 of the Apache License. diff --git a/debian/postinst b/debian/postinst deleted file mode 100644 index b6e7471c4..000000000 --- a/debian/postinst +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -e - -case "$1" in - configure) - if ! id zerotier-one >>/dev/null 2>&1; then - useradd --system --user-group --home-dir /var/lib/zerotier-one --shell /usr/sbin/nologin --no-create-home zerotier-one - fi - ;; -esac - -#DEBHELPER# diff --git a/debian/rules b/debian/rules deleted file mode 100644 index 81fde680b..000000000 --- a/debian/rules +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/make -f - -CFLAGS=-O3 -fstack-protector-strong -CXXFLAGS=-O3 -fstack-protector-strong - -%: - dh $@ --with systemd - -override_dh_auto_build: - make - -override_dh_systemd_start: - dh_systemd_start --restart-after-upgrade - -override_dh_installinit: - dh_installinit --name=zerotier-one -- defaults diff --git a/debian/rules.static b/debian/rules.static deleted file mode 100644 index 72c529552..000000000 --- a/debian/rules.static +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/make -f - -CFLAGS=-O3 -fstack-protector-strong -CXXFLAGS=-O3 -fstack-protector-strong - -%: - dh $@ --with systemd - -override_dh_auto_build: -# make -j 2 - -override_dh_systemd_start: - dh_systemd_start --restart-after-upgrade - -override_dh_installinit: - dh_installinit --name=zerotier-one -- defaults diff --git a/debian/rules.wheezy b/debian/rules.wheezy deleted file mode 100644 index 55e2647a2..000000000 --- a/debian/rules.wheezy +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/make -f - -CFLAGS=-O3 -fstack-protector -CXXFLAGS=-O3 -fstack-protector - -%: - dh $@ - -override_dh_auto_build: - make -j 2 - diff --git a/debian/rules.wheezy.static b/debian/rules.wheezy.static deleted file mode 100644 index 0165be37e..000000000 --- a/debian/rules.wheezy.static +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/make -f - -CFLAGS=-O3 -fstack-protector -CXXFLAGS=-O3 -fstack-protector - -%: - dh $@ - -override_dh_auto_build: -# make -j 2 - diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 46ebe0266..000000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) \ No newline at end of file diff --git a/debian/ufw-zerotier-one b/debian/ufw-zerotier-one deleted file mode 100644 index 7c2908941..000000000 --- a/debian/ufw-zerotier-one +++ /dev/null @@ -1,4 +0,0 @@ -[zerotier-one] -title=ZeroTier One -description=A planetary Ethernet switch -ports=9993/udp diff --git a/debian/zerotier-one.init b/debian/zerotier-one.init deleted file mode 100644 index 41a22a50d..000000000 --- a/debian/zerotier-one.init +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: zerotier-one -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: -# Short-Description: ZeroTier One network virtualization service -### END INIT INFO - -PATH=/bin:/usr/bin:/sbin:/usr/sbin -DESC="zerotier-one daemon" -NAME=zerotier-one -DAEMON=/usr/sbin/zerotier-one -PIDFILE=/var/lib/zerotier-one/zerotier-one.pid -SCRIPTNAME=/etc/init.d/"$NAME" -EXTRA_OPTS=-d - -test -f $DAEMON || exit 0 - -. /lib/lsb/init-functions - -case "$1" in -start) log_daemon_msg "Starting ZeroTier One" "zerotier-one" - start_daemon -p $PIDFILE $DAEMON $EXTRA_OPTS - log_end_msg $? - ;; -stop) log_daemon_msg "Stopping ZeroTier One" "zerotier-one" - killproc -p $PIDFILE $DAEMON - RETVAL=$? - [ $RETVAL -eq 0 ] && [ -e "$PIDFILE" ] && rm -f $PIDFILE - log_end_msg $RETVAL - ;; -restart) log_daemon_msg "Restarting ZeroTier One" "zerotier-one" - $0 stop - $0 start - ;; -reload|force-reload) log_daemon_msg "Reloading ZeroTier One" "zerotier-one" - log_end_msg 0 - ;; -status) - status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $? - ;; -*) log_action_msg "Usage: /etc/init.d/cron {start|stop|status|restart|reload|force-reload}" - exit 2 - ;; -esac -exit 0 diff --git a/debian/zerotier-one.service b/debian/zerotier-one.service deleted file mode 100644 index 9d6a21b0a..000000000 --- a/debian/zerotier-one.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=ZeroTier One -After=network-online.target network.target -Wants=network-online.target - -[Service] -ExecStart=/usr/sbin/zerotier-one -Restart=always -KillMode=process - -[Install] -WantedBy=multi-user.target diff --git a/debian/zerotier-one.upstart b/debian/zerotier-one.upstart deleted file mode 100644 index 7753580a8..000000000 --- a/debian/zerotier-one.upstart +++ /dev/null @@ -1,14 +0,0 @@ -description "ZeroTier One upstart startup script" - -author "Adam Ierymenko " - -start on (local-filesystems and net-device-up IFACE!=lo) -stop on runlevel [!2345] - -respawn -respawn limit 2 300 - -#pre-start script -#end script - -exec /usr/sbin/zerotier-one diff --git a/doc/README.md b/doc/README.md deleted file mode 100644 index 681954cc5..000000000 --- a/doc/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Manual Pages and Other Documentation -===== - -Use "./build.sh" to build the manual pages. - -You'll need either Node.js/npm installed (script will then automatically install the npm *marked-man* package) or */usr/bin/ronn*. The latter is a Ruby program packaged on some distributions as *rubygem-ronn* or *ruby-ronn* or installable as *gem install ronn*. The Node *marked-man* package and *ronn* from RubyGems are two roughly equivalent alternatives for compiling Markdown into roff/man format. diff --git a/doc/build.sh b/doc/build.sh deleted file mode 100755 index 9df72a333..000000000 --- a/doc/build.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin - -if [ ! -f zerotier-cli.1.md ]; then - echo 'This script must be run from the doc/ subfolder of the ZeroTier tree.' -fi - -rm -f *.1 *.2 *.8 - -if [ -e /usr/bin/ronn -o -e /usr/local/bin/ronn ]; then - # Use 'ronn' which is available as a package on many distros including Debian - ronn -r zerotier-cli.1.md - ronn -r zerotier-idtool.1.md - ronn -r zerotier-one.8.md -else - # Use 'marked-man' from npm - NODE=/usr/bin/node - if [ ! -e $NODE ]; then - if [ -e /usr/bin/nodejs ]; then - NODE=/usr/bin/nodejs - elif [ -e /usr/local/bin/node ]; then - NODE=/usr/local/bin/node - elif [ -e /usr/local/bin/nodejs ]; then - NODE=/usr/local/bin/nodejs - else - echo 'Unable to find ronn or node/npm -- cannot build man pages!' - exit 1 - fi - fi - - if [ ! -f node_modules/marked-man/bin/marked-man ]; then - echo 'Installing npm package "marked-man" -- MarkDown to ROFF converter...' - npm install marked-man - fi - - $NODE node_modules/marked-man/bin/marked-man zerotier-cli.1.md >zerotier-cli.1 - $NODE node_modules/marked-man/bin/marked-man zerotier-idtool.1.md >zerotier-idtool.1 - $NODE node_modules/marked-man/bin/marked-man zerotier-one.8.md >zerotier-one.8 -fi - -exit 0 diff --git a/doc/contact@zerotier.com.gpg b/doc/contact@zerotier.com.gpg deleted file mode 100644 index dc7d6455c..000000000 --- a/doc/contact@zerotier.com.gpg +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Comment: GPGTools - https://gpgtools.org - -mQINBFdQq7oBEADEVhyRiaL8dEjMPlI/idO8tA7adjhfvejxrJ3Axxi9YIuIKhWU -5hNjDjZAiV9iSCMfJN3TjC3EDA+7nFyU6nDKeAMkXPbaPk7ti+Tb1nA4TJsBfBlm -CC14aGWLItpp8sI00FUzorxLWRmU4kOkrRUJCq2kAMzbYWmHs0hHkWmvj8gGu6mJ -WU3sDIjvdsm3hlgtqr9grPEnj+gA7xetGs3oIfp6YDKymGAV49HZmVAvSeoqfL1p -pEKlNQ1aO9uNfHLdx6+4pS1miyo7D1s7ru2IcqhTDhg40cHTL/VldC3d8vXRFLIi -Uo2tFZ6J1jyQP5c1K4rTpw3UNVne3ob7uCME+T1+ePeuM5Y/cpcCvAhJhO0rrlr0 -dP3lOKrVdZg4qhtFAspC85ivcuxWNWnfTOBrgnvxCA1fmBX+MLNUEDsuu55LBNQT -5+WyrSchSlsczq+9EdomILhixUflDCShHs+Efvh7li6Pg56fwjEfj9DJYFhRvEvQ -7GZ7xtysFzx4AYD4/g5kCDsMTbc9W4Jv+JrMt3JsXt2zqwI0P4R1cIAu0J6OZ4Xa -dJ7Ci1WisQuJRcCUtBTUxcYAClNGeors5Nhl4zDrNIM7zIJp+GfPYdWKVSuW10mC -r3OS9QctMSeVPX/KE85TexeRtmyd4zUdio49+WKgoBhM8Z9MpTaafn2OPQARAQAB -tFBaZXJvVGllciwgSW5jLiAoWmVyb1RpZXIgU3VwcG9ydCBhbmQgUmVsZWFzZSBT -aWduaW5nIEtleSkgPGNvbnRhY3RAemVyb3RpZXIuY29tPokCNwQTAQoAIQUCV1Cr -ugIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRAWVxmII+UqYViGEACnC3+3 -lRzfv7f7JLWo23FSHjlF3IiWfYd+47BLDx706SDih1H6Qt8CqRy706bWbtictEJ/ -xTaWgTEDzY/lRalYO5NAFTgK9h2zBP1t8zdEA/rmtVPOWOzd6jr0q3l3pKQTeMF0 -6g+uaMDG1OkBz6MCwdg9counz6oa8OHK76tXNIBEnGOPBW375z1O+ExyddQOHDcS -IIsUlFmtIL1yBa7Q5NSfLofPLfS0/o2FItn0riSaAh866nXHynQemjTrqkUxf5On -65RLM+AJQaEkX17vDlsSljHrtYLKrhEueqeq50e89c2Ya4ucmSVeC9lrSqfyvGOO -P3aT/hrmeE9XBf7a9vozq7XhtViEC/ZSd1/z/oeypv4QYenfw8CtXP5bW1mKNK/M -8xnrnYwo9BUMclX2ZAvu1rTyiUvGre9fEGfhlS0rjmCgYfMgBZ+R/bFGiNdn6gAd -PSY/8fP8KFZl0xUzh2EnWe/bptoZ67CKkDbVZnfWtuKA0Ui7anitkjZiv+6wanv4 -+5A3k/H3D4JofIjRNgx/gdVPhJfWjAoutIgGeIWrkfcAP9EpsR5swyc4KuE6kJ/Y -wXXVDQiju0xE1EdNx/S1UOeq0EHhOFqazuu00ojATekUPWenNjPWIjBYQ0Ag4ycL -KU558PFLzqYaHphdWYgxfGR+XSgzVTN1r7lW87kCDQRXUKu6ARAA2wWOywNMzEiP -ZK6CqLYGZqrpfx+drOxSowwfwjP3odcK8shR/3sxOmYVqZi0XVZtb9aJVz578rNb -e4Vfugql1Yt6w3V84z/mtfj6ZbTOOU5yAGZQixm6fkXAnpG5Eer/C8Aw8dH1EreP -Na1gIVcUzlpg2Ql23qjr5LqvGtUB4BqJSF4X8efNi/y0hj/GaivUMqCF6+Vvh3GG -fhvzhgBPku/5wK2XwBL9BELqaQ/tWOXuztMw0xFH/De75IH3LIvQYCuv1pnM4hJL -XYnpAGAWfmFtmXNnPVon6g542Z6c0G/qi657xA5vr6OSSbazDJXNiHXhgBYEzRrH -napcohTQwFKEA3Q4iftrsTDX/eZVTrO9x6qKxwoBVTGwSE52InWAxkkcnZM6tkfV -n7Ukc0oixZ6E70Svls27zFgaWbUFJQ6JFoC6h+5AYbaga6DwKCYOP3AR+q0ZkcH/ -oJIdvKuhF9zDZbQhd76b4gK3YXnMpVsj9sQ9P23gh61RkAQ1HIlGOBrHS/XYcvpk -DcfIlJXKC3V1ggrG+BpKu46kiiYmRR1/yM0EXH2n99XhLNSxxFxxWhjyw8RcR6iG -ovDxWAULW+bJHjaNJdgb8Kab7j2nT2odUjUHMP42uLJgvS5LgRn39IvtzjoScAqg -8I817m8yLU/91D2f5qmJIwFI6ELwImkAEQEAAYkCHwQYAQoACQUCV1CrugIbDAAK -CRAWVxmII+UqYWSSEACxaR/hhr8xUIXkIV52BeD+2BOS8FNOi0aM67L4fEVplrsV -Op9fvAnUNmoiQo+RFdUdaD2Rpq+yUjQHHbj92mlk6Cmaon46wU+5bAWGYpV1Uf+o -wbKw1Xv83Uj9uHo7zv9WDtOUXUiTe/S792icTfRYrKbwkfI8iCltgNhTQNX0lFX/ -Sr2y1/dGCTCMEuA/ClqGKCm9lIYdu+4z32V9VXTSX85DsUjLOCO/hl9SHaelJgmi -IJzRY1XLbNDK4IH5eWtbaprkTNIGt00QhsnM5w+rn1tO80giSxXFpKBE+/pAx8PQ -RdVFzxHtTUGMCkZcgOJolk8y+DJWtX8fP+3a4Vq11a3qKJ19VXk3qnuC1aeW7OQF -j6ISyHsNNsnBw5BRaS5tdrpLXw6Z7TKr1eq+FylmoOK0pIw5xOdRmSVoFm4lVcI5 -e5EwB7IIRF00IFqrXe8dCT0oDT9RXc6CNh6GIs9D9YKwDPRD/NKQlYoegfa13Jz7 -S3RIXtOXudT1+A1kaBpGKnpXOYD3w7jW2l0zAd6a53AAGy4SnL1ac4cml76NIWiF -m2KYzvMJZBk5dAtFa0SgLK4fg8X6Ygoo9E0JsXxSrW9I1JVfo6Ia//YOBMtt4XuN -Awqahjkq87yxOYYTnJmr2OZtQuFboymfMhNqj3G2DYmZ/ZIXXPgwHx0fnd3R0Q== -=JgAv ------END PGP PUBLIC KEY BLOCK----- diff --git a/doc/module.mk b/doc/module.mk new file mode 100644 index 000000000..34fdbaebf --- /dev/null +++ b/doc/module.mk @@ -0,0 +1,52 @@ +# doc/module.mk +# Part of ZeroTier One, a software-defined network layer. +# +# Copyright © 2016 Ben Finney +# This is free software: you may copy, modify, and/or distribute this +# work under the terms of the GNU General Public License, version 3 or +# later as published by the Free Software Foundation. +# No warranty expressed or implied. +# See the file ‘LICENSE.txt’ for details. + +# Makefile module for ZeroTier One documentation. + +TEMPFILE_SUFFIX = .tmp +.INTERMEDIATE: ${DOCUMENTATION_DIR}/*${TEMPFILE_SUFFIX} + +RST_SUFFIX = .txt +manpage_sections = 1 2 3 4 5 6 7 8 +manpage_names += zerotier-one.8 +manpage_names += zerotier-idtool.1 +manpage_names += zerotier-cli.1 +manpage_source_paths = $(addprefix ${DOC_DIR}/, \ + $(addsuffix ${RST_SUFFIX},${manpage_names})) +manpage_paths = $(addprefix ${DOC_DIR}/,${manpage_names}) +manpage_encoding_stub = ${DOC_DIR}/manpage_encoding_declaration.UTF-8 + +GENERATED_FILES += $(addprefix ${DOC_DIR}/,\ + $(foreach section,${manpage_sections},*.${section})) + +RST2MAN = rst2man +RST2MAN_OPTS = + + +.PHONY: doc +doc: manpages + +.PHONY: manpages +manpages: ${manpage_paths} + +%.1: %.1${RST_SUFFIX} + $(RST2MAN) "$<" > "$@"${TEMPFILE_SUFFIX} + cat ${manpage_encoding_stub} "$@"${TEMPFILE_SUFFIX} > "$@" + +%.8: %.8${RST_SUFFIX} + $(RST2MAN) "$<" > "$@"${TEMPFILE_SUFFIX} + cat ${manpage_encoding_stub} "$@"${TEMPFILE_SUFFIX} > "$@" + + +# Local variables: +# coding: utf-8 +# mode: makefile +# End: +# vim: fileencoding=utf-8 filetype=make : diff --git a/doc/zerotier-cli.1 b/doc/zerotier-cli.1 deleted file mode 100644 index 167109ec9..000000000 --- a/doc/zerotier-cli.1 +++ /dev/null @@ -1,83 +0,0 @@ -.TH "ZEROTIER\-CLI" "1" "December 2016" "" "" -.SH "NAME" -\fBzerotier-cli\fR \- control local ZeroTier virtual network service -.SH SYNOPSIS -.P -\fBzerotier\-cli\fP [\-switches] [arguments] -.SH DESCRIPTION -.P -\fBzerotier\-cli\fR provides a simple command line interface to the local JSON API of the ZeroTier virtual network endpoint service zerotier\-one(8)\. -.P -By default \fBzerotier\-cli\fR must be run as root or with \fBsudo\fP\|\. If you want to allow an unprivileged user to use \fBzerotier\-cli\fR to control the system ZeroTier service, you can create a local copy of the ZeroTier service authorization token in the user's home directory: -.P -.RS 2 -.nf -sudo cp /var/lib/zerotier\-one/authtoken\.secret /home/user/\.zeroTierOneAuthToken -chown user /home/user/\.zeroTierOneAuthToken -chmod 0600 /home/user/\.zeroTierOneAuthToken -.fi -.RE -.P -(The location of ZeroTier's service home may differ by platform\. See zerotier\-one(8)\.) -.P -Note that this gives the user the power to connect or disconnect the system to or from any virtual network, which is a significant permission\. -.P -\fBzerotier\-cli\fR has several command line arguments that are visible in \fBhelp\fP output\. The two most commonly used are \fB\-j\fP for raw JSON output and \fB\-D\fP to specify an alternative ZeroTier service working directory\. Raw JSON output is easier to parse in scripts and also contains verbose details not present in the tabular output\. The \fB\-D\fP option specifies where the service's zerotier\-one\.port and authtoken\.secret files are located if the service is not running at the default location for your system\. -.SH COMMANDS -.RS 0 -.IP \(bu 2 -\fBhelp\fP: -Displays \fBzerotier\-cli\fR help\. -.IP \(bu 2 -\fBinfo\fP: -Shows information about this device including its 10\-digit ZeroTier address and apparent connection status\. Use \fB\-j\fP for more verbose output\. -.IP \(bu 2 -\fBlistpeers\fP: -This command lists the ZeroTier VL1 (virtual layer 1, the peer to peer network) peers this service knows about and has recently (within the past 30 minutes or so) communicated with\. These are not necessarily all the devices on your virtual network(s), and may also include a few devices not on any virtual network you've joined\. These are typically either root servers or network controllers\. -.IP \(bu 2 -\fBlistnetworks\fP: -This lists the networks your system belongs to and some information about them, such as any ZeroTier\-managed IP addresses you have been assigned\. (IP addresses assigned manually to ZeroTier interfaces will not be listed here\. Use the standard network interface commands to see these\.) -.IP \(bu 2 -\fBjoin\fP: -To join a network just use \fBjoin\fP and its 16\-digit hex network ID\. That's it\. Then use \fBlistnetworks\fP to see the status\. You'll either get a reply from the network controller with a certificate and other info such as IP assignments, or you'll get "access denied\." In this case you'll need the administrator of this network to authorize your device by its 10\-digit device ID (visible with \fBinfo\fP) on the network's controller\. -.IP \(bu 2 -\fBleave\fP: -Leaving a network is as easy as joining it\. This disconnects from the network and deletes its interface from the system\. Note that peers on the network may hang around in \fBlistpeers\fP for up to 30 minutes until they time out due to lack of traffic\. But if they no longer share a network with you, they can't actually communicate with you in any meaningful way\. - -.RE -.SH EXAMPLES -.P -Join "Earth," ZeroTier's big public party line network: -.P -.RS 2 -.nf -$ sudo zerotier\-cli join 8056c2e21c000001 -$ sudo zerotier\-cli listnetworks -( wait until you get an Earth IP ) -$ ping earth\.zerotier\.net -( you should now be able to ping our Earth test IP ) -.fi -.RE -.P -Leave "Earth": -.P -.RS 2 -.nf -$ sudo zerotier\-cli leave 8056c2e21c000001 -.fi -.RE -.P -List VL1 peers: -.P -.RS 2 -.nf -$ sudo zerotier\-cli listpeers -.fi -.RE -.SH COPYRIGHT -.P -(c)2011\-2016 ZeroTier, Inc\. \-\- https://www\.zerotier\.com/ \-\- https://github\.com/zerotier -.SH SEE ALSO -.P -zerotier\-one(8), zerotier\-idtool(1) - diff --git a/doc/zerotier-cli.1.md b/doc/zerotier-cli.1.md deleted file mode 100644 index 6252d452f..000000000 --- a/doc/zerotier-cli.1.md +++ /dev/null @@ -1,68 +0,0 @@ -zerotier-cli(1) -- control local ZeroTier virtual network service -================================================================= - -## SYNOPSIS - -`zerotier-cli` [-switches] [arguments] - -## DESCRIPTION - -**zerotier-cli** provides a simple command line interface to the local JSON API of the ZeroTier virtual network endpoint service zerotier-one(8). - -By default **zerotier-cli** must be run as root or with `sudo`. If you want to allow an unprivileged user to use **zerotier-cli** to control the system ZeroTier service, you can create a local copy of the ZeroTier service authorization token in the user's home directory: - - sudo cp /var/lib/zerotier-one/authtoken.secret /home/user/.zeroTierOneAuthToken - chown user /home/user/.zeroTierOneAuthToken - chmod 0600 /home/user/.zeroTierOneAuthToken - -(The location of ZeroTier's service home may differ by platform. See zerotier-one(8).) - -Note that this gives the user the power to connect or disconnect the system to or from any virtual network, which is a significant permission. - -**zerotier-cli** has several command line arguments that are visible in `help` output. The two most commonly used are `-j` for raw JSON output and `-D` to specify an alternative ZeroTier service working directory. Raw JSON output is easier to parse in scripts and also contains verbose details not present in the tabular output. The `-D` option specifies where the service's zerotier-one.port and authtoken.secret files are located if the service is not running at the default location for your system. - -## COMMANDS - - * `help`: - Displays **zerotier-cli** help. - - * `info`: - Shows information about this device including its 10-digit ZeroTier address and apparent connection status. Use `-j` for more verbose output. - - * `listpeers`: - This command lists the ZeroTier VL1 (virtual layer 1, the peer to peer network) peers this service knows about and has recently (within the past 30 minutes or so) communicated with. These are not necessarily all the devices on your virtual network(s), and may also include a few devices not on any virtual network you've joined. These are typically either root servers or network controllers. - - * `listnetworks`: - This lists the networks your system belongs to and some information about them, such as any ZeroTier-managed IP addresses you have been assigned. (IP addresses assigned manually to ZeroTier interfaces will not be listed here. Use the standard network interface commands to see these.) - - * `join`: - To join a network just use `join` and its 16-digit hex network ID. That's it. Then use `listnetworks` to see the status. You'll either get a reply from the network controller with a certificate and other info such as IP assignments, or you'll get "access denied." In this case you'll need the administrator of this network to authorize your device by its 10-digit device ID (visible with `info`) on the network's controller. - - * `leave`: - Leaving a network is as easy as joining it. This disconnects from the network and deletes its interface from the system. Note that peers on the network may hang around in `listpeers` for up to 30 minutes until they time out due to lack of traffic. But if they no longer share a network with you, they can't actually communicate with you in any meaningful way. - -## EXAMPLES - -Join "Earth," ZeroTier's big public party line network: - - $ sudo zerotier-cli join 8056c2e21c000001 - $ sudo zerotier-cli listnetworks - ( wait until you get an Earth IP ) - $ ping earth.zerotier.net - ( you should now be able to ping our Earth test IP ) - -Leave "Earth": - - $ sudo zerotier-cli leave 8056c2e21c000001 - -List VL1 peers: - - $ sudo zerotier-cli listpeers - -## COPYRIGHT - -(c)2011-2016 ZeroTier, Inc. -- https://www.zerotier.com/ -- https://github.com/zerotier - -## SEE ALSO - -zerotier-one(8), zerotier-idtool(1) diff --git a/doc/zerotier-cli.1.txt b/doc/zerotier-cli.1.txt new file mode 100644 index 000000000..ae8a4af77 --- /dev/null +++ b/doc/zerotier-cli.1.txt @@ -0,0 +1,109 @@ +============ +zerotier-cli +============ + +-------------------------------------------------- +management interface for ZeroTier One peer process +-------------------------------------------------- + +:Author: |author| +:Date: 2016-03-04 +:Copyright: + Copyright © 2016 ZeroTier Inc. +:Manual section: 1 +:Manual group: ZeroTier + +.. |command| replace:: **zerotier-cli** +.. |license| replace:: + `GNU General Public License, version 3 or later + `__ + + +SYNOPSIS +======== + +| |command| [ **-j** ] [ **-D** `HOMEDIR` ] [ **-p** `PORT` ] [ **-t** `AUTH_TOKEN` ] \ + `command` [ `COMMAND_ARG` ] + + +DESCRIPTION +=========== + +|command| is a tool to manage the running **zerotier-one**\ (8) +process. + +*ZeroTier* is a peer-to-peer virtual network. Its “virtual layer 1” +(VL1) is implemented in the communication between ZeroTier One peers. +This provides the OSI layer 1 functionality on which to build further +network services. + + +COMMANDS +======== + +|command| **info** + + *FIXME*: display status info + +|command| **listpeers** + + *FIXME*: list all peers + +|command| **listnetworks** + + *FIXME*: list all networks + +|command| **join** `NETWORK` + + *FIXME*: join the network `NETWORK` + +|command| **leave** `NETWORK` + + *FIXME*: leave the network `NETWORK` + + +FILES +===== + +The |command| process will discover the running **zerotier-one**\ (8) +process by examining the specified `HOMEDIR` directory (default: +``/var/lib/zerotier-one``). + + +SEE ALSO +======== + +* **zerotier-one**\ (8) + +* ZeroTier One documentation: + + * Product page ``__. + * Configuration guide ``__. + * Technical FAQ ``__. + + +HISTORY +======= + +The |command| program is developed by ZeroTier Inc. + +This manual page was written by |author|. This is free software: you +may copy, modify and/or distribute this work under the terms of the +|license| as published by the Free Software Foundation. No warranty +expressed or implied. + +.. |author| replace:: |authorname| |authoremail| +.. |authorname| replace:: Ben Finney +.. |authoremail| replace:: + + +.. + Local variables: + mode: rst + coding: utf-8 + time-stamp-format: "%:y-%02m-%02d" + time-stamp-start: "^:Date:[ ]+" + time-stamp-end: "$" + time-stamp-line-limit: 20 + End: + vim: filetype=rst fileencoding=utf-8 : diff --git a/doc/zerotier-idtool.1 b/doc/zerotier-idtool.1 deleted file mode 100644 index fbc367a6a..000000000 --- a/doc/zerotier-idtool.1 +++ /dev/null @@ -1,84 +0,0 @@ -.TH "ZEROTIER\-IDTOOL" "1" "December 2016" "" "" -.SH "NAME" -\fBzerotier-idtool\fR \- tool for creating and manipulating ZeroTier identities -.SH SYNOPSIS -.P -\fBzerotier\-idtool\fP [args] -.SH DESCRIPTION -.P -\fBzerotier\-idtool\fR is a command line utility for doing things with ZeroTier identities\. A ZeroTier identity consists of a public/private key pair (or just the public if it's only an identity\.public) and a 10\-digit hexadecimal ZeroTier address derived from the public key by way of a proof of work based hash function\. -.SH COMMANDS -.P -When command arguments call for a public or secret (full) identity, the identity can be specified as a path to a file or directly on the command line\. -.RS 0 -.IP \(bu 2 -\fBhelp\fP: -Display help\. (Also running with no command does this\.) -.IP \(bu 2 -\fBgenerate\fP [secret file] [public file] [vanity]: -Generate a new ZeroTier identity\. If a secret file is specified, the full identity including the private key will be written to this file\. If the public file is specified, the public portion will be written there\. If no file paths are specified the full secret identity is output to STDOUT\. The vanity prefix is a series of hexadecimal digits that the generated identity's address should start with\. Typically this isn't used, and if it's specified generation can take a very long time due to the intrinsic cost of generating identities with their proof of work function\. Generating an identity with a known 16\-bit (4 digit) prefix on a 2\.8ghz Core i5 (using one core) takes an average of two hours\. -.IP \(bu 2 -\fBvalidate\fP : -Locally validate an identity's key and proof of work function correspondence\. -.IP \(bu 2 -\fBgetpublic\fP : -Extract the public portion of an identity\.secret and print to STDOUT\. -.IP \(bu 2 -\fBsign\fP : -Sign a file's contents with SHA512+ECC\-256 (ed25519)\. The signature is output in hex to STDOUT\. -.IP \(bu 2 -\fBverify\fP : -Verify a signature created with \fBsign\fP\|\. -.IP \(bu 2 -\fBmkcom\fP [id,value,maxdelta] [\|\.\.\.]: -Create and sign a network membership certificate\. This is not generally useful since network controllers do this automatically and is included mostly for testing purposes\. - -.RE -.SH EXAMPLES -.P -Generate and dump a new identity: -.P -.RS 2 -.nf -$ zerotier\-idtool generate -.fi -.RE -.P -Generate and write a new identity, both secret and public parts: -.P -.RS 2 -.nf -$ zerotier\-idtool generate identity\.secret identity\.public -.fi -.RE -.P -Generate a vanity address that begins with the hex digits "beef" (this will take a while!): -.P -.RS 2 -.nf -$ zerotier\-idtool generate beef\.secret beef\.public beef -.fi -.RE -.P -Sign a file with an identity's secret key: -.P -.RS 2 -.nf -$ zerotier\-idtool sign identity\.secret last_will_and_testament\.txt -.fi -.RE -.P -Verify a file's signature with a public key: -.P -.RS 2 -.nf -$ zerotier\-idtool verify identity\.public last_will_and_testament\.txt -.fi -.RE -.SH COPYRIGHT -.P -(c)2011\-2016 ZeroTier, Inc\. \-\- https://www\.zerotier\.com/ \-\- https://github\.com/zerotier -.SH SEE ALSO -.P -zerotier\-one(8), zerotier\-cli(1) - diff --git a/doc/zerotier-idtool.1.md b/doc/zerotier-idtool.1.md deleted file mode 100644 index 52a586c11..000000000 --- a/doc/zerotier-idtool.1.md +++ /dev/null @@ -1,65 +0,0 @@ -zerotier-idtool(1) -- tool for creating and manipulating ZeroTier identities -============================================================================ - -## SYNOPSIS - -`zerotier-idtool` [args] - -## DESCRIPTION - -**zerotier-idtool** is a command line utility for doing things with ZeroTier identities. A ZeroTier identity consists of a public/private key pair (or just the public if it's only an identity.public) and a 10-digit hexadecimal ZeroTier address derived from the public key by way of a proof of work based hash function. - -## COMMANDS - -When command arguments call for a public or secret (full) identity, the identity can be specified as a path to a file or directly on the command line. - - * `help`: - Display help. (Also running with no command does this.) - - * `generate` [secret file] [public file] [vanity]: - Generate a new ZeroTier identity. If a secret file is specified, the full identity including the private key will be written to this file. If the public file is specified, the public portion will be written there. If no file paths are specified the full secret identity is output to STDOUT. The vanity prefix is a series of hexadecimal digits that the generated identity's address should start with. Typically this isn't used, and if it's specified generation can take a very long time due to the intrinsic cost of generating identities with their proof of work function. Generating an identity with a known 16-bit (4 digit) prefix on a 2.8ghz Core i5 (using one core) takes an average of two hours. - - * `validate` : - Locally validate an identity's key and proof of work function correspondence. - - * `getpublic` : - Extract the public portion of an identity.secret and print to STDOUT. - - * `sign` : - Sign a file's contents with SHA512+ECC-256 (ed25519). The signature is output in hex to STDOUT. - - * `verify` : - Verify a signature created with `sign`. - - * `mkcom` [id,value,maxdelta] [...]: - Create and sign a network membership certificate. This is not generally useful since network controllers do this automatically and is included mostly for testing purposes. - -## EXAMPLES - -Generate and dump a new identity: - - $ zerotier-idtool generate - -Generate and write a new identity, both secret and public parts: - - $ zerotier-idtool generate identity.secret identity.public - -Generate a vanity address that begins with the hex digits "beef" (this will take a while!): - - $ zerotier-idtool generate beef.secret beef.public beef - -Sign a file with an identity's secret key: - - $ zerotier-idtool sign identity.secret last_will_and_testament.txt - -Verify a file's signature with a public key: - - $ zerotier-idtool verify identity.public last_will_and_testament.txt - -## COPYRIGHT - -(c)2011-2016 ZeroTier, Inc. -- https://www.zerotier.com/ -- https://github.com/zerotier - -## SEE ALSO - -zerotier-one(8), zerotier-cli(1) diff --git a/doc/zerotier-idtool.1.txt b/doc/zerotier-idtool.1.txt new file mode 100644 index 000000000..2ff0e4c1c --- /dev/null +++ b/doc/zerotier-idtool.1.txt @@ -0,0 +1,115 @@ +=============== +zerotier-idtool +=============== + +---------------------------------------------- +identity management tool for ZeroTier One peer +---------------------------------------------- + +:Author: |author| +:Date: 2016-03-04 +:Copyright: + Copyright © 2016 ZeroTier Inc. +:Manual section: 1 +:Manual group: ZeroTier + +.. |command| replace:: **zerotier-idtool** +.. |license| replace:: + `GNU General Public License, version 3 or later + `__ + + +SYNOPSIS +======== + +| |command| **generate** [ `SECRET` ] [ `PUBLIC` ] +| |command| **validate** `SECRET` +| |command| **getpublic** `SECRET` +| |command| **sign** `SECRET` +| |command| **verify** `IDENTITY` `FILE` `SIGNATURE` +| |command| **mkcom** `SECRET` `ID`\ **,**\ `VALUE`\ **,**\ `MAX_DELTA` [ ... ] `IDENTITY` + + +DESCRIPTION +=========== + +|command| is a tool to manage identities for the **zerotier-one**\ (8) +program. + +*ZeroTier* is a peer-to-peer virtual network. Its “virtual layer 1” +(VL1) is implemented in the communication between ZeroTier One peers. +This provides the OSI layer 1 functionality on which to build further +network services. + + +COMMANDS +======== + +|command| **generate** [ `SECRET` ] [ `PUBLIC` ] + + *FIXME*: generate an identity + +|command| **validate** `SECRET` + + *FIXME*: validate a secret identity + +|command| **getpublic** `SECRET` + + *FIXME*: get a public identity + +|command| **sign** `SECRET` + + *FIXME*: sign a secret identity + +|command| **verify** `IDENTITY` `FILE` `SIGNATURE` + + *FIXME*: verify a signature + +|command| **mkcom** `SECRET` `ID`\ **,**\ `VALUE`\ **,**\ `MAX_DELTA` [ ... ] `IDENTITY` + + *FIXME*: mkcom + + +FILES +===== + +*FIXME*: how does the process know its home directory? + + +SEE ALSO +======== + +* **zerotier-one**\ (8) + +* ZeroTier One documentation: + + * Product page ``__. + * Configuration guide ``__. + * Technical FAQ ``__. + + +HISTORY +======= + +The |command| program is developed by ZeroTier Inc. + +This manual page was written by |author|. This is free software: you +may copy, modify and/or distribute this work under the terms of the +|license| as published by the Free Software Foundation. No warranty +expressed or implied. + +.. |author| replace:: |authorname| |authoremail| +.. |authorname| replace:: Ben Finney +.. |authoremail| replace:: + + +.. + Local variables: + mode: rst + coding: utf-8 + time-stamp-format: "%:y-%02m-%02d" + time-stamp-start: "^:Date:[ ]+" + time-stamp-end: "$" + time-stamp-line-limit: 20 + End: + vim: filetype=rst fileencoding=utf-8 : diff --git a/doc/zerotier-one.8 b/doc/zerotier-one.8 deleted file mode 100644 index 4ad7a15d0..000000000 --- a/doc/zerotier-one.8 +++ /dev/null @@ -1,104 +0,0 @@ -.TH "ZEROTIER\-ONE" "8" "December 2016" "" "" -.SH "NAME" -\fBzerotier-one\fR \- ZeroTier virtual network endpoint service -.SH SYNOPSIS -.P -\fBzerotier\-one\fP [\-switches] [working directory] -.SH DESCRIPTION -.P -\fBzerotier\-one\fR is the service/daemon responsible for connecting a Unix (Linux/BSD/OSX) system to one or more ZeroTier virtual networks and presenting those networks to the system as virtual network ports\. You can think of it as a peer to peer VPN client\. -.P -It's typically run by init systems like systemd (Linux) or launchd (Mac) rather than directly by the user, and it must be run as root unless you give it the \fB\-U\fP switch and don't plan on actually joining networks (e\.g\. to run a network controller microservice only)\. -.P -The \fBzerotier\-one\fR service keeps its state and other files in a working directory\. If this directory is not specified at launch it defaults to "/var/lib/zerotier\-one" on Linux, "/Library/Application Support/ZeroTier/One" on Mac, and "/var/db/zerotier\-one" on FreeBSD and other similar BSDs\. The working directory should persist\. It shouldn't be automatically cleaned by system cleanup daemons or stored in a volatile location\. Loss of its identity\.secret file results in loss of this system's unique 10\-digit ZeroTier address and key\. -.P -Multiple instances of \fBzerotier\-one\fR can be run on the same system as long as they are run with different primary ports (see switches) and a different working directory\. But since a single service can join any number of networks, typically there's no point in doing this\. -.P -The \fBzerotier\-one\fR service is controlled via a JSON API available at 127\.0\.0\.1: with the default primary port being 9993\. Access to this API requires an authorization token normally found in the authtoken\.secret file in the service's working directory\. On some platforms access may be guarded by other measures such as socket peer UID/GID lookup if additional security options are enabled (this is not the default)\. -.P -The first time the service is started in a fresh working directory, it generates a ZeroTier identity\. On slow systems this process can take ten seconds or more due to an anti\-DDOS/anti\-counterfeit proof of work function used by ZeroTier in address generation\. This only happens once, and once generated the result is saved in identity\.secret in the working directory\. This file represents and defines/claims your ZeroTier address and associated ECC\-256 key pair\. -.SH SWITCHES -.RS 0 -.IP \(bu 2 -\fB\-h\fP: -Display help\. -.IP \(bu 2 -\fB\-v\fP: -Display ZeroTier One version\. -.IP \(bu 2 -\fB\-U\fP: -Skip privilege check and allow to be run by non\-privileged user\. This is typically used when \fBzerotier\-one\fR is built with the network controller option included\. In this case the ZeroTier service might only be acting as a network controller and might never actually join networks, in which case it does not require elevated system permissions\. -.IP \(bu 2 -\fB\-p\fP: -Specify a different primary port\. If this is not given the default is 9993\. If zero is given a random port is chosen each time\. -.IP \(bu 2 -\fB\-d\fP: -Fork and run as a daemon\. -.IP \(bu 2 -\fB\-i\fP: -Invoke the \fBzerotier\-idtool\fR personality, in which case the binary behaves like zerotier\-idtool(1)\. This happens automatically if the name of the binary (or a symlink to it) is zerotier\-idtool\. -.IP \(bu 2 -\fB\-q\fP: -Invoke the \fBzerotier\-cli\fR personality, in which case the binary behaves like zerotier\-cli(1)\. This happens automatically if the name of the binary (or a symlink to it) is zerotier\-cli\. - -.RE -.SH EXAMPLES -.P -Run as daemon with OS default working directory and default port: -.P -.RS 2 -.nf -$ sudo zerotier\-one \-d -.fi -.RE -.P -Run as daemon with a different working directory and port: -.P -.RS 2 -.nf -$ sudo zerotier\-one \-d \-p12345 /tmp/zerotier\-working\-directory\-test -.fi -.RE -.SH FILES -.P -These are found in the service's working directory\. -.RS 0 -.IP \(bu 2 -\fBidentity\.public\fP: -The public portion of your ZeroTier identity, which is your 10\-digit hex address and the associated public key\. -.IP \(bu 2 -\fBidentity\.secret\fP: -Your full ZeroTier identity including its private key\. This file identifies the system on the network, which means you can move a ZeroTier address around by copying this file and you should back up this file if you want to save your system's static ZeroTier address\. This file must be protected, since theft of its secret key will allow anyone to impersonate your device on any network and decrypt traffic\. For network controllers this file is particularly sensitive since it constitutes the private key for a certificate authority for the controller's networks\. -.IP \(bu 2 -\fBauthtoken\.secret\fP: -The secret token used to authenticate requests to the service's local JSON API\. If it does not exist it is generated from a secure random source on service start\. To use, send it in the "X\-ZT1\-Auth" header with HTTP requests to 127\.0\.0\.1:\|\. -.IP \(bu 2 -\fBdevicemap\fP: -Remembers mappings of zt# interface numbers to ZeroTier networks so they'll persist across restarts\. On some systems that support longer interface names that can encode the network ID (such as FreeBSD) this file may not be present\. -.IP \(bu 2 -\fBzerotier\-one\.pid\fP: -ZeroTier's PID\. This file is deleted on normal shutdown\. -.IP \(bu 2 -\fBzerotier\-one\.port\fP: -ZeroTier's primary port, which is also where its JSON API is found at 127\.0\.0\.1:\|\. This file is created on startup and is read by zerotier\-cli(1) to determine where it should find the control API\. -.IP \(bu 2 -\fBcontroller\.db\fP: -If the ZeroTier One service is built with the network controller enabled, this file contains the controller's SQLite3 database\. -.IP \(bu 2 -\fBcontroller\.db\.backup\fP: -If the ZeroTier One service is built with the network controller enabled, it periodically backs up its controller\.db database in this file (currently every 5 minutes if there have been changes)\. Since this file is not a currently in use SQLite3 database it's safer to back up without corruption\. On new backups the file is rotated out rather than being rewritten in place\. -.IP \(bu 2 -\fBiddb\.d/\fP (directory): -Caches the public identity of every peer ZeroTier has spoken with in the last 60 days\. This directory and its contents can be deleted, but this may result in slower connection initations since it will require that we go out and re\-fetch full identities for peers we're speaking to\. -.IP \(bu 2 -\fBnetworks\.d\fP (directory): -This caches network configurations and certificate information for networks you belong to\. ZeroTier scans this directory for \|\.conf files on startup to recall its networks, so "touch"ing an empty \|\.conf file in this directory is a way of pre\-configuring ZeroTier to join a specific network on startup without using the API\. If the config file is empty ZeroTIer will just fetch it from the network's controller\. - -.RE -.SH COPYRIGHT -.P -(c)2011\-2016 ZeroTier, Inc\. \-\- https://www\.zerotier\.com/ \-\- https://github\.com/zerotier -.SH SEE ALSO -.P -zerotier\-cli(1), zerotier\-idtool(1) - diff --git a/doc/zerotier-one.8.md b/doc/zerotier-one.8.md deleted file mode 100644 index 4f4655076..000000000 --- a/doc/zerotier-one.8.md +++ /dev/null @@ -1,95 +0,0 @@ -zerotier-one(8) -- ZeroTier virtual network endpoint service -============================================================ - -## SYNOPSIS - -`zerotier-one` [-switches] [working directory] - -## DESCRIPTION - -**zerotier-one** is the service/daemon responsible for connecting a Unix (Linux/BSD/OSX) system to one or more ZeroTier virtual networks and presenting those networks to the system as virtual network ports. You can think of it as a peer to peer VPN client. - -It's typically run by init systems like systemd (Linux) or launchd (Mac) rather than directly by the user, and it must be run as root unless you give it the `-U` switch and don't plan on actually joining networks (e.g. to run a network controller microservice only). - -The **zerotier-one** service keeps its state and other files in a working directory. If this directory is not specified at launch it defaults to "/var/lib/zerotier-one" on Linux, "/Library/Application Support/ZeroTier/One" on Mac, and "/var/db/zerotier-one" on FreeBSD and other similar BSDs. The working directory should persist. It shouldn't be automatically cleaned by system cleanup daemons or stored in a volatile location. Loss of its identity.secret file results in loss of this system's unique 10-digit ZeroTier address and key. - -Multiple instances of **zerotier-one** can be run on the same system as long as they are run with different primary ports (see switches) and a different working directory. But since a single service can join any number of networks, typically there's no point in doing this. - -The **zerotier-one** service is controlled via a JSON API available at 127.0.0.1: with the default primary port being 9993. Access to this API requires an authorization token normally found in the authtoken.secret file in the service's working directory. On some platforms access may be guarded by other measures such as socket peer UID/GID lookup if additional security options are enabled (this is not the default). - -The first time the service is started in a fresh working directory, it generates a ZeroTier identity. On slow systems this process can take ten seconds or more due to an anti-DDOS/anti-counterfeit proof of work function used by ZeroTier in address generation. This only happens once, and once generated the result is saved in identity.secret in the working directory. This file represents and defines/claims your ZeroTier address and associated ECC-256 key pair. - -## SWITCHES - - * `-h`: - Display help. - - * `-v`: - Display ZeroTier One version. - - * `-U`: - Skip privilege check and allow to be run by non-privileged user. This is typically used when **zerotier-one** is built with the network controller option included. In this case the ZeroTier service might only be acting as a network controller and might never actually join networks, in which case it does not require elevated system permissions. - - * `-p`: - Specify a different primary port. If this is not given the default is 9993. If zero is given a random port is chosen each time. - - * `-d`: - Fork and run as a daemon. - - * `-i`: - Invoke the **zerotier-idtool** personality, in which case the binary behaves like zerotier-idtool(1). This happens automatically if the name of the binary (or a symlink to it) is zerotier-idtool. - - * `-q`: - Invoke the **zerotier-cli** personality, in which case the binary behaves like zerotier-cli(1). This happens automatically if the name of the binary (or a symlink to it) is zerotier-cli. - -## EXAMPLES - -Run as daemon with OS default working directory and default port: - - $ sudo zerotier-one -d - -Run as daemon with a different working directory and port: - - $ sudo zerotier-one -d -p12345 /tmp/zerotier-working-directory-test - -## FILES - -These are found in the service's working directory. - - * `identity.public`: - The public portion of your ZeroTier identity, which is your 10-digit hex address and the associated public key. - - * `identity.secret`: - Your full ZeroTier identity including its private key. This file identifies the system on the network, which means you can move a ZeroTier address around by copying this file and you should back up this file if you want to save your system's static ZeroTier address. This file must be protected, since theft of its secret key will allow anyone to impersonate your device on any network and decrypt traffic. For network controllers this file is particularly sensitive since it constitutes the private key for a certificate authority for the controller's networks. - - * `authtoken.secret`: - The secret token used to authenticate requests to the service's local JSON API. If it does not exist it is generated from a secure random source on service start. To use, send it in the "X-ZT1-Auth" header with HTTP requests to 127.0.0.1:. - - * `devicemap`: - Remembers mappings of zt# interface numbers to ZeroTier networks so they'll persist across restarts. On some systems that support longer interface names that can encode the network ID (such as FreeBSD) this file may not be present. - - * `zerotier-one.pid`: - ZeroTier's PID. This file is deleted on normal shutdown. - - * `zerotier-one.port`: - ZeroTier's primary port, which is also where its JSON API is found at 127.0.0.1:. This file is created on startup and is read by zerotier-cli(1) to determine where it should find the control API. - - * `controller.db`: - If the ZeroTier One service is built with the network controller enabled, this file contains the controller's SQLite3 database. - - * `controller.db.backup`: - If the ZeroTier One service is built with the network controller enabled, it periodically backs up its controller.db database in this file (currently every 5 minutes if there have been changes). Since this file is not a currently in use SQLite3 database it's safer to back up without corruption. On new backups the file is rotated out rather than being rewritten in place. - - * `iddb.d/` (directory): - Caches the public identity of every peer ZeroTier has spoken with in the last 60 days. This directory and its contents can be deleted, but this may result in slower connection initiations since it will require that we go out and re-fetch full identities for peers we're speaking to. - - * `networks.d` (directory): - This caches network configurations and certificate information for networks you belong to. ZeroTier scans this directory for .conf files on startup to recall its networks, so "touch"ing an empty .conf file in this directory is a way of pre-configuring ZeroTier to join a specific network on startup without using the API. If the config file is empty ZeroTIer will just fetch it from the network's controller. - -## COPYRIGHT - -(c)2011-2016 ZeroTier, Inc. -- https://www.zerotier.com/ -- https://github.com/zerotier - -## SEE ALSO - -zerotier-cli(1), zerotier-idtool(1) diff --git a/doc/zerotier-one.8.txt b/doc/zerotier-one.8.txt new file mode 100644 index 000000000..e730130e3 --- /dev/null +++ b/doc/zerotier-one.8.txt @@ -0,0 +1,119 @@ +============ +zerotier-one +============ + +------------------------------------------------- +end-point peer for ZeroTier virtual network layer +------------------------------------------------- + +:Author: |author| +:Date: 2016-03-04 +:Copyright: + Copyright © 2016 ZeroTier Inc. +:Manual section: 8 +:Manual group: ZeroTier + +.. |command| replace:: **zerotier-one** +.. |license| replace:: + `GNU General Public License, version 3 or later + `__ + + +SYNOPSIS +======== + +| |command| [ **-U** ] [ **-p** `PORT` ] [ **-d** ] [ `HOMEDIR` ] +| |command| **-i** [ `IDTOOL_ARG` ... ] +| |command| **-q** [ `QUERY_ARG` ... ] +| |command| **-h** +| |command| **-v** + + +DESCRIPTION +=========== + +**ZeroTier One** is the end-point peer for the ZeroTier +software-defined network layer. + +*ZeroTier* is a peer-to-peer virtual network. Its “virtual layer 1” +(VL1) is implemented in the communication between ZeroTier One peers. +This provides the OSI layer 1 functionality on which to build further +network services. + + +OPTIONS +======= + +**-h** + Display concise help on command usage. + +**-v** + Display program version. + +**-U** + Run as unprivileged user (skip privilege check). + +**-p** `PORT` + Communicate on network port `PORT` (either TCP or UDP). + +**-d** + Become a conventional daemon process. Only available on Unix-like + operating systems. + +**-i** [ `IDTOOL_ARG` ... ] + Generate and manage identities. + + This is equivalent to running the **zerotier-idtool** command with + all the specified `IDTOOL_ARG` parameters. + +**-q** [ `QUERY_ARG` ... ] + Query the running ZeroTier One process. + + This is equivalent to running the **zerotier-cli** command with + all the specified `QUERY_ARG` parameters. + + +FILES +===== + +The |command| process will store its state in files within the +specified `HOMEDIR` directory (default: ``/var/lib/zerotier-one``). + + +SEE ALSO +======== + +* **zerotier-idtool**\ (1), **zerotier-cli**\ (1) + +* ZeroTier One documentation: + + * Product page ``__. + * Configuration guide ``__. + * Technical FAQ ``__. + + +HISTORY +======= + +The |command| program is developed by ZeroTier Inc. + +This manual page was written by |author|. This is free software: you +may copy, modify and/or distribute this work under the terms of the +|license| as published by the Free Software Foundation. No warranty +expressed or implied. + +.. |author| replace:: |authorname| |authoremail| +.. |authorname| replace:: Ben Finney +.. |authoremail| replace:: + + +.. + Local variables: + mode: rst + coding: utf-8 + time-stamp-format: "%:y-%02m-%02d" + time-stamp-start: "^:Date:[ ]+" + time-stamp-end: "$" + time-stamp-line-limit: 20 + End: + vim: filetype=rst fileencoding=utf-8 : diff --git a/entrypoint.sh.release b/entrypoint.sh.release deleted file mode 100644 index da9b8f8c8..000000000 --- a/entrypoint.sh.release +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/sh - -grepzt() { - [ -f /var/lib/zerotier-one/zerotier-one.pid -a -n "$(cat /var/lib/zerotier-one/zerotier-one.pid 2>/dev/null)" -a -d "/proc/$(cat /var/lib/zerotier-one/zerotier-one.pid 2>/dev/null)" ] - return $? -} - -mkztfile() { - file=$1 - mode=$2 - content=$3 - echo "creating $file" - mkdir -p /var/lib/zerotier-one - echo -n "$content" > "/var/lib/zerotier-one/$file" - chmod "$mode" "/var/lib/zerotier-one/$file" -} - -if [ "x$ZEROTIER_API_SECRET" != "x" ] -then - mkztfile authtoken.secret 0600 "$ZEROTIER_API_SECRET" - mkztfile metricstoken.secret 0600 "$ZEROTIER_API_SECRET" -fi - -if [ "x$ZEROTIER_IDENTITY_PUBLIC" != "x" ] -then - mkztfile identity.public 0644 "$ZEROTIER_IDENTITY_PUBLIC" -fi - -if [ "x$ZEROTIER_IDENTITY_SECRET" != "x" ] -then - mkztfile identity.secret 0600 "$ZEROTIER_IDENTITY_SECRET" -fi - -if [ "x$ZEROTIER_LOCAL_CONF" != "x" ] -then - mkztfile local.conf 0644 "$ZEROTIER_LOCAL_CONF" -fi - -mkztfile zerotier-one.port 0600 "9993" - -killzerotier() { - log "Killing zerotier" - kill $(cat /var/lib/zerotier-one/zerotier-one.pid 2>/dev/null) - exit 0 -} - -log_header() { - echo -n "\r=>" -} - -log_detail_header() { - echo -n "\r===>" -} - -log() { - echo "$(log_header)" "$@" -} - -log_params() { - title=$1 - shift - log "$title" "[$@]" -} - -log_detail() { - echo "$(log_detail_header)" "$@" -} - -log_detail_params() { - title=$1 - shift - log_detail "$title" "[$@]" -} - -trap killzerotier INT TERM - -log "Configuring networks to join" -mkdir -p /var/lib/zerotier-one/networks.d - -log_params "Joining networks from command line:" $@ -for i in "$@" -do - log_detail_params "Configuring join:" "$i" - touch "/var/lib/zerotier-one/networks.d/${i}.conf" -done - -if [ "x$ZEROTIER_JOIN_NETWORKS" != "x" ] -then - log_params "Joining networks from environment:" $ZEROTIER_JOIN_NETWORKS - for i in $ZEROTIER_JOIN_NETWORKS - do - log_detail_params "Configuring join:" "$i" - touch "/var/lib/zerotier-one/networks.d/${i}.conf" - done -fi - -log "Starting ZeroTier" -nohup /usr/sbin/zerotier-one & - -while ! grepzt -do - log_detail "ZeroTier hasn't started, waiting a second" - - if [ -f nohup.out ] - then - tail -n 10 nohup.out - fi - - sleep 1 -done - -log_params "Writing healthcheck for networks:" $@ - -cat >/healthcheck.sh < -#include -#define zt_arm_has_neon() ((getauxval(AT_HWCAP) & HWCAP_NEON) != 0) -#elif defined(__ARM_NEON__) || defined(__ARM_NEON) -#define zt_arm_has_neon() (true) -#else -#define zt_arm_has_neon() (false) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// ciphertext buffer, message/NULL, length, nonce (8 bytes), key (32 bytes) -extern int zt_salsa2012_armneon3_xor(unsigned char *c,const unsigned char *m,unsigned long long len,const unsigned char *n,const unsigned char *k); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/arm32-neon-salsa2012-asm/salsa2012.s b/ext/arm32-neon-salsa2012-asm/salsa2012.s deleted file mode 100644 index 9e5989cd3..000000000 --- a/ext/arm32-neon-salsa2012-asm/salsa2012.s +++ /dev/null @@ -1,2231 +0,0 @@ - -# qhasm: int32 input_0 - -# qhasm: int32 input_1 - -# qhasm: int32 input_2 - -# qhasm: int32 input_3 - -# qhasm: stack32 input_4 - -# qhasm: stack32 input_5 - -# qhasm: stack32 input_6 - -# qhasm: stack32 input_7 - -# qhasm: int32 caller_r4 - -# qhasm: int32 caller_r5 - -# qhasm: int32 caller_r6 - -# qhasm: int32 caller_r7 - -# qhasm: int32 caller_r8 - -# qhasm: int32 caller_r9 - -# qhasm: int32 caller_r10 - -# qhasm: int32 caller_r11 - -# qhasm: int32 caller_r14 - -# qhasm: reg128 caller_q4 - -# qhasm: reg128 caller_q5 - -# qhasm: reg128 caller_q6 - -# qhasm: reg128 caller_q7 - -# qhasm: startcode -.fpu neon -.text - -# qhasm: constant sigma: -.align 2 -sigma: - -# qhasm: const32 1634760805 -.word 1634760805 - -# qhasm: const32 857760878 -.word 857760878 - -# qhasm: const32 2036477234 -.word 2036477234 - -# qhasm: const32 1797285236 -.word 1797285236 - -# qhasm: int128 abab - -# qhasm: int128 diag0 - -# qhasm: int128 diag1 - -# qhasm: int128 diag2 - -# qhasm: int128 diag3 - -# qhasm: int128 a0 - -# qhasm: int128 a1 - -# qhasm: int128 a2 - -# qhasm: int128 a3 - -# qhasm: int128 b0 - -# qhasm: int128 b1 - -# qhasm: int128 b2 - -# qhasm: int128 b3 - -# qhasm: int128 next_diag0 - -# qhasm: int128 next_diag1 - -# qhasm: int128 next_diag2 - -# qhasm: int128 next_diag3 - -# qhasm: int128 next_a0 - -# qhasm: int128 next_a1 - -# qhasm: int128 next_a2 - -# qhasm: int128 next_a3 - -# qhasm: int128 next_b0 - -# qhasm: int128 next_b1 - -# qhasm: int128 next_b2 - -# qhasm: int128 next_b3 - -# qhasm: int128 x0x5x10x15 - -# qhasm: int128 x12x1x6x11 - -# qhasm: int128 x8x13x2x7 - -# qhasm: int128 x4x9x14x3 - -# qhasm: int128 x0x1x10x11 - -# qhasm: int128 x12x13x6x7 - -# qhasm: int128 x8x9x2x3 - -# qhasm: int128 x4x5x14x15 - -# qhasm: int128 x0x1x2x3 - -# qhasm: int128 x4x5x6x7 - -# qhasm: int128 x8x9x10x11 - -# qhasm: int128 x12x13x14x15 - -# qhasm: int128 m0m1m2m3 - -# qhasm: int128 m4m5m6m7 - -# qhasm: int128 m8m9m10m11 - -# qhasm: int128 m12m13m14m15 - -# qhasm: int128 start0 - -# qhasm: int128 start1 - -# qhasm: int128 start2 - -# qhasm: int128 start3 - -# qhasm: stack128 stack_start3 - -# qhasm: stack128 next_start2 - -# qhasm: stack128 next_start3 - -# qhasm: int128 k0k1k2k3 - -# qhasm: int128 k4k5k6k7 - -# qhasm: int128 k1n1k7k2 - -# qhasm: int128 n2n3n3n2 - -# qhasm: int128 k2k3k6k7 - -# qhasm: int128 nextblock - -# qhasm: stack128 stack_q4 - -# qhasm: stack128 stack_q5 - -# qhasm: stack128 stack_q6 - -# qhasm: stack128 stack_q7 - -# qhasm: stack32 stack_r4 - -# qhasm: stack128 k2k3k6k7_stack - -# qhasm: stack128 k1n1k7k2_stack - -# qhasm: stack512 tmp - -# qhasm: stack32 savec - -# qhasm: int32 i - -# qhasm: int32 ci - -# qhasm: int32 mi - -# qhasm: enter zt_salsa2012_armneon3_xor -.align 2 -.global _zt_salsa2012_armneon3_xor -.global zt_salsa2012_armneon3_xor -.type _zt_salsa2012_armneon3_xor STT_FUNC -.type zt_salsa2012_armneon3_xor STT_FUNC -_zt_salsa2012_armneon3_xor: -zt_salsa2012_armneon3_xor: -sub sp,sp,#256 - -# qhasm: new stack_q4 - -# qhasm: new stack_q5 - -# qhasm: new stack_q6 - -# qhasm: new stack_q7 - -# qhasm: stack_q4 bot = caller_q4 bot -# asm 1: vstr stack_r4=stack32#2 -# asm 2: str stack_r4=[sp,#68] -str r4,[sp,#68] - -# qhasm: int32 c - -# qhasm: c = input_0 -# asm 1: mov >c=int32#1,c=r0,m=int32#2,m=r1,mlenlow=int32#3,mlenlow=r2,mlenhigh=int32#4,mlenhigh=r3,n=int32#5,n=r4,k=int32#13,k=r12,k0k1k2k3=reg128#1%bot->k0k1k2k3=reg128#1%top},[k0k1k2k3=d0->k0k1k2k3=d1},[k4k5k6k7=reg128#2%bot->k4k5k6k7=reg128#2%top},[k4k5k6k7=d2->k4k5k6k7=d3},[i=int32#13,=sigma -# asm 2: ldr >i=r12,=sigma -ldr r12,=sigma - -# qhasm: start0 = mem128[i] -# asm 1: vld1.8 {>start0=reg128#3%bot->start0=reg128#3%top},[start0=d4->start0=d5},[start1=reg128#4,#0 -# asm 2: vmov.i64 >start1=q3,#0 -vmov.i64 q3,#0 - -# qhasm: start1 bot = mem64[n] -# asm 1: vld1.8 {k2k3k6k7=reg128#6,k2k3k6k7=q5,n2n3n3n2=reg128#1,#0 -# asm 2: vmov.i64 >n2n3n3n2=q0,#0 -vmov.i64 q0,#0 - -# qhasm: unsigneddiag0=reg128#8,diag0=q7,diag1=reg128#9,diag1=q8,start2=reg128#10,start2=q9,nextblock=reg128#11,#0xff -# asm 2: vmov.i64 >nextblock=q10,#0xff -vmov.i64 q10,#0xff - -# qhasm: 4x nextblock unsigned>>= 7 -# asm 1: vshr.u32 >nextblock=reg128#11,nextblock=q10,n2n3n3n2=reg128#1,n2n3n3n2=q0,n2n3n3n2=reg128#1,n2n3n3n2=q0,next_diag0=reg128#2,next_diag0=q1,next_diag1=reg128#5,next_diag1=q4,i=int32#5,=12 -# asm 2: ldr >i=r4,=12 -ldr r4,=12 - -# qhasm: mainloop2: -._mainloop2: - -# qhasm: 4x a0 = diag1 + diag0 -# asm 1: vadd.i32 >a0=reg128#11,a0=q10,next_a0=reg128#14,next_a0=q13,b0=reg128#15,b0=q14,next_b0=reg128#16,next_b0=q15,> 25 -# asm 1: vsri.i32 > 25 -# asm 1: vsri.i32 diag3=reg128#7,diag3=q6,next_diag3=reg128#11,next_diag3=q10,a1=reg128#13,a1=q12,next_a1=reg128#14,next_a1=q13,b1=reg128#15,b1=q14,next_b1=reg128#16,next_b1=q15,> 23 -# asm 1: vsri.i32 > 23 -# asm 1: vsri.i32 diag2=reg128#6,diag2=q5,next_diag2=reg128#12,next_diag2=q11,a2=reg128#13,a2=q12,diag3=reg128#7,diag3=q6,next_a2=reg128#14,next_a2=q13,b2=reg128#15,b2=q14,next_diag3=reg128#11,next_diag3=q10,next_b2=reg128#16,next_b2=q15,> 19 -# asm 1: vsri.i32 > 19 -# asm 1: vsri.i32 diag1=reg128#9,diag1=q8,next_diag1=reg128#5,next_diag1=q4,a3=reg128#13,a3=q12,next_a3=reg128#14,next_a3=q13,b3=reg128#15,b3=q14,next_b3=reg128#16,next_b3=q15,> 14 -# asm 1: vsri.i32 diag1=reg128#9,diag1=q8,> 14 -# asm 1: vsri.i32 diag0=reg128#8,diag0=q7,next_diag1=reg128#5,next_diag1=q4,next_diag0=reg128#2,next_diag0=q1,a0=reg128#13,a0=q12,next_a0=reg128#14,next_a0=q13,b0=reg128#15,b0=q14,next_b0=reg128#16,next_b0=q15,> 25 -# asm 1: vsri.i32 > 25 -# asm 1: vsri.i32 diag1=reg128#9,diag1=q8,next_diag1=reg128#5,next_diag1=q4,a1=reg128#13,a1=q12,next_a1=reg128#14,next_a1=q13,b1=reg128#15,b1=q14,next_b1=reg128#16,next_b1=q15,> 23 -# asm 1: vsri.i32 ? i -= 2 -# asm 1: subs > 23 -# asm 1: vsri.i32 diag2=reg128#6,diag2=q5,next_diag2=reg128#12,next_diag2=q11,a2=reg128#13,a2=q12,diag1=reg128#9,diag1=q8,next_a2=reg128#14,next_a2=q13,b2=reg128#15,b2=q14,next_diag1=reg128#5,next_diag1=q4,next_b2=reg128#16,next_b2=q15,> 19 -# asm 1: vsri.i32 > 19 -# asm 1: vsri.i32 diag3=reg128#7,diag3=q6,next_diag3=reg128#11,next_diag3=q10,a3=reg128#13,a3=q12,next_a3=reg128#14,next_a3=q13,b3=reg128#15,b3=q14,next_b3=reg128#16,next_b3=q15,> 14 -# asm 1: vsri.i32 diag3=reg128#7,diag3=q6,> 14 -# asm 1: vsri.i32 diag0=reg128#8,diag0=q7,next_diag3=reg128#13,next_diag3=q12,next_diag0=reg128#2,next_diag0=q1, -bhi ._mainloop2 - -# qhasm: 2x abab = 0xffffffff -# asm 1: vmov.i64 >abab=reg128#11,#0xffffffff -# asm 2: vmov.i64 >abab=q10,#0xffffffff -vmov.i64 q10,#0xffffffff - -# qhasm: new x4x9x14x3 - -# qhasm: x4x9x14x3 bot = stack_start3 bot -# asm 1: vldr x0x5x10x15=reg128#8,x0x5x10x15=q7,x12x1x6x11=reg128#9,x12x1x6x11=q8,x8x13x2x7=reg128#6,x8x13x2x7=q5,x4x9x14x3=reg128#7,x4x9x14x3=q6,x0x1x10x11=reg128#10,x0x1x10x11=q9,x12x13x6x7=reg128#14,x12x13x6x7=q13,x8x9x2x3=reg128#15,x8x9x2x3=q14,x4x5x14x15=reg128#16,x4x5x14x15=q15,x0x1x2x3=reg128#6,x0x1x2x3=q5,x4x5x6x7=reg128#7,x4x5x6x7=q6,x8x9x10x11=reg128#8,x8x9x10x11=q7,x12x13x14x15=reg128#9,x12x13x14x15=q8,m0m1m2m3=reg128#10%bot->m0m1m2m3=reg128#10%top},[m0m1m2m3=d18->m0m1m2m3=d19},[m4m5m6m7=reg128#14%bot->m4m5m6m7=reg128#14%top},[m4m5m6m7=d26->m4m5m6m7=d27},[m8m9m10m11=reg128#15%bot->m8m9m10m11=reg128#15%top},[m8m9m10m11=d28->m8m9m10m11=d29},[m12m13m14m15=reg128#16%bot->m12m13m14m15=reg128#16%top},[m12m13m14m15=d30->m12m13m14m15=d31},[x0x1x2x3=reg128#6,x0x1x2x3=q5,x4x5x6x7=reg128#7,x4x5x6x7=q6,x8x9x10x11=reg128#8,x8x9x10x11=q7,x12x13x14x15=reg128#9,x12x13x14x15=q8,x0x5x10x15=reg128#2,x0x5x10x15=q1,x12x1x6x11=reg128#5,x12x1x6x11=q4,x8x13x2x7=reg128#6,x8x13x2x7=q5,x4x9x14x3=reg128#7,x4x9x14x3=q6,x0x1x10x11=reg128#8,x0x1x10x11=q7,x12x13x6x7=reg128#9,x12x13x6x7=q8,x8x9x2x3=reg128#10,x8x9x2x3=q9,x4x5x14x15=reg128#12,x4x5x14x15=q11,x0x1x2x3=reg128#2,x0x1x2x3=q1,x4x5x6x7=reg128#5,x4x5x6x7=q4,x8x9x10x11=reg128#6,x8x9x10x11=q5,x12x13x14x15=reg128#7,x12x13x14x15=q6,m0m1m2m3=reg128#8%bot->m0m1m2m3=reg128#8%top},[m0m1m2m3=d14->m0m1m2m3=d15},[m4m5m6m7=reg128#9%bot->m4m5m6m7=reg128#9%top},[m4m5m6m7=d16->m4m5m6m7=d17},[m8m9m10m11=reg128#10%bot->m8m9m10m11=reg128#10%top},[m8m9m10m11=d18->m8m9m10m11=d19},[m12m13m14m15=reg128#11%bot->m12m13m14m15=reg128#11%top},[m12m13m14m15=d20->m12m13m14m15=d21},[x0x1x2x3=reg128#2,x0x1x2x3=q1,x4x5x6x7=reg128#5,x4x5x6x7=q4,x8x9x10x11=reg128#6,x8x9x10x11=q5,x12x13x14x15=reg128#7,x12x13x14x15=q6,? mlenhigh - 0 -# asm 1: cmp -bhi ._mlenatleast128 - -# qhasm: =? mlenlow - 0 -# asm 1: cmp savec=stack32#1 -# asm 2: str savec=[sp,#64] -str r0,[sp,#64] - -# qhasm: c = &tmp -# asm 1: lea >c=int32#1,c=r0,i=int32#4,=0 -# asm 2: ldr >i=r3,=0 -ldr r3,=0 - -# qhasm: mcopy: -._mcopy: - -# qhasm: mi = mem8[m + 0] -# asm 1: ldrb >mi=int32#5,[mi=r4,[mi=int32#2,=0 -# asm 2: ldr >mi=r1,=0 -ldr r1,=0 - -# qhasm: pad: -._pad: - -# qhasm: mem8[c + 0] = mi -# asm 1: strb m=int32#2,m=r1,diag0=reg128#2,diag0=q1,diag1=reg128#5,diag1=q4,diag2=reg128#8,diag2=q7,diag3=reg128#9,diag3=q8,nextblock=reg128#10,#0xff -# asm 2: vmov.i64 >nextblock=q9,#0xff -vmov.i64 q9,#0xff - -# qhasm: 4x nextblock unsigned>>= 7 -# asm 1: vshr.u32 >nextblock=reg128#10,nextblock=q9,n2n3n3n2=reg128#1,n2n3n3n2=q0,i=int32#4,=12 -# asm 2: ldr >i=r3,=12 -ldr r3,=12 - -# qhasm: mainloop1: -._mainloop1: - -# qhasm: 4x a0 = diag1 + diag0 -# asm 1: vadd.i32 >a0=reg128#10,a0=q9,b0=reg128#11,b0=q10,> 25 -# asm 1: vsri.i32 diag3=reg128#9,diag3=q8,a1=reg128#10,a1=q9,b1=reg128#11,b1=q10,> 23 -# asm 1: vsri.i32 diag2=reg128#8,diag2=q7,a2=reg128#10,a2=q9,diag3=reg128#9,diag3=q8,b2=reg128#11,b2=q10,> 19 -# asm 1: vsri.i32 diag1=reg128#5,diag1=q4,a3=reg128#10,a3=q9,b3=reg128#11,b3=q10,> 14 -# asm 1: vsri.i32 diag1=reg128#5,diag1=q4,diag0=reg128#2,diag0=q1,a0=reg128#10,a0=q9,b0=reg128#11,b0=q10,> 25 -# asm 1: vsri.i32 diag1=reg128#5,diag1=q4,a1=reg128#10,a1=q9,b1=reg128#11,b1=q10,> 23 -# asm 1: vsri.i32 ? i -= 2 -# asm 1: subs diag2=reg128#8,diag2=q7,a2=reg128#10,a2=q9,diag1=reg128#5,diag1=q4,b2=reg128#11,b2=q10,> 19 -# asm 1: vsri.i32 diag3=reg128#9,diag3=q8,a3=reg128#10,a3=q9,b3=reg128#11,b3=q10,> 14 -# asm 1: vsri.i32 diag3=reg128#9,diag3=q8,diag0=reg128#2,diag0=q1, -bhi ._mainloop1 - -# qhasm: 2x abab = 0xffffffff -# asm 1: vmov.i64 >abab=reg128#10,#0xffffffff -# asm 2: vmov.i64 >abab=q9,#0xffffffff -vmov.i64 q9,#0xffffffff - -# qhasm: 4x x0x5x10x15 = diag0 + start0 -# asm 1: vadd.i32 >x0x5x10x15=reg128#2,x0x5x10x15=q1,x12x1x6x11=reg128#5,x12x1x6x11=q4,x8x13x2x7=reg128#6,x8x13x2x7=q5,x4x9x14x3=reg128#7,x4x9x14x3=q6,x0x1x10x11=reg128#8,x0x1x10x11=q7,x12x13x6x7=reg128#9,x12x13x6x7=q8,x8x9x2x3=reg128#11,x8x9x2x3=q10,x4x5x14x15=reg128#12,x4x5x14x15=q11,x0x1x2x3=reg128#2,x0x1x2x3=q1,x4x5x6x7=reg128#5,x4x5x6x7=q4,x8x9x10x11=reg128#6,x8x9x10x11=q5,x12x13x14x15=reg128#7,x12x13x14x15=q6,m0m1m2m3=reg128#8%bot->m0m1m2m3=reg128#8%top},[m0m1m2m3=d14->m0m1m2m3=d15},[m4m5m6m7=reg128#9%bot->m4m5m6m7=reg128#9%top},[m4m5m6m7=d16->m4m5m6m7=d17},[m8m9m10m11=reg128#10%bot->m8m9m10m11=reg128#10%top},[m8m9m10m11=d18->m8m9m10m11=d19},[m12m13m14m15=reg128#11%bot->m12m13m14m15=reg128#11%top},[m12m13m14m15=d20->m12m13m14m15=d21},[x0x1x2x3=reg128#2,x0x1x2x3=q1,x4x5x6x7=reg128#5,x4x5x6x7=q4,x8x9x10x11=reg128#6,x8x9x10x11=q5,x12x13x14x15=reg128#7,x12x13x14x15=q6,i=int32#4,=0 -# asm 2: ldr >i=r3,=0 -ldr r3,=0 - -# qhasm: m = c - 64 -# asm 1: sub >m=int32#2,m=r1,c=int32#1,c=r0,ci=int32#5,[ci=r4,[? mlenlow -= 64 -# asm 1: subs -bhi ._mlenatleast1 - -# qhasm: done: -._done: - -# qhasm: new caller_r4 - -# qhasm: caller_r4 = stack_r4 -# asm 1: ldr >caller_r4=int32#5,caller_r4=r4,result=int32#1,=0 -# asm 2: ldr >result=r0,=0 -ldr r0,=0 - -# qhasm: return result -add sp,sp,#256 -bx lr diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/Info.plist b/ext/bin/tap-mac/tap.kext.old/Contents/Info.plist new file mode 100644 index 000000000..45c2839ad --- /dev/null +++ b/ext/bin/tap-mac/tap.kext.old/Contents/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + tap + CFBundleIdentifier + com.zerotier.tap + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + tap + CFBundlePackageType + KEXT + CFBundleShortVersionString + 20131028 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + OSBundleLibraries + + com.apple.kpi.mach + 8.0 + com.apple.kpi.bsd + 8.0 + com.apple.kpi.libkern + 8.0 + com.apple.kpi.unsupported + 8.0 + + + + diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/MacOS/tap b/ext/bin/tap-mac/tap.kext.old/Contents/MacOS/tap new file mode 100755 index 000000000..6a9021a74 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext.old/Contents/MacOS/tap differ diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeDirectory b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeDirectory new file mode 100644 index 000000000..58c421c29 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeDirectory differ diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeRequirements b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeRequirements new file mode 100644 index 000000000..1df931292 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeRequirements differ diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeResources b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeResources new file mode 100644 index 000000000..0710b4008 --- /dev/null +++ b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeResources @@ -0,0 +1,105 @@ + + + + + files + + files2 + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeSignature b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeSignature new file mode 100644 index 000000000..644297271 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeSignature differ diff --git a/ext/bin/tap-mac/tap.kext/Contents/Info.plist b/ext/bin/tap-mac/tap.kext/Contents/Info.plist new file mode 100644 index 000000000..c20eefa58 --- /dev/null +++ b/ext/bin/tap-mac/tap.kext/Contents/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + tap + CFBundleIdentifier + com.zerotier.tap + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + tap + CFBundlePackageType + KEXT + CFBundleShortVersionString + 20150118 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + OSBundleLibraries + + com.apple.kpi.mach + 8.0 + com.apple.kpi.bsd + 8.0 + com.apple.kpi.libkern + 8.0 + com.apple.kpi.unsupported + 8.0 + + + + diff --git a/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap b/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap new file mode 100755 index 000000000..48bf96255 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap differ diff --git a/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeResources b/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeResources new file mode 100644 index 000000000..0710b4008 --- /dev/null +++ b/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeResources @@ -0,0 +1,105 @@ + + + + + files + + files2 + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/ext/bin/tap-windows-ndis5/x64/WdfCoinstaller01011.dll b/ext/bin/tap-windows-ndis5/x64/WdfCoinstaller01011.dll new file mode 100644 index 000000000..d49d29132 Binary files /dev/null and b/ext/bin/tap-windows-ndis5/x64/WdfCoinstaller01011.dll differ diff --git a/ext/bin/tap-windows-ndis5/x64/zttap200.cat b/ext/bin/tap-windows-ndis5/x64/zttap200.cat new file mode 100644 index 000000000..a3769e405 Binary files /dev/null and b/ext/bin/tap-windows-ndis5/x64/zttap200.cat differ diff --git a/ext/bin/tap-windows-ndis5/x64/zttap200.inf b/ext/bin/tap-windows-ndis5/x64/zttap200.inf new file mode 100644 index 000000000..dc1a74227 --- /dev/null +++ b/ext/bin/tap-windows-ndis5/x64/zttap200.inf @@ -0,0 +1,79 @@ +[Version] +Signature="$WINDOWS NT$" +Class=Net +ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318} +Provider=%Provider% +CatalogFile=zttap200.cat +DriverVer=01/23/2014,15.19.17.816 + +[Strings] +DeviceDescription = "ZeroTier One Virtual Network Port" +Provider = "ZeroTier Networks LLC" + +; To build for x86, take NTamd64 off this and off the named section manually, build, then put it back! +[Manufacturer] +%Provider%=zttap200,NTamd64 + +[zttap200] +%DeviceDescription%=zttap200.ndi,zttap200 + +[ztTap200.NTamd64] +%DeviceDescription%=zttap200.ndi,zttap200 + +[zttap200.ndi] +CopyFiles = zttap200.driver,zttap200.files +AddReg = zttap200.reg +AddReg = zttap200.params.reg +Characteristics = 0x81 + +[zttap200.ndi.Services] +AddService = zttap200, 2, zttap200.service + +[zttap200.reg] +HKR, Ndi, Service, 0, "zttap200" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" +HKR, , Manufacturer, 0, "%Provider%" +HKR, , ProductName, 0, "%DeviceDescription%" + +[zttap200.params.reg] +HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" +HKR, Ndi\params\MTU, Type, 0, "int" +HKR, Ndi\params\MTU, Default, 0, "2800" +HKR, Ndi\params\MTU, Optional, 0, "0" +HKR, Ndi\params\MTU, Min, 0, "100" +HKR, Ndi\params\MTU, Max, 0, "2800" +HKR, Ndi\params\MTU, Step, 0, "1" +HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" +HKR, Ndi\params\MediaStatus, Type, 0, "enum" +HKR, Ndi\params\MediaStatus, Default, 0, "0" +HKR, Ndi\params\MediaStatus, Optional, 0, "0" +HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" +HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" +HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" +HKR, Ndi\params\MAC, Type, 0, "edit" +HKR, Ndi\params\MAC, Optional, 0, "1" + +[zttap200.service] +DisplayName = %DeviceDescription% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +LoadOrderGroup = NDIS +ServiceBinary = %12%\zttap200.sys + +[SourceDisksNames] +1 = %DeviceDescription%, zttap200.sys + +[SourceDisksFiles] +zttap200.sys = 1 + +[DestinationDirs] +zttap200.files = 11 +zttap200.driver = 12 + +[zttap200.files] +; + +[zttap200.driver] +zttap200.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK diff --git a/ext/bin/tap-windows-ndis5/x64/zttap200.sys b/ext/bin/tap-windows-ndis5/x64/zttap200.sys new file mode 100644 index 000000000..339351fb3 Binary files /dev/null and b/ext/bin/tap-windows-ndis5/x64/zttap200.sys differ diff --git a/ext/bin/tap-windows-ndis5/x86/WdfCoinstaller01011.dll b/ext/bin/tap-windows-ndis5/x86/WdfCoinstaller01011.dll new file mode 100644 index 000000000..e943ea45e Binary files /dev/null and b/ext/bin/tap-windows-ndis5/x86/WdfCoinstaller01011.dll differ diff --git a/ext/bin/tap-windows-ndis5/x86/zttap200.cat b/ext/bin/tap-windows-ndis5/x86/zttap200.cat new file mode 100644 index 000000000..d90ecbbee Binary files /dev/null and b/ext/bin/tap-windows-ndis5/x86/zttap200.cat differ diff --git a/ext/bin/tap-windows-ndis5/x86/zttap200.inf b/ext/bin/tap-windows-ndis5/x86/zttap200.inf new file mode 100644 index 000000000..99aac9f2b --- /dev/null +++ b/ext/bin/tap-windows-ndis5/x86/zttap200.inf @@ -0,0 +1,76 @@ +[Version] +Signature="$WINDOWS NT$" +Class=Net +ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318} +Provider=%Provider% +CatalogFile=zttap200.cat +DriverVer=01/24/2014,17.25.51.226 + +[Strings] +DeviceDescription = "ZeroTier One Virtual Network Port" +Provider = "ZeroTier Networks LLC" + +; To build for x86, take NTamd64 off this and off the named section manually, build, then put it back! +[Manufacturer] +%Provider%=zttap200 + +[zttap200] +%DeviceDescription%=zttap200.ndi,zttap200 + +[zttap200.ndi] +CopyFiles = zttap200.driver,zttap200.files +AddReg = zttap200.reg +AddReg = zttap200.params.reg +Characteristics = 0x81 + +[zttap200.ndi.Services] +AddService = zttap200, 2, zttap200.service + +[zttap200.reg] +HKR, Ndi, Service, 0, "zttap200" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" +HKR, , Manufacturer, 0, "%Provider%" +HKR, , ProductName, 0, "%DeviceDescription%" + +[zttap200.params.reg] +HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" +HKR, Ndi\params\MTU, Type, 0, "int" +HKR, Ndi\params\MTU, Default, 0, "2800" +HKR, Ndi\params\MTU, Optional, 0, "0" +HKR, Ndi\params\MTU, Min, 0, "100" +HKR, Ndi\params\MTU, Max, 0, "2800" +HKR, Ndi\params\MTU, Step, 0, "1" +HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" +HKR, Ndi\params\MediaStatus, Type, 0, "enum" +HKR, Ndi\params\MediaStatus, Default, 0, "0" +HKR, Ndi\params\MediaStatus, Optional, 0, "0" +HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" +HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" +HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" +HKR, Ndi\params\MAC, Type, 0, "edit" +HKR, Ndi\params\MAC, Optional, 0, "1" + +[zttap200.service] +DisplayName = %DeviceDescription% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +LoadOrderGroup = NDIS +ServiceBinary = %12%\zttap200.sys + +[SourceDisksNames] +1 = %DeviceDescription%, zttap200.sys + +[SourceDisksFiles] +zttap200.sys = 1 + +[DestinationDirs] +zttap200.files = 11 +zttap200.driver = 12 + +[zttap200.files] +; + +[zttap200.driver] +zttap200.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK diff --git a/ext/bin/tap-windows-ndis5/x86/zttap200.sys b/ext/bin/tap-windows-ndis5/x86/zttap200.sys new file mode 100644 index 000000000..b7b11fbe8 Binary files /dev/null and b/ext/bin/tap-windows-ndis5/x86/zttap200.sys differ diff --git a/ext/bin/tap-windows-ndis6/arm64/zttap300.cat b/ext/bin/tap-windows-ndis6/arm64/zttap300.cat deleted file mode 100644 index 906a15a4b..000000000 Binary files a/ext/bin/tap-windows-ndis6/arm64/zttap300.cat and /dev/null differ diff --git a/ext/bin/tap-windows-ndis6/arm64/zttap300.inf b/ext/bin/tap-windows-ndis6/arm64/zttap300.inf deleted file mode 100644 index 8e74daab1..000000000 --- a/ext/bin/tap-windows-ndis6/arm64/zttap300.inf +++ /dev/null @@ -1,145 +0,0 @@ -; -; **************************************************************************** -; * Copyright (C) 2002-2014 OpenVPN Technologies, Inc. * -; * This program is free software; you can redistribute it and/or modify * -; * it under the terms of the GNU General Public License version 2 * -; * as published by the Free Software Foundation. * -; **************************************************************************** -; - -; -; ZeroTier One Virtual Network Port NDIS6 Driver -; -; Modified by ZeroTier, Inc. - https://www.zerotier.com/ -; -; (1) Comment out 'tun' functionality and related features such as DHCP -; emulation, since we don't use any of that. Just want straight 'tap'. -; (2) Added custom IOCTL to enumerate L2 multicast memberships. -; (3) Increase maximum number of multicast memberships to 128. -; (4) Set default and max device MTU to 2800. -; (5) Rename/rebrand driver as ZeroTier network port driver. -; -; Original copyright below. Modifications released under GPLv2 as well. - -[Version] -Signature = "$Windows NT$" -CatalogFile = zttap300.cat -ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} -Provider = %Provider% -Class = Net -DriverVer=11/24/2020,3.00.00.1 - -[Strings] -DeviceDescription = "ZeroTier Virtual Port" -Provider = "ZeroTier" - -[Manufacturer] -%Provider%=zttap300,NTx86 -%Provider%=zttap300,NTamd64 -%Provider%=zttap300,NTarm64 - -[zttap300.NTx86] -%DeviceDescription% = zttap300.ndi, root\zttap300 ; Root enumerated -%DeviceDescription% = zttap300.ndi, zttap300 ; Legacy - -[zttap300.NTamd64] -%DeviceDescription% = zttap300.ndi, root\zttap300 ; Root enumerated -%DeviceDescription% = zttap300.ndi, zttap300 ; Legacy - -[zttap300.NTarm64] -%DeviceDescription% = zttap300.ndi, root\zttap300 ; Root enumerated -%DeviceDescription% = zttap300.ndi, zttap300 ; Legacy - -;----------------- Characteristics ------------ -; NCF_PHYSICAL = 0x04 -; NCF_VIRTUAL = 0x01 -; NCF_SOFTWARE_ENUMERATED = 0x02 -; NCF_HIDDEN = 0x08 -; NCF_NO_SERVICE = 0x10 -; NCF_HAS_UI = 0x80 -;----------------- Characteristics ------------ -[zttap300.ndi] -CopyFiles = zttap300.driver, zttap300.files -AddReg = zttap300.reg -AddReg = zttap300.params.reg -Characteristics = 0x81 -*IfType = 0x6 ; IF_TYPE_ETHERNET_CSMACD -*MediaType = 0x0 ; NdisMedium802_3 -*PhysicalMediaType = 14 ; NdisPhysicalMedium802_3 - -[zttap300.ndi.Services] -AddService = zttap300, 2, zttap300.service - -[zttap300.reg] -HKR, Ndi, Service, 0, "zttap300" -HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" ; yes, 'ndis5' is correct... yup, Windows. -HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" -HKR, , Manufacturer, 0, "%Provider%" -HKR, , ProductName, 0, "%DeviceDescription%" - -[zttap300.params.reg] -HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" -HKR, Ndi\params\MTU, Type, 0, "int" -HKR, Ndi\params\MTU, Default, 0, "2800" -HKR, Ndi\params\MTU, Optional, 0, "0" -HKR, Ndi\params\MTU, Min, 0, "100" -HKR, Ndi\params\MTU, Max, 0, "2800" -HKR, Ndi\params\MTU, Step, 0, "1" -HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" -HKR, Ndi\params\MediaStatus, Type, 0, "enum" -HKR, Ndi\params\MediaStatus, Default, 0, "0" -HKR, Ndi\params\MediaStatus, Optional, 0, "0" -HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" -HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" -HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" -HKR, Ndi\params\MAC, Type, 0, "edit" -HKR, Ndi\params\MAC, Optional, 0, "1" -HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" -HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" -HKR, Ndi\params\AllowNonAdmin, Default, 0, "0" -HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" -HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" -HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" - -;---------- Service Type ------------- -; SERVICE_KERNEL_DRIVER = 0x01 -; SERVICE_WIN32_OWN_PROCESS = 0x10 -;---------- Service Type ------------- - -;---------- Start Mode --------------- -; SERVICE_BOOT_START = 0x0 -; SERVICE_SYSTEM_START = 0x1 -; SERVICE_AUTO_START = 0x2 -; SERVICE_DEMAND_START = 0x3 -; SERVICE_DISABLED = 0x4 -;---------- Start Mode --------------- - -[zttap300.service] -DisplayName = %DeviceDescription% -ServiceType = 1 -StartType = 3 -ErrorControl = 1 -LoadOrderGroup = NDIS -ServiceBinary = %12%\zttap300.sys - -;----------------- Copy Flags ------------ -; COPYFLG_NOSKIP = 0x02 -; COPYFLG_NOVERSIONCHECK = 0x04 -;----------------- Copy Flags ------------ - -[SourceDisksNames] -1 = %DeviceDescription%, zttap300.sys - -[SourceDisksFiles] -zttap300.sys = 1 - -[DestinationDirs] -zttap300.files = 11 -zttap300.driver = 12 - -[zttap300.files] -; - -[zttap300.driver] -zttap300.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK - diff --git a/ext/bin/tap-windows-ndis6/arm64/zttap300.sys b/ext/bin/tap-windows-ndis6/arm64/zttap300.sys deleted file mode 100644 index ae1a16f4b..000000000 Binary files a/ext/bin/tap-windows-ndis6/arm64/zttap300.sys and /dev/null differ diff --git a/ext/bin/tap-windows-ndis6/x64/ZeroTierOne_NDIS6_x64.msi b/ext/bin/tap-windows-ndis6/x64/ZeroTierOne_NDIS6_x64.msi new file mode 100644 index 000000000..818796f4d Binary files /dev/null and b/ext/bin/tap-windows-ndis6/x64/ZeroTierOne_NDIS6_x64.msi differ diff --git a/ext/bin/tap-windows-ndis6/x64/zttap300.cat b/ext/bin/tap-windows-ndis6/x64/zttap300.cat index 6eef79ff8..8b9114c71 100644 Binary files a/ext/bin/tap-windows-ndis6/x64/zttap300.cat and b/ext/bin/tap-windows-ndis6/x64/zttap300.cat differ diff --git a/ext/bin/tap-windows-ndis6/x64/zttap300.inf b/ext/bin/tap-windows-ndis6/x64/zttap300.inf index e05038dae..453797b38 100644 --- a/ext/bin/tap-windows-ndis6/x64/zttap300.inf +++ b/ext/bin/tap-windows-ndis6/x64/zttap300.inf @@ -30,11 +30,11 @@ CatalogFile = zttap300.cat ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} Provider = %Provider% Class = Net -DriverVer=11/24/2020,3.00.00.1 +DriverVer=08/13/2015,6.2.9200.20557 [Strings] -DeviceDescription = "ZeroTier Virtual Port" -Provider = "ZeroTier" +DeviceDescription = "ZeroTier One Virtual Port" +Provider = "ZeroTier Networks LLC" ; We're ZeroTier, Inc. now but kernel mode certs are $300+ so fuqdat. ; To build for x86, take NTamd64 off this and off the named section manually, build, then put it back! [Manufacturer] @@ -141,4 +141,3 @@ zttap300.driver = 12 [zttap300.driver] zttap300.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK - diff --git a/ext/bin/tap-windows-ndis6/x64/zttap300.sys b/ext/bin/tap-windows-ndis6/x64/zttap300.sys index 2c7922b39..3d846a53a 100644 Binary files a/ext/bin/tap-windows-ndis6/x64/zttap300.sys and b/ext/bin/tap-windows-ndis6/x64/zttap300.sys differ diff --git a/ext/bin/tap-windows-ndis6/x86/ZeroTierOne_NDIS6_x86.msi b/ext/bin/tap-windows-ndis6/x86/ZeroTierOne_NDIS6_x86.msi new file mode 100644 index 000000000..b9e2d7eac Binary files /dev/null and b/ext/bin/tap-windows-ndis6/x86/ZeroTierOne_NDIS6_x86.msi differ diff --git a/ext/bin/tap-windows-ndis6/x86/zttap300.cat b/ext/bin/tap-windows-ndis6/x86/zttap300.cat index f6021aa88..44347f54f 100644 Binary files a/ext/bin/tap-windows-ndis6/x86/zttap300.cat and b/ext/bin/tap-windows-ndis6/x86/zttap300.cat differ diff --git a/ext/bin/tap-windows-ndis6/x86/zttap300.inf b/ext/bin/tap-windows-ndis6/x86/zttap300.inf index a562e9d64..453797b38 100644 --- a/ext/bin/tap-windows-ndis6/x86/zttap300.inf +++ b/ext/bin/tap-windows-ndis6/x86/zttap300.inf @@ -1,15 +1,10 @@ -; -; **************************************************************************** -; * Copyright (C) 2002-2014 OpenVPN Technologies, Inc. * -; * This program is free software; you can redistribute it and/or modify * -; * it under the terms of the GNU General Public License version 2 * -; * as published by the Free Software Foundation. * -; **************************************************************************** -; - ; ; ZeroTier One Virtual Network Port NDIS6 Driver ; +; Based on the OpenVPN tap-windows6 driver version 9.21.1 git +; commit 48f027cfca52b16b5fd23d82e6016ed8a91fc4d3. +; See: https://github.com/OpenVPN/tap-windows6 +; ; Modified by ZeroTier, Inc. - https://www.zerotier.com/ ; ; (1) Comment out 'tun' functionality and related features such as DHCP @@ -20,6 +15,14 @@ ; (5) Rename/rebrand driver as ZeroTier network port driver. ; ; Original copyright below. Modifications released under GPLv2 as well. +; +; **************************************************************************** +; * Copyright (C) 2002-2014 OpenVPN Technologies, Inc. * +; * This program is free software; you can redistribute it and/or modify * +; * it under the terms of the GNU General Public License version 2 * +; * as published by the Free Software Foundation. * +; **************************************************************************** +; [Version] Signature = "$Windows NT$" @@ -27,17 +30,17 @@ CatalogFile = zttap300.cat ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} Provider = %Provider% Class = Net -DriverVer=11/24/2020,3.00.00.1 +DriverVer=08/13/2015,6.2.9200.20557 [Strings] -DeviceDescription = "ZeroTier Virtual Port" -Provider = "ZeroTier" +DeviceDescription = "ZeroTier One Virtual Port" +Provider = "ZeroTier Networks LLC" ; We're ZeroTier, Inc. now but kernel mode certs are $300+ so fuqdat. +; To build for x86, take NTamd64 off this and off the named section manually, build, then put it back! [Manufacturer] -%Provider%=zttap300,NTx86 -;%Provider%=zttap300,NTamd64 +%Provider%=zttap300,NTamd64 -[zttap300.NTx86] +[zttap300] %DeviceDescription% = zttap300.ndi, root\zttap300 ; Root enumerated %DeviceDescription% = zttap300.ndi, zttap300 ; Legacy @@ -138,4 +141,3 @@ zttap300.driver = 12 [zttap300.driver] zttap300.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK - diff --git a/ext/bin/tap-windows-ndis6/x86/zttap300.sys b/ext/bin/tap-windows-ndis6/x86/zttap300.sys index 86e51a3ea..664398e93 100644 Binary files a/ext/bin/tap-windows-ndis6/x86/zttap300.sys and b/ext/bin/tap-windows-ndis6/x86/zttap300.sys differ diff --git a/ext/central-controller-docker/Dockerfile b/ext/central-controller-docker/Dockerfile deleted file mode 100644 index 29670ec68..000000000 --- a/ext/central-controller-docker/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -# Dockerfile for ZeroTier Central Controllers -FROM registry.zerotier.com/zerotier/ctlbuild:2025-07-14 AS builder -ADD . /ZeroTierOne -RUN export PATH=$PATH:~/.cargo/bin && cd ZeroTierOne && make clean && make central-controller -j8 - -FROM golang:bookworm AS go_base -RUN go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest - -FROM registry.zerotier.com/zerotier/ctlrun:2025-07-14 AS run_base -COPY --from=builder /ZeroTierOne/zerotier-one /usr/local/bin/zerotier-one -COPY --from=builder /ZeroTierOne/ext/opentelemetry-cpp-1.21.0/localinstall/lib/*.so /usr/local/lib64/ -COPY --from=go_base /go/bin/migrate /usr/local/bin/migrate -COPY ext/central-controller-docker/migrations /migrations - -RUN chmod a+x /usr/local/bin/zerotier-one -RUN echo "/usr/local/lib64" > /etc/ld.so.conf.d/usr-local-lib64.conf && ldconfig - -ADD ext/central-controller-docker/main.sh / -RUN chmod a+x /main.sh - -ENTRYPOINT /main.sh diff --git a/ext/central-controller-docker/Dockerfile.builder b/ext/central-controller-docker/Dockerfile.builder deleted file mode 100644 index 6e10db887..000000000 --- a/ext/central-controller-docker/Dockerfile.builder +++ /dev/null @@ -1,34 +0,0 @@ -# Dockerfile for building ZeroTier Central Controllers -FROM debian:bookworm - -RUN apt update && apt upgrade -y -RUN apt -y install \ - build-essential \ - pkg-config \ - bash \ - clang \ - libjemalloc2 \ - libjemalloc-dev \ - libpq5 \ - libpq-dev \ - openssl \ - libssl-dev \ - postgresql-client \ - postgresql-client-common \ - curl \ - libcurl4-openssl-dev \ - google-perftools \ - libgoogle-perftools-dev \ - protobuf-compiler \ - protobuf-compiler-grpc \ - protobuf-c-compiler \ - grpc-proto \ - libgrpc++1.51 \ - libgrpc++-dev \ - libgrpc-dev \ - libgrpc29 \ - cmake \ - git - - -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y diff --git a/ext/central-controller-docker/Dockerfile.run_base b/ext/central-controller-docker/Dockerfile.run_base deleted file mode 100644 index fb5d0e2d5..000000000 --- a/ext/central-controller-docker/Dockerfile.run_base +++ /dev/null @@ -1,19 +0,0 @@ -FROM debian:bookworm - - - -RUN apt update && apt upgrade -y -RUN apt -y install \ - netcat-traditional \ - postgresql-client \ - postgresql-client-common \ - libjemalloc2 \ - libpq5 \ - curl \ - binutils \ - perf-tools-unstable \ - google-perftools \ - gnupg \ - libgrpc++1.51 \ - libgrpc29 - diff --git a/ext/central-controller-docker/Makefile b/ext/central-controller-docker/Makefile deleted file mode 100644 index 2318d2903..000000000 --- a/ext/central-controller-docker/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -registry = registry.zerotier.com/zerotier - -all: controller-builder controller-runbase - -buildx: - @echo "docker buildx create" - # docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - docker run --privileged --rm tonistiigi/binfmt --install all - @echo docker buildx create --name multiarch --driver docker-container --use - @echo docker buildx inspect --bootstrap - -controller-builder: buildx - docker buildx build --no-cache --platform linux/amd64,linux/arm64 -t $(registry)/ctlbuild:$(shell date +"%Y-%m-%d") -f Dockerfile.builder . --push - -controller-runbase: buildx - docker buildx build --no-cache --platform linux/amd64,linux/arm64 -t $(registry)/ctlrun:$(shell date +"%Y-%m-%d") -f Dockerfile.run_base . --push diff --git a/ext/central-controller-docker/README.md b/ext/central-controller-docker/README.md deleted file mode 100644 index a954b1c37..000000000 --- a/ext/central-controller-docker/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ZeroTier Central Controller Docker Image - -Dockerfile & startup script for use with [ZeroTier Central](https://my.zerotier.com). Not intended for public use. diff --git a/ext/central-controller-docker/main.sh b/ext/central-controller-docker/main.sh deleted file mode 100755 index b1c4b4cbc..000000000 --- a/ext/central-controller-docker/main.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/bash - -if [ -z "$ZT_DB_HOST" ]; then - echo '*** FAILED: ZT_DB_HOST environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_PORT" ]; then - echo '*** FAILED: ZT_DB_PORT environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_NAME" ]; then - echo '*** FAILED: ZT_DB_NAME environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_USER" ]; then - echo '*** FAILED: ZT_DB_USER environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_PASSWORD" ]; then - echo '*** FAILED: ZT_DB_PASSWORD environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_TYPE" ]; then - ZT_DB_TYPE="postgres" -fi - -REDIS="" -if [ "$ZT_USE_REDIS" == "true" ]; then - if [ -z "$ZT_REDIS_HOST" ]; then - echo '*** FAILED: ZT_REDIS_HOST environment variable not defined' - exit 1 - fi - - if [ -z "$ZT_REDIS_PORT" ]; then - echo '*** FAILED: ZT_REDIS_PORT enivronment variable not defined' - exit 1 - fi - - if [ -z "$ZT_REDIS_CLUSTER_MODE" ]; then - echo '*** FAILED: ZT_REDIS_CLUSTER_MODE environment variable not defined' - exit 1 - fi - - REDIS="\"redis\": { - \"hostname\": \"${ZT_REDIS_HOST}\", - \"port\": ${ZT_REDIS_PORT}, - \"clusterMode\": ${ZT_REDIS_CLUSTER_MODE}, - \"password\": \"${ZT_REDIS_PASSWORD}\" - } - " -else - REDIS="\"redis\": null" -fi - -mkdir -p /var/lib/zerotier-one - -pushd /var/lib/zerotier-one -if [ -d "$ZT_IDENTITY_PATH" ]; then - echo '*** Using existing ZT identity from path $ZT_IDENTITY_PATH' - - ln -s $ZT_IDENTITY_PATH/identity.public identity.public - ln -s $ZT_IDENTITY_PATH/identity.secret identity.secret - if [ -f "$ZT_IDENTITY_PATH/authtoken.secret" ]; then - ln -s $ZT_IDENTITY_PATH/authtoken.secret authtoken.secret - fi -fi -popd - -DEFAULT_PORT=9993 -DEFAULT_LB_MODE=false - -APP_NAME="controller-$(cat /var/lib/zerotier-one/identity.public | cut -d ':' -f 1)" - -echo "{ - \"settings\": { - \"controllerDbPath\": \"${ZT_DB_TYPE}:host=${ZT_DB_HOST} port=${ZT_DB_PORT} dbname=${ZT_DB_NAME} user=${ZT_DB_USER} password=${ZT_DB_PASSWORD} application_name=${APP_NAME} sslmode=prefer sslcert=${DB_CLIENT_CERT} sslkey=${DB_CLIENT_KEY} sslrootcert=${DB_SERVER_CA}\", - \"portMappingEnabled\": true, - \"softwareUpdate\": \"disable\", - \"interfacePrefixBlacklist\": [ - \"inot\", - \"nat64\" - ], - \"lowBandwidthMode\": ${ZT_LB_MODE:-$DEFAULT_LB_MODE}, - \"ssoRedirectURL\": \"${ZT_SSO_REDIRECT_URL}\", - \"allowManagementFrom\": [\"127.0.0.1\", \"::1\", \"10.0.0.0/8\"], - \"otel\": { - \"exporterEndpoint\": \"${ZT_EXPORTER_ENDPOINT}\", - \"exporterSampleRate\": ${ZT_EXPORTER_SAMPLE_RATE:-0} - }, - ${REDIS} - } -} -" > /var/lib/zerotier-one/local.conf - -if [ -n "$DB_SERVER_CA" ]; then - echo "secret list" - chmod 600 /secrets/db/*.pem - ls -l /secrets/db/ - until /usr/bin/pg_isready -h ${ZT_DB_HOST} -p ${ZT_DB_PORT} -d "sslmode=prefer sslcert=${DB_CLIENT_CERT} sslkey=${DB_CLIENT_KEY} sslrootcert=${DB_SERVER_CA}"; do - echo "Waiting for PostgreSQL..."; - sleep 2; - done -else - until /usr/bin/pg_isready -h ${ZT_DB_HOST} -p ${ZT_DB_PORT}; do - echo "Waiting for PostgreSQL..."; - sleep 2; - done -fi - -if [ "$ZT_DB_TYPE" == "cv2" ]; then - echo "Migrating database (if needed)..." - if [ -n "$DB_SERVER_CA" ]; then - /usr/local/bin/migrate -source file:///migrations -database "postgres://$ZT_DB_USER:$ZT_DB_PASSWORD@$ZT_DB_HOST:$ZT_DB_PORT/$ZT_DB_NAME?x-migrations-table=controller_migrations&sslmode=verify-full&sslrootcert=$DB_SERVER_CA&sslcert=$DB_CLIENT_CERT&sslkey=$DB_CLIENT_KEY" up - else - /usr/local/bin/migrate -source file:///migrations -database "postgres://$ZT_DB_USER:$ZT_DB_PASSWORD@$ZT_DB_HOST:$ZT_DB_PORT/$ZT_DB_NAME?x-migrations-table=controller_migrations&sslmode=disable" up - fi -fi - -if [ -n "$ZT_TEMPORAL_HOST" ] && [ -n "$ZT_TEMPORAL_PORT" ]; then - echo "waiting for temporal..." - while ! nc -z ${ZT_TEMPORAL_HOST} ${ZT_TEMPORAL_PORT}; do - echo "waiting..."; - sleep 1; - done - echo "Temporal is up" -fi - -export GLIBCXX_FORCE_NEW=1 -export GLIBCPP_FORCE_NEW=1 -export LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libjemalloc.so.2" -exec /usr/local/bin/zerotier-one -p${ZT_CONTROLLER_PORT:-$DEFAULT_PORT} /var/lib/zerotier-one diff --git a/ext/central-controller-docker/migrations/0001_init.down.sql b/ext/central-controller-docker/migrations/0001_init.down.sql deleted file mode 100644 index 03dc63c81..000000000 --- a/ext/central-controller-docker/migrations/0001_init.down.sql +++ /dev/null @@ -1,3 +0,0 @@ -DROP TABLE IF EXISTS network_memberships_ctl; -DROP TABLE IF EXISTS networks_ctl; -DROP TABLE IF EXISTS controllers_ctl; \ No newline at end of file diff --git a/ext/central-controller-docker/migrations/0001_init.up.sql b/ext/central-controller-docker/migrations/0001_init.up.sql deleted file mode 100644 index 90d29e889..000000000 --- a/ext/central-controller-docker/migrations/0001_init.up.sql +++ /dev/null @@ -1,47 +0,0 @@ --- inits controller db schema - -CREATE TABLE IF NOT EXISTS controllers_ctl ( - id text NOT NULL PRIMARY KEY, - hostname text, - last_heartbeat timestamp with time zone, - public_identity text NOT NULL, - version text -); - -CREATE TABLE IF NOT EXISTS networks_ctl ( - id character varying(22) NOT NULL PRIMARY KEY, - name text NOT NULL, - configuration jsonb DEFAULT '{}'::jsonb NOT NULL, - controller_id text REFERENCES controllers_ctl(id), - revision integer DEFAULT 0 NOT NULL, - last_modified timestamp with time zone DEFAULT now(), - creation_time timestamp with time zone DEFAULT now() -); - -CREATE TABLE IF NOT EXISTS network_memberships_ctl ( - device_id character varying(22) NOT NULL, - network_id character varying(22) NOT NULL REFERENCES networks_ctl(id), - authorized boolean, - active_bridge boolean, - ip_assignments text[], - no_auto_assign_ips boolean, - sso_exempt boolean, - authentication_expiry_time timestamp with time zone, - capabilities jsonb, - creation_time timestamp with time zone DEFAULT now(), - last_modified timestamp with time zone DEFAULT now(), - identity text DEFAULT ''::text, - last_authorized_credential text, - last_authorized_time timestamp with time zone, - last_deauthorized_time timestamp with time zone, - last_seen jsonb DEFAULT '{}'::jsonb NOT NULL, -- in the context of the network - remote_trace_level integer DEFAULT 0 NOT NULL, - remote_trace_target text DEFAULT ''::text NOT NULL, - revision integer DEFAULT 0 NOT NULL, - tags jsonb, - version_major integer DEFAULT 0 NOT NULL, - version_minor integer DEFAULT 0 NOT NULL, - version_revision integer DEFAULT 0 NOT NULL, - version_protocol integer DEFAULT 0 NOT NULL, - PRIMARY KEY (device_id, network_id) -); diff --git a/ext/central-controller-docker/migrations/0002_os_arch.down.sql b/ext/central-controller-docker/migrations/0002_os_arch.down.sql deleted file mode 100644 index 3c90f0a2e..000000000 --- a/ext/central-controller-docker/migrations/0002_os_arch.down.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE network_memberships_ctl - DROP COLUMN os, - DROP COLUMN arch; \ No newline at end of file diff --git a/ext/central-controller-docker/migrations/0002_os_arch.up.sql b/ext/central-controller-docker/migrations/0002_os_arch.up.sql deleted file mode 100644 index 095f7c698..000000000 --- a/ext/central-controller-docker/migrations/0002_os_arch.up.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE network_memberships_ctl - ADD COLUMN os TEXT NOT NULL DEFAULT 'unknown', - ADD COLUMN arch TEXT NOT NULL DEFAULT 'unknown'; \ No newline at end of file diff --git a/ext/contrib/README.md b/ext/contrib/README.md new file mode 100644 index 000000000..feb9ae643 --- /dev/null +++ b/ext/contrib/README.md @@ -0,0 +1,15 @@ +You are reading this file because you want to build a new copy of the LwIP library for +use in ZeroTier. + +Subdirectories: + + ports/ -- contains ports for various architectures (for our purposes, unix) + +In order for the Network Containers feature to work in ZeroTier, a copy of the LwIP libary +is needed since we dynamically load it into memory. You can build a new copy of the libary +by going to /contrib/ports/unix/proj/lib and running make. + +This will generate: liblwip.so + +You can enable LwIP debug traces by adding the flag -DLWIP_DEBUG +See additional debug info here: http://lwip.wikia.com/wiki/Debugging_lwIP diff --git a/ext/contrib/ports/unix/proj/lib/Makefile b/ext/contrib/ports/unix/proj/lib/Makefile new file mode 100644 index 000000000..5bb6a1f36 --- /dev/null +++ b/ext/contrib/ports/unix/proj/lib/Makefile @@ -0,0 +1,106 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +# OF SUCH DAMAGE. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +CONTRIBDIR=../../../.. +LWIPARCH=$(CONTRIBDIR)/ports/unix + +#Set this to where you have the lwip core module checked out from CVS +#default assumes it's a dir named lwip at the same level as the contrib module +LWIPDIR=$(CONTRIBDIR)/../lwip/src + + +CCDEP=gcc +CC=gcc +CFLAGS=-g -Wall -DIPv4 -fPIC + +CFLAGS:=$(CFLAGS) \ + -I$(LWIPDIR)/include -I$(LWIPARCH)/include -I$(LWIPDIR)/include/ipv4 \ + -I$(LWIPDIR) -I. + + +# COREFILES, CORE4FILES: The minimum set of files needed for lwIP. +COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \ + $(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/raw.c $(LWIPDIR)/core/stats.c \ + $(LWIPDIR)/core/sys.c $(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_in.c \ + $(LWIPDIR)/core/tcp_out.c $(LWIPDIR)/core/udp.c $(LWIPDIR)/core/dhcp.c \ + $(LWIPDIR)/core/init.c $(LWIPDIR)/core/timers.c $(LWIPDIR)/core/def.c +CORE4FILES=$(wildcard $(LWIPDIR)/core/ipv4/*.c) $(LWIPDIR)/core/ipv4/inet.c \ + $(LWIPDIR)/core/ipv4/inet_chksum.c + +# SNMPFILES: Extra SNMPv1 agent +SNMPFILES=$(LWIPDIR)/core/snmp/asn1_dec.c $(LWIPDIR)/core/snmp/asn1_enc.c \ + $(LWIPDIR)/core/snmp/mib2.c $(LWIPDIR)/core/snmp/mib_structs.c \ + $(LWIPDIR)/core/snmp/msg_in.c $(LWIPDIR)/core/snmp/msg_out.c + +# APIFILES: The files which implement the sequential and socket APIs. +APIFILES=$(LWIPDIR)/api/api_lib.c $(LWIPDIR)/api/api_msg.c $(LWIPDIR)/api/tcpip.c \ + $(LWIPDIR)/api/err.c $(LWIPDIR)/api/sockets.c $(LWIPDIR)/api/netbuf.c $(LWIPDIR)/api/netdb.c + +# NETIFFILES: Files implementing various generic network interface functions.' +NETIFFILES=$(LWIPDIR)/netif/etharp.c $(LWIPDIR)/netif/slipif.c + +# NETIFFILES: Add PPP netif +NETIFFILES+=$(LWIPDIR)/netif/ppp/auth.c $(LWIPDIR)/netif/ppp/chap.c \ + $(LWIPDIR)/netif/ppp/chpms.c $(LWIPDIR)/netif/ppp/fsm.c \ + $(LWIPDIR)/netif/ppp/ipcp.c $(LWIPDIR)/netif/ppp/lcp.c \ + $(LWIPDIR)/netif/ppp/magic.c $(LWIPDIR)/netif/ppp/md5.c \ + $(LWIPDIR)/netif/ppp/pap.c $(LWIPDIR)/netif/ppp/ppp.c \ + $(LWIPDIR)/netif/ppp/randm.c $(LWIPDIR)/netif/ppp/vj.c + +# ARCHFILES: Architecture specific files. +ARCHFILES=$(wildcard $(LWIPARCH)/*.c $(LWIPARCH)tapif.c $(LWIPARCH)/netif/list.c $(LWIPARCH)/netif/tcpdump.c) + + +# LWIPFILES: All the above. +LWIPFILES=$(COREFILES) $(CORE4FILES) $(SNMPFILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES) +LWIPFILESW=$(wildcard $(LWIPFILES)) +LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o)) + +LWIPLIB=liblwip.so + +%.o: + $(CC) $(CFLAGS) -c $(<:.o=.c) + +all: $(LWIPLIB) +.PHONY: all + +clean: + rm -f *.o $(LWIPLIB) *.s .depend* *.core core + +depend dep: .depend + +include .depend + +$(LWIPLIB): $(LWIPOBJS) unixlib.o + $(CC) -g -nostartfiles -shared -o $@ $^ + +.depend: unixlib.c $(LWIPFILES) + $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend diff --git a/ext/contrib/ports/unix/proj/lib/README b/ext/contrib/ports/unix/proj/lib/README new file mode 100644 index 000000000..cd6cc7b74 --- /dev/null +++ b/ext/contrib/ports/unix/proj/lib/README @@ -0,0 +1,31 @@ +This directory contains an example of how to compile lwIP as a self +initialising shared library on Linux. + +Some brief instructions: + +* Compile the code: + + > make clean all + + This should produce liblwip4unixlib.so. This is the shared library. + +* Link an application against the shared library + + If you're using gcc you can do this by including -llwip4unixlib in +your link command. + +* Run your application + + Ensure that LD_LIBRARY_PATH includes the directory that contains +liblwip4unixlib.so (ie. this directory) + + + +If you are unsure about shared libraries and libraries on linux in +general, you might find this HOWTO useful: + + + + + +Kieran Mansley, October 2002. \ No newline at end of file diff --git a/ext/contrib/ports/unix/proj/lib/lwipopts.h b/ext/contrib/ports/unix/proj/lib/lwipopts.h new file mode 100644 index 000000000..48d35f3df --- /dev/null +++ b/ext/contrib/ports/unix/proj/lib/lwipopts.h @@ -0,0 +1,468 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + + +//#define LWIP_DEBUG 0 +//#define TCP_DEBUG LWIP_DBG_OFF + +/* + +#define LWIP_MALLOC_MEMPOOL 1 +*/ + +/* +#define LWIP_CHECKSUM_ON_COPY 1 + +#define TCP_OVERSIZE TCP_MSS +*/ + +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +//#define TCP_WND + + +//#define PBUF_POOL_BUFSIZE 2048 + +/*------------------------------------------------------------------------------ +---------------------------------- Timers -------------------------------------- +------------------------------------------------------------------------------*/ + +/* these are originally defined in tcp_impl.h */ +#ifndef TCP_TMR_INTERVAL +/* The TCP timer interval in milliseconds. */ +#define TCP_TMR_INTERVAL 25 +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +/* the fine grained timeout in milliseconds */ +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVALs +/* the coarse grained timeout in milliseconds */ +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) +#endif /* TCP_SLOW_INTERVAL */ + + +/*------------------------------------------------------------------------------ +--------------------------- Platform specific locking ------------------------- +------------------------------------------------------------------------------*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 0 + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ + +/* set to 1 so we have no thread behaviour */ +#define NO_SYS 1 + +/* set to 1 so we can use our own timers */ +#define NO_SYS_NO_TIMERS 1 + + +/*------------------------------------------------------------------------------ +-------------------------------- Memory options -------------------------------- +------------------------------------------------------------------------------*/ + + +#define LWIP_CHKSUM_ALGORITHM 2 + + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#define MEM_ALIGNMENT 1 + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#define MEM_SIZE 1024 * 1024 * 64 +#define TCP_SND_BUF 1024 * 63 + + +/*------------------------------------------------------------------------------ +-------------------------- Internal Memory Pool Sizes -------------------------- +------------------------------------------------------------------------------*/ + +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#define MEMP_NUM_PBUF 256 + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#define MEMP_NUM_RAW_PCB 32 + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#define MEMP_NUM_UDP_PCB 4 + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB 128 + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB_LISTEN 128 + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN + +/** + * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for + * reassembly (whole packets, not fragments!) + */ +#define MEMP_NUM_REASSDATA 1 + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#define MEMP_NUM_ARP_QUEUE 2 + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + */ +#define MEMP_NUM_SYS_TIMEOUT 3 + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETBUF 2 + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETCONN 4 + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#define MEMP_NUM_TCPIP_MSG_API 8 + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#define MEMP_NUM_TCPIP_MSG_INPKT 8 + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#define PBUF_POOL_SIZE 128 /* was 32 */ + + +/*------------------------------------------------------------------------------ +----------------------------------- ARP options -------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#define LWIP_ARP 1 + + +/*------------------------------------------------------------------------------ +------------------------------------ IP options--------------------------------- +------------------------------------------------------------------------------*/ + +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#define IP_FORWARD 0 + +/** + * IP_OPTIONS: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#define IP_OPTIONS_ALLOWED 1 + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#define IP_REASSEMBLY 1 + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#define IP_FRAG 1 + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#define IP_REASS_MAXAGE 3 + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#define IP_REASS_MAX_PBUFS 4 + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented. +*/ +#define IP_FRAG_USES_STATIC_BUF 0 + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#define IP_DEFAULT_TTL 255 + + +/*------------------------------------------------------------------------------ +------------------------------- ICMP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#define LWIP_ICMP 1 + + +/*------------------------------------------------------------------------------ +------------------------------- RAW Options ------------------------------------ +------------------------------------------------------------------------------*/ + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#define LWIP_RAW 1 + + +/*------------------------------------------------------------------------------ +------------------------------- DHCP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#define LWIP_DHCP 0 + + +/*------------------------------------------------------------------------------ +------------------------------ AUTOIP Options ---------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#define LWIP_AUTOIP 0 + + +/*------------------------------------------------------------------------------ +------------------------------- SNMP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#define LWIP_SNMP 0 + + +/*------------------------------------------------------------------------------ +------------------------------- IGMP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#define LWIP_IGMP 0 + + +/*------------------------------------------------------------------------------ +-------------------------------- DNS Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#define LWIP_DNS 0 + + +/*------------------------------------------------------------------------------ +-------------------------------- UDP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_UDP==1: Turn on UDP. + */ +#define LWIP_UDP 1 + + +/*------------------------------------------------------------------------------ +-------------------------------- TCP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_TCP==1: Turn on TCP. + */ +#define LWIP_TCP 1 + +#define LWIP_LISTEN_BACKLOG 0 + + +/*------------------------------------------------------------------------------ +-------------------------------- Pbuf Options ---------------------------------- +------------------------------------------------------------------------------*/ + +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#define PBUF_LINK_HLEN 16 + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. +* + */ +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) + + +/*------------------------------------------------------------------------------ +--------------------------------- LOOPIF Options ------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#define LWIP_HAVE_LOOPIF 0 + + +/*------------------------------------------------------------------------------ +---------------------------- Sequential Layer Options -------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 0 + + +/*------------------------------------------------------------------------------ +--------------------------------- Socket Options ------------------------------- +------------------------------------------------------------------------------*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 0 + + +/*------------------------------------------------------------------------------ +------------------------------ Statistics Options ------------------------------ +------------------------------------------------------------------------------*/ + +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#define LWIP_STATS 1 + +/*------------------------------------------------------------------------------ +--------------------------------- PPP Options ---------------------------------- +------------------------------------------------------------------------------*/ + +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#define PPP_SUPPORT 0 + + +/* Misc */ + +#endif /* __LWIPOPTS_H__ */ diff --git a/ext/contrib/ports/unix/proj/lib/unixlib.c b/ext/contrib/ports/unix/proj/lib/unixlib.c new file mode 100644 index 000000000..950ae1cae --- /dev/null +++ b/ext/contrib/ports/unix/proj/lib/unixlib.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Kieran Mansley + * + * $Id: unixlib.c,v 1.10 2010/02/17 16:52:30 goldsimon Exp $ + */ + +/*-----------------------------------------------------------------------------------*/ +/* unixlib.c + * + * The initialisation functions for a shared library + * + * You may need to configure this file to your own needs - it is only an example + * of how lwIP can be used as a self initialising shared library. + * + * In particular, you should change the gateway, ipaddr, and netmask to be the values + * you would like the stack to use. + */ +/*-----------------------------------------------------------------------------------*/ + +/* +#include "lwip/init.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/tcp.h" +#include "lwip/tcpip.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/sockets.h" + +#include "netif/tapif.h" + +struct netif netif; +*/ + +static void +tcpip_init_done(void *arg) +{ + +} + +void _init(void){ + +} + +void _fini(void){ +} diff --git a/ext/cpp-httplib/httplib.h b/ext/cpp-httplib/httplib.h deleted file mode 100644 index 862e97e9e..000000000 --- a/ext/cpp-httplib/httplib.h +++ /dev/null @@ -1,9442 +0,0 @@ -// -// httplib.h -// -// Copyright (c) 2024 Yuji Hirose. All rights reserved. -// MIT License -// - -#ifndef CPPHTTPLIB_HTTPLIB_H -#define CPPHTTPLIB_HTTPLIB_H - -#define CPPHTTPLIB_VERSION "0.15.3" - -/* - * Configuration - */ - -#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND -#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5 -#endif - -#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT -#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 5 -#endif - -#ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND -#define CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND 300 -#endif - -#ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND -#define CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND 0 -#endif - -#ifndef CPPHTTPLIB_READ_TIMEOUT_SECOND -#define CPPHTTPLIB_READ_TIMEOUT_SECOND 5 -#endif - -#ifndef CPPHTTPLIB_READ_TIMEOUT_USECOND -#define CPPHTTPLIB_READ_TIMEOUT_USECOND 0 -#endif - -#ifndef CPPHTTPLIB_WRITE_TIMEOUT_SECOND -#define CPPHTTPLIB_WRITE_TIMEOUT_SECOND 5 -#endif - -#ifndef CPPHTTPLIB_WRITE_TIMEOUT_USECOND -#define CPPHTTPLIB_WRITE_TIMEOUT_USECOND 0 -#endif - -#ifndef CPPHTTPLIB_IDLE_INTERVAL_SECOND -#define CPPHTTPLIB_IDLE_INTERVAL_SECOND 0 -#endif - -#ifndef CPPHTTPLIB_IDLE_INTERVAL_USECOND -#ifdef _WIN32 -#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 10000 -#else -#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 0 -#endif -#endif - -#ifndef CPPHTTPLIB_REQUEST_URI_MAX_LENGTH -#define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192 -#endif - -#ifndef CPPHTTPLIB_HEADER_MAX_LENGTH -#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192 -#endif - -#ifndef CPPHTTPLIB_REDIRECT_MAX_COUNT -#define CPPHTTPLIB_REDIRECT_MAX_COUNT 20 -#endif - -#ifndef CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT -#define CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT 1024 -#endif - -#ifndef CPPHTTPLIB_PAYLOAD_MAX_LENGTH -#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH ((std::numeric_limits::max)()) -#endif - -#ifndef CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH -#define CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH 8192 -#endif - -#ifndef CPPHTTPLIB_RANGE_MAX_COUNT -#define CPPHTTPLIB_RANGE_MAX_COUNT 1024 -#endif - -#ifndef CPPHTTPLIB_TCP_NODELAY -#define CPPHTTPLIB_TCP_NODELAY false -#endif - -#ifndef CPPHTTPLIB_RECV_BUFSIZ -#define CPPHTTPLIB_RECV_BUFSIZ size_t(4096u) -#endif - -#ifndef CPPHTTPLIB_COMPRESSION_BUFSIZ -#define CPPHTTPLIB_COMPRESSION_BUFSIZ size_t(16384u) -#endif - -#ifndef CPPHTTPLIB_THREAD_POOL_COUNT -#define CPPHTTPLIB_THREAD_POOL_COUNT \ - ((std::max)(8u, std::thread::hardware_concurrency() > 0 \ - ? std::thread::hardware_concurrency() - 1 \ - : 0)) -#endif - -#ifndef CPPHTTPLIB_RECV_FLAGS -#define CPPHTTPLIB_RECV_FLAGS 0 -#endif - -#ifndef CPPHTTPLIB_SEND_FLAGS -#define CPPHTTPLIB_SEND_FLAGS 0 -#endif - -#ifndef CPPHTTPLIB_LISTEN_BACKLOG -#define CPPHTTPLIB_LISTEN_BACKLOG 5 -#endif - -/* - * Headers - */ - -#ifdef _WIN32 -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif //_CRT_SECURE_NO_WARNINGS - -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif //_CRT_NONSTDC_NO_DEPRECATE - -#if defined(_MSC_VER) -#if _MSC_VER < 1900 -#error Sorry, Visual Studio versions prior to 2015 are not supported -#endif - -#pragma comment(lib, "ws2_32.lib") - -#ifdef _WIN64 -using ssize_t = __int64; -#else -using ssize_t = long; -#endif -#endif // _MSC_VER - -#ifndef S_ISREG -#define S_ISREG(m) (((m) & S_IFREG) == S_IFREG) -#endif // S_ISREG - -#ifndef S_ISDIR -#define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR) -#endif // S_ISDIR - -#ifndef NOMINMAX -#define NOMINMAX -#endif // NOMINMAX - -#include -#include -#include - -#ifndef WSA_FLAG_NO_HANDLE_INHERIT -#define WSA_FLAG_NO_HANDLE_INHERIT 0x80 -#endif - -using socket_t = SOCKET; -#ifdef CPPHTTPLIB_USE_POLL -#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout) -#endif - -#else // not _WIN32 - -#include -#if !defined(_AIX) && !defined(__MVS__) -#include -#endif -#ifdef __MVS__ -#include -#ifndef NI_MAXHOST -#define NI_MAXHOST 1025 -#endif -#endif -#include -#include -#include -#ifdef __linux__ -#include -#endif -#include -#ifdef CPPHTTPLIB_USE_POLL -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -using socket_t = int; -#ifndef INVALID_SOCKET -#define INVALID_SOCKET (-1) -#endif -#endif //_WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -#ifdef _WIN32 -#include - -// these are defined in wincrypt.h and it breaks compilation if BoringSSL is -// used -#undef X509_NAME -#undef X509_CERT_PAIR -#undef X509_EXTENSIONS -#undef PKCS7_SIGNER_INFO - -#ifdef _MSC_VER -#pragma comment(lib, "crypt32.lib") -#endif -#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) -#include -#if TARGET_OS_OSX -#include -#include -#endif // TARGET_OS_OSX -#endif // _WIN32 - -#include -#include -#include -#include - -#if defined(_WIN32) && defined(OPENSSL_USE_APPLINK) -#include -#endif - -#include -#include - -#if OPENSSL_VERSION_NUMBER < 0x30000000L -#error Sorry, OpenSSL versions prior to 3.0.0 are not supported -#endif - -#endif - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT -#include -#endif - -#ifdef CPPHTTPLIB_BROTLI_SUPPORT -#include -#include -#endif - -/* - * Declaration - */ -namespace httplib { - -namespace detail { - -/* - * Backport std::make_unique from C++14. - * - * NOTE: This code came up with the following stackoverflow post: - * https://stackoverflow.com/questions/10149840/c-arrays-and-make-unique - * - */ - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Args &&...args) { - return std::unique_ptr(new T(std::forward(args)...)); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(std::size_t n) { - typedef typename std::remove_extent::type RT; - return std::unique_ptr(new RT[n]); -} - -struct ci { - bool operator()(const std::string &s1, const std::string &s2) const { - return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), - s2.end(), - [](unsigned char c1, unsigned char c2) { - return ::tolower(c1) < ::tolower(c2); - }); - } -}; - -// This is based on -// "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189". - -struct scope_exit { - explicit scope_exit(std::function &&f) - : exit_function(std::move(f)), execute_on_destruction{true} {} - - scope_exit(scope_exit &&rhs) noexcept - : exit_function(std::move(rhs.exit_function)), - execute_on_destruction{rhs.execute_on_destruction} { - rhs.release(); - } - - ~scope_exit() { - if (execute_on_destruction) { this->exit_function(); } - } - - void release() { this->execute_on_destruction = false; } - -private: - scope_exit(const scope_exit &) = delete; - void operator=(const scope_exit &) = delete; - scope_exit &operator=(scope_exit &&) = delete; - - std::function exit_function; - bool execute_on_destruction; -}; - -} // namespace detail - -enum StatusCode { - // Information responses - Continue_100 = 100, - SwitchingProtocol_101 = 101, - Processing_102 = 102, - EarlyHints_103 = 103, - - // Successful responses - OK_200 = 200, - Created_201 = 201, - Accepted_202 = 202, - NonAuthoritativeInformation_203 = 203, - NoContent_204 = 204, - ResetContent_205 = 205, - PartialContent_206 = 206, - MultiStatus_207 = 207, - AlreadyReported_208 = 208, - IMUsed_226 = 226, - - // Redirection messages - MultipleChoices_300 = 300, - MovedPermanently_301 = 301, - Found_302 = 302, - SeeOther_303 = 303, - NotModified_304 = 304, - UseProxy_305 = 305, - unused_306 = 306, - TemporaryRedirect_307 = 307, - PermanentRedirect_308 = 308, - - // Client error responses - BadRequest_400 = 400, - Unauthorized_401 = 401, - PaymentRequired_402 = 402, - Forbidden_403 = 403, - NotFound_404 = 404, - MethodNotAllowed_405 = 405, - NotAcceptable_406 = 406, - ProxyAuthenticationRequired_407 = 407, - RequestTimeout_408 = 408, - Conflict_409 = 409, - Gone_410 = 410, - LengthRequired_411 = 411, - PreconditionFailed_412 = 412, - PayloadTooLarge_413 = 413, - UriTooLong_414 = 414, - UnsupportedMediaType_415 = 415, - RangeNotSatisfiable_416 = 416, - ExpectationFailed_417 = 417, - ImATeapot_418 = 418, - MisdirectedRequest_421 = 421, - UnprocessableContent_422 = 422, - Locked_423 = 423, - FailedDependency_424 = 424, - TooEarly_425 = 425, - UpgradeRequired_426 = 426, - PreconditionRequired_428 = 428, - TooManyRequests_429 = 429, - RequestHeaderFieldsTooLarge_431 = 431, - UnavailableForLegalReasons_451 = 451, - - // Server error responses - InternalServerError_500 = 500, - NotImplemented_501 = 501, - BadGateway_502 = 502, - ServiceUnavailable_503 = 503, - GatewayTimeout_504 = 504, - HttpVersionNotSupported_505 = 505, - VariantAlsoNegotiates_506 = 506, - InsufficientStorage_507 = 507, - LoopDetected_508 = 508, - NotExtended_510 = 510, - NetworkAuthenticationRequired_511 = 511, -}; - -using Headers = std::multimap; - -using Params = std::multimap; -using Match = std::smatch; - -using Progress = std::function; - -struct Response; -using ResponseHandler = std::function; - -struct MultipartFormData { - std::string name; - std::string content; - std::string filename; - std::string content_type; -}; -using MultipartFormDataItems = std::vector; -using MultipartFormDataMap = std::multimap; - -class DataSink { -public: - DataSink() : os(&sb_), sb_(*this) {} - - DataSink(const DataSink &) = delete; - DataSink &operator=(const DataSink &) = delete; - DataSink(DataSink &&) = delete; - DataSink &operator=(DataSink &&) = delete; - - std::function write; - std::function is_writable; - std::function done; - std::function done_with_trailer; - std::ostream os; - -private: - class data_sink_streambuf : public std::streambuf { - public: - explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {} - - protected: - std::streamsize xsputn(const char *s, std::streamsize n) override { - sink_.write(s, static_cast(n)); - return n; - } - - private: - DataSink &sink_; - }; - - data_sink_streambuf sb_; -}; - -using ContentProvider = - std::function; - -using ContentProviderWithoutLength = - std::function; - -using ContentProviderResourceReleaser = std::function; - -struct MultipartFormDataProvider { - std::string name; - ContentProviderWithoutLength provider; - std::string filename; - std::string content_type; -}; -using MultipartFormDataProviderItems = std::vector; - -using ContentReceiverWithProgress = - std::function; - -using ContentReceiver = - std::function; - -using MultipartContentHeader = - std::function; - -class ContentReader { -public: - using Reader = std::function; - using MultipartReader = std::function; - - ContentReader(Reader reader, MultipartReader multipart_reader) - : reader_(std::move(reader)), - multipart_reader_(std::move(multipart_reader)) {} - - bool operator()(MultipartContentHeader header, - ContentReceiver receiver) const { - return multipart_reader_(std::move(header), std::move(receiver)); - } - - bool operator()(ContentReceiver receiver) const { - return reader_(std::move(receiver)); - } - - Reader reader_; - MultipartReader multipart_reader_; -}; - -using Range = std::pair; -using Ranges = std::vector; - -struct Request { - std::string method; - std::string path; - Headers headers; - std::string body; - - std::string remote_addr; - int remote_port = -1; - std::string local_addr; - int local_port = -1; - - // for server - std::string version; - std::string target; - Params params; - MultipartFormDataMap files; - Ranges ranges; - Match matches; - std::unordered_map path_params; - - // for client - ResponseHandler response_handler; - ContentReceiverWithProgress content_receiver; - Progress progress; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - const SSL *ssl = nullptr; -#endif - - bool has_header(const std::string &key) const; - std::string get_header_value(const std::string &key, size_t id = 0) const; - uint64_t get_header_value_u64(const std::string &key, size_t id = 0) const; - size_t get_header_value_count(const std::string &key) const; - void set_header(const std::string &key, const std::string &val); - - bool has_param(const std::string &key) const; - std::string get_param_value(const std::string &key, size_t id = 0) const; - size_t get_param_value_count(const std::string &key) const; - - bool is_multipart_form_data() const; - - bool has_file(const std::string &key) const; - MultipartFormData get_file_value(const std::string &key) const; - std::vector get_file_values(const std::string &key) const; - - // private members... - size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT; - size_t content_length_ = 0; - ContentProvider content_provider_; - bool is_chunked_content_provider_ = false; - size_t authorization_count_ = 0; -}; - -struct Response { - std::string version; - int status = -1; - std::string reason; - Headers headers; - std::string body; - std::string location; // Redirect location - - bool has_header(const std::string &key) const; - std::string get_header_value(const std::string &key, size_t id = 0) const; - uint64_t get_header_value_u64(const std::string &key, size_t id = 0) const; - size_t get_header_value_count(const std::string &key) const; - void set_header(const std::string &key, const std::string &val); - - void set_redirect(const std::string &url, int status = StatusCode::Found_302); - void set_content(const char *s, size_t n, const std::string &content_type); - void set_content(const std::string &s, const std::string &content_type); - void set_content(std::string &&s, const std::string &content_type); - - void set_content_provider( - size_t length, const std::string &content_type, ContentProvider provider, - ContentProviderResourceReleaser resource_releaser = nullptr); - - void set_content_provider( - const std::string &content_type, ContentProviderWithoutLength provider, - ContentProviderResourceReleaser resource_releaser = nullptr); - - void set_chunked_content_provider( - const std::string &content_type, ContentProviderWithoutLength provider, - ContentProviderResourceReleaser resource_releaser = nullptr); - - Response() = default; - Response(const Response &) = default; - Response &operator=(const Response &) = default; - Response(Response &&) = default; - Response &operator=(Response &&) = default; - ~Response() { - if (content_provider_resource_releaser_) { - content_provider_resource_releaser_(content_provider_success_); - } - } - - // private members... - size_t content_length_ = 0; - ContentProvider content_provider_; - ContentProviderResourceReleaser content_provider_resource_releaser_; - bool is_chunked_content_provider_ = false; - bool content_provider_success_ = false; -}; - -class Stream { -public: - virtual ~Stream() = default; - - virtual bool is_readable() const = 0; - virtual bool is_writable() const = 0; - - virtual ssize_t read(char *ptr, size_t size) = 0; - virtual ssize_t write(const char *ptr, size_t size) = 0; - virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0; - virtual void get_local_ip_and_port(std::string &ip, int &port) const = 0; - virtual socket_t socket() const = 0; - - template - ssize_t write_format(const char *fmt, const Args &...args); - ssize_t write(const char *ptr); - ssize_t write(const std::string &s); -}; - -class TaskQueue { -public: - TaskQueue() = default; - virtual ~TaskQueue() = default; - - virtual bool enqueue(std::function fn) = 0; - virtual void shutdown() = 0; - - virtual void on_idle() {} -}; - -class ThreadPool : public TaskQueue { -public: - explicit ThreadPool(size_t n, size_t mqr = 0) - : shutdown_(false), max_queued_requests_(mqr) { - while (n) { - threads_.emplace_back(worker(*this)); - n--; - } - } - - ThreadPool(const ThreadPool &) = delete; - ~ThreadPool() override = default; - - bool enqueue(std::function fn) override { - { - std::unique_lock lock(mutex_); - if (max_queued_requests_ > 0 && jobs_.size() >= max_queued_requests_) { - return false; - } - jobs_.push_back(std::move(fn)); - } - - cond_.notify_one(); - return true; - } - - void shutdown() override { - // Stop all worker threads... - { - std::unique_lock lock(mutex_); - shutdown_ = true; - } - - cond_.notify_all(); - - // Join... - for (auto &t : threads_) { - t.join(); - } - } - -private: - struct worker { - explicit worker(ThreadPool &pool) : pool_(pool) {} - - void operator()() { - for (;;) { - std::function fn; - { - std::unique_lock lock(pool_.mutex_); - - pool_.cond_.wait( - lock, [&] { return !pool_.jobs_.empty() || pool_.shutdown_; }); - - if (pool_.shutdown_ && pool_.jobs_.empty()) { break; } - - fn = std::move(pool_.jobs_.front()); - pool_.jobs_.pop_front(); - } - - assert(true == static_cast(fn)); - fn(); - } - } - - ThreadPool &pool_; - }; - friend struct worker; - - std::vector threads_; - std::list> jobs_; - - bool shutdown_; - size_t max_queued_requests_ = 0; - - std::condition_variable cond_; - std::mutex mutex_; -}; - -using Logger = std::function; - -using SocketOptions = std::function; - -void default_socket_options(socket_t sock); - -const char *status_message(int status); - -std::string get_bearer_token_auth(const Request &req); - -namespace detail { - -class MatcherBase { -public: - virtual ~MatcherBase() = default; - - // Match request path and populate its matches and - virtual bool match(Request &request) const = 0; -}; - -/** - * Captures parameters in request path and stores them in Request::path_params - * - * Capture name is a substring of a pattern from : to /. - * The rest of the pattern is matched agains the request path directly - * Parameters are captured starting from the next character after - * the end of the last matched static pattern fragment until the next /. - * - * Example pattern: - * "/path/fragments/:capture/more/fragments/:second_capture" - * Static fragments: - * "/path/fragments/", "more/fragments/" - * - * Given the following request path: - * "/path/fragments/:1/more/fragments/:2" - * the resulting capture will be - * {{"capture", "1"}, {"second_capture", "2"}} - */ -class PathParamsMatcher : public MatcherBase { -public: - PathParamsMatcher(const std::string &pattern); - - bool match(Request &request) const override; - -private: - static constexpr char marker = ':'; - // Treat segment separators as the end of path parameter capture - // Does not need to handle query parameters as they are parsed before path - // matching - static constexpr char separator = '/'; - - // Contains static path fragments to match against, excluding the '/' after - // path params - // Fragments are separated by path params - std::vector static_fragments_; - // Stores the names of the path parameters to be used as keys in the - // Request::path_params map - std::vector param_names_; -}; - -/** - * Performs std::regex_match on request path - * and stores the result in Request::matches - * - * Note that regex match is performed directly on the whole request. - * This means that wildcard patterns may match multiple path segments with /: - * "/begin/(.*)/end" will match both "/begin/middle/end" and "/begin/1/2/end". - */ -class RegexMatcher : public MatcherBase { -public: - RegexMatcher(const std::string &pattern) : regex_(pattern) {} - - bool match(Request &request) const override; - -private: - std::regex regex_; -}; - -ssize_t write_headers(Stream &strm, const Headers &headers); - -} // namespace detail - -class Server { -public: - using Handler = std::function; - - using ExceptionHandler = - std::function; - - enum class HandlerResponse { - Handled, - Unhandled, - }; - using HandlerWithResponse = - std::function; - - using HandlerWithContentReader = std::function; - - using Expect100ContinueHandler = - std::function; - - Server(); - - virtual ~Server(); - - virtual bool is_valid() const; - - Server &Get(const std::string &pattern, Handler handler); - Server &Post(const std::string &pattern, Handler handler); - Server &Post(const std::string &pattern, HandlerWithContentReader handler); - Server &Put(const std::string &pattern, Handler handler); - Server &Put(const std::string &pattern, HandlerWithContentReader handler); - Server &Patch(const std::string &pattern, Handler handler); - Server &Patch(const std::string &pattern, HandlerWithContentReader handler); - Server &Delete(const std::string &pattern, Handler handler); - Server &Delete(const std::string &pattern, HandlerWithContentReader handler); - Server &Options(const std::string &pattern, Handler handler); - - bool set_base_dir(const std::string &dir, - const std::string &mount_point = std::string()); - bool set_mount_point(const std::string &mount_point, const std::string &dir, - Headers headers = Headers()); - bool remove_mount_point(const std::string &mount_point); - Server &set_file_extension_and_mimetype_mapping(const std::string &ext, - const std::string &mime); - Server &set_default_file_mimetype(const std::string &mime); - Server &set_file_request_handler(Handler handler); - - Server &set_error_handler(HandlerWithResponse handler); - Server &set_error_handler(Handler handler); - Server &set_exception_handler(ExceptionHandler handler); - Server &set_pre_routing_handler(HandlerWithResponse handler); - Server &set_post_routing_handler(Handler handler); - - Server &set_expect_100_continue_handler(Expect100ContinueHandler handler); - Server &set_logger(Logger logger); - - Server &set_address_family(int family); - Server &set_tcp_nodelay(bool on); - Server &set_socket_options(SocketOptions socket_options); - - Server &set_default_headers(Headers headers); - Server & - set_header_writer(std::function const &writer); - - Server &set_keep_alive_max_count(size_t count); - Server &set_keep_alive_timeout(time_t sec); - - Server &set_read_timeout(time_t sec, time_t usec = 0); - template - Server &set_read_timeout(const std::chrono::duration &duration); - - Server &set_write_timeout(time_t sec, time_t usec = 0); - template - Server &set_write_timeout(const std::chrono::duration &duration); - - Server &set_idle_interval(time_t sec, time_t usec = 0); - template - Server &set_idle_interval(const std::chrono::duration &duration); - - Server &set_payload_max_length(size_t length); - - bool bind_to_port(const std::string &host, int port, int socket_flags = 0); - int bind_to_any_port(const std::string &host, int socket_flags = 0); - bool listen_after_bind(); - - bool listen(const std::string &host, int port, int socket_flags = 0); - - bool is_running() const; - void wait_until_ready() const; - void stop(); - - std::function new_task_queue; - - bool routing(Request &req, Response &res, Stream &strm); - -protected: - bool process_request(Stream &strm, bool close_connection, - bool &connection_closed, - const std::function &setup_request); - - std::atomic svr_sock_{INVALID_SOCKET}; - size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT; - time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND; - time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND; - time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND; - time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND; - time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND; - time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND; - time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND; - size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH; - -private: - using Handlers = - std::vector, Handler>>; - using HandlersForContentReader = - std::vector, - HandlerWithContentReader>>; - - static std::unique_ptr - make_matcher(const std::string &pattern); - - socket_t create_server_socket(const std::string &host, int port, - int socket_flags, - SocketOptions socket_options) const; - int bind_internal(const std::string &host, int port, int socket_flags); - bool listen_internal(); - - bool handle_file_request(const Request &req, Response &res, - bool head = false); - bool dispatch_request(Request &req, Response &res, - const Handlers &handlers) const; - bool dispatch_request_for_content_reader( - Request &req, Response &res, ContentReader content_reader, - const HandlersForContentReader &handlers) const; - - bool parse_request_line(const char *s, Request &req) const; - void apply_ranges(const Request &req, Response &res, - std::string &content_type, std::string &boundary) const; - bool write_response(Stream &strm, bool close_connection, Request &req, - Response &res); - bool write_response_with_content(Stream &strm, bool close_connection, - const Request &req, Response &res); - bool write_response_core(Stream &strm, bool close_connection, - const Request &req, Response &res, - bool need_apply_ranges); - bool write_content_with_provider(Stream &strm, const Request &req, - Response &res, const std::string &boundary, - const std::string &content_type); - bool read_content(Stream &strm, Request &req, Response &res); - bool - read_content_with_content_receiver(Stream &strm, Request &req, Response &res, - ContentReceiver receiver, - MultipartContentHeader multipart_header, - ContentReceiver multipart_receiver); - bool read_content_core(Stream &strm, Request &req, Response &res, - ContentReceiver receiver, - MultipartContentHeader multipart_header, - ContentReceiver multipart_receiver) const; - - virtual bool process_and_close_socket(socket_t sock); - - std::atomic is_running_{false}; - std::atomic done_{false}; - - struct MountPointEntry { - std::string mount_point; - std::string base_dir; - Headers headers; - }; - std::vector base_dirs_; - std::map file_extension_and_mimetype_map_; - std::string default_file_mimetype_ = "application/octet-stream"; - Handler file_request_handler_; - - Handlers get_handlers_; - Handlers post_handlers_; - HandlersForContentReader post_handlers_for_content_reader_; - Handlers put_handlers_; - HandlersForContentReader put_handlers_for_content_reader_; - Handlers patch_handlers_; - HandlersForContentReader patch_handlers_for_content_reader_; - Handlers delete_handlers_; - HandlersForContentReader delete_handlers_for_content_reader_; - Handlers options_handlers_; - - HandlerWithResponse error_handler_; - ExceptionHandler exception_handler_; - HandlerWithResponse pre_routing_handler_; - Handler post_routing_handler_; - Expect100ContinueHandler expect_100_continue_handler_; - - Logger logger_; - - int address_family_ = AF_UNSPEC; - bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY; - SocketOptions socket_options_ = default_socket_options; - - Headers default_headers_; - std::function header_writer_ = - detail::write_headers; -}; - -enum class Error { - Success = 0, - Unknown, - Connection, - BindIPAddress, - Read, - Write, - ExceedRedirectCount, - Canceled, - SSLConnection, - SSLLoadingCerts, - SSLServerVerification, - UnsupportedMultipartBoundaryChars, - Compression, - ConnectionTimeout, - ProxyConnection, - - // For internal use only - SSLPeerCouldBeClosed_, -}; - -std::string to_string(Error error); - -std::ostream &operator<<(std::ostream &os, const Error &obj); - -class Result { -public: - Result() = default; - Result(std::unique_ptr &&res, Error err, - Headers &&request_headers = Headers{}) - : res_(std::move(res)), err_(err), - request_headers_(std::move(request_headers)) {} - // Response - operator bool() const { return res_ != nullptr; } - bool operator==(std::nullptr_t) const { return res_ == nullptr; } - bool operator!=(std::nullptr_t) const { return res_ != nullptr; } - const Response &value() const { return *res_; } - Response &value() { return *res_; } - const Response &operator*() const { return *res_; } - Response &operator*() { return *res_; } - const Response *operator->() const { return res_.get(); } - Response *operator->() { return res_.get(); } - - // Error - Error error() const { return err_; } - - // Request Headers - bool has_request_header(const std::string &key) const; - std::string get_request_header_value(const std::string &key, - size_t id = 0) const; - uint64_t get_request_header_value_u64(const std::string &key, - size_t id = 0) const; - size_t get_request_header_value_count(const std::string &key) const; - -private: - std::unique_ptr res_; - Error err_ = Error::Unknown; - Headers request_headers_; -}; - -class ClientImpl { -public: - explicit ClientImpl(const std::string &host); - - explicit ClientImpl(const std::string &host, int port); - - explicit ClientImpl(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path); - - virtual ~ClientImpl(); - - virtual bool is_valid() const; - - Result Get(const std::string &path); - Result Get(const std::string &path, const Headers &headers); - Result Get(const std::string &path, Progress progress); - Result Get(const std::string &path, const Headers &headers, - Progress progress); - Result Get(const std::string &path, ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver); - Result Get(const std::string &path, ContentReceiver content_receiver, - Progress progress); - Result Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver, Progress progress); - Result Get(const std::string &path, ResponseHandler response_handler, - ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver); - Result Get(const std::string &path, ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress); - Result Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, ContentReceiver content_receiver, - Progress progress); - - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, Progress progress = nullptr); - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, ContentReceiver content_receiver, - Progress progress = nullptr); - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress = nullptr); - - Result Head(const std::string &path); - Result Head(const std::string &path, const Headers &headers); - - Result Post(const std::string &path); - Result Post(const std::string &path, const Headers &headers); - Result Post(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, const char *body, - size_t content_length, const std::string &content_type); - Result Post(const std::string &path, const std::string &body, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Post(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type); - Result Post(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Params ¶ms); - Result Post(const std::string &path, const Headers &headers, - const Params ¶ms); - Result Post(const std::string &path, const MultipartFormDataItems &items); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, const std::string &boundary); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - Result Put(const std::string &path); - Result Put(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, const char *body, - size_t content_length, const std::string &content_type); - Result Put(const std::string &path, const std::string &body, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Put(const std::string &path, size_t content_length, - ContentProvider content_provider, const std::string &content_type); - Result Put(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Params ¶ms); - Result Put(const std::string &path, const Headers &headers, - const Params ¶ms); - Result Put(const std::string &path, const MultipartFormDataItems &items); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, const std::string &boundary); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - Result Patch(const std::string &path); - Result Patch(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type); - Result Patch(const std::string &path, const std::string &body, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Patch(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type); - Result Patch(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - - Result Delete(const std::string &path); - Result Delete(const std::string &path, const Headers &headers); - Result Delete(const std::string &path, const char *body, - size_t content_length, const std::string &content_type); - Result Delete(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type); - Result Delete(const std::string &path, const std::string &body, - const std::string &content_type); - Result Delete(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - - Result Options(const std::string &path); - Result Options(const std::string &path, const Headers &headers); - - bool send(Request &req, Response &res, Error &error); - Result send(const Request &req); - - void stop(); - - std::string host() const; - int port() const; - - size_t is_socket_open() const; - socket_t socket() const; - - void set_hostname_addr_map(std::map addr_map); - - void set_default_headers(Headers headers); - - void - set_header_writer(std::function const &writer); - - void set_address_family(int family); - void set_tcp_nodelay(bool on); - void set_socket_options(SocketOptions socket_options); - - void set_connection_timeout(time_t sec, time_t usec = 0); - template - void - set_connection_timeout(const std::chrono::duration &duration); - - void set_read_timeout(time_t sec, time_t usec = 0); - template - void set_read_timeout(const std::chrono::duration &duration); - - void set_write_timeout(time_t sec, time_t usec = 0); - template - void set_write_timeout(const std::chrono::duration &duration); - - void set_basic_auth(const std::string &username, const std::string &password); - void set_bearer_token_auth(const std::string &token); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_digest_auth(const std::string &username, - const std::string &password); -#endif - - void set_keep_alive(bool on); - void set_follow_location(bool on); - - void set_url_encode(bool on); - - void set_compress(bool on); - - void set_decompress(bool on); - - void set_interface(const std::string &intf); - - void set_proxy(const std::string &host, int port); - void set_proxy_basic_auth(const std::string &username, - const std::string &password); - void set_proxy_bearer_token_auth(const std::string &token); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_proxy_digest_auth(const std::string &username, - const std::string &password); -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_ca_cert_path(const std::string &ca_cert_file_path, - const std::string &ca_cert_dir_path = std::string()); - void set_ca_cert_store(X509_STORE *ca_cert_store); - X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size) const; -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void enable_server_certificate_verification(bool enabled); -#endif - - void set_logger(Logger logger); - -protected: - struct Socket { - socket_t sock = INVALID_SOCKET; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - SSL *ssl = nullptr; -#endif - - bool is_open() const { return sock != INVALID_SOCKET; } - }; - - virtual bool create_and_connect_socket(Socket &socket, Error &error); - - // All of: - // shutdown_ssl - // shutdown_socket - // close_socket - // should ONLY be called when socket_mutex_ is locked. - // Also, shutdown_ssl and close_socket should also NOT be called concurrently - // with a DIFFERENT thread sending requests using that socket. - virtual void shutdown_ssl(Socket &socket, bool shutdown_gracefully); - void shutdown_socket(Socket &socket) const; - void close_socket(Socket &socket); - - bool process_request(Stream &strm, Request &req, Response &res, - bool close_connection, Error &error); - - bool write_content_with_provider(Stream &strm, const Request &req, - Error &error) const; - - void copy_settings(const ClientImpl &rhs); - - // Socket endpoint information - const std::string host_; - const int port_; - const std::string host_and_port_; - - // Current open socket - Socket socket_; - mutable std::mutex socket_mutex_; - std::recursive_mutex request_mutex_; - - // These are all protected under socket_mutex - size_t socket_requests_in_flight_ = 0; - std::thread::id socket_requests_are_from_thread_ = std::thread::id(); - bool socket_should_be_closed_when_request_is_done_ = false; - - // Hostname-IP map - std::map addr_map_; - - // Default headers - Headers default_headers_; - - // Header writer - std::function header_writer_ = - detail::write_headers; - - // Settings - std::string client_cert_path_; - std::string client_key_path_; - - time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND; - time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND; - time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND; - time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND; - time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND; - time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND; - - std::string basic_auth_username_; - std::string basic_auth_password_; - std::string bearer_token_auth_token_; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - std::string digest_auth_username_; - std::string digest_auth_password_; -#endif - - bool keep_alive_ = false; - bool follow_location_ = false; - - bool url_encode_ = true; - - int address_family_ = AF_UNSPEC; - bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY; - SocketOptions socket_options_ = nullptr; - - bool compress_ = false; - bool decompress_ = true; - - std::string interface_; - - std::string proxy_host_; - int proxy_port_ = -1; - - std::string proxy_basic_auth_username_; - std::string proxy_basic_auth_password_; - std::string proxy_bearer_token_auth_token_; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - std::string proxy_digest_auth_username_; - std::string proxy_digest_auth_password_; -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - std::string ca_cert_file_path_; - std::string ca_cert_dir_path_; - - X509_STORE *ca_cert_store_ = nullptr; -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - bool server_certificate_verification_ = true; -#endif - - Logger logger_; - -private: - bool send_(Request &req, Response &res, Error &error); - Result send_(Request &&req); - - socket_t create_client_socket(Error &error) const; - bool read_response_line(Stream &strm, const Request &req, - Response &res) const; - bool write_request(Stream &strm, Request &req, bool close_connection, - Error &error); - bool redirect(Request &req, Response &res, Error &error); - bool handle_request(Stream &strm, Request &req, Response &res, - bool close_connection, Error &error); - std::unique_ptr send_with_content_provider( - Request &req, const char *body, size_t content_length, - ContentProvider content_provider, - ContentProviderWithoutLength content_provider_without_length, - const std::string &content_type, Error &error); - Result send_with_content_provider( - const std::string &method, const std::string &path, - const Headers &headers, const char *body, size_t content_length, - ContentProvider content_provider, - ContentProviderWithoutLength content_provider_without_length, - const std::string &content_type); - ContentProviderWithoutLength get_multipart_content_provider( - const std::string &boundary, const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) const; - - std::string adjust_host_string(const std::string &host) const; - - virtual bool process_socket(const Socket &socket, - std::function callback); - virtual bool is_ssl() const; -}; - -class Client { -public: - // Universal interface - explicit Client(const std::string &scheme_host_port); - - explicit Client(const std::string &scheme_host_port, - const std::string &client_cert_path, - const std::string &client_key_path); - - // HTTP only interface - explicit Client(const std::string &host, int port); - - explicit Client(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path); - - Client(Client &&) = default; - - ~Client(); - - bool is_valid() const; - - Result Get(const std::string &path); - Result Get(const std::string &path, const Headers &headers); - Result Get(const std::string &path, Progress progress); - Result Get(const std::string &path, const Headers &headers, - Progress progress); - Result Get(const std::string &path, ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver); - Result Get(const std::string &path, ContentReceiver content_receiver, - Progress progress); - Result Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver, Progress progress); - Result Get(const std::string &path, ResponseHandler response_handler, - ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, ContentReceiver content_receiver, - Progress progress); - Result Get(const std::string &path, ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress); - - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, Progress progress = nullptr); - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, ContentReceiver content_receiver, - Progress progress = nullptr); - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress = nullptr); - - Result Head(const std::string &path); - Result Head(const std::string &path, const Headers &headers); - - Result Post(const std::string &path); - Result Post(const std::string &path, const Headers &headers); - Result Post(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, const char *body, - size_t content_length, const std::string &content_type); - Result Post(const std::string &path, const std::string &body, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Post(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type); - Result Post(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Params ¶ms); - Result Post(const std::string &path, const Headers &headers, - const Params ¶ms); - Result Post(const std::string &path, const MultipartFormDataItems &items); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, const std::string &boundary); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - Result Put(const std::string &path); - Result Put(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, const char *body, - size_t content_length, const std::string &content_type); - Result Put(const std::string &path, const std::string &body, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Put(const std::string &path, size_t content_length, - ContentProvider content_provider, const std::string &content_type); - Result Put(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Params ¶ms); - Result Put(const std::string &path, const Headers &headers, - const Params ¶ms); - Result Put(const std::string &path, const MultipartFormDataItems &items); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, const std::string &boundary); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - Result Patch(const std::string &path); - Result Patch(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type); - Result Patch(const std::string &path, const std::string &body, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Patch(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type); - Result Patch(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - - Result Delete(const std::string &path); - Result Delete(const std::string &path, const Headers &headers); - Result Delete(const std::string &path, const char *body, - size_t content_length, const std::string &content_type); - Result Delete(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type); - Result Delete(const std::string &path, const std::string &body, - const std::string &content_type); - Result Delete(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - - Result Options(const std::string &path); - Result Options(const std::string &path, const Headers &headers); - - bool send(Request &req, Response &res, Error &error); - Result send(const Request &req); - - void stop(); - - std::string host() const; - int port() const; - - size_t is_socket_open() const; - socket_t socket() const; - - void set_hostname_addr_map(std::map addr_map); - - void set_default_headers(Headers headers); - - void - set_header_writer(std::function const &writer); - - void set_address_family(int family); - void set_tcp_nodelay(bool on); - void set_socket_options(SocketOptions socket_options); - - void set_connection_timeout(time_t sec, time_t usec = 0); - template - void - set_connection_timeout(const std::chrono::duration &duration); - - void set_read_timeout(time_t sec, time_t usec = 0); - template - void set_read_timeout(const std::chrono::duration &duration); - - void set_write_timeout(time_t sec, time_t usec = 0); - template - void set_write_timeout(const std::chrono::duration &duration); - - void set_basic_auth(const std::string &username, const std::string &password); - void set_bearer_token_auth(const std::string &token); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_digest_auth(const std::string &username, - const std::string &password); -#endif - - void set_keep_alive(bool on); - void set_follow_location(bool on); - - void set_url_encode(bool on); - - void set_compress(bool on); - - void set_decompress(bool on); - - void set_interface(const std::string &intf); - - void set_proxy(const std::string &host, int port); - void set_proxy_basic_auth(const std::string &username, - const std::string &password); - void set_proxy_bearer_token_auth(const std::string &token); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_proxy_digest_auth(const std::string &username, - const std::string &password); -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void enable_server_certificate_verification(bool enabled); -#endif - - void set_logger(Logger logger); - - // SSL -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_ca_cert_path(const std::string &ca_cert_file_path, - const std::string &ca_cert_dir_path = std::string()); - - void set_ca_cert_store(X509_STORE *ca_cert_store); - void load_ca_cert_store(const char *ca_cert, std::size_t size); - - long get_openssl_verify_result() const; - - SSL_CTX *ssl_context() const; -#endif - -private: - std::unique_ptr cli_; - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - bool is_ssl_ = false; -#endif -}; - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -class SSLServer : public Server { -public: - SSLServer(const char *cert_path, const char *private_key_path, - const char *client_ca_cert_file_path = nullptr, - const char *client_ca_cert_dir_path = nullptr, - const char *private_key_password = nullptr); - - SSLServer(X509 *cert, EVP_PKEY *private_key, - X509_STORE *client_ca_cert_store = nullptr); - - SSLServer( - const std::function &setup_ssl_ctx_callback); - - ~SSLServer() override; - - bool is_valid() const override; - - SSL_CTX *ssl_context() const; - -private: - bool process_and_close_socket(socket_t sock) override; - - SSL_CTX *ctx_; - std::mutex ctx_mutex_; -}; - -class SSLClient : public ClientImpl { -public: - explicit SSLClient(const std::string &host); - - explicit SSLClient(const std::string &host, int port); - - explicit SSLClient(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path); - - explicit SSLClient(const std::string &host, int port, X509 *client_cert, - EVP_PKEY *client_key); - - ~SSLClient() override; - - bool is_valid() const override; - - void set_ca_cert_store(X509_STORE *ca_cert_store); - void load_ca_cert_store(const char *ca_cert, std::size_t size); - - long get_openssl_verify_result() const; - - SSL_CTX *ssl_context() const; - -private: - bool create_and_connect_socket(Socket &socket, Error &error) override; - void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override; - void shutdown_ssl_impl(Socket &socket, bool shutdown_gracefully); - - bool process_socket(const Socket &socket, - std::function callback) override; - bool is_ssl() const override; - - bool connect_with_proxy(Socket &sock, Response &res, bool &success, - Error &error); - bool initialize_ssl(Socket &socket, Error &error); - - bool load_certs(); - - bool verify_host(X509 *server_cert) const; - bool verify_host_with_subject_alt_name(X509 *server_cert) const; - bool verify_host_with_common_name(X509 *server_cert) const; - bool check_host_name(const char *pattern, size_t pattern_len) const; - - SSL_CTX *ctx_; - std::mutex ctx_mutex_; - std::once_flag initialize_cert_; - - std::vector host_components_; - - long verify_result_ = 0; - - friend class ClientImpl; -}; -#endif - -/* - * Implementation of template methods. - */ - -namespace detail { - -template -inline void duration_to_sec_and_usec(const T &duration, U callback) { - auto sec = std::chrono::duration_cast(duration).count(); - auto usec = std::chrono::duration_cast( - duration - std::chrono::seconds(sec)) - .count(); - callback(static_cast(sec), static_cast(usec)); -} - -inline uint64_t get_header_value_u64(const Headers &headers, - const std::string &key, size_t id, - uint64_t def) { - auto rng = headers.equal_range(key); - auto it = rng.first; - std::advance(it, static_cast(id)); - if (it != rng.second) { - return std::strtoull(it->second.data(), nullptr, 10); - } - return def; -} - -} // namespace detail - -inline uint64_t Request::get_header_value_u64(const std::string &key, - size_t id) const { - return detail::get_header_value_u64(headers, key, id, 0); -} - -inline uint64_t Response::get_header_value_u64(const std::string &key, - size_t id) const { - return detail::get_header_value_u64(headers, key, id, 0); -} - -template -inline ssize_t Stream::write_format(const char *fmt, const Args &...args) { - const auto bufsiz = 2048; - std::array buf{}; - - auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...); - if (sn <= 0) { return sn; } - - auto n = static_cast(sn); - - if (n >= buf.size() - 1) { - std::vector glowable_buf(buf.size()); - - while (n >= glowable_buf.size() - 1) { - glowable_buf.resize(glowable_buf.size() * 2); - n = static_cast( - snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...)); - } - return write(&glowable_buf[0], n); - } else { - return write(buf.data(), n); - } -} - -inline void default_socket_options(socket_t sock) { - int yes = 1; -#ifdef _WIN32 - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - reinterpret_cast(&yes), sizeof(yes)); - setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, - reinterpret_cast(&yes), sizeof(yes)); -#else -#ifdef SO_REUSEPORT - setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, - reinterpret_cast(&yes), sizeof(yes)); -#else - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - reinterpret_cast(&yes), sizeof(yes)); -#endif -#endif -} - -inline const char *status_message(int status) { - switch (status) { - case StatusCode::Continue_100: return "Continue"; - case StatusCode::SwitchingProtocol_101: return "Switching Protocol"; - case StatusCode::Processing_102: return "Processing"; - case StatusCode::EarlyHints_103: return "Early Hints"; - case StatusCode::OK_200: return "OK"; - case StatusCode::Created_201: return "Created"; - case StatusCode::Accepted_202: return "Accepted"; - case StatusCode::NonAuthoritativeInformation_203: - return "Non-Authoritative Information"; - case StatusCode::NoContent_204: return "No Content"; - case StatusCode::ResetContent_205: return "Reset Content"; - case StatusCode::PartialContent_206: return "Partial Content"; - case StatusCode::MultiStatus_207: return "Multi-Status"; - case StatusCode::AlreadyReported_208: return "Already Reported"; - case StatusCode::IMUsed_226: return "IM Used"; - case StatusCode::MultipleChoices_300: return "Multiple Choices"; - case StatusCode::MovedPermanently_301: return "Moved Permanently"; - case StatusCode::Found_302: return "Found"; - case StatusCode::SeeOther_303: return "See Other"; - case StatusCode::NotModified_304: return "Not Modified"; - case StatusCode::UseProxy_305: return "Use Proxy"; - case StatusCode::unused_306: return "unused"; - case StatusCode::TemporaryRedirect_307: return "Temporary Redirect"; - case StatusCode::PermanentRedirect_308: return "Permanent Redirect"; - case StatusCode::BadRequest_400: return "Bad Request"; - case StatusCode::Unauthorized_401: return "Unauthorized"; - case StatusCode::PaymentRequired_402: return "Payment Required"; - case StatusCode::Forbidden_403: return "Forbidden"; - case StatusCode::NotFound_404: return "Not Found"; - case StatusCode::MethodNotAllowed_405: return "Method Not Allowed"; - case StatusCode::NotAcceptable_406: return "Not Acceptable"; - case StatusCode::ProxyAuthenticationRequired_407: - return "Proxy Authentication Required"; - case StatusCode::RequestTimeout_408: return "Request Timeout"; - case StatusCode::Conflict_409: return "Conflict"; - case StatusCode::Gone_410: return "Gone"; - case StatusCode::LengthRequired_411: return "Length Required"; - case StatusCode::PreconditionFailed_412: return "Precondition Failed"; - case StatusCode::PayloadTooLarge_413: return "Payload Too Large"; - case StatusCode::UriTooLong_414: return "URI Too Long"; - case StatusCode::UnsupportedMediaType_415: return "Unsupported Media Type"; - case StatusCode::RangeNotSatisfiable_416: return "Range Not Satisfiable"; - case StatusCode::ExpectationFailed_417: return "Expectation Failed"; - case StatusCode::ImATeapot_418: return "I'm a teapot"; - case StatusCode::MisdirectedRequest_421: return "Misdirected Request"; - case StatusCode::UnprocessableContent_422: return "Unprocessable Content"; - case StatusCode::Locked_423: return "Locked"; - case StatusCode::FailedDependency_424: return "Failed Dependency"; - case StatusCode::TooEarly_425: return "Too Early"; - case StatusCode::UpgradeRequired_426: return "Upgrade Required"; - case StatusCode::PreconditionRequired_428: return "Precondition Required"; - case StatusCode::TooManyRequests_429: return "Too Many Requests"; - case StatusCode::RequestHeaderFieldsTooLarge_431: - return "Request Header Fields Too Large"; - case StatusCode::UnavailableForLegalReasons_451: - return "Unavailable For Legal Reasons"; - case StatusCode::NotImplemented_501: return "Not Implemented"; - case StatusCode::BadGateway_502: return "Bad Gateway"; - case StatusCode::ServiceUnavailable_503: return "Service Unavailable"; - case StatusCode::GatewayTimeout_504: return "Gateway Timeout"; - case StatusCode::HttpVersionNotSupported_505: - return "HTTP Version Not Supported"; - case StatusCode::VariantAlsoNegotiates_506: return "Variant Also Negotiates"; - case StatusCode::InsufficientStorage_507: return "Insufficient Storage"; - case StatusCode::LoopDetected_508: return "Loop Detected"; - case StatusCode::NotExtended_510: return "Not Extended"; - case StatusCode::NetworkAuthenticationRequired_511: - return "Network Authentication Required"; - - default: - case StatusCode::InternalServerError_500: return "Internal Server Error"; - } -} - -inline std::string get_bearer_token_auth(const Request &req) { - if (req.has_header("Authorization")) { - static std::string BearerHeaderPrefix = "Bearer "; - return req.get_header_value("Authorization") - .substr(BearerHeaderPrefix.length()); - } - return ""; -} - -template -inline Server & -Server::set_read_timeout(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); - return *this; -} - -template -inline Server & -Server::set_write_timeout(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); - return *this; -} - -template -inline Server & -Server::set_idle_interval(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_idle_interval(sec, usec); }); - return *this; -} - -inline std::string to_string(const Error error) { - switch (error) { - case Error::Success: return "Success (no error)"; - case Error::Connection: return "Could not establish connection"; - case Error::BindIPAddress: return "Failed to bind IP address"; - case Error::Read: return "Failed to read connection"; - case Error::Write: return "Failed to write connection"; - case Error::ExceedRedirectCount: return "Maximum redirect count exceeded"; - case Error::Canceled: return "Connection handling canceled"; - case Error::SSLConnection: return "SSL connection failed"; - case Error::SSLLoadingCerts: return "SSL certificate loading failed"; - case Error::SSLServerVerification: return "SSL server verification failed"; - case Error::UnsupportedMultipartBoundaryChars: - return "Unsupported HTTP multipart boundary characters"; - case Error::Compression: return "Compression failed"; - case Error::ConnectionTimeout: return "Connection timed out"; - case Error::ProxyConnection: return "Proxy connection failed"; - case Error::Unknown: return "Unknown"; - default: break; - } - - return "Invalid"; -} - -inline std::ostream &operator<<(std::ostream &os, const Error &obj) { - os << to_string(obj); - os << " (" << static_cast::type>(obj) << ')'; - return os; -} - -inline uint64_t Result::get_request_header_value_u64(const std::string &key, - size_t id) const { - return detail::get_header_value_u64(request_headers_, key, id, 0); -} - -template -inline void ClientImpl::set_connection_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) { - set_connection_timeout(sec, usec); - }); -} - -template -inline void ClientImpl::set_read_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); -} - -template -inline void ClientImpl::set_write_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); -} - -template -inline void Client::set_connection_timeout( - const std::chrono::duration &duration) { - cli_->set_connection_timeout(duration); -} - -template -inline void -Client::set_read_timeout(const std::chrono::duration &duration) { - cli_->set_read_timeout(duration); -} - -template -inline void -Client::set_write_timeout(const std::chrono::duration &duration) { - cli_->set_write_timeout(duration); -} - -/* - * Forward declarations and types that will be part of the .h file if split into - * .h + .cc. - */ - -std::string hosted_at(const std::string &hostname); - -void hosted_at(const std::string &hostname, std::vector &addrs); - -std::string append_query_params(const std::string &path, const Params ¶ms); - -std::pair make_range_header(const Ranges &ranges); - -std::pair -make_basic_authentication_header(const std::string &username, - const std::string &password, - bool is_proxy = false); - -namespace detail { - -std::string encode_query_param(const std::string &value); - -std::string decode_url(const std::string &s, bool convert_plus_to_space); - -void read_file(const std::string &path, std::string &out); - -std::string trim_copy(const std::string &s); - -void split(const char *b, const char *e, char d, - std::function fn); - -void split(const char *b, const char *e, char d, size_t m, - std::function fn); - -bool process_client_socket(socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, - std::function callback); - -socket_t create_client_socket( - const std::string &host, const std::string &ip, int port, - int address_family, bool tcp_nodelay, SocketOptions socket_options, - time_t connection_timeout_sec, time_t connection_timeout_usec, - time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, const std::string &intf, Error &error); - -const char *get_header_value(const Headers &headers, const std::string &key, - size_t id = 0, const char *def = nullptr); - -std::string params_to_query_str(const Params ¶ms); - -void parse_query_text(const std::string &s, Params ¶ms); - -bool parse_multipart_boundary(const std::string &content_type, - std::string &boundary); - -bool parse_range_header(const std::string &s, Ranges &ranges); - -int close_socket(socket_t sock); - -ssize_t send_socket(socket_t sock, const void *ptr, size_t size, int flags); - -ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags); - -enum class EncodingType { None = 0, Gzip, Brotli }; - -EncodingType encoding_type(const Request &req, const Response &res); - -class BufferStream : public Stream { -public: - BufferStream() = default; - ~BufferStream() override = default; - - bool is_readable() const override; - bool is_writable() const override; - ssize_t read(char *ptr, size_t size) override; - ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; - void get_local_ip_and_port(std::string &ip, int &port) const override; - socket_t socket() const override; - - const std::string &get_buffer() const; - -private: - std::string buffer; - size_t position = 0; -}; - -class compressor { -public: - virtual ~compressor() = default; - - typedef std::function Callback; - virtual bool compress(const char *data, size_t data_length, bool last, - Callback callback) = 0; -}; - -class decompressor { -public: - virtual ~decompressor() = default; - - virtual bool is_valid() const = 0; - - typedef std::function Callback; - virtual bool decompress(const char *data, size_t data_length, - Callback callback) = 0; -}; - -class nocompressor : public compressor { -public: - ~nocompressor() override = default; - - bool compress(const char *data, size_t data_length, bool /*last*/, - Callback callback) override; -}; - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT -class gzip_compressor : public compressor { -public: - gzip_compressor(); - ~gzip_compressor() override; - - bool compress(const char *data, size_t data_length, bool last, - Callback callback) override; - -private: - bool is_valid_ = false; - z_stream strm_; -}; - -class gzip_decompressor : public decompressor { -public: - gzip_decompressor(); - ~gzip_decompressor() override; - - bool is_valid() const override; - - bool decompress(const char *data, size_t data_length, - Callback callback) override; - -private: - bool is_valid_ = false; - z_stream strm_; -}; -#endif - -#ifdef CPPHTTPLIB_BROTLI_SUPPORT -class brotli_compressor : public compressor { -public: - brotli_compressor(); - ~brotli_compressor(); - - bool compress(const char *data, size_t data_length, bool last, - Callback callback) override; - -private: - BrotliEncoderState *state_ = nullptr; -}; - -class brotli_decompressor : public decompressor { -public: - brotli_decompressor(); - ~brotli_decompressor(); - - bool is_valid() const override; - - bool decompress(const char *data, size_t data_length, - Callback callback) override; - -private: - BrotliDecoderResult decoder_r; - BrotliDecoderState *decoder_s = nullptr; -}; -#endif - -// NOTE: until the read size reaches `fixed_buffer_size`, use `fixed_buffer` -// to store data. The call can set memory on stack for performance. -class stream_line_reader { -public: - stream_line_reader(Stream &strm, char *fixed_buffer, - size_t fixed_buffer_size); - const char *ptr() const; - size_t size() const; - bool end_with_crlf() const; - bool getline(); - -private: - void append(char c); - - Stream &strm_; - char *fixed_buffer_; - const size_t fixed_buffer_size_; - size_t fixed_buffer_used_size_ = 0; - std::string glowable_buffer_; -}; - -class mmap { -public: - mmap(const char *path); - ~mmap(); - - bool open(const char *path); - void close(); - - bool is_open() const; - size_t size() const; - const char *data() const; - -private: -#if defined(_WIN32) - HANDLE hFile_; - HANDLE hMapping_; -#else - int fd_; -#endif - size_t size_; - void *addr_; -}; - -} // namespace detail - -// ---------------------------------------------------------------------------- - -/* - * Implementation that will be part of the .cc file if split into .h + .cc. - */ - -namespace detail { - -inline bool is_hex(char c, int &v) { - if (0x20 <= c && isdigit(c)) { - v = c - '0'; - return true; - } else if ('A' <= c && c <= 'F') { - v = c - 'A' + 10; - return true; - } else if ('a' <= c && c <= 'f') { - v = c - 'a' + 10; - return true; - } - return false; -} - -inline bool from_hex_to_i(const std::string &s, size_t i, size_t cnt, - int &val) { - if (i >= s.size()) { return false; } - - val = 0; - for (; cnt; i++, cnt--) { - if (!s[i]) { return false; } - auto v = 0; - if (is_hex(s[i], v)) { - val = val * 16 + v; - } else { - return false; - } - } - return true; -} - -inline std::string from_i_to_hex(size_t n) { - static const auto charset = "0123456789abcdef"; - std::string ret; - do { - ret = charset[n & 15] + ret; - n >>= 4; - } while (n > 0); - return ret; -} - -inline size_t to_utf8(int code, char *buff) { - if (code < 0x0080) { - buff[0] = static_cast(code & 0x7F); - return 1; - } else if (code < 0x0800) { - buff[0] = static_cast(0xC0 | ((code >> 6) & 0x1F)); - buff[1] = static_cast(0x80 | (code & 0x3F)); - return 2; - } else if (code < 0xD800) { - buff[0] = static_cast(0xE0 | ((code >> 12) & 0xF)); - buff[1] = static_cast(0x80 | ((code >> 6) & 0x3F)); - buff[2] = static_cast(0x80 | (code & 0x3F)); - return 3; - } else if (code < 0xE000) { // D800 - DFFF is invalid... - return 0; - } else if (code < 0x10000) { - buff[0] = static_cast(0xE0 | ((code >> 12) & 0xF)); - buff[1] = static_cast(0x80 | ((code >> 6) & 0x3F)); - buff[2] = static_cast(0x80 | (code & 0x3F)); - return 3; - } else if (code < 0x110000) { - buff[0] = static_cast(0xF0 | ((code >> 18) & 0x7)); - buff[1] = static_cast(0x80 | ((code >> 12) & 0x3F)); - buff[2] = static_cast(0x80 | ((code >> 6) & 0x3F)); - buff[3] = static_cast(0x80 | (code & 0x3F)); - return 4; - } - - // NOTREACHED - return 0; -} - -// NOTE: This code came up with the following stackoverflow post: -// https://stackoverflow.com/questions/180947/base64-decode-snippet-in-c -inline std::string base64_encode(const std::string &in) { - static const auto lookup = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - std::string out; - out.reserve(in.size()); - - auto val = 0; - auto valb = -6; - - for (auto c : in) { - val = (val << 8) + static_cast(c); - valb += 8; - while (valb >= 0) { - out.push_back(lookup[(val >> valb) & 0x3F]); - valb -= 6; - } - } - - if (valb > -6) { out.push_back(lookup[((val << 8) >> (valb + 8)) & 0x3F]); } - - while (out.size() % 4) { - out.push_back('='); - } - - return out; -} - -inline bool is_file(const std::string &path) { -#ifdef _WIN32 - return _access_s(path.c_str(), 0) == 0; -#else - struct stat st; - return stat(path.c_str(), &st) >= 0 && S_ISREG(st.st_mode); -#endif -} - -inline bool is_dir(const std::string &path) { - struct stat st; - return stat(path.c_str(), &st) >= 0 && S_ISDIR(st.st_mode); -} - -inline bool is_valid_path(const std::string &path) { - size_t level = 0; - size_t i = 0; - - // Skip slash - while (i < path.size() && path[i] == '/') { - i++; - } - - while (i < path.size()) { - // Read component - auto beg = i; - while (i < path.size() && path[i] != '/') { - if (path[i] == '\0') { - return false; - } else if (path[i] == '\\') { - return false; - } - i++; - } - - auto len = i - beg; - assert(len > 0); - - if (!path.compare(beg, len, ".")) { - ; - } else if (!path.compare(beg, len, "..")) { - if (level == 0) { return false; } - level--; - } else { - level++; - } - - // Skip slash - while (i < path.size() && path[i] == '/') { - i++; - } - } - - return true; -} - -inline std::string encode_query_param(const std::string &value) { - std::ostringstream escaped; - escaped.fill('0'); - escaped << std::hex; - - for (auto c : value) { - if (std::isalnum(static_cast(c)) || c == '-' || c == '_' || - c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' || c == '(' || - c == ')') { - escaped << c; - } else { - escaped << std::uppercase; - escaped << '%' << std::setw(2) - << static_cast(static_cast(c)); - escaped << std::nouppercase; - } - } - - return escaped.str(); -} - -inline std::string encode_url(const std::string &s) { - std::string result; - result.reserve(s.size()); - - for (size_t i = 0; s[i]; i++) { - switch (s[i]) { - case ' ': result += "%20"; break; - case '+': result += "%2B"; break; - case '\r': result += "%0D"; break; - case '\n': result += "%0A"; break; - case '\'': result += "%27"; break; - case ',': result += "%2C"; break; - // case ':': result += "%3A"; break; // ok? probably... - case ';': result += "%3B"; break; - default: - auto c = static_cast(s[i]); - if (c >= 0x80) { - result += '%'; - char hex[4]; - auto len = snprintf(hex, sizeof(hex) - 1, "%02X", c); - assert(len == 2); - result.append(hex, static_cast(len)); - } else { - result += s[i]; - } - break; - } - } - - return result; -} - -inline std::string decode_url(const std::string &s, - bool convert_plus_to_space) { - std::string result; - - for (size_t i = 0; i < s.size(); i++) { - if (s[i] == '%' && i + 1 < s.size()) { - if (s[i + 1] == 'u') { - auto val = 0; - if (from_hex_to_i(s, i + 2, 4, val)) { - // 4 digits Unicode codes - char buff[4]; - size_t len = to_utf8(val, buff); - if (len > 0) { result.append(buff, len); } - i += 5; // 'u0000' - } else { - result += s[i]; - } - } else { - auto val = 0; - if (from_hex_to_i(s, i + 1, 2, val)) { - // 2 digits hex codes - result += static_cast(val); - i += 2; // '00' - } else { - result += s[i]; - } - } - } else if (convert_plus_to_space && s[i] == '+') { - result += ' '; - } else { - result += s[i]; - } - } - - return result; -} - -inline void read_file(const std::string &path, std::string &out) { - std::ifstream fs(path, std::ios_base::binary); - fs.seekg(0, std::ios_base::end); - auto size = fs.tellg(); - fs.seekg(0); - out.resize(static_cast(size)); - fs.read(&out[0], static_cast(size)); -} - -inline std::string file_extension(const std::string &path) { - std::smatch m; - static auto re = std::regex("\\.([a-zA-Z0-9]+)$"); - if (std::regex_search(path, m, re)) { return m[1].str(); } - return std::string(); -} - -inline bool is_space_or_tab(char c) { return c == ' ' || c == '\t'; } - -inline std::pair trim(const char *b, const char *e, size_t left, - size_t right) { - while (b + left < e && is_space_or_tab(b[left])) { - left++; - } - while (right > 0 && is_space_or_tab(b[right - 1])) { - right--; - } - return std::make_pair(left, right); -} - -inline std::string trim_copy(const std::string &s) { - auto r = trim(s.data(), s.data() + s.size(), 0, s.size()); - return s.substr(r.first, r.second - r.first); -} - -inline std::string trim_double_quotes_copy(const std::string &s) { - if (s.length() >= 2 && s.front() == '"' && s.back() == '"') { - return s.substr(1, s.size() - 2); - } - return s; -} - -inline void split(const char *b, const char *e, char d, - std::function fn) { - return split(b, e, d, (std::numeric_limits::max)(), std::move(fn)); -} - -inline void split(const char *b, const char *e, char d, size_t m, - std::function fn) { - size_t i = 0; - size_t beg = 0; - size_t count = 1; - - while (e ? (b + i < e) : (b[i] != '\0')) { - if (b[i] == d && count < m) { - auto r = trim(b, e, beg, i); - if (r.first < r.second) { fn(&b[r.first], &b[r.second]); } - beg = i + 1; - count++; - } - i++; - } - - if (i) { - auto r = trim(b, e, beg, i); - if (r.first < r.second) { fn(&b[r.first], &b[r.second]); } - } -} - -inline stream_line_reader::stream_line_reader(Stream &strm, char *fixed_buffer, - size_t fixed_buffer_size) - : strm_(strm), fixed_buffer_(fixed_buffer), - fixed_buffer_size_(fixed_buffer_size) {} - -inline const char *stream_line_reader::ptr() const { - if (glowable_buffer_.empty()) { - return fixed_buffer_; - } else { - return glowable_buffer_.data(); - } -} - -inline size_t stream_line_reader::size() const { - if (glowable_buffer_.empty()) { - return fixed_buffer_used_size_; - } else { - return glowable_buffer_.size(); - } -} - -inline bool stream_line_reader::end_with_crlf() const { - auto end = ptr() + size(); - return size() >= 2 && end[-2] == '\r' && end[-1] == '\n'; -} - -inline bool stream_line_reader::getline() { - fixed_buffer_used_size_ = 0; - glowable_buffer_.clear(); - - for (size_t i = 0;; i++) { - char byte; - auto n = strm_.read(&byte, 1); - - if (n < 0) { - return false; - } else if (n == 0) { - if (i == 0) { - return false; - } else { - break; - } - } - - append(byte); - - if (byte == '\n') { break; } - } - - return true; -} - -inline void stream_line_reader::append(char c) { - if (fixed_buffer_used_size_ < fixed_buffer_size_ - 1) { - fixed_buffer_[fixed_buffer_used_size_++] = c; - fixed_buffer_[fixed_buffer_used_size_] = '\0'; - } else { - if (glowable_buffer_.empty()) { - assert(fixed_buffer_[fixed_buffer_used_size_] == '\0'); - glowable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_); - } - glowable_buffer_ += c; - } -} - -inline mmap::mmap(const char *path) -#if defined(_WIN32) - : hFile_(NULL), hMapping_(NULL) -#else - : fd_(-1) -#endif - , - size_(0), addr_(nullptr) { - open(path); -} - -inline mmap::~mmap() { close(); } - -inline bool mmap::open(const char *path) { - close(); - -#if defined(_WIN32) - hFile_ = ::CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (hFile_ == INVALID_HANDLE_VALUE) { return false; } - - size_ = ::GetFileSize(hFile_, NULL); - - hMapping_ = ::CreateFileMapping(hFile_, NULL, PAGE_READONLY, 0, 0, NULL); - - if (hMapping_ == NULL) { - close(); - return false; - } - - addr_ = ::MapViewOfFile(hMapping_, FILE_MAP_READ, 0, 0, 0); -#else - fd_ = ::open(path, O_RDONLY); - if (fd_ == -1) { return false; } - - struct stat sb; - if (fstat(fd_, &sb) == -1) { - close(); - return false; - } - size_ = static_cast(sb.st_size); - - addr_ = ::mmap(NULL, size_, PROT_READ, MAP_PRIVATE, fd_, 0); -#endif - - if (addr_ == nullptr) { - close(); - return false; - } - - return true; -} - -inline bool mmap::is_open() const { return addr_ != nullptr; } - -inline size_t mmap::size() const { return size_; } - -inline const char *mmap::data() const { - return static_cast(addr_); -} - -inline void mmap::close() { -#if defined(_WIN32) - if (addr_) { - ::UnmapViewOfFile(addr_); - addr_ = nullptr; - } - - if (hMapping_) { - ::CloseHandle(hMapping_); - hMapping_ = NULL; - } - - if (hFile_ != INVALID_HANDLE_VALUE) { - ::CloseHandle(hFile_); - hFile_ = INVALID_HANDLE_VALUE; - } -#else - if (addr_ != nullptr) { - munmap(addr_, size_); - addr_ = nullptr; - } - - if (fd_ != -1) { - ::close(fd_); - fd_ = -1; - } -#endif - size_ = 0; -} -inline int close_socket(socket_t sock) { -#ifdef _WIN32 - return closesocket(sock); -#else - return close(sock); -#endif -} - -template inline ssize_t handle_EINTR(T fn) { - ssize_t res = 0; - while (true) { - res = fn(); - if (res < 0 && errno == EINTR) { continue; } - break; - } - return res; -} - -inline ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags) { - return handle_EINTR([&]() { - return recv(sock, -#ifdef _WIN32 - static_cast(ptr), static_cast(size), -#else - ptr, size, -#endif - flags); - }); -} - -inline ssize_t send_socket(socket_t sock, const void *ptr, size_t size, - int flags) { - return handle_EINTR([&]() { - return send(sock, -#ifdef _WIN32 - static_cast(ptr), static_cast(size), -#else - ptr, size, -#endif - flags); - }); -} - -inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) { -#ifdef CPPHTTPLIB_USE_POLL - struct pollfd pfd_read; - pfd_read.fd = sock; - pfd_read.events = POLLIN; - - auto timeout = static_cast(sec * 1000 + usec / 1000); - - return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); -#else -#ifndef _WIN32 - if (sock >= FD_SETSIZE) { return -1; } -#endif - - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - timeval tv; - tv.tv_sec = static_cast(sec); - tv.tv_usec = static_cast(usec); - - return handle_EINTR([&]() { - return select(static_cast(sock + 1), &fds, nullptr, nullptr, &tv); - }); -#endif -} - -inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) { -#ifdef CPPHTTPLIB_USE_POLL - struct pollfd pfd_read; - pfd_read.fd = sock; - pfd_read.events = POLLOUT; - - auto timeout = static_cast(sec * 1000 + usec / 1000); - - return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); -#else -#ifndef _WIN32 - if (sock >= FD_SETSIZE) { return -1; } -#endif - - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - timeval tv; - tv.tv_sec = static_cast(sec); - tv.tv_usec = static_cast(usec); - - return handle_EINTR([&]() { - return select(static_cast(sock + 1), nullptr, &fds, nullptr, &tv); - }); -#endif -} - -inline Error wait_until_socket_is_ready(socket_t sock, time_t sec, - time_t usec) { -#ifdef CPPHTTPLIB_USE_POLL - struct pollfd pfd_read; - pfd_read.fd = sock; - pfd_read.events = POLLIN | POLLOUT; - - auto timeout = static_cast(sec * 1000 + usec / 1000); - - auto poll_res = handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); - - if (poll_res == 0) { return Error::ConnectionTimeout; } - - if (poll_res > 0 && pfd_read.revents & (POLLIN | POLLOUT)) { - auto error = 0; - socklen_t len = sizeof(error); - auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR, - reinterpret_cast(&error), &len); - auto successful = res >= 0 && !error; - return successful ? Error::Success : Error::Connection; - } - - return Error::Connection; -#else -#ifndef _WIN32 - if (sock >= FD_SETSIZE) { return Error::Connection; } -#endif - - fd_set fdsr; - FD_ZERO(&fdsr); - FD_SET(sock, &fdsr); - - auto fdsw = fdsr; - auto fdse = fdsr; - - timeval tv; - tv.tv_sec = static_cast(sec); - tv.tv_usec = static_cast(usec); - - auto ret = handle_EINTR([&]() { - return select(static_cast(sock + 1), &fdsr, &fdsw, &fdse, &tv); - }); - - if (ret == 0) { return Error::ConnectionTimeout; } - - if (ret > 0 && (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw))) { - auto error = 0; - socklen_t len = sizeof(error); - auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR, - reinterpret_cast(&error), &len); - auto successful = res >= 0 && !error; - return successful ? Error::Success : Error::Connection; - } - return Error::Connection; -#endif -} - -inline bool is_socket_alive(socket_t sock) { - const auto val = detail::select_read(sock, 0, 0); - if (val == 0) { - return true; - } else if (val < 0 && errno == EBADF) { - return false; - } - char buf[1]; - return detail::read_socket(sock, &buf[0], sizeof(buf), MSG_PEEK) > 0; -} - -class SocketStream : public Stream { -public: - SocketStream(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec, - time_t write_timeout_sec, time_t write_timeout_usec); - ~SocketStream() override; - - bool is_readable() const override; - bool is_writable() const override; - ssize_t read(char *ptr, size_t size) override; - ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; - void get_local_ip_and_port(std::string &ip, int &port) const override; - socket_t socket() const override; - -private: - socket_t sock_; - time_t read_timeout_sec_; - time_t read_timeout_usec_; - time_t write_timeout_sec_; - time_t write_timeout_usec_; - - std::vector read_buff_; - size_t read_buff_off_ = 0; - size_t read_buff_content_size_ = 0; - - static const size_t read_buff_size_ = 1024l * 4; -}; - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -class SSLSocketStream : public Stream { -public: - SSLSocketStream(socket_t sock, SSL *ssl, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec); - ~SSLSocketStream() override; - - bool is_readable() const override; - bool is_writable() const override; - ssize_t read(char *ptr, size_t size) override; - ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; - void get_local_ip_and_port(std::string &ip, int &port) const override; - socket_t socket() const override; - -private: - socket_t sock_; - SSL *ssl_; - time_t read_timeout_sec_; - time_t read_timeout_usec_; - time_t write_timeout_sec_; - time_t write_timeout_usec_; -}; -#endif - -inline bool keep_alive(socket_t sock, time_t keep_alive_timeout_sec) { - using namespace std::chrono; - auto start = steady_clock::now(); - while (true) { - auto val = select_read(sock, 0, 10000); - if (val < 0) { - return false; - } else if (val == 0) { - auto current = steady_clock::now(); - auto duration = duration_cast(current - start); - auto timeout = keep_alive_timeout_sec * 1000; - if (duration.count() > timeout) { return false; } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } else { - return true; - } - } -} - -template -inline bool -process_server_socket_core(const std::atomic &svr_sock, socket_t sock, - size_t keep_alive_max_count, - time_t keep_alive_timeout_sec, T callback) { - assert(keep_alive_max_count > 0); - auto ret = false; - auto count = keep_alive_max_count; - while (svr_sock != INVALID_SOCKET && count > 0 && - keep_alive(sock, keep_alive_timeout_sec)) { - auto close_connection = count == 1; - auto connection_closed = false; - ret = callback(close_connection, connection_closed); - if (!ret || connection_closed) { break; } - count--; - } - return ret; -} - -template -inline bool -process_server_socket(const std::atomic &svr_sock, socket_t sock, - size_t keep_alive_max_count, - time_t keep_alive_timeout_sec, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, T callback) { - return process_server_socket_core( - svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec, - [&](bool close_connection, bool &connection_closed) { - SocketStream strm(sock, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm, close_connection, connection_closed); - }); -} - -inline bool process_client_socket(socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, - time_t write_timeout_sec, - time_t write_timeout_usec, - std::function callback) { - SocketStream strm(sock, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm); -} - -inline int shutdown_socket(socket_t sock) { -#ifdef _WIN32 - return shutdown(sock, SD_BOTH); -#else - return shutdown(sock, SHUT_RDWR); -#endif -} - -template -socket_t create_socket(const std::string &host, const std::string &ip, int port, - int address_family, int socket_flags, bool tcp_nodelay, - SocketOptions socket_options, - BindOrConnect bind_or_connect) { - // Get address info - const char *node = nullptr; - struct addrinfo hints; - struct addrinfo *result; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (!ip.empty()) { - node = ip.c_str(); - // Ask getaddrinfo to convert IP in c-string to address - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - } else { - if (!host.empty()) { node = host.c_str(); } - hints.ai_family = address_family; - hints.ai_flags = socket_flags; - } - -#ifndef _WIN32 - if (hints.ai_family == AF_UNIX) { - const auto addrlen = host.length(); - if (addrlen > sizeof(sockaddr_un::sun_path)) { return INVALID_SOCKET; } - - auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol); - if (sock != INVALID_SOCKET) { - sockaddr_un addr{}; - addr.sun_family = AF_UNIX; - std::copy(host.begin(), host.end(), addr.sun_path); - - hints.ai_addr = reinterpret_cast(&addr); - hints.ai_addrlen = static_cast( - sizeof(addr) - sizeof(addr.sun_path) + addrlen); - - fcntl(sock, F_SETFD, FD_CLOEXEC); - if (socket_options) { socket_options(sock); } - - if (!bind_or_connect(sock, hints)) { - close_socket(sock); - sock = INVALID_SOCKET; - } - } - return sock; - } -#endif - - auto service = std::to_string(port); - - if (getaddrinfo(node, service.c_str(), &hints, &result)) { -#if defined __linux__ && !defined __ANDROID__ - res_init(); -#endif - return INVALID_SOCKET; - } - - for (auto rp = result; rp; rp = rp->ai_next) { - // Create a socket -#ifdef _WIN32 - auto sock = - WSASocketW(rp->ai_family, rp->ai_socktype, rp->ai_protocol, nullptr, 0, - WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED); - /** - * Since the WSA_FLAG_NO_HANDLE_INHERIT is only supported on Windows 7 SP1 - * and above the socket creation fails on older Windows Systems. - * - * Let's try to create a socket the old way in this case. - * - * Reference: - * https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketa - * - * WSA_FLAG_NO_HANDLE_INHERIT: - * This flag is supported on Windows 7 with SP1, Windows Server 2008 R2 with - * SP1, and later - * - */ - if (sock == INVALID_SOCKET) { - sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - } -#else - auto sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); -#endif - if (sock == INVALID_SOCKET) { continue; } - -#ifndef _WIN32 - if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { - close_socket(sock); - continue; - } -#endif - - if (tcp_nodelay) { - auto yes = 1; -#ifdef _WIN32 - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - reinterpret_cast(&yes), sizeof(yes)); -#else - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - reinterpret_cast(&yes), sizeof(yes)); -#endif - } - - if (socket_options) { socket_options(sock); } - - if (rp->ai_family == AF_INET6) { - auto no = 0; -#ifdef _WIN32 - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, - reinterpret_cast(&no), sizeof(no)); -#else - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, - reinterpret_cast(&no), sizeof(no)); -#endif - } - - // bind or connect - if (bind_or_connect(sock, *rp)) { - freeaddrinfo(result); - return sock; - } - - close_socket(sock); - } - - freeaddrinfo(result); - return INVALID_SOCKET; -} - -inline void set_nonblocking(socket_t sock, bool nonblocking) { -#ifdef _WIN32 - auto flags = nonblocking ? 1UL : 0UL; - ioctlsocket(sock, FIONBIO, &flags); -#else - auto flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, - nonblocking ? (flags | O_NONBLOCK) : (flags & (~O_NONBLOCK))); -#endif -} - -inline bool is_connection_error() { -#ifdef _WIN32 - return WSAGetLastError() != WSAEWOULDBLOCK; -#else - return errno != EINPROGRESS; -#endif -} - -inline bool bind_ip_address(socket_t sock, const std::string &host) { - struct addrinfo hints; - struct addrinfo *result; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(host.c_str(), "0", &hints, &result)) { return false; } - - auto ret = false; - for (auto rp = result; rp; rp = rp->ai_next) { - const auto &ai = *rp; - if (!::bind(sock, ai.ai_addr, static_cast(ai.ai_addrlen))) { - ret = true; - break; - } - } - - freeaddrinfo(result); - return ret; -} - -#if !defined _WIN32 && !defined ANDROID && !defined _AIX && !defined __MVS__ -#define USE_IF2IP -#endif - -#ifdef USE_IF2IP -inline std::string if2ip(int address_family, const std::string &ifn) { - struct ifaddrs *ifap; - getifaddrs(&ifap); - std::string addr_candidate; - for (auto ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr && ifn == ifa->ifa_name && - (AF_UNSPEC == address_family || - ifa->ifa_addr->sa_family == address_family)) { - if (ifa->ifa_addr->sa_family == AF_INET) { - auto sa = reinterpret_cast(ifa->ifa_addr); - char buf[INET_ADDRSTRLEN]; - if (inet_ntop(AF_INET, &sa->sin_addr, buf, INET_ADDRSTRLEN)) { - freeifaddrs(ifap); - return std::string(buf, INET_ADDRSTRLEN); - } - } else if (ifa->ifa_addr->sa_family == AF_INET6) { - auto sa = reinterpret_cast(ifa->ifa_addr); - if (!IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) { - char buf[INET6_ADDRSTRLEN] = {}; - if (inet_ntop(AF_INET6, &sa->sin6_addr, buf, INET6_ADDRSTRLEN)) { - // equivalent to mac's IN6_IS_ADDR_UNIQUE_LOCAL - auto s6_addr_head = sa->sin6_addr.s6_addr[0]; - if (s6_addr_head == 0xfc || s6_addr_head == 0xfd) { - addr_candidate = std::string(buf, INET6_ADDRSTRLEN); - } else { - freeifaddrs(ifap); - return std::string(buf, INET6_ADDRSTRLEN); - } - } - } - } - } - } - freeifaddrs(ifap); - return addr_candidate; -} -#endif - -inline socket_t create_client_socket( - const std::string &host, const std::string &ip, int port, - int address_family, bool tcp_nodelay, SocketOptions socket_options, - time_t connection_timeout_sec, time_t connection_timeout_usec, - time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, const std::string &intf, Error &error) { - auto sock = create_socket( - host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options), - [&](socket_t sock2, struct addrinfo &ai) -> bool { - if (!intf.empty()) { -#ifdef USE_IF2IP - auto ip_from_if = if2ip(address_family, intf); - if (ip_from_if.empty()) { ip_from_if = intf; } - if (!bind_ip_address(sock2, ip_from_if)) { - error = Error::BindIPAddress; - return false; - } -#endif - } - - set_nonblocking(sock2, true); - - auto ret = - ::connect(sock2, ai.ai_addr, static_cast(ai.ai_addrlen)); - - if (ret < 0) { - if (is_connection_error()) { - error = Error::Connection; - return false; - } - error = wait_until_socket_is_ready(sock2, connection_timeout_sec, - connection_timeout_usec); - if (error != Error::Success) { return false; } - } - - set_nonblocking(sock2, false); - - { -#ifdef _WIN32 - auto timeout = static_cast(read_timeout_sec * 1000 + - read_timeout_usec / 1000); - setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, - reinterpret_cast(&timeout), sizeof(timeout)); -#else - timeval tv; - tv.tv_sec = static_cast(read_timeout_sec); - tv.tv_usec = static_cast(read_timeout_usec); - setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, - reinterpret_cast(&tv), sizeof(tv)); -#endif - } - { - -#ifdef _WIN32 - auto timeout = static_cast(write_timeout_sec * 1000 + - write_timeout_usec / 1000); - setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, - reinterpret_cast(&timeout), sizeof(timeout)); -#else - timeval tv; - tv.tv_sec = static_cast(write_timeout_sec); - tv.tv_usec = static_cast(write_timeout_usec); - setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, - reinterpret_cast(&tv), sizeof(tv)); -#endif - } - - error = Error::Success; - return true; - }); - - if (sock != INVALID_SOCKET) { - error = Error::Success; - } else { - if (error == Error::Success) { error = Error::Connection; } - } - - return sock; -} - -inline bool get_ip_and_port(const struct sockaddr_storage &addr, - socklen_t addr_len, std::string &ip, int &port) { - if (addr.ss_family == AF_INET) { - port = ntohs(reinterpret_cast(&addr)->sin_port); - } else if (addr.ss_family == AF_INET6) { - port = - ntohs(reinterpret_cast(&addr)->sin6_port); - } else { - return false; - } - - std::array ipstr{}; - if (getnameinfo(reinterpret_cast(&addr), addr_len, - ipstr.data(), static_cast(ipstr.size()), nullptr, - 0, NI_NUMERICHOST)) { - return false; - } - - ip = ipstr.data(); - return true; -} - -inline void get_local_ip_and_port(socket_t sock, std::string &ip, int &port) { - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - if (!getsockname(sock, reinterpret_cast(&addr), - &addr_len)) { - get_ip_and_port(addr, addr_len, ip, port); - } -} - -inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) { - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - - if (!getpeername(sock, reinterpret_cast(&addr), - &addr_len)) { -#ifndef _WIN32 - if (addr.ss_family == AF_UNIX) { -#if defined(__linux__) - struct ucred ucred; - socklen_t len = sizeof(ucred); - if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == 0) { - port = ucred.pid; - } -#elif defined(SOL_LOCAL) && defined(SO_PEERPID) // __APPLE__ - pid_t pid; - socklen_t len = sizeof(pid); - if (getsockopt(sock, SOL_LOCAL, SO_PEERPID, &pid, &len) == 0) { - port = pid; - } -#endif - return; - } -#endif - get_ip_and_port(addr, addr_len, ip, port); - } -} - -inline constexpr unsigned int str2tag_core(const char *s, size_t l, - unsigned int h) { - return (l == 0) - ? h - : str2tag_core( - s + 1, l - 1, - // Unsets the 6 high bits of h, therefore no overflow happens - (((std::numeric_limits::max)() >> 6) & - h * 33) ^ - static_cast(*s)); -} - -inline unsigned int str2tag(const std::string &s) { - return str2tag_core(s.data(), s.size(), 0); -} - -namespace udl { - -inline constexpr unsigned int operator"" _t(const char *s, size_t l) { - return str2tag_core(s, l, 0); -} - -} // namespace udl - -inline std::string -find_content_type(const std::string &path, - const std::map &user_data, - const std::string &default_content_type) { - auto ext = file_extension(path); - - auto it = user_data.find(ext); - if (it != user_data.end()) { return it->second; } - - using udl::operator""_t; - - switch (str2tag(ext)) { - default: return default_content_type; - - case "css"_t: return "text/css"; - case "csv"_t: return "text/csv"; - case "htm"_t: - case "html"_t: return "text/html"; - case "js"_t: - case "mjs"_t: return "text/javascript"; - case "txt"_t: return "text/plain"; - case "vtt"_t: return "text/vtt"; - - case "apng"_t: return "image/apng"; - case "avif"_t: return "image/avif"; - case "bmp"_t: return "image/bmp"; - case "gif"_t: return "image/gif"; - case "png"_t: return "image/png"; - case "svg"_t: return "image/svg+xml"; - case "webp"_t: return "image/webp"; - case "ico"_t: return "image/x-icon"; - case "tif"_t: return "image/tiff"; - case "tiff"_t: return "image/tiff"; - case "jpg"_t: - case "jpeg"_t: return "image/jpeg"; - - case "mp4"_t: return "video/mp4"; - case "mpeg"_t: return "video/mpeg"; - case "webm"_t: return "video/webm"; - - case "mp3"_t: return "audio/mp3"; - case "mpga"_t: return "audio/mpeg"; - case "weba"_t: return "audio/webm"; - case "wav"_t: return "audio/wave"; - - case "otf"_t: return "font/otf"; - case "ttf"_t: return "font/ttf"; - case "woff"_t: return "font/woff"; - case "woff2"_t: return "font/woff2"; - - case "7z"_t: return "application/x-7z-compressed"; - case "atom"_t: return "application/atom+xml"; - case "pdf"_t: return "application/pdf"; - case "json"_t: return "application/json"; - case "rss"_t: return "application/rss+xml"; - case "tar"_t: return "application/x-tar"; - case "xht"_t: - case "xhtml"_t: return "application/xhtml+xml"; - case "xslt"_t: return "application/xslt+xml"; - case "xml"_t: return "application/xml"; - case "gz"_t: return "application/gzip"; - case "zip"_t: return "application/zip"; - case "wasm"_t: return "application/wasm"; - } -} - -inline bool can_compress_content_type(const std::string &content_type) { - using udl::operator""_t; - - auto tag = str2tag(content_type); - - switch (tag) { - case "image/svg+xml"_t: - case "application/javascript"_t: - case "application/json"_t: - case "application/xml"_t: - case "application/protobuf"_t: - case "application/xhtml+xml"_t: return true; - - default: - return !content_type.rfind("text/", 0) && tag != "text/event-stream"_t; - } -} - -inline EncodingType encoding_type(const Request &req, const Response &res) { - auto ret = - detail::can_compress_content_type(res.get_header_value("Content-Type")); - if (!ret) { return EncodingType::None; } - - const auto &s = req.get_header_value("Accept-Encoding"); - (void)(s); - -#ifdef CPPHTTPLIB_BROTLI_SUPPORT - // TODO: 'Accept-Encoding' has br, not br;q=0 - ret = s.find("br") != std::string::npos; - if (ret) { return EncodingType::Brotli; } -#endif - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - // TODO: 'Accept-Encoding' has gzip, not gzip;q=0 - ret = s.find("gzip") != std::string::npos; - if (ret) { return EncodingType::Gzip; } -#endif - - return EncodingType::None; -} - -inline bool nocompressor::compress(const char *data, size_t data_length, - bool /*last*/, Callback callback) { - if (!data_length) { return true; } - return callback(data, data_length); -} - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT -inline gzip_compressor::gzip_compressor() { - std::memset(&strm_, 0, sizeof(strm_)); - strm_.zalloc = Z_NULL; - strm_.zfree = Z_NULL; - strm_.opaque = Z_NULL; - - is_valid_ = deflateInit2(&strm_, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, - Z_DEFAULT_STRATEGY) == Z_OK; -} - -inline gzip_compressor::~gzip_compressor() { deflateEnd(&strm_); } - -inline bool gzip_compressor::compress(const char *data, size_t data_length, - bool last, Callback callback) { - assert(is_valid_); - - do { - constexpr size_t max_avail_in = - (std::numeric_limits::max)(); - - strm_.avail_in = static_cast( - (std::min)(data_length, max_avail_in)); - strm_.next_in = const_cast(reinterpret_cast(data)); - - data_length -= strm_.avail_in; - data += strm_.avail_in; - - auto flush = (last && data_length == 0) ? Z_FINISH : Z_NO_FLUSH; - auto ret = Z_OK; - - std::array buff{}; - do { - strm_.avail_out = static_cast(buff.size()); - strm_.next_out = reinterpret_cast(buff.data()); - - ret = deflate(&strm_, flush); - if (ret == Z_STREAM_ERROR) { return false; } - - if (!callback(buff.data(), buff.size() - strm_.avail_out)) { - return false; - } - } while (strm_.avail_out == 0); - - assert((flush == Z_FINISH && ret == Z_STREAM_END) || - (flush == Z_NO_FLUSH && ret == Z_OK)); - assert(strm_.avail_in == 0); - } while (data_length > 0); - - return true; -} - -inline gzip_decompressor::gzip_decompressor() { - std::memset(&strm_, 0, sizeof(strm_)); - strm_.zalloc = Z_NULL; - strm_.zfree = Z_NULL; - strm_.opaque = Z_NULL; - - // 15 is the value of wbits, which should be at the maximum possible value - // to ensure that any gzip stream can be decoded. The offset of 32 specifies - // that the stream type should be automatically detected either gzip or - // deflate. - is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK; -} - -inline gzip_decompressor::~gzip_decompressor() { inflateEnd(&strm_); } - -inline bool gzip_decompressor::is_valid() const { return is_valid_; } - -inline bool gzip_decompressor::decompress(const char *data, size_t data_length, - Callback callback) { - assert(is_valid_); - - auto ret = Z_OK; - - do { - constexpr size_t max_avail_in = - (std::numeric_limits::max)(); - - strm_.avail_in = static_cast( - (std::min)(data_length, max_avail_in)); - strm_.next_in = const_cast(reinterpret_cast(data)); - - data_length -= strm_.avail_in; - data += strm_.avail_in; - - std::array buff{}; - while (strm_.avail_in > 0 && ret == Z_OK) { - strm_.avail_out = static_cast(buff.size()); - strm_.next_out = reinterpret_cast(buff.data()); - - ret = inflate(&strm_, Z_NO_FLUSH); - - assert(ret != Z_STREAM_ERROR); - switch (ret) { - case Z_NEED_DICT: - case Z_DATA_ERROR: - case Z_MEM_ERROR: inflateEnd(&strm_); return false; - } - - if (!callback(buff.data(), buff.size() - strm_.avail_out)) { - return false; - } - } - - if (ret != Z_OK && ret != Z_STREAM_END) { return false; } - - } while (data_length > 0); - - return true; -} -#endif - -#ifdef CPPHTTPLIB_BROTLI_SUPPORT -inline brotli_compressor::brotli_compressor() { - state_ = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr); -} - -inline brotli_compressor::~brotli_compressor() { - BrotliEncoderDestroyInstance(state_); -} - -inline bool brotli_compressor::compress(const char *data, size_t data_length, - bool last, Callback callback) { - std::array buff{}; - - auto operation = last ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS; - auto available_in = data_length; - auto next_in = reinterpret_cast(data); - - for (;;) { - if (last) { - if (BrotliEncoderIsFinished(state_)) { break; } - } else { - if (!available_in) { break; } - } - - auto available_out = buff.size(); - auto next_out = buff.data(); - - if (!BrotliEncoderCompressStream(state_, operation, &available_in, &next_in, - &available_out, &next_out, nullptr)) { - return false; - } - - auto output_bytes = buff.size() - available_out; - if (output_bytes) { - callback(reinterpret_cast(buff.data()), output_bytes); - } - } - - return true; -} - -inline brotli_decompressor::brotli_decompressor() { - decoder_s = BrotliDecoderCreateInstance(0, 0, 0); - decoder_r = decoder_s ? BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT - : BROTLI_DECODER_RESULT_ERROR; -} - -inline brotli_decompressor::~brotli_decompressor() { - if (decoder_s) { BrotliDecoderDestroyInstance(decoder_s); } -} - -inline bool brotli_decompressor::is_valid() const { return decoder_s; } - -inline bool brotli_decompressor::decompress(const char *data, - size_t data_length, - Callback callback) { - if (decoder_r == BROTLI_DECODER_RESULT_SUCCESS || - decoder_r == BROTLI_DECODER_RESULT_ERROR) { - return 0; - } - - auto next_in = reinterpret_cast(data); - size_t avail_in = data_length; - size_t total_out; - - decoder_r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; - - std::array buff{}; - while (decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { - char *next_out = buff.data(); - size_t avail_out = buff.size(); - - decoder_r = BrotliDecoderDecompressStream( - decoder_s, &avail_in, &next_in, &avail_out, - reinterpret_cast(&next_out), &total_out); - - if (decoder_r == BROTLI_DECODER_RESULT_ERROR) { return false; } - - if (!callback(buff.data(), buff.size() - avail_out)) { return false; } - } - - return decoder_r == BROTLI_DECODER_RESULT_SUCCESS || - decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; -} -#endif - -inline bool has_header(const Headers &headers, const std::string &key) { - return headers.find(key) != headers.end(); -} - -inline const char *get_header_value(const Headers &headers, - const std::string &key, size_t id, - const char *def) { - auto rng = headers.equal_range(key); - auto it = rng.first; - std::advance(it, static_cast(id)); - if (it != rng.second) { return it->second.c_str(); } - return def; -} - -inline bool compare_case_ignore(const std::string &a, const std::string &b) { - if (a.size() != b.size()) { return false; } - for (size_t i = 0; i < b.size(); i++) { - if (::tolower(a[i]) != ::tolower(b[i])) { return false; } - } - return true; -} - -template -inline bool parse_header(const char *beg, const char *end, T fn) { - // Skip trailing spaces and tabs. - while (beg < end && is_space_or_tab(end[-1])) { - end--; - } - - auto p = beg; - while (p < end && *p != ':') { - p++; - } - - if (p == end) { return false; } - - auto key_end = p; - - if (*p++ != ':') { return false; } - - while (p < end && is_space_or_tab(*p)) { - p++; - } - - if (p < end) { - auto key_len = key_end - beg; - if (!key_len) { return false; } - - auto key = std::string(beg, key_end); - auto val = compare_case_ignore(key, "Location") - ? std::string(p, end) - : decode_url(std::string(p, end), false); - fn(std::move(key), std::move(val)); - return true; - } - - return false; -} - -inline bool read_headers(Stream &strm, Headers &headers) { - const auto bufsiz = 2048; - char buf[bufsiz]; - stream_line_reader line_reader(strm, buf, bufsiz); - - for (;;) { - if (!line_reader.getline()) { return false; } - - // Check if the line ends with CRLF. - auto line_terminator_len = 2; - if (line_reader.end_with_crlf()) { - // Blank line indicates end of headers. - if (line_reader.size() == 2) { break; } -#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR - } else { - // Blank line indicates end of headers. - if (line_reader.size() == 1) { break; } - line_terminator_len = 1; - } -#else - } else { - continue; // Skip invalid line. - } -#endif - - if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } - - // Exclude line terminator - auto end = line_reader.ptr() + line_reader.size() - line_terminator_len; - - parse_header(line_reader.ptr(), end, - [&](std::string &&key, std::string &&val) { - headers.emplace(std::move(key), std::move(val)); - }); - } - - return true; -} - -inline bool read_content_with_length(Stream &strm, uint64_t len, - Progress progress, - ContentReceiverWithProgress out) { - char buf[CPPHTTPLIB_RECV_BUFSIZ]; - - uint64_t r = 0; - while (r < len) { - auto read_len = static_cast(len - r); - auto n = strm.read(buf, (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ)); - if (n <= 0) { return false; } - - if (!out(buf, static_cast(n), r, len)) { return false; } - r += static_cast(n); - - if (progress) { - if (!progress(r, len)) { return false; } - } - } - - return true; -} - -inline void skip_content_with_length(Stream &strm, uint64_t len) { - char buf[CPPHTTPLIB_RECV_BUFSIZ]; - uint64_t r = 0; - while (r < len) { - auto read_len = static_cast(len - r); - auto n = strm.read(buf, (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ)); - if (n <= 0) { return; } - r += static_cast(n); - } -} - -inline bool read_content_without_length(Stream &strm, - ContentReceiverWithProgress out) { - char buf[CPPHTTPLIB_RECV_BUFSIZ]; - uint64_t r = 0; - for (;;) { - auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ); - if (n <= 0) { return true; } - - if (!out(buf, static_cast(n), r, 0)) { return false; } - r += static_cast(n); - } - - return true; -} - -template -inline bool read_content_chunked(Stream &strm, T &x, - ContentReceiverWithProgress out) { - const auto bufsiz = 16; - char buf[bufsiz]; - - stream_line_reader line_reader(strm, buf, bufsiz); - - if (!line_reader.getline()) { return false; } - - unsigned long chunk_len; - while (true) { - char *end_ptr; - - chunk_len = std::strtoul(line_reader.ptr(), &end_ptr, 16); - - if (end_ptr == line_reader.ptr()) { return false; } - if (chunk_len == ULONG_MAX) { return false; } - - if (chunk_len == 0) { break; } - - if (!read_content_with_length(strm, chunk_len, nullptr, out)) { - return false; - } - - if (!line_reader.getline()) { return false; } - - if (strcmp(line_reader.ptr(), "\r\n") != 0) { return false; } - - if (!line_reader.getline()) { return false; } - } - - assert(chunk_len == 0); - - // Trailer - if (!line_reader.getline()) { return false; } - - while (strcmp(line_reader.ptr(), "\r\n") != 0) { - if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } - - // Exclude line terminator - constexpr auto line_terminator_len = 2; - auto end = line_reader.ptr() + line_reader.size() - line_terminator_len; - - parse_header(line_reader.ptr(), end, - [&](std::string &&key, std::string &&val) { - x.headers.emplace(std::move(key), std::move(val)); - }); - - if (!line_reader.getline()) { return false; } - } - - return true; -} - -inline bool is_chunked_transfer_encoding(const Headers &headers) { - return compare_case_ignore( - get_header_value(headers, "Transfer-Encoding", 0, ""), "chunked"); -} - -template -bool prepare_content_receiver(T &x, int &status, - ContentReceiverWithProgress receiver, - bool decompress, U callback) { - if (decompress) { - std::string encoding = x.get_header_value("Content-Encoding"); - std::unique_ptr decompressor; - - if (encoding == "gzip" || encoding == "deflate") { -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - decompressor = detail::make_unique(); -#else - status = StatusCode::UnsupportedMediaType_415; - return false; -#endif - } else if (encoding.find("br") != std::string::npos) { -#ifdef CPPHTTPLIB_BROTLI_SUPPORT - decompressor = detail::make_unique(); -#else - status = StatusCode::UnsupportedMediaType_415; - return false; -#endif - } - - if (decompressor) { - if (decompressor->is_valid()) { - ContentReceiverWithProgress out = [&](const char *buf, size_t n, - uint64_t off, uint64_t len) { - return decompressor->decompress(buf, n, - [&](const char *buf2, size_t n2) { - return receiver(buf2, n2, off, len); - }); - }; - return callback(std::move(out)); - } else { - status = StatusCode::InternalServerError_500; - return false; - } - } - } - - ContentReceiverWithProgress out = [&](const char *buf, size_t n, uint64_t off, - uint64_t len) { - return receiver(buf, n, off, len); - }; - return callback(std::move(out)); -} - -template -bool read_content(Stream &strm, T &x, size_t payload_max_length, int &status, - Progress progress, ContentReceiverWithProgress receiver, - bool decompress) { - return prepare_content_receiver( - x, status, std::move(receiver), decompress, - [&](const ContentReceiverWithProgress &out) { - auto ret = true; - auto exceed_payload_max_length = false; - - if (is_chunked_transfer_encoding(x.headers)) { - ret = read_content_chunked(strm, x, out); - } else if (!has_header(x.headers, "Content-Length")) { - ret = read_content_without_length(strm, out); - } else { - auto len = get_header_value_u64(x.headers, "Content-Length", 0, 0); - if (len > payload_max_length) { - exceed_payload_max_length = true; - skip_content_with_length(strm, len); - ret = false; - } else if (len > 0) { - ret = read_content_with_length(strm, len, std::move(progress), out); - } - } - - if (!ret) { - status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413 - : StatusCode::BadRequest_400; - } - return ret; - }); -} // namespace detail - -inline ssize_t write_headers(Stream &strm, const Headers &headers) { - ssize_t write_len = 0; - for (const auto &x : headers) { - auto len = - strm.write_format("%s: %s\r\n", x.first.c_str(), x.second.c_str()); - if (len < 0) { return len; } - write_len += len; - } - auto len = strm.write("\r\n"); - if (len < 0) { return len; } - write_len += len; - return write_len; -} - -inline bool write_data(Stream &strm, const char *d, size_t l) { - size_t offset = 0; - while (offset < l) { - auto length = strm.write(d + offset, l - offset); - if (length < 0) { return false; } - offset += static_cast(length); - } - return true; -} - -template -inline bool write_content(Stream &strm, const ContentProvider &content_provider, - size_t offset, size_t length, T is_shutting_down, - Error &error) { - size_t end_offset = offset + length; - auto ok = true; - DataSink data_sink; - - data_sink.write = [&](const char *d, size_t l) -> bool { - if (ok) { - if (strm.is_writable() && write_data(strm, d, l)) { - offset += l; - } else { - ok = false; - } - } - return ok; - }; - - data_sink.is_writable = [&]() -> bool { return strm.is_writable(); }; - - while (offset < end_offset && !is_shutting_down()) { - if (!strm.is_writable()) { - error = Error::Write; - return false; - } else if (!content_provider(offset, end_offset - offset, data_sink)) { - error = Error::Canceled; - return false; - } else if (!ok) { - error = Error::Write; - return false; - } - } - - error = Error::Success; - return true; -} - -template -inline bool write_content(Stream &strm, const ContentProvider &content_provider, - size_t offset, size_t length, - const T &is_shutting_down) { - auto error = Error::Success; - return write_content(strm, content_provider, offset, length, is_shutting_down, - error); -} - -template -inline bool -write_content_without_length(Stream &strm, - const ContentProvider &content_provider, - const T &is_shutting_down) { - size_t offset = 0; - auto data_available = true; - auto ok = true; - DataSink data_sink; - - data_sink.write = [&](const char *d, size_t l) -> bool { - if (ok) { - offset += l; - if (!strm.is_writable() || !write_data(strm, d, l)) { ok = false; } - } - return ok; - }; - - data_sink.is_writable = [&]() -> bool { return strm.is_writable(); }; - - data_sink.done = [&](void) { data_available = false; }; - - while (data_available && !is_shutting_down()) { - if (!strm.is_writable()) { - return false; - } else if (!content_provider(offset, 0, data_sink)) { - return false; - } else if (!ok) { - return false; - } - } - return true; -} - -template -inline bool -write_content_chunked(Stream &strm, const ContentProvider &content_provider, - const T &is_shutting_down, U &compressor, Error &error) { - size_t offset = 0; - auto data_available = true; - auto ok = true; - DataSink data_sink; - - data_sink.write = [&](const char *d, size_t l) -> bool { - if (ok) { - data_available = l > 0; - offset += l; - - std::string payload; - if (compressor.compress(d, l, false, - [&](const char *data, size_t data_len) { - payload.append(data, data_len); - return true; - })) { - if (!payload.empty()) { - // Emit chunked response header and footer for each chunk - auto chunk = - from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n"; - if (!strm.is_writable() || - !write_data(strm, chunk.data(), chunk.size())) { - ok = false; - } - } - } else { - ok = false; - } - } - return ok; - }; - - data_sink.is_writable = [&]() -> bool { return strm.is_writable(); }; - - auto done_with_trailer = [&](const Headers *trailer) { - if (!ok) { return; } - - data_available = false; - - std::string payload; - if (!compressor.compress(nullptr, 0, true, - [&](const char *data, size_t data_len) { - payload.append(data, data_len); - return true; - })) { - ok = false; - return; - } - - if (!payload.empty()) { - // Emit chunked response header and footer for each chunk - auto chunk = from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n"; - if (!strm.is_writable() || - !write_data(strm, chunk.data(), chunk.size())) { - ok = false; - return; - } - } - - static const std::string done_marker("0\r\n"); - if (!write_data(strm, done_marker.data(), done_marker.size())) { - ok = false; - } - - // Trailer - if (trailer) { - for (const auto &kv : *trailer) { - std::string field_line = kv.first + ": " + kv.second + "\r\n"; - if (!write_data(strm, field_line.data(), field_line.size())) { - ok = false; - } - } - } - - static const std::string crlf("\r\n"); - if (!write_data(strm, crlf.data(), crlf.size())) { ok = false; } - }; - - data_sink.done = [&](void) { done_with_trailer(nullptr); }; - - data_sink.done_with_trailer = [&](const Headers &trailer) { - done_with_trailer(&trailer); - }; - - while (data_available && !is_shutting_down()) { - if (!strm.is_writable()) { - error = Error::Write; - return false; - } else if (!content_provider(offset, 0, data_sink)) { - error = Error::Canceled; - return false; - } else if (!ok) { - error = Error::Write; - return false; - } - } - - error = Error::Success; - return true; -} - -template -inline bool write_content_chunked(Stream &strm, - const ContentProvider &content_provider, - const T &is_shutting_down, U &compressor) { - auto error = Error::Success; - return write_content_chunked(strm, content_provider, is_shutting_down, - compressor, error); -} - -template -inline bool redirect(T &cli, Request &req, Response &res, - const std::string &path, const std::string &location, - Error &error) { - Request new_req = req; - new_req.path = path; - new_req.redirect_count_ -= 1; - - if (res.status == StatusCode::SeeOther_303 && - (req.method != "GET" && req.method != "HEAD")) { - new_req.method = "GET"; - new_req.body.clear(); - new_req.headers.clear(); - } - - Response new_res; - - auto ret = cli.send(new_req, new_res, error); - if (ret) { - req = new_req; - res = new_res; - - if (res.location.empty()) { res.location = location; } - } - return ret; -} - -inline std::string params_to_query_str(const Params ¶ms) { - std::string query; - - for (auto it = params.begin(); it != params.end(); ++it) { - if (it != params.begin()) { query += "&"; } - query += it->first; - query += "="; - query += encode_query_param(it->second); - } - return query; -} - -inline void parse_query_text(const std::string &s, Params ¶ms) { - std::set cache; - split(s.data(), s.data() + s.size(), '&', [&](const char *b, const char *e) { - std::string kv(b, e); - if (cache.find(kv) != cache.end()) { return; } - cache.insert(kv); - - std::string key; - std::string val; - split(b, e, '=', [&](const char *b2, const char *e2) { - if (key.empty()) { - key.assign(b2, e2); - } else { - val.assign(b2, e2); - } - }); - - if (!key.empty()) { - params.emplace(decode_url(key, true), decode_url(val, true)); - } - }); -} - -inline bool parse_multipart_boundary(const std::string &content_type, - std::string &boundary) { - auto boundary_keyword = "boundary="; - auto pos = content_type.find(boundary_keyword); - if (pos == std::string::npos) { return false; } - auto end = content_type.find(';', pos); - auto beg = pos + strlen(boundary_keyword); - boundary = trim_double_quotes_copy(content_type.substr(beg, end - beg)); - return !boundary.empty(); -} - -inline void parse_disposition_params(const std::string &s, Params ¶ms) { - std::set cache; - split(s.data(), s.data() + s.size(), ';', [&](const char *b, const char *e) { - std::string kv(b, e); - if (cache.find(kv) != cache.end()) { return; } - cache.insert(kv); - - std::string key; - std::string val; - split(b, e, '=', [&](const char *b2, const char *e2) { - if (key.empty()) { - key.assign(b2, e2); - } else { - val.assign(b2, e2); - } - }); - - if (!key.empty()) { - params.emplace(trim_double_quotes_copy((key)), - trim_double_quotes_copy((val))); - } - }); -} - -#ifdef CPPHTTPLIB_NO_EXCEPTIONS -inline bool parse_range_header(const std::string &s, Ranges &ranges) { -#else -inline bool parse_range_header(const std::string &s, Ranges &ranges) try { -#endif - static auto re_first_range = std::regex(R"(bytes=(\d*-\d*(?:,\s*\d*-\d*)*))"); - std::smatch m; - if (std::regex_match(s, m, re_first_range)) { - auto pos = static_cast(m.position(1)); - auto len = static_cast(m.length(1)); - auto all_valid_ranges = true; - split(&s[pos], &s[pos + len], ',', [&](const char *b, const char *e) { - if (!all_valid_ranges) { return; } - static auto re_another_range = std::regex(R"(\s*(\d*)-(\d*))"); - std::cmatch cm; - if (std::regex_match(b, e, cm, re_another_range)) { - ssize_t first = -1; - if (!cm.str(1).empty()) { - first = static_cast(std::stoll(cm.str(1))); - } - - ssize_t last = -1; - if (!cm.str(2).empty()) { - last = static_cast(std::stoll(cm.str(2))); - } - - if (first != -1 && last != -1 && first > last) { - all_valid_ranges = false; - return; - } - ranges.emplace_back(std::make_pair(first, last)); - } - }); - return all_valid_ranges; - } - return false; -#ifdef CPPHTTPLIB_NO_EXCEPTIONS -} -#else -} catch (...) { return false; } -#endif - -class MultipartFormDataParser { -public: - MultipartFormDataParser() = default; - - void set_boundary(std::string &&boundary) { - boundary_ = boundary; - dash_boundary_crlf_ = dash_ + boundary_ + crlf_; - crlf_dash_boundary_ = crlf_ + dash_ + boundary_; - } - - bool is_valid() const { return is_valid_; } - - bool parse(const char *buf, size_t n, const ContentReceiver &content_callback, - const MultipartContentHeader &header_callback) { - - buf_append(buf, n); - - while (buf_size() > 0) { - switch (state_) { - case 0: { // Initial boundary - buf_erase(buf_find(dash_boundary_crlf_)); - if (dash_boundary_crlf_.size() > buf_size()) { return true; } - if (!buf_start_with(dash_boundary_crlf_)) { return false; } - buf_erase(dash_boundary_crlf_.size()); - state_ = 1; - break; - } - case 1: { // New entry - clear_file_info(); - state_ = 2; - break; - } - case 2: { // Headers - auto pos = buf_find(crlf_); - if (pos > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } - while (pos < buf_size()) { - // Empty line - if (pos == 0) { - if (!header_callback(file_)) { - is_valid_ = false; - return false; - } - buf_erase(crlf_.size()); - state_ = 3; - break; - } - - const auto header = buf_head(pos); - - if (!parse_header(header.data(), header.data() + header.size(), - [&](std::string &&, std::string &&) {})) { - is_valid_ = false; - return false; - } - - static const std::string header_content_type = "Content-Type:"; - - if (start_with_case_ignore(header, header_content_type)) { - file_.content_type = - trim_copy(header.substr(header_content_type.size())); - } else { - static const std::regex re_content_disposition( - R"~(^Content-Disposition:\s*form-data;\s*(.*)$)~", - std::regex_constants::icase); - - std::smatch m; - if (std::regex_match(header, m, re_content_disposition)) { - Params params; - parse_disposition_params(m[1], params); - - auto it = params.find("name"); - if (it != params.end()) { - file_.name = it->second; - } else { - is_valid_ = false; - return false; - } - - it = params.find("filename"); - if (it != params.end()) { file_.filename = it->second; } - - it = params.find("filename*"); - if (it != params.end()) { - // Only allow UTF-8 enconnding... - static const std::regex re_rfc5987_encoding( - R"~(^UTF-8''(.+?)$)~", std::regex_constants::icase); - - std::smatch m2; - if (std::regex_match(it->second, m2, re_rfc5987_encoding)) { - file_.filename = decode_url(m2[1], false); // override... - } else { - is_valid_ = false; - return false; - } - } - } - } - buf_erase(pos + crlf_.size()); - pos = buf_find(crlf_); - } - if (state_ != 3) { return true; } - break; - } - case 3: { // Body - if (crlf_dash_boundary_.size() > buf_size()) { return true; } - auto pos = buf_find(crlf_dash_boundary_); - if (pos < buf_size()) { - if (!content_callback(buf_data(), pos)) { - is_valid_ = false; - return false; - } - buf_erase(pos + crlf_dash_boundary_.size()); - state_ = 4; - } else { - auto len = buf_size() - crlf_dash_boundary_.size(); - if (len > 0) { - if (!content_callback(buf_data(), len)) { - is_valid_ = false; - return false; - } - buf_erase(len); - } - return true; - } - break; - } - case 4: { // Boundary - if (crlf_.size() > buf_size()) { return true; } - if (buf_start_with(crlf_)) { - buf_erase(crlf_.size()); - state_ = 1; - } else { - if (dash_.size() > buf_size()) { return true; } - if (buf_start_with(dash_)) { - buf_erase(dash_.size()); - is_valid_ = true; - buf_erase(buf_size()); // Remove epilogue - } else { - return true; - } - } - break; - } - } - } - - return true; - } - -private: - void clear_file_info() { - file_.name.clear(); - file_.filename.clear(); - file_.content_type.clear(); - } - - bool start_with_case_ignore(const std::string &a, - const std::string &b) const { - if (a.size() < b.size()) { return false; } - for (size_t i = 0; i < b.size(); i++) { - if (::tolower(a[i]) != ::tolower(b[i])) { return false; } - } - return true; - } - - const std::string dash_ = "--"; - const std::string crlf_ = "\r\n"; - std::string boundary_; - std::string dash_boundary_crlf_; - std::string crlf_dash_boundary_; - - size_t state_ = 0; - bool is_valid_ = false; - MultipartFormData file_; - - // Buffer - bool start_with(const std::string &a, size_t spos, size_t epos, - const std::string &b) const { - if (epos - spos < b.size()) { return false; } - for (size_t i = 0; i < b.size(); i++) { - if (a[i + spos] != b[i]) { return false; } - } - return true; - } - - size_t buf_size() const { return buf_epos_ - buf_spos_; } - - const char *buf_data() const { return &buf_[buf_spos_]; } - - std::string buf_head(size_t l) const { return buf_.substr(buf_spos_, l); } - - bool buf_start_with(const std::string &s) const { - return start_with(buf_, buf_spos_, buf_epos_, s); - } - - size_t buf_find(const std::string &s) const { - auto c = s.front(); - - size_t off = buf_spos_; - while (off < buf_epos_) { - auto pos = off; - while (true) { - if (pos == buf_epos_) { return buf_size(); } - if (buf_[pos] == c) { break; } - pos++; - } - - auto remaining_size = buf_epos_ - pos; - if (s.size() > remaining_size) { return buf_size(); } - - if (start_with(buf_, pos, buf_epos_, s)) { return pos - buf_spos_; } - - off = pos + 1; - } - - return buf_size(); - } - - void buf_append(const char *data, size_t n) { - auto remaining_size = buf_size(); - if (remaining_size > 0 && buf_spos_ > 0) { - for (size_t i = 0; i < remaining_size; i++) { - buf_[i] = buf_[buf_spos_ + i]; - } - } - buf_spos_ = 0; - buf_epos_ = remaining_size; - - if (remaining_size + n > buf_.size()) { buf_.resize(remaining_size + n); } - - for (size_t i = 0; i < n; i++) { - buf_[buf_epos_ + i] = data[i]; - } - buf_epos_ += n; - } - - void buf_erase(size_t size) { buf_spos_ += size; } - - std::string buf_; - size_t buf_spos_ = 0; - size_t buf_epos_ = 0; -}; - -inline std::string to_lower(const char *beg, const char *end) { - std::string out; - auto it = beg; - while (it != end) { - out += static_cast(::tolower(*it)); - it++; - } - return out; -} - -inline std::string random_string(size_t length) { - static const char data[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - // std::random_device might actually be deterministic on some - // platforms, but due to lack of support in the c++ standard library, - // doing better requires either some ugly hacks or breaking portability. - static std::random_device seed_gen; - - // Request 128 bits of entropy for initialization - static std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), - seed_gen()}; - - static std::mt19937 engine(seed_sequence); - - std::string result; - for (size_t i = 0; i < length; i++) { - result += data[engine() % (sizeof(data) - 1)]; - } - return result; -} - -inline std::string make_multipart_data_boundary() { - return "--cpp-httplib-multipart-data-" + detail::random_string(16); -} - -inline bool is_multipart_boundary_chars_valid(const std::string &boundary) { - auto valid = true; - for (size_t i = 0; i < boundary.size(); i++) { - auto c = boundary[i]; - if (!std::isalnum(c) && c != '-' && c != '_') { - valid = false; - break; - } - } - return valid; -} - -template -inline std::string -serialize_multipart_formdata_item_begin(const T &item, - const std::string &boundary) { - std::string body = "--" + boundary + "\r\n"; - body += "Content-Disposition: form-data; name=\"" + item.name + "\""; - if (!item.filename.empty()) { - body += "; filename=\"" + item.filename + "\""; - } - body += "\r\n"; - if (!item.content_type.empty()) { - body += "Content-Type: " + item.content_type + "\r\n"; - } - body += "\r\n"; - - return body; -} - -inline std::string serialize_multipart_formdata_item_end() { return "\r\n"; } - -inline std::string -serialize_multipart_formdata_finish(const std::string &boundary) { - return "--" + boundary + "--\r\n"; -} - -inline std::string -serialize_multipart_formdata_get_content_type(const std::string &boundary) { - return "multipart/form-data; boundary=" + boundary; -} - -inline std::string -serialize_multipart_formdata(const MultipartFormDataItems &items, - const std::string &boundary, bool finish = true) { - std::string body; - - for (const auto &item : items) { - body += serialize_multipart_formdata_item_begin(item, boundary); - body += item.content + serialize_multipart_formdata_item_end(); - } - - if (finish) { body += serialize_multipart_formdata_finish(boundary); } - - return body; -} - -inline bool range_error(Request &req, Response &res) { - if (!req.ranges.empty() && 200 <= res.status && res.status < 300) { - ssize_t contant_len = static_cast( - res.content_length_ ? res.content_length_ : res.body.size()); - - ssize_t prev_first_pos = -1; - ssize_t prev_last_pos = -1; - size_t overwrapping_count = 0; - - // NOTE: The following Range check is based on '14.2. Range' in RFC 9110 - // 'HTTP Semantics' to avoid potential denial-of-service attacks. - // https://www.rfc-editor.org/rfc/rfc9110#section-14.2 - - // Too many ranges - if (req.ranges.size() > CPPHTTPLIB_RANGE_MAX_COUNT) { return true; } - - for (auto &r : req.ranges) { - auto &first_pos = r.first; - auto &last_pos = r.second; - - if (first_pos == -1 && last_pos == -1) { - first_pos = 0; - last_pos = contant_len; - } - - if (first_pos == -1) { - first_pos = contant_len - last_pos; - last_pos = contant_len - 1; - } - - if (last_pos == -1) { last_pos = contant_len - 1; } - - // Range must be within content length - if (!(0 <= first_pos && first_pos <= last_pos && - last_pos <= contant_len - 1)) { - return true; - } - - // Ranges must be in ascending order - if (first_pos <= prev_first_pos) { return true; } - - // Request must not have more than two overlapping ranges - if (first_pos <= prev_last_pos) { - overwrapping_count++; - if (overwrapping_count > 2) { return true; } - } - - prev_first_pos = (std::max)(prev_first_pos, first_pos); - prev_last_pos = (std::max)(prev_last_pos, last_pos); - } - } - - return false; -} - -inline std::pair -get_range_offset_and_length(Range r, size_t content_length) { - assert(r.first != -1 && r.second != -1); - assert(0 <= r.first && r.first < static_cast(content_length)); - assert(r.first <= r.second && - r.second < static_cast(content_length)); - - return std::make_pair(r.first, static_cast(r.second - r.first) + 1); -} - -inline std::string make_content_range_header_field( - const std::pair &offset_and_length, size_t content_length) { - auto st = offset_and_length.first; - auto ed = st + offset_and_length.second - 1; - - std::string field = "bytes "; - field += std::to_string(st); - field += "-"; - field += std::to_string(ed); - field += "/"; - field += std::to_string(content_length); - return field; -} - -template -bool process_multipart_ranges_data(const Request &req, - const std::string &boundary, - const std::string &content_type, - size_t content_length, SToken stoken, - CToken ctoken, Content content) { - for (size_t i = 0; i < req.ranges.size(); i++) { - ctoken("--"); - stoken(boundary); - ctoken("\r\n"); - if (!content_type.empty()) { - ctoken("Content-Type: "); - stoken(content_type); - ctoken("\r\n"); - } - - auto offset_and_length = - get_range_offset_and_length(req.ranges[i], content_length); - - ctoken("Content-Range: "); - stoken(make_content_range_header_field(offset_and_length, content_length)); - ctoken("\r\n"); - ctoken("\r\n"); - - if (!content(offset_and_length.first, offset_and_length.second)) { - return false; - } - ctoken("\r\n"); - } - - ctoken("--"); - stoken(boundary); - ctoken("--"); - - return true; -} - -inline void make_multipart_ranges_data(const Request &req, Response &res, - const std::string &boundary, - const std::string &content_type, - size_t content_length, - std::string &data) { - process_multipart_ranges_data( - req, boundary, content_type, content_length, - [&](const std::string &token) { data += token; }, - [&](const std::string &token) { data += token; }, - [&](size_t offset, size_t length) { - assert(offset + length <= content_length); - data += res.body.substr(offset, length); - return true; - }); -} - -inline size_t get_multipart_ranges_data_length(const Request &req, - const std::string &boundary, - const std::string &content_type, - size_t content_length) { - size_t data_length = 0; - - process_multipart_ranges_data( - req, boundary, content_type, content_length, - [&](const std::string &token) { data_length += token.size(); }, - [&](const std::string &token) { data_length += token.size(); }, - [&](size_t /*offset*/, size_t length) { - data_length += length; - return true; - }); - - return data_length; -} - -template -inline bool -write_multipart_ranges_data(Stream &strm, const Request &req, Response &res, - const std::string &boundary, - const std::string &content_type, - size_t content_length, const T &is_shutting_down) { - return process_multipart_ranges_data( - req, boundary, content_type, content_length, - [&](const std::string &token) { strm.write(token); }, - [&](const std::string &token) { strm.write(token); }, - [&](size_t offset, size_t length) { - return write_content(strm, res.content_provider_, offset, length, - is_shutting_down); - }); -} - -inline bool expect_content(const Request &req) { - if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH" || - req.method == "PRI" || req.method == "DELETE") { - return true; - } - // TODO: check if Content-Length is set - return false; -} - -inline bool has_crlf(const std::string &s) { - auto p = s.c_str(); - while (*p) { - if (*p == '\r' || *p == '\n') { return true; } - p++; - } - return false; -} - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline std::string message_digest(const std::string &s, const EVP_MD *algo) { - auto context = std::unique_ptr( - EVP_MD_CTX_new(), EVP_MD_CTX_free); - - unsigned int hash_length = 0; - unsigned char hash[EVP_MAX_MD_SIZE]; - - EVP_DigestInit_ex(context.get(), algo, nullptr); - EVP_DigestUpdate(context.get(), s.c_str(), s.size()); - EVP_DigestFinal_ex(context.get(), hash, &hash_length); - - std::stringstream ss; - for (auto i = 0u; i < hash_length; ++i) { - ss << std::hex << std::setw(2) << std::setfill('0') - << static_cast(hash[i]); - } - - return ss.str(); -} - -inline std::string MD5(const std::string &s) { - return message_digest(s, EVP_md5()); -} - -inline std::string SHA_256(const std::string &s) { - return message_digest(s, EVP_sha256()); -} - -inline std::string SHA_512(const std::string &s) { - return message_digest(s, EVP_sha512()); -} -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -#ifdef _WIN32 -// NOTE: This code came up with the following stackoverflow post: -// https://stackoverflow.com/questions/9507184/can-openssl-on-windows-use-the-system-certificate-store -inline bool load_system_certs_on_windows(X509_STORE *store) { - auto hStore = CertOpenSystemStoreW((HCRYPTPROV_LEGACY)NULL, L"ROOT"); - if (!hStore) { return false; } - - auto result = false; - PCCERT_CONTEXT pContext = NULL; - while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != - nullptr) { - auto encoded_cert = - static_cast(pContext->pbCertEncoded); - - auto x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded); - if (x509) { - X509_STORE_add_cert(store, x509); - X509_free(x509); - result = true; - } - } - - CertFreeCertificateContext(pContext); - CertCloseStore(hStore, 0); - - return result; -} -#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) -#if TARGET_OS_OSX -template -using CFObjectPtr = - std::unique_ptr::type, void (*)(CFTypeRef)>; - -inline void cf_object_ptr_deleter(CFTypeRef obj) { - if (obj) { CFRelease(obj); } -} - -inline bool retrieve_certs_from_keychain(CFObjectPtr &certs) { - CFStringRef keys[] = {kSecClass, kSecMatchLimit, kSecReturnRef}; - CFTypeRef values[] = {kSecClassCertificate, kSecMatchLimitAll, - kCFBooleanTrue}; - - CFObjectPtr query( - CFDictionaryCreate(nullptr, reinterpret_cast(keys), values, - sizeof(keys) / sizeof(keys[0]), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks), - cf_object_ptr_deleter); - - if (!query) { return false; } - - CFTypeRef security_items = nullptr; - if (SecItemCopyMatching(query.get(), &security_items) != errSecSuccess || - CFArrayGetTypeID() != CFGetTypeID(security_items)) { - return false; - } - - certs.reset(reinterpret_cast(security_items)); - return true; -} - -inline bool retrieve_root_certs_from_keychain(CFObjectPtr &certs) { - CFArrayRef root_security_items = nullptr; - if (SecTrustCopyAnchorCertificates(&root_security_items) != errSecSuccess) { - return false; - } - - certs.reset(root_security_items); - return true; -} - -inline bool add_certs_to_x509_store(CFArrayRef certs, X509_STORE *store) { - auto result = false; - for (auto i = 0; i < CFArrayGetCount(certs); ++i) { - const auto cert = reinterpret_cast( - CFArrayGetValueAtIndex(certs, i)); - - if (SecCertificateGetTypeID() != CFGetTypeID(cert)) { continue; } - - CFDataRef cert_data = nullptr; - if (SecItemExport(cert, kSecFormatX509Cert, 0, nullptr, &cert_data) != - errSecSuccess) { - continue; - } - - CFObjectPtr cert_data_ptr(cert_data, cf_object_ptr_deleter); - - auto encoded_cert = static_cast( - CFDataGetBytePtr(cert_data_ptr.get())); - - auto x509 = - d2i_X509(NULL, &encoded_cert, CFDataGetLength(cert_data_ptr.get())); - - if (x509) { - X509_STORE_add_cert(store, x509); - X509_free(x509); - result = true; - } - } - - return result; -} - -inline bool load_system_certs_on_macos(X509_STORE *store) { - auto result = false; - CFObjectPtr certs(nullptr, cf_object_ptr_deleter); - if (retrieve_certs_from_keychain(certs) && certs) { - result = add_certs_to_x509_store(certs.get(), store); - } - - if (retrieve_root_certs_from_keychain(certs) && certs) { - result = add_certs_to_x509_store(certs.get(), store) || result; - } - - return result; -} -#endif // TARGET_OS_OSX -#endif // _WIN32 -#endif // CPPHTTPLIB_OPENSSL_SUPPORT - -#ifdef _WIN32 -class WSInit { -public: - WSInit() { - WSADATA wsaData; - if (WSAStartup(0x0002, &wsaData) == 0) is_valid_ = true; - } - - ~WSInit() { - if (is_valid_) WSACleanup(); - } - - bool is_valid_ = false; -}; - -static WSInit wsinit_; -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline std::pair make_digest_authentication_header( - const Request &req, const std::map &auth, - size_t cnonce_count, const std::string &cnonce, const std::string &username, - const std::string &password, bool is_proxy = false) { - std::string nc; - { - std::stringstream ss; - ss << std::setfill('0') << std::setw(8) << std::hex << cnonce_count; - nc = ss.str(); - } - - std::string qop; - if (auth.find("qop") != auth.end()) { - qop = auth.at("qop"); - if (qop.find("auth-int") != std::string::npos) { - qop = "auth-int"; - } else if (qop.find("auth") != std::string::npos) { - qop = "auth"; - } else { - qop.clear(); - } - } - - std::string algo = "MD5"; - if (auth.find("algorithm") != auth.end()) { algo = auth.at("algorithm"); } - - std::string response; - { - auto H = algo == "SHA-256" ? detail::SHA_256 - : algo == "SHA-512" ? detail::SHA_512 - : detail::MD5; - - auto A1 = username + ":" + auth.at("realm") + ":" + password; - - auto A2 = req.method + ":" + req.path; - if (qop == "auth-int") { A2 += ":" + H(req.body); } - - if (qop.empty()) { - response = H(H(A1) + ":" + auth.at("nonce") + ":" + H(A2)); - } else { - response = H(H(A1) + ":" + auth.at("nonce") + ":" + nc + ":" + cnonce + - ":" + qop + ":" + H(A2)); - } - } - - auto opaque = (auth.find("opaque") != auth.end()) ? auth.at("opaque") : ""; - - auto field = "Digest username=\"" + username + "\", realm=\"" + - auth.at("realm") + "\", nonce=\"" + auth.at("nonce") + - "\", uri=\"" + req.path + "\", algorithm=" + algo + - (qop.empty() ? ", response=\"" - : ", qop=" + qop + ", nc=" + nc + ", cnonce=\"" + - cnonce + "\", response=\"") + - response + "\"" + - (opaque.empty() ? "" : ", opaque=\"" + opaque + "\""); - - auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; - return std::make_pair(key, field); -} -#endif - -inline bool parse_www_authenticate(const Response &res, - std::map &auth, - bool is_proxy) { - auto auth_key = is_proxy ? "Proxy-Authenticate" : "WWW-Authenticate"; - if (res.has_header(auth_key)) { - static auto re = std::regex(R"~((?:(?:,\s*)?(.+?)=(?:"(.*?)"|([^,]*))))~"); - auto s = res.get_header_value(auth_key); - auto pos = s.find(' '); - if (pos != std::string::npos) { - auto type = s.substr(0, pos); - if (type == "Basic") { - return false; - } else if (type == "Digest") { - s = s.substr(pos + 1); - auto beg = std::sregex_iterator(s.begin(), s.end(), re); - for (auto i = beg; i != std::sregex_iterator(); ++i) { - const auto &m = *i; - auto key = s.substr(static_cast(m.position(1)), - static_cast(m.length(1))); - auto val = m.length(2) > 0 - ? s.substr(static_cast(m.position(2)), - static_cast(m.length(2))) - : s.substr(static_cast(m.position(3)), - static_cast(m.length(3))); - auth[key] = val; - } - return true; - } - } - } - return false; -} - -class ContentProviderAdapter { -public: - explicit ContentProviderAdapter( - ContentProviderWithoutLength &&content_provider) - : content_provider_(content_provider) {} - - bool operator()(size_t offset, size_t, DataSink &sink) { - return content_provider_(offset, sink); - } - -private: - ContentProviderWithoutLength content_provider_; -}; - -} // namespace detail - -inline std::string hosted_at(const std::string &hostname) { - std::vector addrs; - hosted_at(hostname, addrs); - if (addrs.empty()) { return std::string(); } - return addrs[0]; -} - -inline void hosted_at(const std::string &hostname, - std::vector &addrs) { - struct addrinfo hints; - struct addrinfo *result; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(hostname.c_str(), nullptr, &hints, &result)) { -#if defined __linux__ && !defined __ANDROID__ - res_init(); -#endif - return; - } - - for (auto rp = result; rp; rp = rp->ai_next) { - const auto &addr = - *reinterpret_cast(rp->ai_addr); - std::string ip; - auto dummy = -1; - if (detail::get_ip_and_port(addr, sizeof(struct sockaddr_storage), ip, - dummy)) { - addrs.push_back(ip); - } - } - - freeaddrinfo(result); -} - -inline std::string append_query_params(const std::string &path, - const Params ¶ms) { - std::string path_with_query = path; - const static std::regex re("[^?]+\\?.*"); - auto delm = std::regex_match(path, re) ? '&' : '?'; - path_with_query += delm + detail::params_to_query_str(params); - return path_with_query; -} - -// Header utilities -inline std::pair -make_range_header(const Ranges &ranges) { - std::string field = "bytes="; - auto i = 0; - for (const auto &r : ranges) { - if (i != 0) { field += ", "; } - if (r.first != -1) { field += std::to_string(r.first); } - field += '-'; - if (r.second != -1) { field += std::to_string(r.second); } - i++; - } - return std::make_pair("Range", std::move(field)); -} - -inline std::pair -make_basic_authentication_header(const std::string &username, - const std::string &password, bool is_proxy) { - auto field = "Basic " + detail::base64_encode(username + ":" + password); - auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; - return std::make_pair(key, std::move(field)); -} - -inline std::pair -make_bearer_token_authentication_header(const std::string &token, - bool is_proxy = false) { - auto field = "Bearer " + token; - auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; - return std::make_pair(key, std::move(field)); -} - -// Request implementation -inline bool Request::has_header(const std::string &key) const { - return detail::has_header(headers, key); -} - -inline std::string Request::get_header_value(const std::string &key, - size_t id) const { - return detail::get_header_value(headers, key, id, ""); -} - -inline size_t Request::get_header_value_count(const std::string &key) const { - auto r = headers.equal_range(key); - return static_cast(std::distance(r.first, r.second)); -} - -inline void Request::set_header(const std::string &key, - const std::string &val) { - if (!detail::has_crlf(key) && !detail::has_crlf(val)) { - headers.emplace(key, val); - } -} - -inline bool Request::has_param(const std::string &key) const { - return params.find(key) != params.end(); -} - -inline std::string Request::get_param_value(const std::string &key, - size_t id) const { - auto rng = params.equal_range(key); - auto it = rng.first; - std::advance(it, static_cast(id)); - if (it != rng.second) { return it->second; } - return std::string(); -} - -inline size_t Request::get_param_value_count(const std::string &key) const { - auto r = params.equal_range(key); - return static_cast(std::distance(r.first, r.second)); -} - -inline bool Request::is_multipart_form_data() const { - const auto &content_type = get_header_value("Content-Type"); - return !content_type.rfind("multipart/form-data", 0); -} - -inline bool Request::has_file(const std::string &key) const { - return files.find(key) != files.end(); -} - -inline MultipartFormData Request::get_file_value(const std::string &key) const { - auto it = files.find(key); - if (it != files.end()) { return it->second; } - return MultipartFormData(); -} - -inline std::vector -Request::get_file_values(const std::string &key) const { - std::vector values; - auto rng = files.equal_range(key); - for (auto it = rng.first; it != rng.second; it++) { - values.push_back(it->second); - } - return values; -} - -// Response implementation -inline bool Response::has_header(const std::string &key) const { - return headers.find(key) != headers.end(); -} - -inline std::string Response::get_header_value(const std::string &key, - size_t id) const { - return detail::get_header_value(headers, key, id, ""); -} - -inline size_t Response::get_header_value_count(const std::string &key) const { - auto r = headers.equal_range(key); - return static_cast(std::distance(r.first, r.second)); -} - -inline void Response::set_header(const std::string &key, - const std::string &val) { - if (!detail::has_crlf(key) && !detail::has_crlf(val)) { - headers.emplace(key, val); - } -} - -inline void Response::set_redirect(const std::string &url, int stat) { - if (!detail::has_crlf(url)) { - set_header("Location", url); - if (300 <= stat && stat < 400) { - this->status = stat; - } else { - this->status = StatusCode::Found_302; - } - } -} - -inline void Response::set_content(const char *s, size_t n, - const std::string &content_type) { - body.assign(s, n); - - auto rng = headers.equal_range("Content-Type"); - headers.erase(rng.first, rng.second); - set_header("Content-Type", content_type); -} - -inline void Response::set_content(const std::string &s, - const std::string &content_type) { - set_content(s.data(), s.size(), content_type); -} - -inline void Response::set_content(std::string &&s, - const std::string &content_type) { - body = std::move(s); - - auto rng = headers.equal_range("Content-Type"); - headers.erase(rng.first, rng.second); - set_header("Content-Type", content_type); -} - -inline void Response::set_content_provider( - size_t in_length, const std::string &content_type, ContentProvider provider, - ContentProviderResourceReleaser resource_releaser) { - set_header("Content-Type", content_type); - content_length_ = in_length; - if (in_length > 0) { content_provider_ = std::move(provider); } - content_provider_resource_releaser_ = std::move(resource_releaser); - is_chunked_content_provider_ = false; -} - -inline void Response::set_content_provider( - const std::string &content_type, ContentProviderWithoutLength provider, - ContentProviderResourceReleaser resource_releaser) { - set_header("Content-Type", content_type); - content_length_ = 0; - content_provider_ = detail::ContentProviderAdapter(std::move(provider)); - content_provider_resource_releaser_ = std::move(resource_releaser); - is_chunked_content_provider_ = false; -} - -inline void Response::set_chunked_content_provider( - const std::string &content_type, ContentProviderWithoutLength provider, - ContentProviderResourceReleaser resource_releaser) { - set_header("Content-Type", content_type); - content_length_ = 0; - content_provider_ = detail::ContentProviderAdapter(std::move(provider)); - content_provider_resource_releaser_ = std::move(resource_releaser); - is_chunked_content_provider_ = true; -} - -// Result implementation -inline bool Result::has_request_header(const std::string &key) const { - return request_headers_.find(key) != request_headers_.end(); -} - -inline std::string Result::get_request_header_value(const std::string &key, - size_t id) const { - return detail::get_header_value(request_headers_, key, id, ""); -} - -inline size_t -Result::get_request_header_value_count(const std::string &key) const { - auto r = request_headers_.equal_range(key); - return static_cast(std::distance(r.first, r.second)); -} - -// Stream implementation -inline ssize_t Stream::write(const char *ptr) { - return write(ptr, strlen(ptr)); -} - -inline ssize_t Stream::write(const std::string &s) { - return write(s.data(), s.size()); -} - -namespace detail { - -// Socket stream implementation -inline SocketStream::SocketStream(socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, - time_t write_timeout_sec, - time_t write_timeout_usec) - : sock_(sock), read_timeout_sec_(read_timeout_sec), - read_timeout_usec_(read_timeout_usec), - write_timeout_sec_(write_timeout_sec), - write_timeout_usec_(write_timeout_usec), read_buff_(read_buff_size_, 0) {} - -inline SocketStream::~SocketStream() = default; - -inline bool SocketStream::is_readable() const { - return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0; -} - -inline bool SocketStream::is_writable() const { - return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 && - is_socket_alive(sock_); -} - -inline ssize_t SocketStream::read(char *ptr, size_t size) { -#ifdef _WIN32 - size = - (std::min)(size, static_cast((std::numeric_limits::max)())); -#else - size = (std::min)(size, - static_cast((std::numeric_limits::max)())); -#endif - - if (read_buff_off_ < read_buff_content_size_) { - auto remaining_size = read_buff_content_size_ - read_buff_off_; - if (size <= remaining_size) { - memcpy(ptr, read_buff_.data() + read_buff_off_, size); - read_buff_off_ += size; - return static_cast(size); - } else { - memcpy(ptr, read_buff_.data() + read_buff_off_, remaining_size); - read_buff_off_ += remaining_size; - return static_cast(remaining_size); - } - } - - if (!is_readable()) { return -1; } - - read_buff_off_ = 0; - read_buff_content_size_ = 0; - - if (size < read_buff_size_) { - auto n = read_socket(sock_, read_buff_.data(), read_buff_size_, - CPPHTTPLIB_RECV_FLAGS); - if (n <= 0) { - return n; - } else if (n <= static_cast(size)) { - memcpy(ptr, read_buff_.data(), static_cast(n)); - return n; - } else { - memcpy(ptr, read_buff_.data(), size); - read_buff_off_ = size; - read_buff_content_size_ = static_cast(n); - return static_cast(size); - } - } else { - return read_socket(sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS); - } -} - -inline ssize_t SocketStream::write(const char *ptr, size_t size) { - if (!is_writable()) { return -1; } - -#if defined(_WIN32) && !defined(_WIN64) - size = - (std::min)(size, static_cast((std::numeric_limits::max)())); -#endif - - return send_socket(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS); -} - -inline void SocketStream::get_remote_ip_and_port(std::string &ip, - int &port) const { - return detail::get_remote_ip_and_port(sock_, ip, port); -} - -inline void SocketStream::get_local_ip_and_port(std::string &ip, - int &port) const { - return detail::get_local_ip_and_port(sock_, ip, port); -} - -inline socket_t SocketStream::socket() const { return sock_; } - -// Buffer stream implementation -inline bool BufferStream::is_readable() const { return true; } - -inline bool BufferStream::is_writable() const { return true; } - -inline ssize_t BufferStream::read(char *ptr, size_t size) { -#if defined(_MSC_VER) && _MSC_VER < 1910 - auto len_read = buffer._Copy_s(ptr, size, size, position); -#else - auto len_read = buffer.copy(ptr, size, position); -#endif - position += static_cast(len_read); - return static_cast(len_read); -} - -inline ssize_t BufferStream::write(const char *ptr, size_t size) { - buffer.append(ptr, size); - return static_cast(size); -} - -inline void BufferStream::get_remote_ip_and_port(std::string & /*ip*/, - int & /*port*/) const {} - -inline void BufferStream::get_local_ip_and_port(std::string & /*ip*/, - int & /*port*/) const {} - -inline socket_t BufferStream::socket() const { return 0; } - -inline const std::string &BufferStream::get_buffer() const { return buffer; } - -inline PathParamsMatcher::PathParamsMatcher(const std::string &pattern) { - // One past the last ending position of a path param substring - std::size_t last_param_end = 0; - -#ifndef CPPHTTPLIB_NO_EXCEPTIONS - // Needed to ensure that parameter names are unique during matcher - // construction - // If exceptions are disabled, only last duplicate path - // parameter will be set - std::unordered_set param_name_set; -#endif - - while (true) { - const auto marker_pos = pattern.find(marker, last_param_end); - if (marker_pos == std::string::npos) { break; } - - static_fragments_.push_back( - pattern.substr(last_param_end, marker_pos - last_param_end)); - - const auto param_name_start = marker_pos + 1; - - auto sep_pos = pattern.find(separator, param_name_start); - if (sep_pos == std::string::npos) { sep_pos = pattern.length(); } - - auto param_name = - pattern.substr(param_name_start, sep_pos - param_name_start); - -#ifndef CPPHTTPLIB_NO_EXCEPTIONS - if (param_name_set.find(param_name) != param_name_set.cend()) { - std::string msg = "Encountered path parameter '" + param_name + - "' multiple times in route pattern '" + pattern + "'."; - throw std::invalid_argument(msg); - } -#endif - - param_names_.push_back(std::move(param_name)); - - last_param_end = sep_pos + 1; - } - - if (last_param_end < pattern.length()) { - static_fragments_.push_back(pattern.substr(last_param_end)); - } -} - -inline bool PathParamsMatcher::match(Request &request) const { - request.matches = std::smatch(); - request.path_params.clear(); - request.path_params.reserve(param_names_.size()); - - // One past the position at which the path matched the pattern last time - std::size_t starting_pos = 0; - for (size_t i = 0; i < static_fragments_.size(); ++i) { - const auto &fragment = static_fragments_[i]; - - if (starting_pos + fragment.length() > request.path.length()) { - return false; - } - - // Avoid unnecessary allocation by using strncmp instead of substr + - // comparison - if (std::strncmp(request.path.c_str() + starting_pos, fragment.c_str(), - fragment.length()) != 0) { - return false; - } - - starting_pos += fragment.length(); - - // Should only happen when we have a static fragment after a param - // Example: '/users/:id/subscriptions' - // The 'subscriptions' fragment here does not have a corresponding param - if (i >= param_names_.size()) { continue; } - - auto sep_pos = request.path.find(separator, starting_pos); - if (sep_pos == std::string::npos) { sep_pos = request.path.length(); } - - const auto ¶m_name = param_names_[i]; - - request.path_params.emplace( - param_name, request.path.substr(starting_pos, sep_pos - starting_pos)); - - // Mark everythin up to '/' as matched - starting_pos = sep_pos + 1; - } - // Returns false if the path is longer than the pattern - return starting_pos >= request.path.length(); -} - -inline bool RegexMatcher::match(Request &request) const { - request.path_params.clear(); - return std::regex_match(request.path, request.matches, regex_); -} - -} // namespace detail - -// HTTP server implementation -inline Server::Server() - : new_task_queue( - [] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }) { -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif -} - -inline Server::~Server() = default; - -inline std::unique_ptr -Server::make_matcher(const std::string &pattern) { - if (pattern.find("/:") != std::string::npos) { - return detail::make_unique(pattern); - } else { - return detail::make_unique(pattern); - } -} - -inline Server &Server::Get(const std::string &pattern, Handler handler) { - get_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); - return *this; -} - -inline Server &Server::Post(const std::string &pattern, Handler handler) { - post_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); - return *this; -} - -inline Server &Server::Post(const std::string &pattern, - HandlerWithContentReader handler) { - post_handlers_for_content_reader_.emplace_back(make_matcher(pattern), - std::move(handler)); - return *this; -} - -inline Server &Server::Put(const std::string &pattern, Handler handler) { - put_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); - return *this; -} - -inline Server &Server::Put(const std::string &pattern, - HandlerWithContentReader handler) { - put_handlers_for_content_reader_.emplace_back(make_matcher(pattern), - std::move(handler)); - return *this; -} - -inline Server &Server::Patch(const std::string &pattern, Handler handler) { - patch_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); - return *this; -} - -inline Server &Server::Patch(const std::string &pattern, - HandlerWithContentReader handler) { - patch_handlers_for_content_reader_.emplace_back(make_matcher(pattern), - std::move(handler)); - return *this; -} - -inline Server &Server::Delete(const std::string &pattern, Handler handler) { - delete_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); - return *this; -} - -inline Server &Server::Delete(const std::string &pattern, - HandlerWithContentReader handler) { - delete_handlers_for_content_reader_.emplace_back(make_matcher(pattern), - std::move(handler)); - return *this; -} - -inline Server &Server::Options(const std::string &pattern, Handler handler) { - options_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); - return *this; -} - -inline bool Server::set_base_dir(const std::string &dir, - const std::string &mount_point) { - return set_mount_point(mount_point, dir); -} - -inline bool Server::set_mount_point(const std::string &mount_point, - const std::string &dir, Headers headers) { - if (detail::is_dir(dir)) { - std::string mnt = !mount_point.empty() ? mount_point : "/"; - if (!mnt.empty() && mnt[0] == '/') { - base_dirs_.push_back({mnt, dir, std::move(headers)}); - return true; - } - } - return false; -} - -inline bool Server::remove_mount_point(const std::string &mount_point) { - for (auto it = base_dirs_.begin(); it != base_dirs_.end(); ++it) { - if (it->mount_point == mount_point) { - base_dirs_.erase(it); - return true; - } - } - return false; -} - -inline Server & -Server::set_file_extension_and_mimetype_mapping(const std::string &ext, - const std::string &mime) { - file_extension_and_mimetype_map_[ext] = mime; - return *this; -} - -inline Server &Server::set_default_file_mimetype(const std::string &mime) { - default_file_mimetype_ = mime; - return *this; -} - -inline Server &Server::set_file_request_handler(Handler handler) { - file_request_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_error_handler(HandlerWithResponse handler) { - error_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_error_handler(Handler handler) { - error_handler_ = [handler](const Request &req, Response &res) { - handler(req, res); - return HandlerResponse::Handled; - }; - return *this; -} - -inline Server &Server::set_exception_handler(ExceptionHandler handler) { - exception_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_pre_routing_handler(HandlerWithResponse handler) { - pre_routing_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_post_routing_handler(Handler handler) { - post_routing_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_logger(Logger logger) { - logger_ = std::move(logger); - return *this; -} - -inline Server & -Server::set_expect_100_continue_handler(Expect100ContinueHandler handler) { - expect_100_continue_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_address_family(int family) { - address_family_ = family; - return *this; -} - -inline Server &Server::set_tcp_nodelay(bool on) { - tcp_nodelay_ = on; - return *this; -} - -inline Server &Server::set_socket_options(SocketOptions socket_options) { - socket_options_ = std::move(socket_options); - return *this; -} - -inline Server &Server::set_default_headers(Headers headers) { - default_headers_ = std::move(headers); - return *this; -} - -inline Server &Server::set_header_writer( - std::function const &writer) { - header_writer_ = writer; - return *this; -} - -inline Server &Server::set_keep_alive_max_count(size_t count) { - keep_alive_max_count_ = count; - return *this; -} - -inline Server &Server::set_keep_alive_timeout(time_t sec) { - keep_alive_timeout_sec_ = sec; - return *this; -} - -inline Server &Server::set_read_timeout(time_t sec, time_t usec) { - read_timeout_sec_ = sec; - read_timeout_usec_ = usec; - return *this; -} - -inline Server &Server::set_write_timeout(time_t sec, time_t usec) { - write_timeout_sec_ = sec; - write_timeout_usec_ = usec; - return *this; -} - -inline Server &Server::set_idle_interval(time_t sec, time_t usec) { - idle_interval_sec_ = sec; - idle_interval_usec_ = usec; - return *this; -} - -inline Server &Server::set_payload_max_length(size_t length) { - payload_max_length_ = length; - return *this; -} - -inline bool Server::bind_to_port(const std::string &host, int port, - int socket_flags) { - return bind_internal(host, port, socket_flags) >= 0; -} -inline int Server::bind_to_any_port(const std::string &host, int socket_flags) { - return bind_internal(host, 0, socket_flags); -} - -inline bool Server::listen_after_bind() { - auto se = detail::scope_exit([&]() { done_ = true; }); - return listen_internal(); -} - -inline bool Server::listen(const std::string &host, int port, - int socket_flags) { - auto se = detail::scope_exit([&]() { done_ = true; }); - return bind_to_port(host, port, socket_flags) && listen_internal(); -} - -inline bool Server::is_running() const { return is_running_; } - -inline void Server::wait_until_ready() const { - while (!is_running() && !done_) { - std::this_thread::sleep_for(std::chrono::milliseconds{1}); - } -} - -inline void Server::stop() { - if (is_running_) { - assert(svr_sock_ != INVALID_SOCKET); - std::atomic sock(svr_sock_.exchange(INVALID_SOCKET)); - detail::shutdown_socket(sock); - detail::close_socket(sock); - } -} - -inline bool Server::parse_request_line(const char *s, Request &req) const { - auto len = strlen(s); - if (len < 2 || s[len - 2] != '\r' || s[len - 1] != '\n') { return false; } - len -= 2; - - { - size_t count = 0; - - detail::split(s, s + len, ' ', [&](const char *b, const char *e) { - switch (count) { - case 0: req.method = std::string(b, e); break; - case 1: req.target = std::string(b, e); break; - case 2: req.version = std::string(b, e); break; - default: break; - } - count++; - }); - - if (count != 3) { return false; } - } - - static const std::set methods{ - "GET", "HEAD", "POST", "PUT", "DELETE", - "CONNECT", "OPTIONS", "TRACE", "PATCH", "PRI"}; - - if (methods.find(req.method) == methods.end()) { return false; } - - if (req.version != "HTTP/1.1" && req.version != "HTTP/1.0") { return false; } - - { - // Skip URL fragment - for (size_t i = 0; i < req.target.size(); i++) { - if (req.target[i] == '#') { - req.target.erase(i); - break; - } - } - - size_t count = 0; - - detail::split(req.target.data(), req.target.data() + req.target.size(), '?', - 2, [&](const char *b, const char *e) { - switch (count) { - case 0: - req.path = detail::decode_url(std::string(b, e), false); - break; - case 1: { - if (e - b > 0) { - detail::parse_query_text(std::string(b, e), req.params); - } - break; - } - default: break; - } - count++; - }); - - if (count > 2) { return false; } - } - - return true; -} - -inline bool Server::write_response(Stream &strm, bool close_connection, - Request &req, Response &res) { - // NOTE: `req.ranges` should be empty, otherwise it will be applied - // incorrectly to the error content. - req.ranges.clear(); - return write_response_core(strm, close_connection, req, res, false); -} - -inline bool Server::write_response_with_content(Stream &strm, - bool close_connection, - const Request &req, - Response &res) { - return write_response_core(strm, close_connection, req, res, true); -} - -inline bool Server::write_response_core(Stream &strm, bool close_connection, - const Request &req, Response &res, - bool need_apply_ranges) { - assert(res.status != -1); - - if (400 <= res.status && error_handler_ && - error_handler_(req, res) == HandlerResponse::Handled) { - need_apply_ranges = true; - } - - std::string content_type; - std::string boundary; - if (need_apply_ranges) { apply_ranges(req, res, content_type, boundary); } - - // Prepare additional headers - if (close_connection || req.get_header_value("Connection") == "close") { - res.set_header("Connection", "close"); - } else { - std::stringstream ss; - ss << "timeout=" << keep_alive_timeout_sec_ - << ", max=" << keep_alive_max_count_; - res.set_header("Keep-Alive", ss.str()); - } - - if (!res.has_header("Content-Type") && - (!res.body.empty() || res.content_length_ > 0 || res.content_provider_)) { - res.set_header("Content-Type", "text/plain"); - } - - if (!res.has_header("Content-Length") && res.body.empty() && - !res.content_length_ && !res.content_provider_) { - res.set_header("Content-Length", "0"); - } - - if (!res.has_header("Accept-Ranges") && req.method == "HEAD") { - res.set_header("Accept-Ranges", "bytes"); - } - - if (post_routing_handler_) { post_routing_handler_(req, res); } - - // Response line and headers - { - detail::BufferStream bstrm; - - if (!bstrm.write_format("HTTP/1.1 %d %s\r\n", res.status, - status_message(res.status))) { - return false; - } - - if (!header_writer_(bstrm, res.headers)) { return false; } - - // Flush buffer - auto &data = bstrm.get_buffer(); - detail::write_data(strm, data.data(), data.size()); - } - - // Body - auto ret = true; - if (req.method != "HEAD") { - if (!res.body.empty()) { - if (!detail::write_data(strm, res.body.data(), res.body.size())) { - ret = false; - } - } else if (res.content_provider_) { - if (write_content_with_provider(strm, req, res, boundary, content_type)) { - res.content_provider_success_ = true; - } else { - ret = false; - } - } - } - - // Log - if (logger_) { logger_(req, res); } - - return ret; -} - -inline bool -Server::write_content_with_provider(Stream &strm, const Request &req, - Response &res, const std::string &boundary, - const std::string &content_type) { - auto is_shutting_down = [this]() { - return this->svr_sock_ == INVALID_SOCKET; - }; - - if (res.content_length_ > 0) { - if (req.ranges.empty()) { - return detail::write_content(strm, res.content_provider_, 0, - res.content_length_, is_shutting_down); - } else if (req.ranges.size() == 1) { - auto offset_and_length = detail::get_range_offset_and_length( - req.ranges[0], res.content_length_); - - return detail::write_content(strm, res.content_provider_, - offset_and_length.first, - offset_and_length.second, is_shutting_down); - } else { - return detail::write_multipart_ranges_data( - strm, req, res, boundary, content_type, res.content_length_, - is_shutting_down); - } - } else { - if (res.is_chunked_content_provider_) { - auto type = detail::encoding_type(req, res); - - std::unique_ptr compressor; - if (type == detail::EncodingType::Gzip) { -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - compressor = detail::make_unique(); -#endif - } else if (type == detail::EncodingType::Brotli) { -#ifdef CPPHTTPLIB_BROTLI_SUPPORT - compressor = detail::make_unique(); -#endif - } else { - compressor = detail::make_unique(); - } - assert(compressor != nullptr); - - return detail::write_content_chunked(strm, res.content_provider_, - is_shutting_down, *compressor); - } else { - return detail::write_content_without_length(strm, res.content_provider_, - is_shutting_down); - } - } -} - -inline bool Server::read_content(Stream &strm, Request &req, Response &res) { - MultipartFormDataMap::iterator cur; - auto file_count = 0; - if (read_content_core( - strm, req, res, - // Regular - [&](const char *buf, size_t n) { - if (req.body.size() + n > req.body.max_size()) { return false; } - req.body.append(buf, n); - return true; - }, - // Multipart - [&](const MultipartFormData &file) { - if (file_count++ == CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT) { - return false; - } - cur = req.files.emplace(file.name, file); - return true; - }, - [&](const char *buf, size_t n) { - auto &content = cur->second.content; - if (content.size() + n > content.max_size()) { return false; } - content.append(buf, n); - return true; - })) { - const auto &content_type = req.get_header_value("Content-Type"); - if (!content_type.find("application/x-www-form-urlencoded")) { - if (req.body.size() > CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH) { - res.status = StatusCode::PayloadTooLarge_413; // NOTE: should be 414? - return false; - } - detail::parse_query_text(req.body, req.params); - } - return true; - } - return false; -} - -inline bool Server::read_content_with_content_receiver( - Stream &strm, Request &req, Response &res, ContentReceiver receiver, - MultipartContentHeader multipart_header, - ContentReceiver multipart_receiver) { - return read_content_core(strm, req, res, std::move(receiver), - std::move(multipart_header), - std::move(multipart_receiver)); -} - -inline bool -Server::read_content_core(Stream &strm, Request &req, Response &res, - ContentReceiver receiver, - MultipartContentHeader multipart_header, - ContentReceiver multipart_receiver) const { - detail::MultipartFormDataParser multipart_form_data_parser; - ContentReceiverWithProgress out; - - if (req.is_multipart_form_data()) { - const auto &content_type = req.get_header_value("Content-Type"); - std::string boundary; - if (!detail::parse_multipart_boundary(content_type, boundary)) { - res.status = StatusCode::BadRequest_400; - return false; - } - - multipart_form_data_parser.set_boundary(std::move(boundary)); - out = [&](const char *buf, size_t n, uint64_t /*off*/, uint64_t /*len*/) { - /* For debug - size_t pos = 0; - while (pos < n) { - auto read_size = (std::min)(1, n - pos); - auto ret = multipart_form_data_parser.parse( - buf + pos, read_size, multipart_receiver, multipart_header); - if (!ret) { return false; } - pos += read_size; - } - return true; - */ - return multipart_form_data_parser.parse(buf, n, multipart_receiver, - multipart_header); - }; - } else { - out = [receiver](const char *buf, size_t n, uint64_t /*off*/, - uint64_t /*len*/) { return receiver(buf, n); }; - } - - if (req.method == "DELETE" && !req.has_header("Content-Length")) { - return true; - } - - if (!detail::read_content(strm, req, payload_max_length_, res.status, nullptr, - out, true)) { - return false; - } - - if (req.is_multipart_form_data()) { - if (!multipart_form_data_parser.is_valid()) { - res.status = StatusCode::BadRequest_400; - return false; - } - } - - return true; -} - -inline bool Server::handle_file_request(const Request &req, Response &res, - bool head) { - for (const auto &entry : base_dirs_) { - // Prefix match - if (!req.path.compare(0, entry.mount_point.size(), entry.mount_point)) { - std::string sub_path = "/" + req.path.substr(entry.mount_point.size()); - if (detail::is_valid_path(sub_path)) { - auto path = entry.base_dir + sub_path; - if (path.back() == '/') { path += "index.html"; } - - if (detail::is_file(path)) { - for (const auto &kv : entry.headers) { - res.set_header(kv.first, kv.second); - } - - auto mm = std::make_shared(path.c_str()); - if (!mm->is_open()) { return false; } - - res.set_content_provider( - mm->size(), - detail::find_content_type(path, file_extension_and_mimetype_map_, - default_file_mimetype_), - [mm](size_t offset, size_t length, DataSink &sink) -> bool { - sink.write(mm->data() + offset, length); - return true; - }); - - if (!head && file_request_handler_) { - file_request_handler_(req, res); - } - - return true; - } - } - } - } - return false; -} - -inline socket_t -Server::create_server_socket(const std::string &host, int port, - int socket_flags, - SocketOptions socket_options) const { - return detail::create_socket( - host, std::string(), port, address_family_, socket_flags, tcp_nodelay_, - std::move(socket_options), - [](socket_t sock, struct addrinfo &ai) -> bool { - if (::bind(sock, ai.ai_addr, static_cast(ai.ai_addrlen))) { - return false; - } - if (::listen(sock, CPPHTTPLIB_LISTEN_BACKLOG)) { return false; } - return true; - }); -} - -inline int Server::bind_internal(const std::string &host, int port, - int socket_flags) { - if (!is_valid()) { return -1; } - - svr_sock_ = create_server_socket(host, port, socket_flags, socket_options_); - if (svr_sock_ == INVALID_SOCKET) { return -1; } - - if (port == 0) { - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - if (getsockname(svr_sock_, reinterpret_cast(&addr), - &addr_len) == -1) { - return -1; - } - if (addr.ss_family == AF_INET) { - return ntohs(reinterpret_cast(&addr)->sin_port); - } else if (addr.ss_family == AF_INET6) { - return ntohs(reinterpret_cast(&addr)->sin6_port); - } else { - return -1; - } - } else { - return port; - } -} - -inline bool Server::listen_internal() { - auto ret = true; - is_running_ = true; - auto se = detail::scope_exit([&]() { is_running_ = false; }); - - { - std::unique_ptr task_queue(new_task_queue()); - - while (svr_sock_ != INVALID_SOCKET) { -#ifndef _WIN32 - if (idle_interval_sec_ > 0 || idle_interval_usec_ > 0) { -#endif - auto val = detail::select_read(svr_sock_, idle_interval_sec_, - idle_interval_usec_); - if (val == 0) { // Timeout - task_queue->on_idle(); - continue; - } -#ifndef _WIN32 - } -#endif - socket_t sock = accept(svr_sock_, nullptr, nullptr); - - if (sock == INVALID_SOCKET) { - if (errno == EMFILE) { - // The per-process limit of open file descriptors has been reached. - // Try to accept new connections after a short sleep. - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - continue; - } else if (errno == EINTR || errno == EAGAIN) { - continue; - } - if (svr_sock_ != INVALID_SOCKET) { - detail::close_socket(svr_sock_); - ret = false; - } else { - ; // The server socket was closed by user. - } - break; - } - - { -#ifdef _WIN32 - auto timeout = static_cast(read_timeout_sec_ * 1000 + - read_timeout_usec_ / 1000); - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, - reinterpret_cast(&timeout), sizeof(timeout)); -#else - timeval tv; - tv.tv_sec = static_cast(read_timeout_sec_); - tv.tv_usec = static_cast(read_timeout_usec_); - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, - reinterpret_cast(&tv), sizeof(tv)); -#endif - } - { - -#ifdef _WIN32 - auto timeout = static_cast(write_timeout_sec_ * 1000 + - write_timeout_usec_ / 1000); - setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, - reinterpret_cast(&timeout), sizeof(timeout)); -#else - timeval tv; - tv.tv_sec = static_cast(write_timeout_sec_); - tv.tv_usec = static_cast(write_timeout_usec_); - setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, - reinterpret_cast(&tv), sizeof(tv)); -#endif - } - - if (!task_queue->enqueue( - [this, sock]() { process_and_close_socket(sock); })) { - detail::shutdown_socket(sock); - detail::close_socket(sock); - } - } - - task_queue->shutdown(); - } - - return ret; -} - -inline bool Server::routing(Request &req, Response &res, Stream &strm) { - if (pre_routing_handler_ && - pre_routing_handler_(req, res) == HandlerResponse::Handled) { - return true; - } - - // File handler - auto is_head_request = req.method == "HEAD"; - if ((req.method == "GET" || is_head_request) && - handle_file_request(req, res, is_head_request)) { - return true; - } - - if (detail::expect_content(req)) { - // Content reader handler - { - ContentReader reader( - [&](ContentReceiver receiver) { - return read_content_with_content_receiver( - strm, req, res, std::move(receiver), nullptr, nullptr); - }, - [&](MultipartContentHeader header, ContentReceiver receiver) { - return read_content_with_content_receiver(strm, req, res, nullptr, - std::move(header), - std::move(receiver)); - }); - - if (req.method == "POST") { - if (dispatch_request_for_content_reader( - req, res, std::move(reader), - post_handlers_for_content_reader_)) { - return true; - } - } else if (req.method == "PUT") { - if (dispatch_request_for_content_reader( - req, res, std::move(reader), - put_handlers_for_content_reader_)) { - return true; - } - } else if (req.method == "PATCH") { - if (dispatch_request_for_content_reader( - req, res, std::move(reader), - patch_handlers_for_content_reader_)) { - return true; - } - } else if (req.method == "DELETE") { - if (dispatch_request_for_content_reader( - req, res, std::move(reader), - delete_handlers_for_content_reader_)) { - return true; - } - } - } - - // Read content into `req.body` - if (!read_content(strm, req, res)) { return false; } - } - - // Regular handler - if (req.method == "GET" || req.method == "HEAD") { - return dispatch_request(req, res, get_handlers_); - } else if (req.method == "POST") { - return dispatch_request(req, res, post_handlers_); - } else if (req.method == "PUT") { - return dispatch_request(req, res, put_handlers_); - } else if (req.method == "DELETE") { - return dispatch_request(req, res, delete_handlers_); - } else if (req.method == "OPTIONS") { - return dispatch_request(req, res, options_handlers_); - } else if (req.method == "PATCH") { - return dispatch_request(req, res, patch_handlers_); - } - - res.status = StatusCode::BadRequest_400; - return false; -} - -inline bool Server::dispatch_request(Request &req, Response &res, - const Handlers &handlers) const { - for (const auto &x : handlers) { - const auto &matcher = x.first; - const auto &handler = x.second; - - if (matcher->match(req)) { - handler(req, res); - return true; - } - } - return false; -} - -inline void Server::apply_ranges(const Request &req, Response &res, - std::string &content_type, - std::string &boundary) const { - if (req.ranges.size() > 1) { - auto it = res.headers.find("Content-Type"); - if (it != res.headers.end()) { - content_type = it->second; - res.headers.erase(it); - } - - boundary = detail::make_multipart_data_boundary(); - - res.set_header("Content-Type", - "multipart/byteranges; boundary=" + boundary); - } - - auto type = detail::encoding_type(req, res); - - if (res.body.empty()) { - if (res.content_length_ > 0) { - size_t length = 0; - if (req.ranges.empty()) { - length = res.content_length_; - } else if (req.ranges.size() == 1) { - auto offset_and_length = detail::get_range_offset_and_length( - req.ranges[0], res.content_length_); - - length = offset_and_length.second; - - auto content_range = detail::make_content_range_header_field( - offset_and_length, res.content_length_); - res.set_header("Content-Range", content_range); - } else { - length = detail::get_multipart_ranges_data_length( - req, boundary, content_type, res.content_length_); - } - res.set_header("Content-Length", std::to_string(length)); - } else { - if (res.content_provider_) { - if (res.is_chunked_content_provider_) { - res.set_header("Transfer-Encoding", "chunked"); - if (type == detail::EncodingType::Gzip) { - res.set_header("Content-Encoding", "gzip"); - } else if (type == detail::EncodingType::Brotli) { - res.set_header("Content-Encoding", "br"); - } - } - } - } - } else { - if (req.ranges.empty()) { - ; - } else if (req.ranges.size() == 1) { - auto offset_and_length = - detail::get_range_offset_and_length(req.ranges[0], res.body.size()); - auto offset = offset_and_length.first; - auto length = offset_and_length.second; - - auto content_range = detail::make_content_range_header_field( - offset_and_length, res.body.size()); - res.set_header("Content-Range", content_range); - - assert(offset + length <= res.body.size()); - res.body = res.body.substr(offset, length); - } else { - std::string data; - detail::make_multipart_ranges_data(req, res, boundary, content_type, - res.body.size(), data); - res.body.swap(data); - } - - if (type != detail::EncodingType::None) { - std::unique_ptr compressor; - std::string content_encoding; - - if (type == detail::EncodingType::Gzip) { -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - compressor = detail::make_unique(); - content_encoding = "gzip"; -#endif - } else if (type == detail::EncodingType::Brotli) { -#ifdef CPPHTTPLIB_BROTLI_SUPPORT - compressor = detail::make_unique(); - content_encoding = "br"; -#endif - } - - if (compressor) { - std::string compressed; - if (compressor->compress(res.body.data(), res.body.size(), true, - [&](const char *data, size_t data_len) { - compressed.append(data, data_len); - return true; - })) { - res.body.swap(compressed); - res.set_header("Content-Encoding", content_encoding); - } - } - } - - auto length = std::to_string(res.body.size()); - res.set_header("Content-Length", length); - } -} - -inline bool Server::dispatch_request_for_content_reader( - Request &req, Response &res, ContentReader content_reader, - const HandlersForContentReader &handlers) const { - for (const auto &x : handlers) { - const auto &matcher = x.first; - const auto &handler = x.second; - - if (matcher->match(req)) { - handler(req, res, content_reader); - return true; - } - } - return false; -} - -inline bool -Server::process_request(Stream &strm, bool close_connection, - bool &connection_closed, - const std::function &setup_request) { - std::array buf{}; - - detail::stream_line_reader line_reader(strm, buf.data(), buf.size()); - - // Connection has been closed on client - if (!line_reader.getline()) { return false; } - - Request req; - - Response res; - res.version = "HTTP/1.1"; - res.headers = default_headers_; - -#ifdef _WIN32 - // TODO: Increase FD_SETSIZE statically (libzmq), dynamically (MySQL). -#else -#ifndef CPPHTTPLIB_USE_POLL - // Socket file descriptor exceeded FD_SETSIZE... - if (strm.socket() >= FD_SETSIZE) { - Headers dummy; - detail::read_headers(strm, dummy); - res.status = StatusCode::InternalServerError_500; - return write_response(strm, close_connection, req, res); - } -#endif -#endif - - // Check if the request URI doesn't exceed the limit - if (line_reader.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) { - Headers dummy; - detail::read_headers(strm, dummy); - res.status = StatusCode::UriTooLong_414; - return write_response(strm, close_connection, req, res); - } - - // Request line and headers - if (!parse_request_line(line_reader.ptr(), req) || - !detail::read_headers(strm, req.headers)) { - res.status = StatusCode::BadRequest_400; - return write_response(strm, close_connection, req, res); - } - - if (req.get_header_value("Connection") == "close") { - connection_closed = true; - } - - if (req.version == "HTTP/1.0" && - req.get_header_value("Connection") != "Keep-Alive") { - connection_closed = true; - } - - strm.get_remote_ip_and_port(req.remote_addr, req.remote_port); - req.set_header("REMOTE_ADDR", req.remote_addr); - req.set_header("REMOTE_PORT", std::to_string(req.remote_port)); - - strm.get_local_ip_and_port(req.local_addr, req.local_port); - req.set_header("LOCAL_ADDR", req.local_addr); - req.set_header("LOCAL_PORT", std::to_string(req.local_port)); - - if (req.has_header("Range")) { - const auto &range_header_value = req.get_header_value("Range"); - if (!detail::parse_range_header(range_header_value, req.ranges)) { - res.status = StatusCode::RangeNotSatisfiable_416; - return write_response(strm, close_connection, req, res); - } - } - - if (setup_request) { setup_request(req); } - - if (req.get_header_value("Expect") == "100-continue") { - int status = StatusCode::Continue_100; - if (expect_100_continue_handler_) { - status = expect_100_continue_handler_(req, res); - } - switch (status) { - case StatusCode::Continue_100: - case StatusCode::ExpectationFailed_417: - strm.write_format("HTTP/1.1 %d %s\r\n\r\n", status, - status_message(status)); - break; - default: return write_response(strm, close_connection, req, res); - } - } - - // Routing - auto routed = false; -#ifdef CPPHTTPLIB_NO_EXCEPTIONS - routed = routing(req, res, strm); -#else - try { - routed = routing(req, res, strm); - } catch (std::exception &e) { - if (exception_handler_) { - auto ep = std::current_exception(); - exception_handler_(req, res, ep); - routed = true; - } else { - res.status = StatusCode::InternalServerError_500; - std::string val; - auto s = e.what(); - for (size_t i = 0; s[i]; i++) { - switch (s[i]) { - case '\r': val += "\\r"; break; - case '\n': val += "\\n"; break; - default: val += s[i]; break; - } - } - res.set_header("EXCEPTION_WHAT", val); - } - } catch (...) { - if (exception_handler_) { - auto ep = std::current_exception(); - exception_handler_(req, res, ep); - routed = true; - } else { - res.status = StatusCode::InternalServerError_500; - res.set_header("EXCEPTION_WHAT", "UNKNOWN"); - } - } -#endif - if (routed) { - if (res.status == -1) { - res.status = req.ranges.empty() ? StatusCode::OK_200 - : StatusCode::PartialContent_206; - } - - if (detail::range_error(req, res)) { - res.body.clear(); - res.content_length_ = 0; - res.content_provider_ = nullptr; - res.status = StatusCode::RangeNotSatisfiable_416; - return write_response(strm, close_connection, req, res); - } - - return write_response_with_content(strm, close_connection, req, res); - } else { - if (res.status == -1) { res.status = StatusCode::NotFound_404; } - - return write_response(strm, close_connection, req, res); - } -} - -inline bool Server::is_valid() const { return true; } - -inline bool Server::process_and_close_socket(socket_t sock) { - auto ret = detail::process_server_socket( - svr_sock_, sock, keep_alive_max_count_, keep_alive_timeout_sec_, - read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, - [this](Stream &strm, bool close_connection, bool &connection_closed) { - return process_request(strm, close_connection, connection_closed, - nullptr); - }); - - detail::shutdown_socket(sock); - detail::close_socket(sock); - return ret; -} - -// HTTP client implementation -inline ClientImpl::ClientImpl(const std::string &host) - : ClientImpl(host, 80, std::string(), std::string()) {} - -inline ClientImpl::ClientImpl(const std::string &host, int port) - : ClientImpl(host, port, std::string(), std::string()) {} - -inline ClientImpl::ClientImpl(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path) - : host_(host), port_(port), - host_and_port_(adjust_host_string(host) + ":" + std::to_string(port)), - client_cert_path_(client_cert_path), client_key_path_(client_key_path) {} - -inline ClientImpl::~ClientImpl() { - std::lock_guard guard(socket_mutex_); - shutdown_socket(socket_); - close_socket(socket_); -} - -inline bool ClientImpl::is_valid() const { return true; } - -inline void ClientImpl::copy_settings(const ClientImpl &rhs) { - client_cert_path_ = rhs.client_cert_path_; - client_key_path_ = rhs.client_key_path_; - connection_timeout_sec_ = rhs.connection_timeout_sec_; - read_timeout_sec_ = rhs.read_timeout_sec_; - read_timeout_usec_ = rhs.read_timeout_usec_; - write_timeout_sec_ = rhs.write_timeout_sec_; - write_timeout_usec_ = rhs.write_timeout_usec_; - basic_auth_username_ = rhs.basic_auth_username_; - basic_auth_password_ = rhs.basic_auth_password_; - bearer_token_auth_token_ = rhs.bearer_token_auth_token_; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - digest_auth_username_ = rhs.digest_auth_username_; - digest_auth_password_ = rhs.digest_auth_password_; -#endif - keep_alive_ = rhs.keep_alive_; - follow_location_ = rhs.follow_location_; - url_encode_ = rhs.url_encode_; - address_family_ = rhs.address_family_; - tcp_nodelay_ = rhs.tcp_nodelay_; - socket_options_ = rhs.socket_options_; - compress_ = rhs.compress_; - decompress_ = rhs.decompress_; - interface_ = rhs.interface_; - proxy_host_ = rhs.proxy_host_; - proxy_port_ = rhs.proxy_port_; - proxy_basic_auth_username_ = rhs.proxy_basic_auth_username_; - proxy_basic_auth_password_ = rhs.proxy_basic_auth_password_; - proxy_bearer_token_auth_token_ = rhs.proxy_bearer_token_auth_token_; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - proxy_digest_auth_username_ = rhs.proxy_digest_auth_username_; - proxy_digest_auth_password_ = rhs.proxy_digest_auth_password_; -#endif -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - ca_cert_file_path_ = rhs.ca_cert_file_path_; - ca_cert_dir_path_ = rhs.ca_cert_dir_path_; - ca_cert_store_ = rhs.ca_cert_store_; -#endif -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - server_certificate_verification_ = rhs.server_certificate_verification_; -#endif - logger_ = rhs.logger_; -} - -inline socket_t ClientImpl::create_client_socket(Error &error) const { - if (!proxy_host_.empty() && proxy_port_ != -1) { - return detail::create_client_socket( - proxy_host_, std::string(), proxy_port_, address_family_, tcp_nodelay_, - socket_options_, connection_timeout_sec_, connection_timeout_usec_, - read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, interface_, error); - } - - // Check is custom IP specified for host_ - std::string ip; - auto it = addr_map_.find(host_); - if (it != addr_map_.end()) { ip = it->second; } - - return detail::create_client_socket( - host_, ip, port_, address_family_, tcp_nodelay_, socket_options_, - connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_, - read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_, - error); -} - -inline bool ClientImpl::create_and_connect_socket(Socket &socket, - Error &error) { - auto sock = create_client_socket(error); - if (sock == INVALID_SOCKET) { return false; } - socket.sock = sock; - return true; -} - -inline void ClientImpl::shutdown_ssl(Socket & /*socket*/, - bool /*shutdown_gracefully*/) { - // If there are any requests in flight from threads other than us, then it's - // a thread-unsafe race because individual ssl* objects are not thread-safe. - assert(socket_requests_in_flight_ == 0 || - socket_requests_are_from_thread_ == std::this_thread::get_id()); -} - -inline void ClientImpl::shutdown_socket(Socket &socket) const { - if (socket.sock == INVALID_SOCKET) { return; } - detail::shutdown_socket(socket.sock); -} - -inline void ClientImpl::close_socket(Socket &socket) { - // If there are requests in flight in another thread, usually closing - // the socket will be fine and they will simply receive an error when - // using the closed socket, but it is still a bug since rarely the OS - // may reassign the socket id to be used for a new socket, and then - // suddenly they will be operating on a live socket that is different - // than the one they intended! - assert(socket_requests_in_flight_ == 0 || - socket_requests_are_from_thread_ == std::this_thread::get_id()); - - // It is also a bug if this happens while SSL is still active -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - assert(socket.ssl == nullptr); -#endif - if (socket.sock == INVALID_SOCKET) { return; } - detail::close_socket(socket.sock); - socket.sock = INVALID_SOCKET; -} - -inline bool ClientImpl::read_response_line(Stream &strm, const Request &req, - Response &res) const { - std::array buf{}; - - detail::stream_line_reader line_reader(strm, buf.data(), buf.size()); - - if (!line_reader.getline()) { return false; } - -#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR - const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n"); -#else - const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n"); -#endif - - std::cmatch m; - if (!std::regex_match(line_reader.ptr(), m, re)) { - return req.method == "CONNECT"; - } - res.version = std::string(m[1]); - res.status = std::stoi(std::string(m[2])); - res.reason = std::string(m[3]); - - // Ignore '100 Continue' - while (res.status == StatusCode::Continue_100) { - if (!line_reader.getline()) { return false; } // CRLF - if (!line_reader.getline()) { return false; } // next response line - - if (!std::regex_match(line_reader.ptr(), m, re)) { return false; } - res.version = std::string(m[1]); - res.status = std::stoi(std::string(m[2])); - res.reason = std::string(m[3]); - } - - return true; -} - -inline bool ClientImpl::send(Request &req, Response &res, Error &error) { - std::lock_guard request_mutex_guard(request_mutex_); - auto ret = send_(req, res, error); - if (error == Error::SSLPeerCouldBeClosed_) { - assert(!ret); - ret = send_(req, res, error); - } - return ret; -} - -inline bool ClientImpl::send_(Request &req, Response &res, Error &error) { - { - std::lock_guard guard(socket_mutex_); - - // Set this to false immediately - if it ever gets set to true by the end of - // the request, we know another thread instructed us to close the socket. - socket_should_be_closed_when_request_is_done_ = false; - - auto is_alive = false; - if (socket_.is_open()) { - is_alive = detail::is_socket_alive(socket_.sock); - if (!is_alive) { - // Attempt to avoid sigpipe by shutting down nongracefully if it seems - // like the other side has already closed the connection Also, there - // cannot be any requests in flight from other threads since we locked - // request_mutex_, so safe to close everything immediately - const bool shutdown_gracefully = false; - shutdown_ssl(socket_, shutdown_gracefully); - shutdown_socket(socket_); - close_socket(socket_); - } - } - - if (!is_alive) { - if (!create_and_connect_socket(socket_, error)) { return false; } - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - // TODO: refactoring - if (is_ssl()) { - auto &scli = static_cast(*this); - if (!proxy_host_.empty() && proxy_port_ != -1) { - auto success = false; - if (!scli.connect_with_proxy(socket_, res, success, error)) { - return success; - } - } - - if (!scli.initialize_ssl(socket_, error)) { return false; } - } -#endif - } - - // Mark the current socket as being in use so that it cannot be closed by - // anyone else while this request is ongoing, even though we will be - // releasing the mutex. - if (socket_requests_in_flight_ > 1) { - assert(socket_requests_are_from_thread_ == std::this_thread::get_id()); - } - socket_requests_in_flight_ += 1; - socket_requests_are_from_thread_ = std::this_thread::get_id(); - } - - for (const auto &header : default_headers_) { - if (req.headers.find(header.first) == req.headers.end()) { - req.headers.insert(header); - } - } - - auto ret = false; - auto close_connection = !keep_alive_; - - auto se = detail::scope_exit([&]() { - // Briefly lock mutex in order to mark that a request is no longer ongoing - std::lock_guard guard(socket_mutex_); - socket_requests_in_flight_ -= 1; - if (socket_requests_in_flight_ <= 0) { - assert(socket_requests_in_flight_ == 0); - socket_requests_are_from_thread_ = std::thread::id(); - } - - if (socket_should_be_closed_when_request_is_done_ || close_connection || - !ret) { - shutdown_ssl(socket_, true); - shutdown_socket(socket_); - close_socket(socket_); - } - }); - - ret = process_socket(socket_, [&](Stream &strm) { - return handle_request(strm, req, res, close_connection, error); - }); - - if (!ret) { - if (error == Error::Success) { error = Error::Unknown; } - } - - return ret; -} - -inline Result ClientImpl::send(const Request &req) { - auto req2 = req; - return send_(std::move(req2)); -} - -inline Result ClientImpl::send_(Request &&req) { - auto res = detail::make_unique(); - auto error = Error::Success; - auto ret = send(req, *res, error); - return Result{ret ? std::move(res) : nullptr, error, std::move(req.headers)}; -} - -inline bool ClientImpl::handle_request(Stream &strm, Request &req, - Response &res, bool close_connection, - Error &error) { - if (req.path.empty()) { - error = Error::Connection; - return false; - } - - auto req_save = req; - - bool ret; - - if (!is_ssl() && !proxy_host_.empty() && proxy_port_ != -1) { - auto req2 = req; - req2.path = "http://" + host_and_port_ + req.path; - ret = process_request(strm, req2, res, close_connection, error); - req = req2; - req.path = req_save.path; - } else { - ret = process_request(strm, req, res, close_connection, error); - } - - if (!ret) { return false; } - - if (res.get_header_value("Connection") == "close" || - (res.version == "HTTP/1.0" && res.reason != "Connection established")) { - // TODO this requires a not-entirely-obvious chain of calls to be correct - // for this to be safe. - - // This is safe to call because handle_request is only called by send_ - // which locks the request mutex during the process. It would be a bug - // to call it from a different thread since it's a thread-safety issue - // to do these things to the socket if another thread is using the socket. - std::lock_guard guard(socket_mutex_); - shutdown_ssl(socket_, true); - shutdown_socket(socket_); - close_socket(socket_); - } - - if (300 < res.status && res.status < 400 && follow_location_) { - req = req_save; - ret = redirect(req, res, error); - } - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - if ((res.status == StatusCode::Unauthorized_401 || - res.status == StatusCode::ProxyAuthenticationRequired_407) && - req.authorization_count_ < 5) { - auto is_proxy = res.status == StatusCode::ProxyAuthenticationRequired_407; - const auto &username = - is_proxy ? proxy_digest_auth_username_ : digest_auth_username_; - const auto &password = - is_proxy ? proxy_digest_auth_password_ : digest_auth_password_; - - if (!username.empty() && !password.empty()) { - std::map auth; - if (detail::parse_www_authenticate(res, auth, is_proxy)) { - Request new_req = req; - new_req.authorization_count_ += 1; - new_req.headers.erase(is_proxy ? "Proxy-Authorization" - : "Authorization"); - new_req.headers.insert(detail::make_digest_authentication_header( - req, auth, new_req.authorization_count_, detail::random_string(10), - username, password, is_proxy)); - - Response new_res; - - ret = send(new_req, new_res, error); - if (ret) { res = new_res; } - } - } - } -#endif - - return ret; -} - -inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { - if (req.redirect_count_ == 0) { - error = Error::ExceedRedirectCount; - return false; - } - - auto location = res.get_header_value("location"); - if (location.empty()) { return false; } - - const static std::regex re( - R"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*)(\?[^#]*)?(?:#.*)?)"); - - std::smatch m; - if (!std::regex_match(location, m, re)) { return false; } - - auto scheme = is_ssl() ? "https" : "http"; - - auto next_scheme = m[1].str(); - auto next_host = m[2].str(); - if (next_host.empty()) { next_host = m[3].str(); } - auto port_str = m[4].str(); - auto next_path = m[5].str(); - auto next_query = m[6].str(); - - auto next_port = port_; - if (!port_str.empty()) { - next_port = std::stoi(port_str); - } else if (!next_scheme.empty()) { - next_port = next_scheme == "https" ? 443 : 80; - } - - if (next_scheme.empty()) { next_scheme = scheme; } - if (next_host.empty()) { next_host = host_; } - if (next_path.empty()) { next_path = "/"; } - - auto path = detail::decode_url(next_path, true) + next_query; - - if (next_scheme == scheme && next_host == host_ && next_port == port_) { - return detail::redirect(*this, req, res, path, location, error); - } else { - if (next_scheme == "https") { -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - SSLClient cli(next_host, next_port); - cli.copy_settings(*this); - if (ca_cert_store_) { cli.set_ca_cert_store(ca_cert_store_); } - return detail::redirect(cli, req, res, path, location, error); -#else - return false; -#endif - } else { - ClientImpl cli(next_host, next_port); - cli.copy_settings(*this); - return detail::redirect(cli, req, res, path, location, error); - } - } -} - -inline bool ClientImpl::write_content_with_provider(Stream &strm, - const Request &req, - Error &error) const { - auto is_shutting_down = []() { return false; }; - - if (req.is_chunked_content_provider_) { - // TODO: Brotli support - std::unique_ptr compressor; -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - if (compress_) { - compressor = detail::make_unique(); - } else -#endif - { - compressor = detail::make_unique(); - } - - return detail::write_content_chunked(strm, req.content_provider_, - is_shutting_down, *compressor, error); - } else { - return detail::write_content(strm, req.content_provider_, 0, - req.content_length_, is_shutting_down, error); - } -} - -inline bool ClientImpl::write_request(Stream &strm, Request &req, - bool close_connection, Error &error) { - // Prepare additional headers - if (close_connection) { - if (!req.has_header("Connection")) { - req.set_header("Connection", "close"); - } - } - - if (!req.has_header("Host")) { - if (is_ssl()) { - if (port_ == 443) { - req.set_header("Host", host_); - } else { - req.set_header("Host", host_and_port_); - } - } else { - if (port_ == 80) { - req.set_header("Host", host_); - } else { - req.set_header("Host", host_and_port_); - } - } - } - - if (!req.has_header("Accept")) { req.set_header("Accept", "*/*"); } - -#ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT - if (!req.has_header("User-Agent")) { - auto agent = std::string("cpp-httplib/") + CPPHTTPLIB_VERSION; - req.set_header("User-Agent", agent); - } -#endif - - if (req.body.empty()) { - if (req.content_provider_) { - if (!req.is_chunked_content_provider_) { - if (!req.has_header("Content-Length")) { - auto length = std::to_string(req.content_length_); - req.set_header("Content-Length", length); - } - } - } else { - if (req.method == "POST" || req.method == "PUT" || - req.method == "PATCH") { - req.set_header("Content-Length", "0"); - } - } - } else { - if (!req.has_header("Content-Type")) { - req.set_header("Content-Type", "text/plain"); - } - - if (!req.has_header("Content-Length")) { - auto length = std::to_string(req.body.size()); - req.set_header("Content-Length", length); - } - } - - if (!basic_auth_password_.empty() || !basic_auth_username_.empty()) { - if (!req.has_header("Authorization")) { - req.headers.insert(make_basic_authentication_header( - basic_auth_username_, basic_auth_password_, false)); - } - } - - if (!proxy_basic_auth_username_.empty() && - !proxy_basic_auth_password_.empty()) { - if (!req.has_header("Proxy-Authorization")) { - req.headers.insert(make_basic_authentication_header( - proxy_basic_auth_username_, proxy_basic_auth_password_, true)); - } - } - - if (!bearer_token_auth_token_.empty()) { - if (!req.has_header("Authorization")) { - req.headers.insert(make_bearer_token_authentication_header( - bearer_token_auth_token_, false)); - } - } - - if (!proxy_bearer_token_auth_token_.empty()) { - if (!req.has_header("Proxy-Authorization")) { - req.headers.insert(make_bearer_token_authentication_header( - proxy_bearer_token_auth_token_, true)); - } - } - - // Request line and headers - { - detail::BufferStream bstrm; - - const auto &path = url_encode_ ? detail::encode_url(req.path) : req.path; - bstrm.write_format("%s %s HTTP/1.1\r\n", req.method.c_str(), path.c_str()); - - header_writer_(bstrm, req.headers); - - // Flush buffer - auto &data = bstrm.get_buffer(); - if (!detail::write_data(strm, data.data(), data.size())) { - error = Error::Write; - return false; - } - } - - // Body - if (req.body.empty()) { - return write_content_with_provider(strm, req, error); - } - - if (!detail::write_data(strm, req.body.data(), req.body.size())) { - error = Error::Write; - return false; - } - - return true; -} - -inline std::unique_ptr ClientImpl::send_with_content_provider( - Request &req, const char *body, size_t content_length, - ContentProvider content_provider, - ContentProviderWithoutLength content_provider_without_length, - const std::string &content_type, Error &error) { - if (!content_type.empty()) { req.set_header("Content-Type", content_type); } - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - if (compress_) { req.set_header("Content-Encoding", "gzip"); } -#endif - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - if (compress_ && !content_provider_without_length) { - // TODO: Brotli support - detail::gzip_compressor compressor; - - if (content_provider) { - auto ok = true; - size_t offset = 0; - DataSink data_sink; - - data_sink.write = [&](const char *data, size_t data_len) -> bool { - if (ok) { - auto last = offset + data_len == content_length; - - auto ret = compressor.compress( - data, data_len, last, - [&](const char *compressed_data, size_t compressed_data_len) { - req.body.append(compressed_data, compressed_data_len); - return true; - }); - - if (ret) { - offset += data_len; - } else { - ok = false; - } - } - return ok; - }; - - while (ok && offset < content_length) { - if (!content_provider(offset, content_length - offset, data_sink)) { - error = Error::Canceled; - return nullptr; - } - } - } else { - if (!compressor.compress(body, content_length, true, - [&](const char *data, size_t data_len) { - req.body.append(data, data_len); - return true; - })) { - error = Error::Compression; - return nullptr; - } - } - } else -#endif - { - if (content_provider) { - req.content_length_ = content_length; - req.content_provider_ = std::move(content_provider); - req.is_chunked_content_provider_ = false; - } else if (content_provider_without_length) { - req.content_length_ = 0; - req.content_provider_ = detail::ContentProviderAdapter( - std::move(content_provider_without_length)); - req.is_chunked_content_provider_ = true; - req.set_header("Transfer-Encoding", "chunked"); - } else { - req.body.assign(body, content_length); - } - } - - auto res = detail::make_unique(); - return send(req, *res, error) ? std::move(res) : nullptr; -} - -inline Result ClientImpl::send_with_content_provider( - const std::string &method, const std::string &path, const Headers &headers, - const char *body, size_t content_length, ContentProvider content_provider, - ContentProviderWithoutLength content_provider_without_length, - const std::string &content_type) { - Request req; - req.method = method; - req.headers = headers; - req.path = path; - - auto error = Error::Success; - - auto res = send_with_content_provider( - req, body, content_length, std::move(content_provider), - std::move(content_provider_without_length), content_type, error); - - return Result{std::move(res), error, std::move(req.headers)}; -} - -inline std::string -ClientImpl::adjust_host_string(const std::string &host) const { - if (host.find(':') != std::string::npos) { return "[" + host + "]"; } - return host; -} - -inline bool ClientImpl::process_request(Stream &strm, Request &req, - Response &res, bool close_connection, - Error &error) { - // Send request - if (!write_request(strm, req, close_connection, error)) { return false; } - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - if (is_ssl()) { - auto is_proxy_enabled = !proxy_host_.empty() && proxy_port_ != -1; - if (!is_proxy_enabled) { - char buf[1]; - if (SSL_peek(socket_.ssl, buf, 1) == 0 && - SSL_get_error(socket_.ssl, 0) == SSL_ERROR_ZERO_RETURN) { - error = Error::SSLPeerCouldBeClosed_; - return false; - } - } - } -#endif - - // Receive response and headers - if (!read_response_line(strm, req, res) || - !detail::read_headers(strm, res.headers)) { - error = Error::Read; - return false; - } - - // Body - if ((res.status != StatusCode::NoContent_204) && req.method != "HEAD" && - req.method != "CONNECT") { - auto redirect = 300 < res.status && res.status < 400 && follow_location_; - - if (req.response_handler && !redirect) { - if (!req.response_handler(res)) { - error = Error::Canceled; - return false; - } - } - - auto out = - req.content_receiver - ? static_cast( - [&](const char *buf, size_t n, uint64_t off, uint64_t len) { - if (redirect) { return true; } - auto ret = req.content_receiver(buf, n, off, len); - if (!ret) { error = Error::Canceled; } - return ret; - }) - : static_cast( - [&](const char *buf, size_t n, uint64_t /*off*/, - uint64_t /*len*/) { - if (res.body.size() + n > res.body.max_size()) { - return false; - } - res.body.append(buf, n); - return true; - }); - - auto progress = [&](uint64_t current, uint64_t total) { - if (!req.progress || redirect) { return true; } - auto ret = req.progress(current, total); - if (!ret) { error = Error::Canceled; } - return ret; - }; - - int dummy_status; - if (!detail::read_content(strm, res, (std::numeric_limits::max)(), - dummy_status, std::move(progress), std::move(out), - decompress_)) { - if (error != Error::Canceled) { error = Error::Read; } - return false; - } - } - - // Log - if (logger_) { logger_(req, res); } - - return true; -} - -inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider( - const std::string &boundary, const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) const { - size_t cur_item = 0; - size_t cur_start = 0; - // cur_item and cur_start are copied to within the std::function and maintain - // state between successive calls - return [&, cur_item, cur_start](size_t offset, - DataSink &sink) mutable -> bool { - if (!offset && !items.empty()) { - sink.os << detail::serialize_multipart_formdata(items, boundary, false); - return true; - } else if (cur_item < provider_items.size()) { - if (!cur_start) { - const auto &begin = detail::serialize_multipart_formdata_item_begin( - provider_items[cur_item], boundary); - offset += begin.size(); - cur_start = offset; - sink.os << begin; - } - - DataSink cur_sink; - auto has_data = true; - cur_sink.write = sink.write; - cur_sink.done = [&]() { has_data = false; }; - - if (!provider_items[cur_item].provider(offset - cur_start, cur_sink)) { - return false; - } - - if (!has_data) { - sink.os << detail::serialize_multipart_formdata_item_end(); - cur_item++; - cur_start = 0; - } - return true; - } else { - sink.os << detail::serialize_multipart_formdata_finish(boundary); - sink.done(); - return true; - } - }; -} - -inline bool -ClientImpl::process_socket(const Socket &socket, - std::function callback) { - return detail::process_client_socket( - socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, std::move(callback)); -} - -inline bool ClientImpl::is_ssl() const { return false; } - -inline Result ClientImpl::Get(const std::string &path) { - return Get(path, Headers(), Progress()); -} - -inline Result ClientImpl::Get(const std::string &path, Progress progress) { - return Get(path, Headers(), std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers) { - return Get(path, headers, Progress()); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - Progress progress) { - Request req; - req.method = "GET"; - req.path = path; - req.headers = headers; - req.progress = std::move(progress); - - return send_(std::move(req)); -} - -inline Result ClientImpl::Get(const std::string &path, - ContentReceiver content_receiver) { - return Get(path, Headers(), nullptr, std::move(content_receiver), nullptr); -} - -inline Result ClientImpl::Get(const std::string &path, - ContentReceiver content_receiver, - Progress progress) { - return Get(path, Headers(), nullptr, std::move(content_receiver), - std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver) { - return Get(path, headers, nullptr, std::move(content_receiver), nullptr); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver, - Progress progress) { - return Get(path, headers, nullptr, std::move(content_receiver), - std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, - ResponseHandler response_handler, - ContentReceiver content_receiver) { - return Get(path, Headers(), std::move(response_handler), - std::move(content_receiver), nullptr); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver) { - return Get(path, headers, std::move(response_handler), - std::move(content_receiver), nullptr); -} - -inline Result ClientImpl::Get(const std::string &path, - ResponseHandler response_handler, - ContentReceiver content_receiver, - Progress progress) { - return Get(path, Headers(), std::move(response_handler), - std::move(content_receiver), std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver, - Progress progress) { - Request req; - req.method = "GET"; - req.path = path; - req.headers = headers; - req.response_handler = std::move(response_handler); - req.content_receiver = - [content_receiver](const char *data, size_t data_length, - uint64_t /*offset*/, uint64_t /*total_length*/) { - return content_receiver(data, data_length); - }; - req.progress = std::move(progress); - - return send_(std::move(req)); -} - -inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, - const Headers &headers, Progress progress) { - if (params.empty()) { return Get(path, headers); } - - std::string path_with_query = append_query_params(path, params); - return Get(path_with_query, headers, std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, - const Headers &headers, - ContentReceiver content_receiver, - Progress progress) { - return Get(path, params, headers, nullptr, std::move(content_receiver), - std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, - const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver, - Progress progress) { - if (params.empty()) { - return Get(path, headers, std::move(response_handler), - std::move(content_receiver), std::move(progress)); - } - - std::string path_with_query = append_query_params(path, params); - return Get(path_with_query, headers, std::move(response_handler), - std::move(content_receiver), std::move(progress)); -} - -inline Result ClientImpl::Head(const std::string &path) { - return Head(path, Headers()); -} - -inline Result ClientImpl::Head(const std::string &path, - const Headers &headers) { - Request req; - req.method = "HEAD"; - req.headers = headers; - req.path = path; - - return send_(std::move(req)); -} - -inline Result ClientImpl::Post(const std::string &path) { - return Post(path, std::string(), std::string()); -} - -inline Result ClientImpl::Post(const std::string &path, - const Headers &headers) { - return Post(path, headers, nullptr, 0, std::string()); -} - -inline Result ClientImpl::Post(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return Post(path, Headers(), body, content_length, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return send_with_content_provider("POST", path, headers, body, content_length, - nullptr, nullptr, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const std::string &body, - const std::string &content_type) { - return Post(path, Headers(), body, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return send_with_content_provider("POST", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Params ¶ms) { - return Post(path, Headers(), params); -} - -inline Result ClientImpl::Post(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return Post(path, Headers(), content_length, std::move(content_provider), - content_type); -} - -inline Result ClientImpl::Post(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return Post(path, Headers(), std::move(content_provider), content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return send_with_content_provider("POST", path, headers, nullptr, - content_length, std::move(content_provider), - nullptr, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return send_with_content_provider("POST", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const Params ¶ms) { - auto query = detail::params_to_query_str(params); - return Post(path, headers, query, "application/x-www-form-urlencoded"); -} - -inline Result ClientImpl::Post(const std::string &path, - const MultipartFormDataItems &items) { - return Post(path, Headers(), items); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items) { - const auto &boundary = detail::make_multipart_data_boundary(); - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - const auto &body = detail::serialize_multipart_formdata(items, boundary); - return Post(path, headers, body, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - if (!detail::is_multipart_boundary_chars_valid(boundary)) { - return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; - } - - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - const auto &body = detail::serialize_multipart_formdata(items, boundary); - return Post(path, headers, body, content_type); -} - -inline Result -ClientImpl::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - const auto &boundary = detail::make_multipart_data_boundary(); - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - return send_with_content_provider( - "POST", path, headers, nullptr, 0, nullptr, - get_multipart_content_provider(boundary, items, provider_items), - content_type); -} - -inline Result ClientImpl::Put(const std::string &path) { - return Put(path, std::string(), std::string()); -} - -inline Result ClientImpl::Put(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return Put(path, Headers(), body, content_length, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return send_with_content_provider("PUT", path, headers, body, content_length, - nullptr, nullptr, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const std::string &body, - const std::string &content_type) { - return Put(path, Headers(), body, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return send_with_content_provider("PUT", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); -} - -inline Result ClientImpl::Put(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return Put(path, Headers(), content_length, std::move(content_provider), - content_type); -} - -inline Result ClientImpl::Put(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return Put(path, Headers(), std::move(content_provider), content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return send_with_content_provider("PUT", path, headers, nullptr, - content_length, std::move(content_provider), - nullptr, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return send_with_content_provider("PUT", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Params ¶ms) { - return Put(path, Headers(), params); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const Params ¶ms) { - auto query = detail::params_to_query_str(params); - return Put(path, headers, query, "application/x-www-form-urlencoded"); -} - -inline Result ClientImpl::Put(const std::string &path, - const MultipartFormDataItems &items) { - return Put(path, Headers(), items); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items) { - const auto &boundary = detail::make_multipart_data_boundary(); - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - const auto &body = detail::serialize_multipart_formdata(items, boundary); - return Put(path, headers, body, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - if (!detail::is_multipart_boundary_chars_valid(boundary)) { - return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; - } - - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - const auto &body = detail::serialize_multipart_formdata(items, boundary); - return Put(path, headers, body, content_type); -} - -inline Result -ClientImpl::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - const auto &boundary = detail::make_multipart_data_boundary(); - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - return send_with_content_provider( - "PUT", path, headers, nullptr, 0, nullptr, - get_multipart_content_provider(boundary, items, provider_items), - content_type); -} -inline Result ClientImpl::Patch(const std::string &path) { - return Patch(path, std::string(), std::string()); -} - -inline Result ClientImpl::Patch(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return Patch(path, Headers(), body, content_length, content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return send_with_content_provider("PATCH", path, headers, body, - content_length, nullptr, nullptr, - content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, - const std::string &body, - const std::string &content_type) { - return Patch(path, Headers(), body, content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return send_with_content_provider("PATCH", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return Patch(path, Headers(), content_length, std::move(content_provider), - content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return Patch(path, Headers(), std::move(content_provider), content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return send_with_content_provider("PATCH", path, headers, nullptr, - content_length, std::move(content_provider), - nullptr, content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return send_with_content_provider("PATCH", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); -} - -inline Result ClientImpl::Delete(const std::string &path) { - return Delete(path, Headers(), std::string(), std::string()); -} - -inline Result ClientImpl::Delete(const std::string &path, - const Headers &headers) { - return Delete(path, headers, std::string(), std::string()); -} - -inline Result ClientImpl::Delete(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return Delete(path, Headers(), body, content_length, content_type); -} - -inline Result ClientImpl::Delete(const std::string &path, - const Headers &headers, const char *body, - size_t content_length, - const std::string &content_type) { - Request req; - req.method = "DELETE"; - req.headers = headers; - req.path = path; - - if (!content_type.empty()) { req.set_header("Content-Type", content_type); } - req.body.assign(body, content_length); - - return send_(std::move(req)); -} - -inline Result ClientImpl::Delete(const std::string &path, - const std::string &body, - const std::string &content_type) { - return Delete(path, Headers(), body.data(), body.size(), content_type); -} - -inline Result ClientImpl::Delete(const std::string &path, - const Headers &headers, - const std::string &body, - const std::string &content_type) { - return Delete(path, headers, body.data(), body.size(), content_type); -} - -inline Result ClientImpl::Options(const std::string &path) { - return Options(path, Headers()); -} - -inline Result ClientImpl::Options(const std::string &path, - const Headers &headers) { - Request req; - req.method = "OPTIONS"; - req.headers = headers; - req.path = path; - - return send_(std::move(req)); -} - -inline void ClientImpl::stop() { - std::lock_guard guard(socket_mutex_); - - // If there is anything ongoing right now, the ONLY thread-safe thing we can - // do is to shutdown_socket, so that threads using this socket suddenly - // discover they can't read/write any more and error out. Everything else - // (closing the socket, shutting ssl down) is unsafe because these actions are - // not thread-safe. - if (socket_requests_in_flight_ > 0) { - shutdown_socket(socket_); - - // Aside from that, we set a flag for the socket to be closed when we're - // done. - socket_should_be_closed_when_request_is_done_ = true; - return; - } - - // Otherwise, still holding the mutex, we can shut everything down ourselves - shutdown_ssl(socket_, true); - shutdown_socket(socket_); - close_socket(socket_); -} - -inline std::string ClientImpl::host() const { return host_; } - -inline int ClientImpl::port() const { return port_; } - -inline size_t ClientImpl::is_socket_open() const { - std::lock_guard guard(socket_mutex_); - return socket_.is_open(); -} - -inline socket_t ClientImpl::socket() const { return socket_.sock; } - -inline void ClientImpl::set_connection_timeout(time_t sec, time_t usec) { - connection_timeout_sec_ = sec; - connection_timeout_usec_ = usec; -} - -inline void ClientImpl::set_read_timeout(time_t sec, time_t usec) { - read_timeout_sec_ = sec; - read_timeout_usec_ = usec; -} - -inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) { - write_timeout_sec_ = sec; - write_timeout_usec_ = usec; -} - -inline void ClientImpl::set_basic_auth(const std::string &username, - const std::string &password) { - basic_auth_username_ = username; - basic_auth_password_ = password; -} - -inline void ClientImpl::set_bearer_token_auth(const std::string &token) { - bearer_token_auth_token_ = token; -} - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::set_digest_auth(const std::string &username, - const std::string &password) { - digest_auth_username_ = username; - digest_auth_password_ = password; -} -#endif - -inline void ClientImpl::set_keep_alive(bool on) { keep_alive_ = on; } - -inline void ClientImpl::set_follow_location(bool on) { follow_location_ = on; } - -inline void ClientImpl::set_url_encode(bool on) { url_encode_ = on; } - -inline void -ClientImpl::set_hostname_addr_map(std::map addr_map) { - addr_map_ = std::move(addr_map); -} - -inline void ClientImpl::set_default_headers(Headers headers) { - default_headers_ = std::move(headers); -} - -inline void ClientImpl::set_header_writer( - std::function const &writer) { - header_writer_ = writer; -} - -inline void ClientImpl::set_address_family(int family) { - address_family_ = family; -} - -inline void ClientImpl::set_tcp_nodelay(bool on) { tcp_nodelay_ = on; } - -inline void ClientImpl::set_socket_options(SocketOptions socket_options) { - socket_options_ = std::move(socket_options); -} - -inline void ClientImpl::set_compress(bool on) { compress_ = on; } - -inline void ClientImpl::set_decompress(bool on) { decompress_ = on; } - -inline void ClientImpl::set_interface(const std::string &intf) { - interface_ = intf; -} - -inline void ClientImpl::set_proxy(const std::string &host, int port) { - proxy_host_ = host; - proxy_port_ = port; -} - -inline void ClientImpl::set_proxy_basic_auth(const std::string &username, - const std::string &password) { - proxy_basic_auth_username_ = username; - proxy_basic_auth_password_ = password; -} - -inline void ClientImpl::set_proxy_bearer_token_auth(const std::string &token) { - proxy_bearer_token_auth_token_ = token; -} - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::set_proxy_digest_auth(const std::string &username, - const std::string &password) { - proxy_digest_auth_username_ = username; - proxy_digest_auth_password_ = password; -} - -inline void ClientImpl::set_ca_cert_path(const std::string &ca_cert_file_path, - const std::string &ca_cert_dir_path) { - ca_cert_file_path_ = ca_cert_file_path; - ca_cert_dir_path_ = ca_cert_dir_path; -} - -inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) { - if (ca_cert_store && ca_cert_store != ca_cert_store_) { - ca_cert_store_ = ca_cert_store; - } -} - -inline X509_STORE *ClientImpl::create_ca_cert_store(const char *ca_cert, - std::size_t size) const { - auto mem = BIO_new_mem_buf(ca_cert, static_cast(size)); - if (!mem) { return nullptr; } - - auto inf = PEM_X509_INFO_read_bio(mem, nullptr, nullptr, nullptr); - if (!inf) { - BIO_free_all(mem); - return nullptr; - } - - auto cts = X509_STORE_new(); - if (cts) { - for (auto i = 0; i < static_cast(sk_X509_INFO_num(inf)); i++) { - auto itmp = sk_X509_INFO_value(inf, i); - if (!itmp) { continue; } - - if (itmp->x509) { X509_STORE_add_cert(cts, itmp->x509); } - if (itmp->crl) { X509_STORE_add_crl(cts, itmp->crl); } - } - } - - sk_X509_INFO_pop_free(inf, X509_INFO_free); - BIO_free_all(mem); - return cts; -} - -inline void ClientImpl::enable_server_certificate_verification(bool enabled) { - server_certificate_verification_ = enabled; -} -#endif - -inline void ClientImpl::set_logger(Logger logger) { - logger_ = std::move(logger); -} - -/* - * SSL Implementation - */ -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -namespace detail { - -template -inline SSL *ssl_new(socket_t sock, SSL_CTX *ctx, std::mutex &ctx_mutex, - U SSL_connect_or_accept, V setup) { - SSL *ssl = nullptr; - { - std::lock_guard guard(ctx_mutex); - ssl = SSL_new(ctx); - } - - if (ssl) { - set_nonblocking(sock, true); - auto bio = BIO_new_socket(static_cast(sock), BIO_NOCLOSE); - BIO_set_nbio(bio, 1); - SSL_set_bio(ssl, bio, bio); - - if (!setup(ssl) || SSL_connect_or_accept(ssl) != 1) { - SSL_shutdown(ssl); - { - std::lock_guard guard(ctx_mutex); - SSL_free(ssl); - } - set_nonblocking(sock, false); - return nullptr; - } - BIO_set_nbio(bio, 0); - set_nonblocking(sock, false); - } - - return ssl; -} - -inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, - bool shutdown_gracefully) { - // sometimes we may want to skip this to try to avoid SIGPIPE if we know - // the remote has closed the network connection - // Note that it is not always possible to avoid SIGPIPE, this is merely a - // best-efforts. - if (shutdown_gracefully) { SSL_shutdown(ssl); } - - std::lock_guard guard(ctx_mutex); - SSL_free(ssl); -} - -template -bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl, - U ssl_connect_or_accept, - time_t timeout_sec, - time_t timeout_usec) { - auto res = 0; - while ((res = ssl_connect_or_accept(ssl)) != 1) { - auto err = SSL_get_error(ssl, res); - switch (err) { - case SSL_ERROR_WANT_READ: - if (select_read(sock, timeout_sec, timeout_usec) > 0) { continue; } - break; - case SSL_ERROR_WANT_WRITE: - if (select_write(sock, timeout_sec, timeout_usec) > 0) { continue; } - break; - default: break; - } - return false; - } - return true; -} - -template -inline bool process_server_socket_ssl( - const std::atomic &svr_sock, SSL *ssl, socket_t sock, - size_t keep_alive_max_count, time_t keep_alive_timeout_sec, - time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, T callback) { - return process_server_socket_core( - svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec, - [&](bool close_connection, bool &connection_closed) { - SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm, close_connection, connection_closed); - }); -} - -template -inline bool -process_client_socket_ssl(SSL *ssl, socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, T callback) { - SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm); -} - -class SSLInit { -public: - SSLInit() { - OPENSSL_init_ssl( - OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); - } -}; - -// SSL socket stream implementation -inline SSLSocketStream::SSLSocketStream(socket_t sock, SSL *ssl, - time_t read_timeout_sec, - time_t read_timeout_usec, - time_t write_timeout_sec, - time_t write_timeout_usec) - : sock_(sock), ssl_(ssl), read_timeout_sec_(read_timeout_sec), - read_timeout_usec_(read_timeout_usec), - write_timeout_sec_(write_timeout_sec), - write_timeout_usec_(write_timeout_usec) { - SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY); -} - -inline SSLSocketStream::~SSLSocketStream() = default; - -inline bool SSLSocketStream::is_readable() const { - return detail::select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0; -} - -inline bool SSLSocketStream::is_writable() const { - return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 && - is_socket_alive(sock_); -} - -inline ssize_t SSLSocketStream::read(char *ptr, size_t size) { - if (SSL_pending(ssl_) > 0) { - return SSL_read(ssl_, ptr, static_cast(size)); - } else if (is_readable()) { - auto ret = SSL_read(ssl_, ptr, static_cast(size)); - if (ret < 0) { - auto err = SSL_get_error(ssl_, ret); - auto n = 1000; -#ifdef _WIN32 - while (--n >= 0 && (err == SSL_ERROR_WANT_READ || - (err == SSL_ERROR_SYSCALL && - WSAGetLastError() == WSAETIMEDOUT))) { -#else - while (--n >= 0 && err == SSL_ERROR_WANT_READ) { -#endif - if (SSL_pending(ssl_) > 0) { - return SSL_read(ssl_, ptr, static_cast(size)); - } else if (is_readable()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - ret = SSL_read(ssl_, ptr, static_cast(size)); - if (ret >= 0) { return ret; } - err = SSL_get_error(ssl_, ret); - } else { - return -1; - } - } - } - return ret; - } - return -1; -} - -inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) { - if (is_writable()) { - auto handle_size = static_cast( - std::min(size, (std::numeric_limits::max)())); - - auto ret = SSL_write(ssl_, ptr, static_cast(handle_size)); - if (ret < 0) { - auto err = SSL_get_error(ssl_, ret); - auto n = 1000; -#ifdef _WIN32 - while (--n >= 0 && (err == SSL_ERROR_WANT_WRITE || - (err == SSL_ERROR_SYSCALL && - WSAGetLastError() == WSAETIMEDOUT))) { -#else - while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) { -#endif - if (is_writable()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - ret = SSL_write(ssl_, ptr, static_cast(handle_size)); - if (ret >= 0) { return ret; } - err = SSL_get_error(ssl_, ret); - } else { - return -1; - } - } - } - return ret; - } - return -1; -} - -inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip, - int &port) const { - detail::get_remote_ip_and_port(sock_, ip, port); -} - -inline void SSLSocketStream::get_local_ip_and_port(std::string &ip, - int &port) const { - detail::get_local_ip_and_port(sock_, ip, port); -} - -inline socket_t SSLSocketStream::socket() const { return sock_; } - -static SSLInit sslinit_; - -} // namespace detail - -// SSL HTTP server implementation -inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path, - const char *client_ca_cert_file_path, - const char *client_ca_cert_dir_path, - const char *private_key_password) { - ctx_ = SSL_CTX_new(TLS_server_method()); - - if (ctx_) { - SSL_CTX_set_options(ctx_, - SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); - - SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION); - - // add default password callback before opening encrypted private key - if (private_key_password != nullptr && (private_key_password[0] != '\0')) { - SSL_CTX_set_default_passwd_cb_userdata( - ctx_, - reinterpret_cast(const_cast(private_key_password))); - } - - if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 || - SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) != - 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } else if (client_ca_cert_file_path || client_ca_cert_dir_path) { - SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path, - client_ca_cert_dir_path); - - SSL_CTX_set_verify( - ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); - } - } -} - -inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key, - X509_STORE *client_ca_cert_store) { - ctx_ = SSL_CTX_new(TLS_server_method()); - - if (ctx_) { - SSL_CTX_set_options(ctx_, - SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); - - SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION); - - if (SSL_CTX_use_certificate(ctx_, cert) != 1 || - SSL_CTX_use_PrivateKey(ctx_, private_key) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } else if (client_ca_cert_store) { - SSL_CTX_set_cert_store(ctx_, client_ca_cert_store); - - SSL_CTX_set_verify( - ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); - } - } -} - -inline SSLServer::SSLServer( - const std::function &setup_ssl_ctx_callback) { - ctx_ = SSL_CTX_new(TLS_method()); - if (ctx_) { - if (!setup_ssl_ctx_callback(*ctx_)) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } - } -} - -inline SSLServer::~SSLServer() { - if (ctx_) { SSL_CTX_free(ctx_); } -} - -inline bool SSLServer::is_valid() const { return ctx_; } - -inline SSL_CTX *SSLServer::ssl_context() const { return ctx_; } - -inline bool SSLServer::process_and_close_socket(socket_t sock) { - auto ssl = detail::ssl_new( - sock, ctx_, ctx_mutex_, - [&](SSL *ssl2) { - return detail::ssl_connect_or_accept_nonblocking( - sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_); - }, - [](SSL * /*ssl2*/) { return true; }); - - auto ret = false; - if (ssl) { - ret = detail::process_server_socket_ssl( - svr_sock_, ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_, - read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, - [this, ssl](Stream &strm, bool close_connection, - bool &connection_closed) { - return process_request(strm, close_connection, connection_closed, - [&](Request &req) { req.ssl = ssl; }); - }); - - // Shutdown gracefully if the result seemed successful, non-gracefully if - // the connection appeared to be closed. - const bool shutdown_gracefully = ret; - detail::ssl_delete(ctx_mutex_, ssl, shutdown_gracefully); - } - - detail::shutdown_socket(sock); - detail::close_socket(sock); - return ret; -} - -// SSL HTTP client implementation -inline SSLClient::SSLClient(const std::string &host) - : SSLClient(host, 443, std::string(), std::string()) {} - -inline SSLClient::SSLClient(const std::string &host, int port) - : SSLClient(host, port, std::string(), std::string()) {} - -inline SSLClient::SSLClient(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path) - : ClientImpl(host, port, client_cert_path, client_key_path) { - ctx_ = SSL_CTX_new(TLS_client_method()); - - detail::split(&host_[0], &host_[host_.size()], '.', - [&](const char *b, const char *e) { - host_components_.emplace_back(b, e); - }); - - if (!client_cert_path.empty() && !client_key_path.empty()) { - if (SSL_CTX_use_certificate_file(ctx_, client_cert_path.c_str(), - SSL_FILETYPE_PEM) != 1 || - SSL_CTX_use_PrivateKey_file(ctx_, client_key_path.c_str(), - SSL_FILETYPE_PEM) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } - } -} - -inline SSLClient::SSLClient(const std::string &host, int port, - X509 *client_cert, EVP_PKEY *client_key) - : ClientImpl(host, port) { - ctx_ = SSL_CTX_new(TLS_client_method()); - - detail::split(&host_[0], &host_[host_.size()], '.', - [&](const char *b, const char *e) { - host_components_.emplace_back(b, e); - }); - - if (client_cert != nullptr && client_key != nullptr) { - if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 || - SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } - } -} - -inline SSLClient::~SSLClient() { - if (ctx_) { SSL_CTX_free(ctx_); } - // Make sure to shut down SSL since shutdown_ssl will resolve to the - // base function rather than the derived function once we get to the - // base class destructor, and won't free the SSL (causing a leak). - shutdown_ssl_impl(socket_, true); -} - -inline bool SSLClient::is_valid() const { return ctx_; } - -inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) { - if (ca_cert_store) { - if (ctx_) { - if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) { - // Free memory allocated for old cert and use new store `ca_cert_store` - SSL_CTX_set_cert_store(ctx_, ca_cert_store); - } - } else { - X509_STORE_free(ca_cert_store); - } - } -} - -inline void SSLClient::load_ca_cert_store(const char *ca_cert, - std::size_t size) { - set_ca_cert_store(ClientImpl::create_ca_cert_store(ca_cert, size)); -} - -inline long SSLClient::get_openssl_verify_result() const { - return verify_result_; -} - -inline SSL_CTX *SSLClient::ssl_context() const { return ctx_; } - -inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) { - return is_valid() && ClientImpl::create_and_connect_socket(socket, error); -} - -// Assumes that socket_mutex_ is locked and that there are no requests in flight -inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res, - bool &success, Error &error) { - success = true; - Response proxy_res; - if (!detail::process_client_socket( - socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { - Request req2; - req2.method = "CONNECT"; - req2.path = host_and_port_; - return process_request(strm, req2, proxy_res, false, error); - })) { - // Thread-safe to close everything because we are assuming there are no - // requests in flight - shutdown_ssl(socket, true); - shutdown_socket(socket); - close_socket(socket); - success = false; - return false; - } - - if (proxy_res.status == StatusCode::ProxyAuthenticationRequired_407) { - if (!proxy_digest_auth_username_.empty() && - !proxy_digest_auth_password_.empty()) { - std::map auth; - if (detail::parse_www_authenticate(proxy_res, auth, true)) { - proxy_res = Response(); - if (!detail::process_client_socket( - socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { - Request req3; - req3.method = "CONNECT"; - req3.path = host_and_port_; - req3.headers.insert(detail::make_digest_authentication_header( - req3, auth, 1, detail::random_string(10), - proxy_digest_auth_username_, proxy_digest_auth_password_, - true)); - return process_request(strm, req3, proxy_res, false, error); - })) { - // Thread-safe to close everything because we are assuming there are - // no requests in flight - shutdown_ssl(socket, true); - shutdown_socket(socket); - close_socket(socket); - success = false; - return false; - } - } - } - } - - // If status code is not 200, proxy request is failed. - // Set error to ProxyConnection and return proxy response - // as the response of the request - if (proxy_res.status != StatusCode::OK_200) { - error = Error::ProxyConnection; - res = std::move(proxy_res); - // Thread-safe to close everything because we are assuming there are - // no requests in flight - shutdown_ssl(socket, true); - shutdown_socket(socket); - close_socket(socket); - return false; - } - - return true; -} - -inline bool SSLClient::load_certs() { - auto ret = true; - - std::call_once(initialize_cert_, [&]() { - std::lock_guard guard(ctx_mutex_); - if (!ca_cert_file_path_.empty()) { - if (!SSL_CTX_load_verify_locations(ctx_, ca_cert_file_path_.c_str(), - nullptr)) { - ret = false; - } - } else if (!ca_cert_dir_path_.empty()) { - if (!SSL_CTX_load_verify_locations(ctx_, nullptr, - ca_cert_dir_path_.c_str())) { - ret = false; - } - } else { - auto loaded = false; -#ifdef _WIN32 - loaded = - detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_)); -#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) -#if TARGET_OS_OSX - loaded = detail::load_system_certs_on_macos(SSL_CTX_get_cert_store(ctx_)); -#endif // TARGET_OS_OSX -#endif // _WIN32 - if (!loaded) { SSL_CTX_set_default_verify_paths(ctx_); } - } - }); - - return ret; -} - -inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) { - auto ssl = detail::ssl_new( - socket.sock, ctx_, ctx_mutex_, - [&](SSL *ssl2) { - if (server_certificate_verification_) { - if (!load_certs()) { - error = Error::SSLLoadingCerts; - return false; - } - SSL_set_verify(ssl2, SSL_VERIFY_NONE, nullptr); - } - - if (!detail::ssl_connect_or_accept_nonblocking( - socket.sock, ssl2, SSL_connect, connection_timeout_sec_, - connection_timeout_usec_)) { - error = Error::SSLConnection; - return false; - } - - if (server_certificate_verification_) { - verify_result_ = SSL_get_verify_result(ssl2); - - if (verify_result_ != X509_V_OK) { - error = Error::SSLServerVerification; - return false; - } - - auto server_cert = SSL_get1_peer_certificate(ssl2); - - if (server_cert == nullptr) { - error = Error::SSLServerVerification; - return false; - } - - if (!verify_host(server_cert)) { - X509_free(server_cert); - error = Error::SSLServerVerification; - return false; - } - X509_free(server_cert); - } - - return true; - }, - [&](SSL *ssl2) { - // NOTE: Direct call instead of using the OpenSSL macro to suppress - // -Wold-style-cast warning - // SSL_set_tlsext_host_name(ssl2, host_.c_str()); - SSL_ctrl(ssl2, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, - static_cast(const_cast(host_.c_str()))); - return true; - }); - - if (ssl) { - socket.ssl = ssl; - return true; - } - - shutdown_socket(socket); - close_socket(socket); - return false; -} - -inline void SSLClient::shutdown_ssl(Socket &socket, bool shutdown_gracefully) { - shutdown_ssl_impl(socket, shutdown_gracefully); -} - -inline void SSLClient::shutdown_ssl_impl(Socket &socket, - bool shutdown_gracefully) { - if (socket.sock == INVALID_SOCKET) { - assert(socket.ssl == nullptr); - return; - } - if (socket.ssl) { - detail::ssl_delete(ctx_mutex_, socket.ssl, shutdown_gracefully); - socket.ssl = nullptr; - } - assert(socket.ssl == nullptr); -} - -inline bool -SSLClient::process_socket(const Socket &socket, - std::function callback) { - assert(socket.ssl); - return detail::process_client_socket_ssl( - socket.ssl, socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, std::move(callback)); -} - -inline bool SSLClient::is_ssl() const { return true; } - -inline bool SSLClient::verify_host(X509 *server_cert) const { - /* Quote from RFC2818 section 3.1 "Server Identity" - - If a subjectAltName extension of type dNSName is present, that MUST - be used as the identity. Otherwise, the (most specific) Common Name - field in the Subject field of the certificate MUST be used. Although - the use of the Common Name is existing practice, it is deprecated and - Certification Authorities are encouraged to use the dNSName instead. - - Matching is performed using the matching rules specified by - [RFC2459]. If more than one identity of a given type is present in - the certificate (e.g., more than one dNSName name, a match in any one - of the set is considered acceptable.) Names may contain the wildcard - character * which is considered to match any single domain name - component or component fragment. E.g., *.a.com matches foo.a.com but - not bar.foo.a.com. f*.com matches foo.com but not bar.com. - - In some cases, the URI is specified as an IP address rather than a - hostname. In this case, the iPAddress subjectAltName must be present - in the certificate and must exactly match the IP in the URI. - - */ - return verify_host_with_subject_alt_name(server_cert) || - verify_host_with_common_name(server_cert); -} - -inline bool -SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const { - auto ret = false; - - auto type = GEN_DNS; - - struct in6_addr addr6 {}; - struct in_addr addr {}; - size_t addr_len = 0; - -#ifndef __MINGW32__ - if (inet_pton(AF_INET6, host_.c_str(), &addr6)) { - type = GEN_IPADD; - addr_len = sizeof(struct in6_addr); - } else if (inet_pton(AF_INET, host_.c_str(), &addr)) { - type = GEN_IPADD; - addr_len = sizeof(struct in_addr); - } -#endif - - auto alt_names = static_cast( - X509_get_ext_d2i(server_cert, NID_subject_alt_name, nullptr, nullptr)); - - if (alt_names) { - auto dsn_matched = false; - auto ip_matched = false; - - auto count = sk_GENERAL_NAME_num(alt_names); - - for (decltype(count) i = 0; i < count && !dsn_matched; i++) { - auto val = sk_GENERAL_NAME_value(alt_names, i); - if (val->type == type) { - auto name = - reinterpret_cast(ASN1_STRING_get0_data(val->d.ia5)); - auto name_len = static_cast(ASN1_STRING_length(val->d.ia5)); - - switch (type) { - case GEN_DNS: dsn_matched = check_host_name(name, name_len); break; - - case GEN_IPADD: - if (!memcmp(&addr6, name, addr_len) || - !memcmp(&addr, name, addr_len)) { - ip_matched = true; - } - break; - } - } - } - - if (dsn_matched || ip_matched) { ret = true; } - } - - GENERAL_NAMES_free(const_cast( - reinterpret_cast(alt_names))); - return ret; -} - -inline bool SSLClient::verify_host_with_common_name(X509 *server_cert) const { - const auto subject_name = X509_get_subject_name(server_cert); - - if (subject_name != nullptr) { - char name[BUFSIZ]; - auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName, - name, sizeof(name)); - - if (name_len != -1) { - return check_host_name(name, static_cast(name_len)); - } - } - - return false; -} - -inline bool SSLClient::check_host_name(const char *pattern, - size_t pattern_len) const { - if (host_.size() == pattern_len && host_ == pattern) { return true; } - - // Wildcard match - // https://bugs.launchpad.net/ubuntu/+source/firefox-3.0/+bug/376484 - std::vector pattern_components; - detail::split(&pattern[0], &pattern[pattern_len], '.', - [&](const char *b, const char *e) { - pattern_components.emplace_back(b, e); - }); - - if (host_components_.size() != pattern_components.size()) { return false; } - - auto itr = pattern_components.begin(); - for (const auto &h : host_components_) { - auto &p = *itr; - if (p != h && p != "*") { - auto partial_match = (p.size() > 0 && p[p.size() - 1] == '*' && - !p.compare(0, p.size() - 1, h)); - if (!partial_match) { return false; } - } - ++itr; - } - - return true; -} -#endif - -// Universal client implementation -inline Client::Client(const std::string &scheme_host_port) - : Client(scheme_host_port, std::string(), std::string()) {} - -inline Client::Client(const std::string &scheme_host_port, - const std::string &client_cert_path, - const std::string &client_key_path) { - const static std::regex re( - R"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)"); - - std::smatch m; - if (std::regex_match(scheme_host_port, m, re)) { - auto scheme = m[1].str(); - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - if (!scheme.empty() && (scheme != "http" && scheme != "https")) { -#else - if (!scheme.empty() && scheme != "http") { -#endif -#ifndef CPPHTTPLIB_NO_EXCEPTIONS - std::string msg = "'" + scheme + "' scheme is not supported."; - throw std::invalid_argument(msg); -#endif - return; - } - - auto is_ssl = scheme == "https"; - - auto host = m[2].str(); - if (host.empty()) { host = m[3].str(); } - - auto port_str = m[4].str(); - auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80); - - if (is_ssl) { -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - cli_ = detail::make_unique(host, port, client_cert_path, - client_key_path); - is_ssl_ = is_ssl; -#endif - } else { - cli_ = detail::make_unique(host, port, client_cert_path, - client_key_path); - } - } else { - cli_ = detail::make_unique(scheme_host_port, 80, - client_cert_path, client_key_path); - } -} - -inline Client::Client(const std::string &host, int port) - : cli_(detail::make_unique(host, port)) {} - -inline Client::Client(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path) - : cli_(detail::make_unique(host, port, client_cert_path, - client_key_path)) {} - -inline Client::~Client() = default; - -inline bool Client::is_valid() const { - return cli_ != nullptr && cli_->is_valid(); -} - -inline Result Client::Get(const std::string &path) { return cli_->Get(path); } -inline Result Client::Get(const std::string &path, const Headers &headers) { - return cli_->Get(path, headers); -} -inline Result Client::Get(const std::string &path, Progress progress) { - return cli_->Get(path, std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - Progress progress) { - return cli_->Get(path, headers, std::move(progress)); -} -inline Result Client::Get(const std::string &path, - ContentReceiver content_receiver) { - return cli_->Get(path, std::move(content_receiver)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver) { - return cli_->Get(path, headers, std::move(content_receiver)); -} -inline Result Client::Get(const std::string &path, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, std::move(content_receiver), std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, headers, std::move(content_receiver), - std::move(progress)); -} -inline Result Client::Get(const std::string &path, - ResponseHandler response_handler, - ContentReceiver content_receiver) { - return cli_->Get(path, std::move(response_handler), - std::move(content_receiver)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver) { - return cli_->Get(path, headers, std::move(response_handler), - std::move(content_receiver)); -} -inline Result Client::Get(const std::string &path, - ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, std::move(response_handler), - std::move(content_receiver), std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, headers, std::move(response_handler), - std::move(content_receiver), std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Params ¶ms, - const Headers &headers, Progress progress) { - return cli_->Get(path, params, headers, std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Params ¶ms, - const Headers &headers, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, params, headers, std::move(content_receiver), - std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Params ¶ms, - const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, params, headers, std::move(response_handler), - std::move(content_receiver), std::move(progress)); -} - -inline Result Client::Head(const std::string &path) { return cli_->Head(path); } -inline Result Client::Head(const std::string &path, const Headers &headers) { - return cli_->Head(path, headers); -} - -inline Result Client::Post(const std::string &path) { return cli_->Post(path); } -inline Result Client::Post(const std::string &path, const Headers &headers) { - return cli_->Post(path, headers); -} -inline Result Client::Post(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return cli_->Post(path, body, content_length, content_type); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return cli_->Post(path, headers, body, content_length, content_type); -} -inline Result Client::Post(const std::string &path, const std::string &body, - const std::string &content_type) { - return cli_->Post(path, body, content_type); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return cli_->Post(path, headers, body, content_type); -} -inline Result Client::Post(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Post(path, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Post(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Post(path, std::move(content_provider), content_type); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Post(path, headers, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Post(path, headers, std::move(content_provider), content_type); -} -inline Result Client::Post(const std::string &path, const Params ¶ms) { - return cli_->Post(path, params); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const Params ¶ms) { - return cli_->Post(path, headers, params); -} -inline Result Client::Post(const std::string &path, - const MultipartFormDataItems &items) { - return cli_->Post(path, items); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items) { - return cli_->Post(path, headers, items); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - return cli_->Post(path, headers, items, boundary); -} -inline Result -Client::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - return cli_->Post(path, headers, items, provider_items); -} -inline Result Client::Put(const std::string &path) { return cli_->Put(path); } -inline Result Client::Put(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return cli_->Put(path, body, content_length, content_type); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return cli_->Put(path, headers, body, content_length, content_type); -} -inline Result Client::Put(const std::string &path, const std::string &body, - const std::string &content_type) { - return cli_->Put(path, body, content_type); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return cli_->Put(path, headers, body, content_type); -} -inline Result Client::Put(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Put(path, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Put(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Put(path, std::move(content_provider), content_type); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Put(path, headers, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Put(path, headers, std::move(content_provider), content_type); -} -inline Result Client::Put(const std::string &path, const Params ¶ms) { - return cli_->Put(path, params); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const Params ¶ms) { - return cli_->Put(path, headers, params); -} -inline Result Client::Put(const std::string &path, - const MultipartFormDataItems &items) { - return cli_->Put(path, items); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items) { - return cli_->Put(path, headers, items); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - return cli_->Put(path, headers, items, boundary); -} -inline Result -Client::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - return cli_->Put(path, headers, items, provider_items); -} -inline Result Client::Patch(const std::string &path) { - return cli_->Patch(path); -} -inline Result Client::Patch(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return cli_->Patch(path, body, content_length, content_type); -} -inline Result Client::Patch(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return cli_->Patch(path, headers, body, content_length, content_type); -} -inline Result Client::Patch(const std::string &path, const std::string &body, - const std::string &content_type) { - return cli_->Patch(path, body, content_type); -} -inline Result Client::Patch(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return cli_->Patch(path, headers, body, content_type); -} -inline Result Client::Patch(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Patch(path, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Patch(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Patch(path, std::move(content_provider), content_type); -} -inline Result Client::Patch(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Patch(path, headers, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Patch(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Patch(path, headers, std::move(content_provider), content_type); -} -inline Result Client::Delete(const std::string &path) { - return cli_->Delete(path); -} -inline Result Client::Delete(const std::string &path, const Headers &headers) { - return cli_->Delete(path, headers); -} -inline Result Client::Delete(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return cli_->Delete(path, body, content_length, content_type); -} -inline Result Client::Delete(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return cli_->Delete(path, headers, body, content_length, content_type); -} -inline Result Client::Delete(const std::string &path, const std::string &body, - const std::string &content_type) { - return cli_->Delete(path, body, content_type); -} -inline Result Client::Delete(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return cli_->Delete(path, headers, body, content_type); -} -inline Result Client::Options(const std::string &path) { - return cli_->Options(path); -} -inline Result Client::Options(const std::string &path, const Headers &headers) { - return cli_->Options(path, headers); -} - -inline bool Client::send(Request &req, Response &res, Error &error) { - return cli_->send(req, res, error); -} - -inline Result Client::send(const Request &req) { return cli_->send(req); } - -inline void Client::stop() { cli_->stop(); } - -inline std::string Client::host() const { return cli_->host(); } - -inline int Client::port() const { return cli_->port(); } - -inline size_t Client::is_socket_open() const { return cli_->is_socket_open(); } - -inline socket_t Client::socket() const { return cli_->socket(); } - -inline void -Client::set_hostname_addr_map(std::map addr_map) { - cli_->set_hostname_addr_map(std::move(addr_map)); -} - -inline void Client::set_default_headers(Headers headers) { - cli_->set_default_headers(std::move(headers)); -} - -inline void Client::set_header_writer( - std::function const &writer) { - cli_->set_header_writer(writer); -} - -inline void Client::set_address_family(int family) { - cli_->set_address_family(family); -} - -inline void Client::set_tcp_nodelay(bool on) { cli_->set_tcp_nodelay(on); } - -inline void Client::set_socket_options(SocketOptions socket_options) { - cli_->set_socket_options(std::move(socket_options)); -} - -inline void Client::set_connection_timeout(time_t sec, time_t usec) { - cli_->set_connection_timeout(sec, usec); -} - -inline void Client::set_read_timeout(time_t sec, time_t usec) { - cli_->set_read_timeout(sec, usec); -} - -inline void Client::set_write_timeout(time_t sec, time_t usec) { - cli_->set_write_timeout(sec, usec); -} - -inline void Client::set_basic_auth(const std::string &username, - const std::string &password) { - cli_->set_basic_auth(username, password); -} -inline void Client::set_bearer_token_auth(const std::string &token) { - cli_->set_bearer_token_auth(token); -} -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_digest_auth(const std::string &username, - const std::string &password) { - cli_->set_digest_auth(username, password); -} -#endif - -inline void Client::set_keep_alive(bool on) { cli_->set_keep_alive(on); } -inline void Client::set_follow_location(bool on) { - cli_->set_follow_location(on); -} - -inline void Client::set_url_encode(bool on) { cli_->set_url_encode(on); } - -inline void Client::set_compress(bool on) { cli_->set_compress(on); } - -inline void Client::set_decompress(bool on) { cli_->set_decompress(on); } - -inline void Client::set_interface(const std::string &intf) { - cli_->set_interface(intf); -} - -inline void Client::set_proxy(const std::string &host, int port) { - cli_->set_proxy(host, port); -} -inline void Client::set_proxy_basic_auth(const std::string &username, - const std::string &password) { - cli_->set_proxy_basic_auth(username, password); -} -inline void Client::set_proxy_bearer_token_auth(const std::string &token) { - cli_->set_proxy_bearer_token_auth(token); -} -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_proxy_digest_auth(const std::string &username, - const std::string &password) { - cli_->set_proxy_digest_auth(username, password); -} -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::enable_server_certificate_verification(bool enabled) { - cli_->enable_server_certificate_verification(enabled); -} -#endif - -inline void Client::set_logger(Logger logger) { - cli_->set_logger(std::move(logger)); -} - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_ca_cert_path(const std::string &ca_cert_file_path, - const std::string &ca_cert_dir_path) { - cli_->set_ca_cert_path(ca_cert_file_path, ca_cert_dir_path); -} - -inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) { - if (is_ssl_) { - static_cast(*cli_).set_ca_cert_store(ca_cert_store); - } else { - cli_->set_ca_cert_store(ca_cert_store); - } -} - -inline void Client::load_ca_cert_store(const char *ca_cert, std::size_t size) { - set_ca_cert_store(cli_->create_ca_cert_store(ca_cert, size)); -} - -inline long Client::get_openssl_verify_result() const { - if (is_ssl_) { - return static_cast(*cli_).get_openssl_verify_result(); - } - return -1; // NOTE: -1 doesn't match any of X509_V_ERR_??? -} - -inline SSL_CTX *Client::ssl_context() const { - if (is_ssl_) { return static_cast(*cli_).ssl_context(); } - return nullptr; -} -#endif - -// ---------------------------------------------------------------------------- - -} // namespace httplib - -#if defined(_WIN32) && defined(CPPHTTPLIB_USE_POLL) -#undef poll -#endif - -#endif // CPPHTTPLIB_HTTPLIB_H diff --git a/ext/ed25519-amd64-asm/batch.c b/ext/ed25519-amd64-asm/batch.c deleted file mode 100644 index 955392eac..000000000 --- a/ext/ed25519-amd64-asm/batch.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "crypto_sign.h" - -#include "crypto_verify_32.h" -#include "crypto_hash_sha512.h" -#include "randombytes.h" - -#include "ge25519.h" -#include "hram.h" - -#define MAXBATCH 64 - -int crypto_sign_open_batch( - unsigned char* const m[],unsigned long long mlen[], - unsigned char* const sm[],const unsigned long long smlen[], - unsigned char* const pk[], - unsigned long long num - ) -{ - int ret = 0; - unsigned long long i, j; - shortsc25519 r[MAXBATCH]; - sc25519 scalars[2*MAXBATCH+1]; - ge25519 points[2*MAXBATCH+1]; - unsigned char hram[crypto_hash_sha512_BYTES]; - unsigned long long batchsize; - - for (i = 0;i < num;++i) mlen[i] = -1; - - while (num >= 3) { - batchsize = num; - if (batchsize > MAXBATCH) batchsize = MAXBATCH; - - for (i = 0;i < batchsize;++i) - if (smlen[i] < 64) goto fallback; - - randombytes((unsigned char*)r,sizeof(shortsc25519) * batchsize); - - /* Computing scalars[0] = ((r1s1 + r2s2 + ...)) */ - for(i=0;icaller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: tp_stack = tp -# asm 1: movq tp_stack=stack64#8 -# asm 2: movq tp_stack=56(%rsp) -movq %rdi,56(%rsp) - -# qhasm: pos *= 768 -# asm 1: imulq $768,pos=int64#1 -# asm 2: imulq $768,pos=%rdi -imulq $768,%rsi,%rdi - -# qhasm: mask = b -# asm 1: mov mask=int64#2 -# asm 2: mov mask=%rsi -mov %rdx,%rsi - -# qhasm: (int64) mask >>= 7 -# asm 1: sar $7,u=int64#5 -# asm 2: mov u=%r8 -mov %rdx,%r8 - -# qhasm: u += mask -# asm 1: add tysubx0=int64#2 -# asm 2: mov $1,>tysubx0=%rsi -mov $1,%rsi - -# qhasm: tysubx1 = 0 -# asm 1: mov $0,>tysubx1=int64#6 -# asm 2: mov $0,>tysubx1=%r9 -mov $0,%r9 - -# qhasm: tysubx2 = 0 -# asm 1: mov $0,>tysubx2=int64#7 -# asm 2: mov $0,>tysubx2=%rax -mov $0,%rax - -# qhasm: tysubx3 = 0 -# asm 1: mov $0,>tysubx3=int64#8 -# asm 2: mov $0,>tysubx3=%r10 -mov $0,%r10 - -# qhasm: txaddy0 = 1 -# asm 1: mov $1,>txaddy0=int64#9 -# asm 2: mov $1,>txaddy0=%r11 -mov $1,%r11 - -# qhasm: txaddy1 = 0 -# asm 1: mov $0,>txaddy1=int64#10 -# asm 2: mov $0,>txaddy1=%r12 -mov $0,%r12 - -# qhasm: txaddy2 = 0 -# asm 1: mov $0,>txaddy2=int64#11 -# asm 2: mov $0,>txaddy2=%r13 -mov $0,%r13 - -# qhasm: txaddy3 = 0 -# asm 1: mov $0,>txaddy3=int64#12 -# asm 2: mov $0,>txaddy3=%r14 -mov $0,%r14 - -# qhasm: =? u - 1 -# asm 1: cmp $1,t=int64#13 -# asm 2: movq 0(t=%r15 -movq 0(%rcx,%rdi),%r15 - -# qhasm: tysubx0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 8(t=%r15 -movq 8(%rcx,%rdi),%r15 - -# qhasm: tysubx1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 16(t=%r15 -movq 16(%rcx,%rdi),%r15 - -# qhasm: tysubx2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 24(t=%r15 -movq 24(%rcx,%rdi),%r15 - -# qhasm: tysubx3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 32(t=%r15 -movq 32(%rcx,%rdi),%r15 - -# qhasm: txaddy0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 40(t=%r15 -movq 40(%rcx,%rdi),%r15 - -# qhasm: txaddy1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 48(t=%r15 -movq 48(%rcx,%rdi),%r15 - -# qhasm: txaddy2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 56(t=%r15 -movq 56(%rcx,%rdi),%r15 - -# qhasm: txaddy3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 96(t=%r15 -movq 96(%rcx,%rdi),%r15 - -# qhasm: tysubx0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 104(t=%r15 -movq 104(%rcx,%rdi),%r15 - -# qhasm: tysubx1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 112(t=%r15 -movq 112(%rcx,%rdi),%r15 - -# qhasm: tysubx2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 120(t=%r15 -movq 120(%rcx,%rdi),%r15 - -# qhasm: tysubx3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 128(t=%r15 -movq 128(%rcx,%rdi),%r15 - -# qhasm: txaddy0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 136(t=%r15 -movq 136(%rcx,%rdi),%r15 - -# qhasm: txaddy1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 144(t=%r15 -movq 144(%rcx,%rdi),%r15 - -# qhasm: txaddy2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 152(t=%r15 -movq 152(%rcx,%rdi),%r15 - -# qhasm: txaddy3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 192(t=%r15 -movq 192(%rcx,%rdi),%r15 - -# qhasm: tysubx0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 200(t=%r15 -movq 200(%rcx,%rdi),%r15 - -# qhasm: tysubx1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 208(t=%r15 -movq 208(%rcx,%rdi),%r15 - -# qhasm: tysubx2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 216(t=%r15 -movq 216(%rcx,%rdi),%r15 - -# qhasm: tysubx3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 224(t=%r15 -movq 224(%rcx,%rdi),%r15 - -# qhasm: txaddy0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 232(t=%r15 -movq 232(%rcx,%rdi),%r15 - -# qhasm: txaddy1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 240(t=%r15 -movq 240(%rcx,%rdi),%r15 - -# qhasm: txaddy2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 248(t=%r15 -movq 248(%rcx,%rdi),%r15 - -# qhasm: txaddy3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 288(t=%r15 -movq 288(%rcx,%rdi),%r15 - -# qhasm: tysubx0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 296(t=%r15 -movq 296(%rcx,%rdi),%r15 - -# qhasm: tysubx1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 304(t=%r15 -movq 304(%rcx,%rdi),%r15 - -# qhasm: tysubx2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 312(t=%r15 -movq 312(%rcx,%rdi),%r15 - -# qhasm: tysubx3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 320(t=%r15 -movq 320(%rcx,%rdi),%r15 - -# qhasm: txaddy0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 328(t=%r15 -movq 328(%rcx,%rdi),%r15 - -# qhasm: txaddy1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 336(t=%r15 -movq 336(%rcx,%rdi),%r15 - -# qhasm: txaddy2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 344(t=%r15 -movq 344(%rcx,%rdi),%r15 - -# qhasm: txaddy3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 384(t=%r15 -movq 384(%rcx,%rdi),%r15 - -# qhasm: tysubx0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 392(t=%r15 -movq 392(%rcx,%rdi),%r15 - -# qhasm: tysubx1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 400(t=%r15 -movq 400(%rcx,%rdi),%r15 - -# qhasm: tysubx2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 408(t=%r15 -movq 408(%rcx,%rdi),%r15 - -# qhasm: tysubx3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 416(t=%r15 -movq 416(%rcx,%rdi),%r15 - -# qhasm: txaddy0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 424(t=%r15 -movq 424(%rcx,%rdi),%r15 - -# qhasm: txaddy1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 432(t=%r15 -movq 432(%rcx,%rdi),%r15 - -# qhasm: txaddy2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 440(t=%r15 -movq 440(%rcx,%rdi),%r15 - -# qhasm: txaddy3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 480(t=%r15 -movq 480(%rcx,%rdi),%r15 - -# qhasm: tysubx0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 488(t=%r15 -movq 488(%rcx,%rdi),%r15 - -# qhasm: tysubx1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 496(t=%r15 -movq 496(%rcx,%rdi),%r15 - -# qhasm: tysubx2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 504(t=%r15 -movq 504(%rcx,%rdi),%r15 - -# qhasm: tysubx3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 512(t=%r15 -movq 512(%rcx,%rdi),%r15 - -# qhasm: txaddy0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 520(t=%r15 -movq 520(%rcx,%rdi),%r15 - -# qhasm: txaddy1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 528(t=%r15 -movq 528(%rcx,%rdi),%r15 - -# qhasm: txaddy2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 536(t=%r15 -movq 536(%rcx,%rdi),%r15 - -# qhasm: txaddy3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 576(t=%r15 -movq 576(%rcx,%rdi),%r15 - -# qhasm: tysubx0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 584(t=%r15 -movq 584(%rcx,%rdi),%r15 - -# qhasm: tysubx1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 592(t=%r15 -movq 592(%rcx,%rdi),%r15 - -# qhasm: tysubx2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 600(t=%r15 -movq 600(%rcx,%rdi),%r15 - -# qhasm: tysubx3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 608(t=%r15 -movq 608(%rcx,%rdi),%r15 - -# qhasm: txaddy0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 616(t=%r15 -movq 616(%rcx,%rdi),%r15 - -# qhasm: txaddy1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 624(t=%r15 -movq 624(%rcx,%rdi),%r15 - -# qhasm: txaddy2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 632(t=%r15 -movq 632(%rcx,%rdi),%r15 - -# qhasm: txaddy3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 672(t=%r15 -movq 672(%rcx,%rdi),%r15 - -# qhasm: tysubx0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 680(t=%r15 -movq 680(%rcx,%rdi),%r15 - -# qhasm: tysubx1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 688(t=%r15 -movq 688(%rcx,%rdi),%r15 - -# qhasm: tysubx2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 696(t=%r15 -movq 696(%rcx,%rdi),%r15 - -# qhasm: tysubx3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 704(t=%r15 -movq 704(%rcx,%rdi),%r15 - -# qhasm: txaddy0 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 712(t=%r15 -movq 712(%rcx,%rdi),%r15 - -# qhasm: txaddy1 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 720(t=%r15 -movq 720(%rcx,%rdi),%r15 - -# qhasm: txaddy2 = t if = -# asm 1: cmove t=int64#13 -# asm 2: movq 728(t=%r15 -movq 728(%rcx,%rdi),%r15 - -# qhasm: txaddy3 = t if = -# asm 1: cmove t=int64#13 -# asm 2: mov t=%r15 -mov %rsi,%r15 - -# qhasm: tysubx0 = txaddy0 if signed< -# asm 1: cmovl t=int64#13 -# asm 2: mov t=%r15 -mov %r9,%r15 - -# qhasm: tysubx1 = txaddy1 if signed< -# asm 1: cmovl t=int64#13 -# asm 2: mov t=%r15 -mov %rax,%r15 - -# qhasm: tysubx2 = txaddy2 if signed< -# asm 1: cmovl t=int64#13 -# asm 2: mov t=%r15 -mov %r10,%r15 - -# qhasm: tysubx3 = txaddy3 if signed< -# asm 1: cmovl tp=int64#13 -# asm 2: movq tp=%r15 -movq 56(%rsp),%r15 - -# qhasm: *(uint64 *)(tp + 0) = tysubx0 -# asm 1: movq tt2d0=int64#2 -# asm 2: mov $0,>tt2d0=%rsi -mov $0,%rsi - -# qhasm: tt2d1 = 0 -# asm 1: mov $0,>tt2d1=int64#6 -# asm 2: mov $0,>tt2d1=%r9 -mov $0,%r9 - -# qhasm: tt2d2 = 0 -# asm 1: mov $0,>tt2d2=int64#7 -# asm 2: mov $0,>tt2d2=%rax -mov $0,%rax - -# qhasm: tt2d3 = 0 -# asm 1: mov $0,>tt2d3=int64#8 -# asm 2: mov $0,>tt2d3=%r10 -mov $0,%r10 - -# qhasm: =? u - 1 -# asm 1: cmp $1,t=int64#9 -# asm 2: movq 64(t=%r11 -movq 64(%rcx,%rdi),%r11 - -# qhasm: tt2d0 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 72(t=%r11 -movq 72(%rcx,%rdi),%r11 - -# qhasm: tt2d1 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 80(t=%r11 -movq 80(%rcx,%rdi),%r11 - -# qhasm: tt2d2 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 88(t=%r11 -movq 88(%rcx,%rdi),%r11 - -# qhasm: tt2d3 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 160(t=%r11 -movq 160(%rcx,%rdi),%r11 - -# qhasm: tt2d0 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 168(t=%r11 -movq 168(%rcx,%rdi),%r11 - -# qhasm: tt2d1 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 176(t=%r11 -movq 176(%rcx,%rdi),%r11 - -# qhasm: tt2d2 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 184(t=%r11 -movq 184(%rcx,%rdi),%r11 - -# qhasm: tt2d3 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 256(t=%r11 -movq 256(%rcx,%rdi),%r11 - -# qhasm: tt2d0 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 264(t=%r11 -movq 264(%rcx,%rdi),%r11 - -# qhasm: tt2d1 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 272(t=%r11 -movq 272(%rcx,%rdi),%r11 - -# qhasm: tt2d2 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 280(t=%r11 -movq 280(%rcx,%rdi),%r11 - -# qhasm: tt2d3 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 352(t=%r11 -movq 352(%rcx,%rdi),%r11 - -# qhasm: tt2d0 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 360(t=%r11 -movq 360(%rcx,%rdi),%r11 - -# qhasm: tt2d1 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 368(t=%r11 -movq 368(%rcx,%rdi),%r11 - -# qhasm: tt2d2 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 376(t=%r11 -movq 376(%rcx,%rdi),%r11 - -# qhasm: tt2d3 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 448(t=%r11 -movq 448(%rcx,%rdi),%r11 - -# qhasm: tt2d0 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 456(t=%r11 -movq 456(%rcx,%rdi),%r11 - -# qhasm: tt2d1 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 464(t=%r11 -movq 464(%rcx,%rdi),%r11 - -# qhasm: tt2d2 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 472(t=%r11 -movq 472(%rcx,%rdi),%r11 - -# qhasm: tt2d3 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 544(t=%r11 -movq 544(%rcx,%rdi),%r11 - -# qhasm: tt2d0 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 552(t=%r11 -movq 552(%rcx,%rdi),%r11 - -# qhasm: tt2d1 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 560(t=%r11 -movq 560(%rcx,%rdi),%r11 - -# qhasm: tt2d2 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 568(t=%r11 -movq 568(%rcx,%rdi),%r11 - -# qhasm: tt2d3 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 640(t=%r11 -movq 640(%rcx,%rdi),%r11 - -# qhasm: tt2d0 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 648(t=%r11 -movq 648(%rcx,%rdi),%r11 - -# qhasm: tt2d1 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 656(t=%r11 -movq 656(%rcx,%rdi),%r11 - -# qhasm: tt2d2 = t if = -# asm 1: cmove t=int64#9 -# asm 2: movq 664(t=%r11 -movq 664(%rcx,%rdi),%r11 - -# qhasm: tt2d3 = t if = -# asm 1: cmove t=int64#5 -# asm 2: movq 736(t=%r8 -movq 736(%rcx,%rdi),%r8 - -# qhasm: tt2d0 = t if = -# asm 1: cmove t=int64#5 -# asm 2: movq 744(t=%r8 -movq 744(%rcx,%rdi),%r8 - -# qhasm: tt2d1 = t if = -# asm 1: cmove t=int64#5 -# asm 2: movq 752(t=%r8 -movq 752(%rcx,%rdi),%r8 - -# qhasm: tt2d2 = t if = -# asm 1: cmove t=int64#1 -# asm 2: movq 760(t=%rdi -movq 760(%rcx,%rdi),%rdi - -# qhasm: tt2d3 = t if = -# asm 1: cmove tt0=int64#1 -# asm 2: mov $0,>tt0=%rdi -mov $0,%rdi - -# qhasm: tt1 = 0 -# asm 1: mov $0,>tt1=int64#4 -# asm 2: mov $0,>tt1=%rcx -mov $0,%rcx - -# qhasm: tt2 = 0 -# asm 1: mov $0,>tt2=int64#5 -# asm 2: mov $0,>tt2=%r8 -mov $0,%r8 - -# qhasm: tt3 = 0 -# asm 1: mov $0,>tt3=int64#9 -# asm 2: mov $0,>tt3=%r11 -mov $0,%r11 - -# qhasm: carry? tt0 -= tt2d0 -# asm 1: sub subt0=int64#10 -# asm 2: mov $0,>subt0=%r12 -mov $0,%r12 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#11 -# asm 2: mov $38,>subt1=%r13 -mov $38,%r13 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/consts.s b/ext/ed25519-amd64-asm/consts.s deleted file mode 100644 index c272383f6..000000000 --- a/ext/ed25519-amd64-asm/consts.s +++ /dev/null @@ -1,39 +0,0 @@ -.data - -.globl crypto_sign_ed25519_amd64_64_121666 -.globl crypto_sign_ed25519_amd64_64_MU0 -.globl crypto_sign_ed25519_amd64_64_MU1 -.globl crypto_sign_ed25519_amd64_64_MU2 -.globl crypto_sign_ed25519_amd64_64_MU3 -.globl crypto_sign_ed25519_amd64_64_MU4 -.globl crypto_sign_ed25519_amd64_64_ORDER0 -.globl crypto_sign_ed25519_amd64_64_ORDER1 -.globl crypto_sign_ed25519_amd64_64_ORDER2 -.globl crypto_sign_ed25519_amd64_64_ORDER3 -.globl crypto_sign_ed25519_amd64_64_EC2D0 -.globl crypto_sign_ed25519_amd64_64_EC2D1 -.globl crypto_sign_ed25519_amd64_64_EC2D2 -.globl crypto_sign_ed25519_amd64_64_EC2D3 -.globl crypto_sign_ed25519_amd64_64_38 - -.p2align 4 - -crypto_sign_ed25519_amd64_64_121666: .quad 121666 - -crypto_sign_ed25519_amd64_64_MU0: .quad 0xED9CE5A30A2C131B -crypto_sign_ed25519_amd64_64_MU1: .quad 0x2106215D086329A7 -crypto_sign_ed25519_amd64_64_MU2: .quad 0xFFFFFFFFFFFFFFEB -crypto_sign_ed25519_amd64_64_MU3: .quad 0xFFFFFFFFFFFFFFFF -crypto_sign_ed25519_amd64_64_MU4: .quad 0x000000000000000F - -crypto_sign_ed25519_amd64_64_ORDER0: .quad 0x5812631A5CF5D3ED -crypto_sign_ed25519_amd64_64_ORDER1: .quad 0x14DEF9DEA2F79CD6 -crypto_sign_ed25519_amd64_64_ORDER2: .quad 0x0000000000000000 -crypto_sign_ed25519_amd64_64_ORDER3: .quad 0x1000000000000000 - -crypto_sign_ed25519_amd64_64_EC2D0: .quad 0xEBD69B9426B2F146 -crypto_sign_ed25519_amd64_64_EC2D1: .quad 0x00E0149A8283B156 -crypto_sign_ed25519_amd64_64_EC2D2: .quad 0x198E80F2EEF3D130 -crypto_sign_ed25519_amd64_64_EC2D3: .quad 0xA406D9DC56DFFCE7 - -crypto_sign_ed25519_amd64_64_38: .quad 38 diff --git a/ext/ed25519-amd64-asm/fe25519.h b/ext/ed25519-amd64-asm/fe25519.h deleted file mode 100644 index 33ffabbe7..000000000 --- a/ext/ed25519-amd64-asm/fe25519.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef FE25519_H -#define FE25519_H - -#define fe25519 crypto_sign_ed25519_amd64_64_fe25519 -#define fe25519_freeze crypto_sign_ed25519_amd64_64_fe25519_freeze -#define fe25519_unpack crypto_sign_ed25519_amd64_64_fe25519_unpack -#define fe25519_pack crypto_sign_ed25519_amd64_64_fe25519_pack -#define fe25519_iszero_vartime crypto_sign_ed25519_amd64_64_fe25519_iszero_vartime -#define fe25519_iseq_vartime crypto_sign_ed25519_amd64_64_fe25519_iseq_vartime -#define fe25519_cmov crypto_sign_ed25519_amd64_64_fe25519_cmov -#define fe25519_setint crypto_sign_ed25519_amd64_64_fe25519_setint -#define fe25519_neg crypto_sign_ed25519_amd64_64_fe25519_neg -#define fe25519_getparity crypto_sign_ed25519_amd64_64_fe25519_getparity -#define fe25519_add crypto_sign_ed25519_amd64_64_fe25519_add -#define fe25519_sub crypto_sign_ed25519_amd64_64_fe25519_sub -#define fe25519_mul crypto_sign_ed25519_amd64_64_fe25519_mul -#define fe25519_mul121666 crypto_sign_ed25519_amd64_64_fe25519_mul121666 -#define fe25519_square crypto_sign_ed25519_amd64_64_fe25519_square -#define fe25519_invert crypto_sign_ed25519_amd64_64_fe25519_invert -#define fe25519_pow2523 crypto_sign_ed25519_amd64_64_fe25519_pow2523 - -typedef struct -{ - unsigned long long v[4]; -} -fe25519; - -void fe25519_freeze(fe25519 *r); - -void fe25519_unpack(fe25519 *r, const unsigned char x[32]); - -void fe25519_pack(unsigned char r[32], const fe25519 *x); - -void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b); - -void fe25519_cswap(fe25519 *r, fe25519 *x, unsigned char b); - -void fe25519_setint(fe25519 *r, unsigned int v); - -void fe25519_neg(fe25519 *r, const fe25519 *x); - -unsigned char fe25519_getparity(const fe25519 *x); - -int fe25519_iszero_vartime(const fe25519 *x); - -int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y); - -void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y); - -void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); - -void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y); - -void fe25519_mul121666(fe25519 *r, const fe25519 *x); - -void fe25519_square(fe25519 *r, const fe25519 *x); - -void fe25519_pow(fe25519 *r, const fe25519 *x, const unsigned char *e); - -void fe25519_invert(fe25519 *r, const fe25519 *x); - -void fe25519_pow2523(fe25519 *r, const fe25519 *x); - -#endif diff --git a/ext/ed25519-amd64-asm/fe25519_add.s b/ext/ed25519-amd64-asm/fe25519_add.s deleted file mode 100644 index b2e562520..000000000 --- a/ext/ed25519-amd64-asm/fe25519_add.s +++ /dev/null @@ -1,189 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 xp - -# qhasm: int64 yp - -# qhasm: input rp - -# qhasm: input xp - -# qhasm: input yp - -# qhasm: int64 r0 - -# qhasm: int64 r1 - -# qhasm: int64 r2 - -# qhasm: int64 r3 - -# qhasm: int64 addt0 - -# qhasm: int64 addt1 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_add -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_fe25519_add -.globl crypto_sign_ed25519_amd64_64_fe25519_add -_crypto_sign_ed25519_amd64_64_fe25519_add: -crypto_sign_ed25519_amd64_64_fe25519_add: -mov %rsp,%r11 -and $31,%r11 -add $0,%r11 -sub %r11,%rsp - -# qhasm: r0 = *(uint64 *)(xp + 0) -# asm 1: movq 0(r0=int64#4 -# asm 2: movq 0(r0=%rcx -movq 0(%rsi),%rcx - -# qhasm: r1 = *(uint64 *)(xp + 8) -# asm 1: movq 8(r1=int64#5 -# asm 2: movq 8(r1=%r8 -movq 8(%rsi),%r8 - -# qhasm: r2 = *(uint64 *)(xp + 16) -# asm 1: movq 16(r2=int64#6 -# asm 2: movq 16(r2=%r9 -movq 16(%rsi),%r9 - -# qhasm: r3 = *(uint64 *)(xp + 24) -# asm 1: movq 24(r3=int64#2 -# asm 2: movq 24(r3=%rsi -movq 24(%rsi),%rsi - -# qhasm: carry? r0 += *(uint64 *)(yp + 0) -# asm 1: addq 0(addt0=int64#3 -# asm 2: mov $0,>addt0=%rdx -mov $0,%rdx - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#7 -# asm 2: mov $38,>addt1=%rax -mov $38,%rax - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: r0 = *(uint64 *) (rp + 0) -# asm 1: movq 0(r0=int64#2 -# asm 2: movq 0(r0=%rsi -movq 0(%rdi),%rsi - -# qhasm: r1 = *(uint64 *) (rp + 8) -# asm 1: movq 8(r1=int64#3 -# asm 2: movq 8(r1=%rdx -movq 8(%rdi),%rdx - -# qhasm: r2 = *(uint64 *) (rp + 16) -# asm 1: movq 16(r2=int64#4 -# asm 2: movq 16(r2=%rcx -movq 16(%rdi),%rcx - -# qhasm: r3 = *(uint64 *) (rp + 24) -# asm 1: movq 24(r3=int64#5 -# asm 2: movq 24(r3=%r8 -movq 24(%rdi),%r8 - -# qhasm: t0 = r0 -# asm 1: mov t0=int64#6 -# asm 2: mov t0=%r9 -mov %rsi,%r9 - -# qhasm: t1 = r1 -# asm 1: mov t1=int64#7 -# asm 2: mov t1=%rax -mov %rdx,%rax - -# qhasm: t2 = r2 -# asm 1: mov t2=int64#8 -# asm 2: mov t2=%r10 -mov %rcx,%r10 - -# qhasm: t3 = r3 -# asm 1: mov t3=int64#9 -# asm 2: mov t3=%r11 -mov %r8,%r11 - -# qhasm: two63 = 1 -# asm 1: mov $1,>two63=int64#10 -# asm 2: mov $1,>two63=%r12 -mov $1,%r12 - -# qhasm: two63 <<= 63 -# asm 1: shl $63,t0=int64#6 -# asm 2: mov t0=%r9 -mov %rsi,%r9 - -# qhasm: t1 = r1 -# asm 1: mov t1=int64#7 -# asm 2: mov t1=%rax -mov %rdx,%rax - -# qhasm: t2 = r2 -# asm 1: mov t2=int64#8 -# asm 2: mov t2=%r10 -mov %rcx,%r10 - -# qhasm: t3 = r3 -# asm 1: mov t3=int64#9 -# asm 2: mov t3=%r11 -mov %r8,%r11 - -# qhasm: carry? t0 += 19 -# asm 1: add $19,caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/fe25519_getparity.c b/ext/ed25519-amd64-asm/fe25519_getparity.c deleted file mode 100644 index a003ec8f5..000000000 --- a/ext/ed25519-amd64-asm/fe25519_getparity.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "fe25519.h" - -unsigned char fe25519_getparity(const fe25519 *x) -{ - fe25519 t = *x; - fe25519_freeze(&t); - return (unsigned char)t.v[0] & 1; -} diff --git a/ext/ed25519-amd64-asm/fe25519_invert.c b/ext/ed25519-amd64-asm/fe25519_invert.c deleted file mode 100644 index a46d141ff..000000000 --- a/ext/ed25519-amd64-asm/fe25519_invert.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "fe25519.h" - -void fe25519_invert(fe25519 *r, const fe25519 *x) -{ - fe25519 z2; - fe25519 z9; - fe25519 z11; - fe25519 z2_5_0; - fe25519 z2_10_0; - fe25519 z2_20_0; - fe25519 z2_50_0; - fe25519 z2_100_0; - fe25519 t; - int i; - - /* 2 */ fe25519_square(&z2,x); - /* 4 */ fe25519_square(&t,&z2); - /* 8 */ fe25519_square(&t,&t); - /* 9 */ fe25519_mul(&z9,&t,x); - /* 11 */ fe25519_mul(&z11,&z9,&z2); - /* 22 */ fe25519_square(&t,&z11); - /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9); - - /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0); - /* 2^20 - 2^10 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); } - /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0); - - /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0); - /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } - /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0); - - /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0); - /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); } - /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0); - - /* 2^41 - 2^1 */ fe25519_square(&t,&t); - /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } - /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0); - - /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0); - /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } - /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0); - - /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0); - /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); } - /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0); - - /* 2^201 - 2^1 */ fe25519_square(&t,&t); - /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } - /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0); - - /* 2^251 - 2^1 */ fe25519_square(&t,&t); - /* 2^252 - 2^2 */ fe25519_square(&t,&t); - /* 2^253 - 2^3 */ fe25519_square(&t,&t); - - /* 2^254 - 2^4 */ fe25519_square(&t,&t); - - /* 2^255 - 2^5 */ fe25519_square(&t,&t); - /* 2^255 - 21 */ fe25519_mul(r,&t,&z11); -} diff --git a/ext/ed25519-amd64-asm/fe25519_iseq.c b/ext/ed25519-amd64-asm/fe25519_iseq.c deleted file mode 100644 index bf72f8c91..000000000 --- a/ext/ed25519-amd64-asm/fe25519_iseq.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "fe25519.h" - -int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) -{ - fe25519 t1 = *x; - fe25519 t2 = *y; - fe25519_freeze(&t1); - fe25519_freeze(&t2); - if(t1.v[0] != t2.v[0]) return 0; - if(t1.v[1] != t2.v[1]) return 0; - if(t1.v[2] != t2.v[2]) return 0; - if(t1.v[3] != t2.v[3]) return 0; - return 1; -} diff --git a/ext/ed25519-amd64-asm/fe25519_iszero.c b/ext/ed25519-amd64-asm/fe25519_iszero.c deleted file mode 100644 index 99e4dafa7..000000000 --- a/ext/ed25519-amd64-asm/fe25519_iszero.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "fe25519.h" - -int fe25519_iszero_vartime(const fe25519 *x) -{ - fe25519 t = *x; - fe25519_freeze(&t); - if (t.v[0]) return 0; - if (t.v[1]) return 0; - if (t.v[2]) return 0; - if (t.v[3]) return 0; - return 1; -} diff --git a/ext/ed25519-amd64-asm/fe25519_mul.s b/ext/ed25519-amd64-asm/fe25519_mul.s deleted file mode 100644 index 147842811..000000000 --- a/ext/ed25519-amd64-asm/fe25519_mul.s +++ /dev/null @@ -1,865 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 xp - -# qhasm: int64 yp - -# qhasm: input rp - -# qhasm: input xp - -# qhasm: input yp - -# qhasm: int64 r0 - -# qhasm: int64 r1 - -# qhasm: int64 r2 - -# qhasm: int64 r3 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 mulr4 - -# qhasm: int64 mulr5 - -# qhasm: int64 mulr6 - -# qhasm: int64 mulr7 - -# qhasm: int64 mulr8 - -# qhasm: int64 mulrax - -# qhasm: int64 mulrdx - -# qhasm: int64 mulx0 - -# qhasm: int64 mulx1 - -# qhasm: int64 mulx2 - -# qhasm: int64 mulx3 - -# qhasm: int64 mulc - -# qhasm: int64 mulzero - -# qhasm: int64 muli38 - -# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_mul -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_fe25519_mul -.globl crypto_sign_ed25519_amd64_64_fe25519_mul -_crypto_sign_ed25519_amd64_64_fe25519_mul: -crypto_sign_ed25519_amd64_64_fe25519_mul: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: yp = yp -# asm 1: mov yp=int64#4 -# asm 2: mov yp=%rcx -mov %rdx,%rcx - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = *(uint64 *)(xp + 0) -# asm 1: movq 0(mulx0=int64#10 -# asm 2: movq 0(mulx0=%r12 -movq 0(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(yp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul r0=int64#11 -# asm 2: mov r0=%r13 -mov %rax,%r13 - -# qhasm: r1 = mulrdx -# asm 1: mov r1=int64#12 -# asm 2: mov r1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(yp + 8) -# asm 1: movq 8(mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul r2=int64#13 -# asm 2: mov $0,>r2=%r15 -mov $0,%r15 - -# qhasm: r2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul r3=int64#14 -# asm 2: mov $0,>r3=%rbx -mov $0,%rbx - -# qhasm: r3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq 8(mulx1=%r12 -movq 8(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(yp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq 16(mulx2=%r12 -movq 16(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(yp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#2 -# asm 2: movq 24(mulx3=%rsi -movq 24(%rsi),%rsi - -# qhasm: mulrax = *(uint64 *)(yp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? r0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: r0 += mulzero -# asm 1: add caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/fe25519_neg.c b/ext/ed25519-amd64-asm/fe25519_neg.c deleted file mode 100644 index 235b209dd..000000000 --- a/ext/ed25519-amd64-asm/fe25519_neg.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "fe25519.h" - -void fe25519_neg(fe25519 *r, const fe25519 *x) -{ - fe25519 t; - fe25519_setint(&t,0); - fe25519_sub(r,&t,x); -} diff --git a/ext/ed25519-amd64-asm/fe25519_pack.c b/ext/ed25519-amd64-asm/fe25519_pack.c deleted file mode 100644 index caf518530..000000000 --- a/ext/ed25519-amd64-asm/fe25519_pack.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "fe25519.h" - -/* Assumes input x being reduced below 2^255 */ -void fe25519_pack(unsigned char r[32], const fe25519 *x) -{ - int i; - fe25519 t; - t = *x; - fe25519_freeze(&t); - /* assuming little-endian */ - for(i=0;i<32;i++) r[i] = i[(unsigned char *)&t.v]; -} - diff --git a/ext/ed25519-amd64-asm/fe25519_pow2523.c b/ext/ed25519-amd64-asm/fe25519_pow2523.c deleted file mode 100644 index 60042a0a1..000000000 --- a/ext/ed25519-amd64-asm/fe25519_pow2523.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "fe25519.h" - -void fe25519_pow2523(fe25519 *r, const fe25519 *x) -{ - fe25519 z2; - fe25519 z9; - fe25519 z11; - fe25519 z2_5_0; - fe25519 z2_10_0; - fe25519 z2_20_0; - fe25519 z2_50_0; - fe25519 z2_100_0; - fe25519 t; - int i; - - /* 2 */ fe25519_square(&z2,x); - /* 4 */ fe25519_square(&t,&z2); - /* 8 */ fe25519_square(&t,&t); - /* 9 */ fe25519_mul(&z9,&t,x); - /* 11 */ fe25519_mul(&z11,&z9,&z2); - /* 22 */ fe25519_square(&t,&z11); - /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9); - - /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0); - /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); } - /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0); - - /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0); - /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } - /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0); - - /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0); - /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); } - /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0); - - /* 2^41 - 2^1 */ fe25519_square(&t,&t); - /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } - /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0); - - /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0); - /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } - /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0); - - /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0); - /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); } - /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0); - - /* 2^201 - 2^1 */ fe25519_square(&t,&t); - /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } - /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0); - - /* 2^251 - 2^1 */ fe25519_square(&t,&t); - /* 2^252 - 2^2 */ fe25519_square(&t,&t); - /* 2^252 - 3 */ fe25519_mul(r,&t,x); -} diff --git a/ext/ed25519-amd64-asm/fe25519_setint.c b/ext/ed25519-amd64-asm/fe25519_setint.c deleted file mode 100644 index 585c4bdd5..000000000 --- a/ext/ed25519-amd64-asm/fe25519_setint.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "fe25519.h" - -void fe25519_setint(fe25519 *r, unsigned int v) -{ - r->v[0] = v; - r->v[1] = 0; - r->v[2] = 0; - r->v[3] = 0; -} diff --git a/ext/ed25519-amd64-asm/fe25519_square.s b/ext/ed25519-amd64-asm/fe25519_square.s deleted file mode 100644 index a74d9e888..000000000 --- a/ext/ed25519-amd64-asm/fe25519_square.s +++ /dev/null @@ -1,639 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 xp - -# qhasm: input rp - -# qhasm: input xp - -# qhasm: int64 r0 - -# qhasm: int64 r1 - -# qhasm: int64 r2 - -# qhasm: int64 r3 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 squarer4 - -# qhasm: int64 squarer5 - -# qhasm: int64 squarer6 - -# qhasm: int64 squarer7 - -# qhasm: int64 squarer8 - -# qhasm: int64 squarerax - -# qhasm: int64 squarerdx - -# qhasm: int64 squaret1 - -# qhasm: int64 squaret2 - -# qhasm: int64 squaret3 - -# qhasm: int64 squarec - -# qhasm: int64 squarezero - -# qhasm: int64 squarei38 - -# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_square -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_fe25519_square -.globl crypto_sign_ed25519_amd64_64_fe25519_square -_crypto_sign_ed25519_amd64_64_fe25519_square: -crypto_sign_ed25519_amd64_64_fe25519_square: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#4 -# asm 2: mov $0,>squarer7=%rcx -mov $0,%rcx - -# qhasm: squarerax = *(uint64 *)(xp + 8) -# asm 1: movq 8(squarerax=int64#7 -# asm 2: movq 8(squarerax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 0) -# asm 1: mulq 0(r1=int64#5 -# asm 2: mov r1=%r8 -mov %rax,%r8 - -# qhasm: r2 = squarerdx -# asm 1: mov r2=int64#6 -# asm 2: mov r2=%r9 -mov %rdx,%r9 - -# qhasm: squarerax = *(uint64 *)(xp + 16) -# asm 1: movq 16(squarerax=int64#7 -# asm 2: movq 16(squarerax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 8) -# asm 1: mulq 8(r3=int64#8 -# asm 2: mov r3=%r10 -mov %rax,%r10 - -# qhasm: squarer4 = squarerdx -# asm 1: mov squarer4=int64#9 -# asm 2: mov squarer4=%r11 -mov %rdx,%r11 - -# qhasm: squarerax = *(uint64 *)(xp + 24) -# asm 1: movq 24(squarerax=int64#7 -# asm 2: movq 24(squarerax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 16) -# asm 1: mulq 16(squarer5=int64#10 -# asm 2: mov squarer5=%r12 -mov %rax,%r12 - -# qhasm: squarer6 = squarerdx -# asm 1: mov squarer6=int64#11 -# asm 2: mov squarer6=%r13 -mov %rdx,%r13 - -# qhasm: squarerax = *(uint64 *)(xp + 16) -# asm 1: movq 16(squarerax=int64#7 -# asm 2: movq 16(squarerax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 0) -# asm 1: mulq 0(squarerax=int64#7 -# asm 2: movq 24(squarerax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 8) -# asm 1: mulq 8(squarerax=int64#7 -# asm 2: movq 24(squarerax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 0) -# asm 1: mulq 0(squarerax=int64#7 -# asm 2: movq 0(squarerax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 0) -# asm 1: mulq 0(r0=int64#12 -# asm 2: mov r0=%r14 -mov %rax,%r14 - -# qhasm: squaret1 = squarerdx -# asm 1: mov squaret1=int64#13 -# asm 2: mov squaret1=%r15 -mov %rdx,%r15 - -# qhasm: squarerax = *(uint64 *)(xp + 8) -# asm 1: movq 8(squarerax=int64#7 -# asm 2: movq 8(squarerax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 8) -# asm 1: mulq 8(squaret2=int64#14 -# asm 2: mov squaret2=%rbx -mov %rax,%rbx - -# qhasm: squaret3 = squarerdx -# asm 1: mov squaret3=int64#15 -# asm 2: mov squaret3=%rbp -mov %rdx,%rbp - -# qhasm: squarerax = *(uint64 *)(xp + 16) -# asm 1: movq 16(squarerax=int64#7 -# asm 2: movq 16(squarerax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 16) -# asm 1: mulq 16(squarerax=int64#7 -# asm 2: movq 24(squarerax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 24) -# asm 1: mulq 24(squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r11,%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: squarer4 = squarerax -# asm 1: mov squarer4=int64#2 -# asm 2: mov squarer4=%rsi -mov %rax,%rsi - -# qhasm: squarerax = squarer5 -# asm 1: mov squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r12,%rax - -# qhasm: squarer5 = squarerdx -# asm 1: mov squarer5=int64#9 -# asm 2: mov squarer5=%r11 -mov %rdx,%r11 - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? squarer5 += squarerax -# asm 1: add squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r13,%rax - -# qhasm: squarer6 = 0 -# asm 1: mov $0,>squarer6=int64#10 -# asm 2: mov $0,>squarer6=%r12 -mov $0,%r12 - -# qhasm: squarer6 += squarerdx + carry -# asm 1: adc squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %rcx,%rax - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#4 -# asm 2: mov $0,>squarer7=%rcx -mov $0,%rcx - -# qhasm: squarer7 += squarerdx + carry -# asm 1: adc squarer8=int64#7 -# asm 2: mov $0,>squarer8=%rax -mov $0,%rax - -# qhasm: squarer8 += squarerdx + carry -# asm 1: adc squarezero=int64#2 -# asm 2: mov $0,>squarezero=%rsi -mov $0,%rsi - -# qhasm: squarer8 += squarezero + carry -# asm 1: adc squarer8=int64#3 -# asm 2: imulq $38,squarer8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? r0 += squarer8 -# asm 1: add squarezero=int64#2 -# asm 2: imulq $38,squarezero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: r0 += squarezero -# asm 1: add caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/fe25519_sub.s b/ext/ed25519-amd64-asm/fe25519_sub.s deleted file mode 100644 index 0b395bce7..000000000 --- a/ext/ed25519-amd64-asm/fe25519_sub.s +++ /dev/null @@ -1,189 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 xp - -# qhasm: int64 yp - -# qhasm: input rp - -# qhasm: input xp - -# qhasm: input yp - -# qhasm: int64 r0 - -# qhasm: int64 r1 - -# qhasm: int64 r2 - -# qhasm: int64 r3 - -# qhasm: int64 subt0 - -# qhasm: int64 subt1 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_sub -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_fe25519_sub -.globl crypto_sign_ed25519_amd64_64_fe25519_sub -_crypto_sign_ed25519_amd64_64_fe25519_sub: -crypto_sign_ed25519_amd64_64_fe25519_sub: -mov %rsp,%r11 -and $31,%r11 -add $0,%r11 -sub %r11,%rsp - -# qhasm: r0 = *(uint64 *)(xp + 0) -# asm 1: movq 0(r0=int64#4 -# asm 2: movq 0(r0=%rcx -movq 0(%rsi),%rcx - -# qhasm: r1 = *(uint64 *)(xp + 8) -# asm 1: movq 8(r1=int64#5 -# asm 2: movq 8(r1=%r8 -movq 8(%rsi),%r8 - -# qhasm: r2 = *(uint64 *)(xp + 16) -# asm 1: movq 16(r2=int64#6 -# asm 2: movq 16(r2=%r9 -movq 16(%rsi),%r9 - -# qhasm: r3 = *(uint64 *)(xp + 24) -# asm 1: movq 24(r3=int64#2 -# asm 2: movq 24(r3=%rsi -movq 24(%rsi),%rsi - -# qhasm: carry? r0 -= *(uint64 *)(yp + 0) -# asm 1: subq 0(subt0=int64#3 -# asm 2: mov $0,>subt0=%rdx -mov $0,%rdx - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#7 -# asm 2: mov $38,>subt1=%rax -mov $38,%rax - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae v[0] = *(unsigned long long *)x; - r->v[1] = *(((unsigned long long *)x)+1); - r->v[2] = *(((unsigned long long *)x)+2); - r->v[3] = *(((unsigned long long *)x)+3); - r->v[3] &= 0x7fffffffffffffffULL; -} diff --git a/ext/ed25519-amd64-asm/ge25519.h b/ext/ed25519-amd64-asm/ge25519.h deleted file mode 100644 index 0b15136b9..000000000 --- a/ext/ed25519-amd64-asm/ge25519.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef GE25519_H -#define GE25519_H - -#include "fe25519.h" -#include "sc25519.h" - -#define ge25519 crypto_sign_ed25519_amd64_64_ge25519 -#define ge25519_base crypto_sign_ed25519_amd64_64_ge25519_base -#define ge25519_unpackneg_vartime crypto_sign_ed25519_amd64_64_unpackneg_vartime -#define ge25519_pack crypto_sign_ed25519_amd64_64_pack -#define ge25519_isneutral_vartime crypto_sign_ed25519_amd64_64_isneutral_vartime -#define ge25519_add crypto_sign_ed25519_amd64_64_ge25519_add -#define ge25519_double crypto_sign_ed25519_amd64_64_ge25519_double -#define ge25519_double_scalarmult_vartime crypto_sign_ed25519_amd64_64_double_scalarmult_vartime -#define ge25519_multi_scalarmult_vartime crypto_sign_ed25519_amd64_64_ge25519_multi_scalarmult_vartime -#define ge25519_scalarmult_base crypto_sign_ed25519_amd64_64_scalarmult_base -#define ge25519_p1p1_to_p2 crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2 -#define ge25519_p1p1_to_p3 crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3 -#define ge25519_add_p1p1 crypto_sign_ed25519_amd64_64_ge25519_add_p1p1 -#define ge25519_dbl_p1p1 crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1 -#define choose_t crypto_sign_ed25519_amd64_64_choose_t -#define ge25519_nielsadd2 crypto_sign_ed25519_amd64_64_ge25519_nielsadd2 -#define ge25519_nielsadd_p1p1 crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1 -#define ge25519_pnielsadd_p1p1 crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1 - - -#define ge25519_p3 ge25519 - -typedef struct -{ - fe25519 x; - fe25519 y; - fe25519 z; - fe25519 t; -} ge25519; - -typedef struct -{ - fe25519 x; - fe25519 z; - fe25519 y; - fe25519 t; -} ge25519_p1p1; - -typedef struct -{ - fe25519 x; - fe25519 y; - fe25519 z; -} ge25519_p2; - -typedef struct -{ - fe25519 ysubx; - fe25519 xaddy; - fe25519 t2d; -} ge25519_niels; - -typedef struct -{ - fe25519 ysubx; - fe25519 xaddy; - fe25519 z; - fe25519 t2d; -} ge25519_pniels; - -extern void ge25519_p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p); -extern void ge25519_p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p); -extern void ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q); -extern void ge25519_dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p); -extern void choose_t(ge25519_niels *t, unsigned long long pos, signed long long b, const ge25519_niels *base_multiples); -extern void ge25519_nielsadd2(ge25519_p3 *r, const ge25519_niels *q); -extern void ge25519_nielsadd_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_niels *q); -extern void ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_pniels *q); - -extern const ge25519 ge25519_base; - -extern int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]); - -extern void ge25519_pack(unsigned char r[32], const ge25519 *p); - -extern int ge25519_isneutral_vartime(const ge25519 *p); - -extern void ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q); - -extern void ge25519_double(ge25519 *r, const ge25519 *p); - -/* computes [s1]p1 + [s2]ge25519_base */ -extern void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25519 *s1, const sc25519 *s2); - -extern void ge25519_multi_scalarmult_vartime(ge25519 *r, ge25519 *p, sc25519 *s, const unsigned long long npoints); - -extern void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s); - -#endif diff --git a/ext/ed25519-amd64-asm/ge25519_add.c b/ext/ed25519-amd64-asm/ge25519_add.c deleted file mode 100644 index c4d1c68a4..000000000 --- a/ext/ed25519-amd64-asm/ge25519_add.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "ge25519.h" - -void ge25519_add(ge25519_p3 *r, const ge25519_p3 *p, const ge25519_p3 *q) -{ - ge25519_p1p1 grp1p1; - ge25519_add_p1p1(&grp1p1, p, q); - ge25519_p1p1_to_p3(r, &grp1p1); -} diff --git a/ext/ed25519-amd64-asm/ge25519_add_p1p1.s b/ext/ed25519-amd64-asm/ge25519_add_p1p1.s deleted file mode 100644 index 0cb138980..000000000 --- a/ext/ed25519-amd64-asm/ge25519_add_p1p1.s +++ /dev/null @@ -1,4554 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 pp - -# qhasm: int64 qp - -# qhasm: input rp - -# qhasm: input pp - -# qhasm: input qp - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 a0 - -# qhasm: int64 a1 - -# qhasm: int64 a2 - -# qhasm: int64 a3 - -# qhasm: stack64 a0_stack - -# qhasm: stack64 a1_stack - -# qhasm: stack64 a2_stack - -# qhasm: stack64 a3_stack - -# qhasm: int64 b0 - -# qhasm: int64 b1 - -# qhasm: int64 b2 - -# qhasm: int64 b3 - -# qhasm: stack64 b0_stack - -# qhasm: stack64 b1_stack - -# qhasm: stack64 b2_stack - -# qhasm: stack64 b3_stack - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: stack64 c0_stack - -# qhasm: stack64 c1_stack - -# qhasm: stack64 c2_stack - -# qhasm: stack64 c3_stack - -# qhasm: int64 d0 - -# qhasm: int64 d1 - -# qhasm: int64 d2 - -# qhasm: int64 d3 - -# qhasm: stack64 d0_stack - -# qhasm: stack64 d1_stack - -# qhasm: stack64 d2_stack - -# qhasm: stack64 d3_stack - -# qhasm: int64 t10 - -# qhasm: int64 t11 - -# qhasm: int64 t12 - -# qhasm: int64 t13 - -# qhasm: stack64 t10_stack - -# qhasm: stack64 t11_stack - -# qhasm: stack64 t12_stack - -# qhasm: stack64 t13_stack - -# qhasm: int64 t20 - -# qhasm: int64 t21 - -# qhasm: int64 t22 - -# qhasm: int64 t23 - -# qhasm: stack64 t20_stack - -# qhasm: stack64 t21_stack - -# qhasm: stack64 t22_stack - -# qhasm: stack64 t23_stack - -# qhasm: int64 rx0 - -# qhasm: int64 rx1 - -# qhasm: int64 rx2 - -# qhasm: int64 rx3 - -# qhasm: int64 ry0 - -# qhasm: int64 ry1 - -# qhasm: int64 ry2 - -# qhasm: int64 ry3 - -# qhasm: int64 rz0 - -# qhasm: int64 rz1 - -# qhasm: int64 rz2 - -# qhasm: int64 rz3 - -# qhasm: int64 rt0 - -# qhasm: int64 rt1 - -# qhasm: int64 rt2 - -# qhasm: int64 rt3 - -# qhasm: int64 x0 - -# qhasm: int64 x1 - -# qhasm: int64 x2 - -# qhasm: int64 x3 - -# qhasm: int64 mulr4 - -# qhasm: int64 mulr5 - -# qhasm: int64 mulr6 - -# qhasm: int64 mulr7 - -# qhasm: int64 mulr8 - -# qhasm: int64 mulrax - -# qhasm: int64 mulrdx - -# qhasm: int64 mulx0 - -# qhasm: int64 mulx1 - -# qhasm: int64 mulx2 - -# qhasm: int64 mulx3 - -# qhasm: int64 mulc - -# qhasm: int64 mulzero - -# qhasm: int64 muli38 - -# qhasm: int64 addt0 - -# qhasm: int64 addt1 - -# qhasm: int64 subt0 - -# qhasm: int64 subt1 - -# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_add_p1p1 -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_ge25519_add_p1p1 -.globl crypto_sign_ed25519_amd64_64_ge25519_add_p1p1 -_crypto_sign_ed25519_amd64_64_ge25519_add_p1p1: -crypto_sign_ed25519_amd64_64_ge25519_add_p1p1: -mov %rsp,%r11 -and $31,%r11 -add $192,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: qp = qp -# asm 1: mov qp=int64#4 -# asm 2: mov qp=%rcx -mov %rdx,%rcx - -# qhasm: a0 = *(uint64 *)(pp + 32) -# asm 1: movq 32(a0=int64#3 -# asm 2: movq 32(a0=%rdx -movq 32(%rsi),%rdx - -# qhasm: a1 = *(uint64 *)(pp + 40) -# asm 1: movq 40(a1=int64#5 -# asm 2: movq 40(a1=%r8 -movq 40(%rsi),%r8 - -# qhasm: a2 = *(uint64 *)(pp + 48) -# asm 1: movq 48(a2=int64#6 -# asm 2: movq 48(a2=%r9 -movq 48(%rsi),%r9 - -# qhasm: a3 = *(uint64 *)(pp + 56) -# asm 1: movq 56(a3=int64#7 -# asm 2: movq 56(a3=%rax -movq 56(%rsi),%rax - -# qhasm: b0 = a0 -# asm 1: mov b0=int64#8 -# asm 2: mov b0=%r10 -mov %rdx,%r10 - -# qhasm: b1 = a1 -# asm 1: mov b1=int64#9 -# asm 2: mov b1=%r11 -mov %r8,%r11 - -# qhasm: b2 = a2 -# asm 1: mov b2=int64#10 -# asm 2: mov b2=%r12 -mov %r9,%r12 - -# qhasm: b3 = a3 -# asm 1: mov b3=int64#11 -# asm 2: mov b3=%r13 -mov %rax,%r13 - -# qhasm: carry? a0 -= *(uint64 *)(pp + 0) -# asm 1: subq 0(subt0=int64#12 -# asm 2: mov $0,>subt0=%r14 -mov $0,%r14 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#13 -# asm 2: mov $38,>subt1=%r15 -mov $38,%r15 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#12 -# asm 2: mov $0,>addt0=%r14 -mov $0,%r14 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#13 -# asm 2: mov $38,>addt1=%r15 -mov $38,%r15 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %rdx,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %r8,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r9,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %rax,80(%rsp) - -# qhasm: b0_stack = b0 -# asm 1: movq b0_stack=stack64#12 -# asm 2: movq b0_stack=88(%rsp) -movq %r10,88(%rsp) - -# qhasm: b1_stack = b1 -# asm 1: movq b1_stack=stack64#13 -# asm 2: movq b1_stack=96(%rsp) -movq %r11,96(%rsp) - -# qhasm: b2_stack = b2 -# asm 1: movq b2_stack=stack64#14 -# asm 2: movq b2_stack=104(%rsp) -movq %r12,104(%rsp) - -# qhasm: b3_stack = b3 -# asm 1: movq b3_stack=stack64#15 -# asm 2: movq b3_stack=112(%rsp) -movq %r13,112(%rsp) - -# qhasm: t10 = *(uint64 *)(qp + 32) -# asm 1: movq 32(t10=int64#3 -# asm 2: movq 32(t10=%rdx -movq 32(%rcx),%rdx - -# qhasm: t11 = *(uint64 *)(qp + 40) -# asm 1: movq 40(t11=int64#5 -# asm 2: movq 40(t11=%r8 -movq 40(%rcx),%r8 - -# qhasm: t12 = *(uint64 *)(qp + 48) -# asm 1: movq 48(t12=int64#6 -# asm 2: movq 48(t12=%r9 -movq 48(%rcx),%r9 - -# qhasm: t13 = *(uint64 *)(qp + 56) -# asm 1: movq 56(t13=int64#7 -# asm 2: movq 56(t13=%rax -movq 56(%rcx),%rax - -# qhasm: t20 = t10 -# asm 1: mov t20=int64#8 -# asm 2: mov t20=%r10 -mov %rdx,%r10 - -# qhasm: t21 = t11 -# asm 1: mov t21=int64#9 -# asm 2: mov t21=%r11 -mov %r8,%r11 - -# qhasm: t22 = t12 -# asm 1: mov t22=int64#10 -# asm 2: mov t22=%r12 -mov %r9,%r12 - -# qhasm: t23 = t13 -# asm 1: mov t23=int64#11 -# asm 2: mov t23=%r13 -mov %rax,%r13 - -# qhasm: carry? t10 -= *(uint64 *) (qp + 0) -# asm 1: subq 0(subt0=int64#12 -# asm 2: mov $0,>subt0=%r14 -mov $0,%r14 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#13 -# asm 2: mov $38,>subt1=%r15 -mov $38,%r15 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#12 -# asm 2: mov $0,>addt0=%r14 -mov $0,%r14 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#13 -# asm 2: mov $38,>addt1=%r15 -mov $38,%r15 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae t10_stack=stack64#16 -# asm 2: movq t10_stack=120(%rsp) -movq %rdx,120(%rsp) - -# qhasm: t11_stack = t11 -# asm 1: movq t11_stack=stack64#17 -# asm 2: movq t11_stack=128(%rsp) -movq %r8,128(%rsp) - -# qhasm: t12_stack = t12 -# asm 1: movq t12_stack=stack64#18 -# asm 2: movq t12_stack=136(%rsp) -movq %r9,136(%rsp) - -# qhasm: t13_stack = t13 -# asm 1: movq t13_stack=stack64#19 -# asm 2: movq t13_stack=144(%rsp) -movq %rax,144(%rsp) - -# qhasm: t20_stack = t20 -# asm 1: movq t20_stack=stack64#20 -# asm 2: movq t20_stack=152(%rsp) -movq %r10,152(%rsp) - -# qhasm: t21_stack = t21 -# asm 1: movq t21_stack=stack64#21 -# asm 2: movq t21_stack=160(%rsp) -movq %r11,160(%rsp) - -# qhasm: t22_stack = t22 -# asm 1: movq t22_stack=stack64#22 -# asm 2: movq t22_stack=168(%rsp) -movq %r12,168(%rsp) - -# qhasm: t23_stack = t23 -# asm 1: movq t23_stack=stack64#23 -# asm 2: movq t23_stack=176(%rsp) -movq %r13,176(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = a0_stack -# asm 1: movq mulx0=int64#10 -# asm 2: movq mulx0=%r12 -movq 56(%rsp),%r12 - -# qhasm: mulrax = t10_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 120(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a0=int64#11 -# asm 2: mov a0=%r13 -mov %rax,%r13 - -# qhasm: a1 = mulrdx -# asm 1: mov a1=int64#12 -# asm 2: mov a1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = t11_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 128(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a2=int64#13 -# asm 2: mov $0,>a2=%r15 -mov $0,%r15 - -# qhasm: a2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 136(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a3=int64#14 -# asm 2: mov $0,>a3=%rbx -mov $0,%rbx - -# qhasm: a3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 144(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq mulx1=%r12 -movq 64(%rsp),%r12 - -# qhasm: mulrax = t10_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 120(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 128(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 136(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 144(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq mulx2=%r12 -movq 72(%rsp),%r12 - -# qhasm: mulrax = t10_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 120(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 128(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 136(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 144(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq mulx3=%r12 -movq 80(%rsp),%r12 - -# qhasm: mulrax = t10_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 120(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 128(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 136(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 144(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? a0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: a0 += mulzero -# asm 1: add a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %r13,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %r14,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r15,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %rbx,80(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = b0_stack -# asm 1: movq mulx0=int64#10 -# asm 2: movq mulx0=%r12 -movq 88(%rsp),%r12 - -# qhasm: mulrax = t20_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx0=int64#11 -# asm 2: mov rx0=%r13 -mov %rax,%r13 - -# qhasm: rx1 = mulrdx -# asm 1: mov rx1=int64#12 -# asm 2: mov rx1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = t21_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx2=int64#13 -# asm 2: mov $0,>rx2=%r15 -mov $0,%r15 - -# qhasm: rx2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx3=int64#14 -# asm 2: mov $0,>rx3=%rbx -mov $0,%rbx - -# qhasm: rx3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq mulx1=%r12 -movq 96(%rsp),%r12 - -# qhasm: mulrax = t20_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq mulx2=%r12 -movq 104(%rsp),%r12 - -# qhasm: mulrax = t20_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq mulx3=%r12 -movq 112(%rsp),%r12 - -# qhasm: mulrax = t20_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? rx0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: rx0 += mulzero -# asm 1: add ry0=int64#3 -# asm 2: mov ry0=%rdx -mov %r13,%rdx - -# qhasm: ry1 = rx1 -# asm 1: mov ry1=int64#5 -# asm 2: mov ry1=%r8 -mov %r14,%r8 - -# qhasm: ry2 = rx2 -# asm 1: mov ry2=int64#6 -# asm 2: mov ry2=%r9 -mov %r15,%r9 - -# qhasm: ry3 = rx3 -# asm 1: mov ry3=int64#7 -# asm 2: mov ry3=%rax -mov %rbx,%rax - -# qhasm: carry? ry0 += a0_stack -# asm 1: addq addt0=int64#8 -# asm 2: mov $0,>addt0=%r10 -mov $0,%r10 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#9 -# asm 2: mov $38,>addt1=%r11 -mov $38,%r11 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae subt0=int64#8 -# asm 2: mov $0,>subt0=%r10 -mov $0,%r10 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#9 -# asm 2: mov $38,>subt1=%r11 -mov $38,%r11 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulx0=int64#10 -# asm 2: movq 96(mulx0=%r12 -movq 96(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c0=int64#11 -# asm 2: mov c0=%r13 -mov %rax,%r13 - -# qhasm: c1 = mulrdx -# asm 1: mov c1=int64#12 -# asm 2: mov c1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 104) -# asm 1: movq 104(mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c2=int64#13 -# asm 2: mov $0,>c2=%r15 -mov $0,%r15 - -# qhasm: c2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c3=int64#14 -# asm 2: mov $0,>c3=%rbx -mov $0,%rbx - -# qhasm: c3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq 104(mulx1=%r12 -movq 104(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq 112(mulx2=%r12 -movq 112(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq 120(mulx3=%r12 -movq 120(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? c0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: c0 += mulzero -# asm 1: add c0_stack=stack64#8 -# asm 2: movq c0_stack=56(%rsp) -movq %r13,56(%rsp) - -# qhasm: c1_stack = c1 -# asm 1: movq c1_stack=stack64#9 -# asm 2: movq c1_stack=64(%rsp) -movq %r14,64(%rsp) - -# qhasm: c2_stack = c2 -# asm 1: movq c2_stack=stack64#10 -# asm 2: movq c2_stack=72(%rsp) -movq %r15,72(%rsp) - -# qhasm: c3_stack = c3 -# asm 1: movq c3_stack=stack64#11 -# asm 2: movq c3_stack=80(%rsp) -movq %rbx,80(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = c0_stack -# asm 1: movq mulx0=int64#10 -# asm 2: movq mulx0=%r12 -movq 56(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D0 -# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D0(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c0=int64#11 -# asm 2: mov c0=%r13 -mov %rax,%r13 - -# qhasm: c1 = mulrdx -# asm 1: mov c1=int64#12 -# asm 2: mov c1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D1 -# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D1(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c2=int64#13 -# asm 2: mov $0,>c2=%r15 -mov $0,%r15 - -# qhasm: c2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D2(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c3=int64#14 -# asm 2: mov $0,>c3=%rbx -mov $0,%rbx - -# qhasm: c3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D3(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq mulx1=%r12 -movq 64(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D0 -# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D0(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D1(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D2(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D3(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq mulx2=%r12 -movq 72(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D0 -# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D0(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D1(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D2(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D3(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq mulx3=%r12 -movq 80(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D0 -# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D0(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D1(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D2(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=%rax -movq crypto_sign_ed25519_amd64_64_EC2D3(%rip),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? c0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: c0 += mulzero -# asm 1: add c0_stack=stack64#8 -# asm 2: movq c0_stack=56(%rsp) -movq %r13,56(%rsp) - -# qhasm: c1_stack = c1 -# asm 1: movq c1_stack=stack64#9 -# asm 2: movq c1_stack=64(%rsp) -movq %r14,64(%rsp) - -# qhasm: c2_stack = c2 -# asm 1: movq c2_stack=stack64#10 -# asm 2: movq c2_stack=72(%rsp) -movq %r15,72(%rsp) - -# qhasm: c3_stack = c3 -# asm 1: movq c3_stack=stack64#11 -# asm 2: movq c3_stack=80(%rsp) -movq %rbx,80(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = *(uint64 *)(pp + 64) -# asm 1: movq 64(mulx0=int64#10 -# asm 2: movq 64(mulx0=%r12 -movq 64(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt0=int64#11 -# asm 2: mov rt0=%r13 -mov %rax,%r13 - -# qhasm: rt1 = mulrdx -# asm 1: mov rt1=int64#12 -# asm 2: mov rt1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 72) -# asm 1: movq 72(mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt2=int64#13 -# asm 2: mov $0,>rt2=%r15 -mov $0,%r15 - -# qhasm: rt2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt3=int64#14 -# asm 2: mov $0,>rt3=%rbx -mov $0,%rbx - -# qhasm: rt3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq 72(mulx1=%r12 -movq 72(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq 80(mulx2=%r12 -movq 80(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#2 -# asm 2: movq 88(mulx3=%rsi -movq 88(%rsi),%rsi - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? rt0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: rt0 += mulzero -# asm 1: add addt0=int64#2 -# asm 2: mov $0,>addt0=%rsi -mov $0,%rsi - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#3 -# asm 2: mov $38,>addt1=%rdx -mov $38,%rdx - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae rz0=int64#2 -# asm 2: mov rz0=%rsi -mov %r13,%rsi - -# qhasm: rz1 = rt1 -# asm 1: mov rz1=int64#3 -# asm 2: mov rz1=%rdx -mov %r14,%rdx - -# qhasm: rz2 = rt2 -# asm 1: mov rz2=int64#4 -# asm 2: mov rz2=%rcx -mov %r15,%rcx - -# qhasm: rz3 = rt3 -# asm 1: mov rz3=int64#5 -# asm 2: mov rz3=%r8 -mov %rbx,%r8 - -# qhasm: carry? rz0 += c0_stack -# asm 1: addq addt0=int64#6 -# asm 2: mov $0,>addt0=%r9 -mov $0,%r9 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#7 -# asm 2: mov $38,>addt1=%rax -mov $38,%rax - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae subt0=int64#6 -# asm 2: mov $0,>subt0=%r9 -mov $0,%r9 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#7 -# asm 2: mov $38,>subt1=%rax -mov $38,%rax - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/ge25519_base.c b/ext/ed25519-amd64-asm/ge25519_base.c deleted file mode 100644 index a7ae97864..000000000 --- a/ext/ed25519-amd64-asm/ge25519_base.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "ge25519.h" - -const ge25519 ge25519_base = {{{0xC9562D608F25D51A, 0x692CC7609525A7B2, 0xC0A4E231FDD6DC5C, 0x216936D3CD6E53FE}}, - {{0x6666666666666658, 0x6666666666666666, 0x6666666666666666, 0x6666666666666666}}, - {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 000000000000000000}}, - {{0x6DDE8AB3A5B7DDA3, 0x20F09F80775152F5, 0x66EA4E8E64ABE37D, 0x67875F0FD78B7665}}}; - diff --git a/ext/ed25519-amd64-asm/ge25519_base_niels.data b/ext/ed25519-amd64-asm/ge25519_base_niels.data deleted file mode 100644 index 8e3300cf4..000000000 --- a/ext/ed25519-amd64-asm/ge25519_base_niels.data +++ /dev/null @@ -1,1536 +0,0 @@ -{{{0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267}}, - {{0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65}}, - {{0xdbbd15674b6fbb59, 0x41e13f00eea2a5ea, 0xcdd49d1cc957c6fa, 0x4f0ebe1faf16ecca}}}, -{{{0x8a99a56042b4d5a8, 0x8f2b810c4e60acf6, 0xe09e236bb16e37aa, 0x6bb595a669c92555}}, - {{0x9224e7fc933c71d7, 0x9f469d967a0ff5b5, 0x5aa69a65e1d60702, 0x590c063fa87d2e2e}}, - {{0x6e347eaadad36802, 0xbaf3599383ee4805, 0x3bcabe10e6076826, 0x49314f0a165ed1b8}}}, -{{{0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62}}, - {{0xaf25b0a84cee9730, 0x025a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4}}, - {{0x9bf211f4f1674834, 0xb84e6b17f62df895, 0xd7de6f075b722a4e, 0x549a04b963bb2a21}}}, -{{{0x95fe050a056818bf, 0x327e89715660faa9, 0xc3e8e3cd06a05073, 0x27933f4c7445a49a}}, - {{0x287351b98efc099f, 0x6765c6f47dfd2538, 0xca348d3dfb0a9265, 0x680e910321e58727}}, - {{0xbf1e45ece51426b0, 0xe32bc63d6dba0f94, 0xe42974d58cf852c0, 0x44f079b1b0e64c18}}}, -{{{0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3}}, - {{0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb}}, - {{0xc832a179e7d003b3, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98}}}, -{{{0x499806b67b7d8ca4, 0x575be28427d22739, 0xbb085ce7204553b9, 0x38b64c41ae417884}}, - {{0x3a0ceeeb77157131, 0x9b27158900c8af88, 0x8065b668da59a736, 0x51e57bb6a2cc38bd}}, - {{0x8f9dad91689de3a4, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f}}}, -{{{0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0}}, - {{0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e}}, - {{0x217a8aacab0fda36, 0xa528c6543d3549c8, 0x37d05b8b13ab7568, 0x233cef623a2cbc37}}}, -{{{0xe2a75dedf39234d9, 0x963d7680e1b558f9, 0x2c2741ac6e3c23fb, 0x3a9024a1320e01c3}}, - {{0x59b7596604dd3e8f, 0x6cb30377e288702c, 0xb1339c665ed9c323, 0x0915e76061bce52f}}, - {{0xdf7de835a834a37e, 0x8be19cda689857ea, 0x2c1185367167b326, 0x589eb3d9dbefd5c2}}}, -{{{0x7ec851ca553e2df3, 0xa71284cba64878b3, 0xe6b5e4193288d1e7, 0x4cf210ec5a9a8883}}, - {{0x322d04a52d9021f6, 0xb9c19f3375c6bf9c, 0x587a3a4342d20b09, 0x143b1cf8aa64fe61}}, - {{0x9f867c7d968acaab, 0x5f54258e27092729, 0xd0a7d34bea180975, 0x21b546a3374126e1}}}, -{{{0xa94ff858a2888343, 0xce0ed4565313ed3c, 0xf55c3dcfb5bf34fa, 0x0a653ca5c9eab371}}, - {{0x490a7a45d185218f, 0x9a15377846049335, 0x0060ea09cc31e1f6, 0x7e041577f86ee965}}, - {{0x66b2a496ce5b67f3, 0xff5492d8bd569796, 0x503cec294a592cd0, 0x566943650813acb2}}}, -{{{0xb818db0c26620798, 0x5d5c31d9606e354a, 0x0982fa4f00a8cdc7, 0x17e12bcd4653e2d4}}, - {{0x5672f9eb1dabb69d, 0xba70b535afe853fc, 0x47ac0f752796d66d, 0x32a5351794117275}}, - {{0xd3a644a6df648437, 0x703b6559880fbfdd, 0xcb852540ad3a1aa5, 0x0900b3f78e4c6468}}}, -{{{0x0a851b9f679d651b, 0xe108cb61033342f2, 0xd601f57fe88b30a3, 0x371f3acaed2dd714}}, - {{0xed280fbec816ad31, 0x52d9595bd8e6efe3, 0x0fe71772f6c623f5, 0x4314030b051e293c}}, - {{0xd560005efbf0bcad, 0x8eb70f2ed1870c5e, 0x201f9033d084e6a0, 0x4c3a5ae1ce7b6670}}}, -{{{0x4138a434dcb8fa95, 0x870cf67d6c96840b, 0xde388574297be82c, 0x7c814db27262a55a}}, - {{0xbaf875e4c93da0dd, 0xb93282a771b9294d, 0x80d63fb7f4c6c460, 0x6de9c73dea66c181}}, - {{0x478904d5a04df8f2, 0xfafbae4ab10142d3, 0xf6c8ac63555d0998, 0x5aac4a412f90b104}}}, -{{{0xc64f326b3ac92908, 0x5551b282e663e1e0, 0x476b35f54a1a4b83, 0x1b9da3fe189f68c2}}, - {{0x603a0d0abd7f5134, 0x8089c932e1d3ae46, 0xdf2591398798bd63, 0x1c145cd274ba0235}}, - {{0x32e8386475f3d743, 0x365b8baf6ae5d9ef, 0x825238b6385b681e, 0x234929c1167d65e1}}}, -{{{0x984decaba077ade8, 0x383f77ad19eb389d, 0xc7ec6b7e2954d794, 0x59c77b3aeb7c3a7a}}, - {{0x48145cc21d099fcf, 0x4535c192cc28d7e5, 0x80e7c1e548247e01, 0x4a5f28743b2973ee}}, - {{0xd3add725225ccf62, 0x911a3381b2152c5d, 0xd8b39fad5b08f87d, 0x6f05606b4799fe3b}}}, -{{{0x9ffe9e92177ba962, 0x98aee71d0de5cae1, 0x3ff4ae942d831044, 0x714de12e58533ac8}}, - {{0x5b433149f91b6483, 0xadb5dc655a2cbf62, 0x87fa8412632827b3, 0x60895e91ab49f8d8}}, - {{0xe9ecf2ed0cf86c18, 0xb46d06120735dfd4, 0xbc9da09804b96be7, 0x73e2e62fd96dc26b}}}, -{{{0xed5b635449aa515e, 0xa865c49f0bc6823a, 0x850c1fe95b42d1c4, 0x30d76d6f03d315b9}}, - {{0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39}}, - {{0x6c4444172106e4c7, 0xfb53d680928d7f69, 0xb4739ea4694d3f26, 0x10c697112e864bb0}}}, -{{{0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09}}, - {{0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef}}, - {{0x3f13e128cc586604, 0x6f5873ecb459747e, 0xa0b63dedcc1268f5, 0x566d78634586e22c}}}, -{{{0x1637a49f9cc10834, 0xbc8e56d5a89bc451, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9}}, - {{0xa1054285c65a2fd0, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a}}, - {{0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c}}}, -{{{0xff437b8497dd95c2, 0x6c744e30aa4eb5a7, 0x9e0c5d613c85e88b, 0x2fd9c71e5f758173}}, - {{0x21e70b2f4e71ecb8, 0xe656ddb940a477e3, 0xbf6556cece1d4f80, 0x05fc3bc4535d7b7e}}, - {{0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04}}}, -{{{0x2fba99fd40d1add9, 0xb307166f96f4d027, 0x4363f05215f03bae, 0x1fbea56c3b18f999}}, - {{0x634095cb14246590, 0xef12144016c15535, 0x9e38140c8910bc60, 0x6bf5905730907c8c}}, - {{0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56}}}, -{{{0x513fee0b0a9d5294, 0x8f98e75c0fdf5a66, 0xd4618688bfe107ce, 0x3fa00a7e71382ced}}, - {{0xb1146720772f5ee4, 0xe8f894b196079ace, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4}}, - {{0x3c69232d963ddb34, 0x1dde87dab4973858, 0xaad7d1f9a091f285, 0x12b5fe2fa048edb6}}}, -{{{0x71f0fbc496fce34d, 0x73b9826badf35bed, 0xd2047261ff28c561, 0x749b76f96fb1206f}}, - {{0xdf2b7c26ad6f1e92, 0x4b66d323504b8913, 0x8c409dc0751c8bc3, 0x6f7e93c20796c7b8}}, - {{0x1f5af604aea6ae05, 0xc12351f1bee49c99, 0x61a808b5eeff6b66, 0x0fcec10f01e02151}}}, -{{{0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3}}, - {{0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a}}, - {{0x08b1b7548c1af8f0, 0xce0f7a7c246299b4, 0xf760b0f91e06d939, 0x41bb887b726d1213}}}, -{{{0x9267806c567c49d8, 0x066d04ccca791e6a, 0xa69f5645e3cc394b, 0x5c95b686a0788cd2}}, - {{0x97d980e0aa39f7d2, 0x35d0384252c6b51c, 0x7d43f49307cd55aa, 0x56bd36cfb78ac362}}, - {{0x2ac519c10d14a954, 0xeaf474b494b5fa90, 0xe6af8382a9f87a5a, 0x0dea6db1879be094}}}, -{{{0xaa66bf547344e5ab, 0xda1258888f1b4309, 0x5e87d2b3fd564b2f, 0x5b2c78885483b1dd}}, - {{0x15baeb74d6a8797a, 0x7ef55cf1fac41732, 0x29001f5a3c8b05c5, 0x0ad7cc8752eaccfb}}, - {{0x52151362793408cf, 0xeb0f170319963d94, 0xa833b2fa883d9466, 0x093a7fa775003c78}}}, -{{{0xe5107de63a16d7be, 0xa377ffdc9af332cf, 0x70d5bf18440b677f, 0x6a252b19a4a31403}}, - {{0xb8e9604460a91286, 0x7f3fd8047778d3de, 0x67d01e31bf8a5e2d, 0x7b038a06c27b653e}}, - {{0x9ed919d5d36990f3, 0x5213aebbdb4eb9f2, 0xc708ea054cb99135, 0x58ded57f72260e56}}}, -{{{0x78e79dade9413d77, 0xf257f9d59729e67d, 0x59db910ee37aa7e6, 0x6aa11b5bbb9e039c}}, - {{0xda6d53265b0fd48b, 0x8960823193bfa988, 0xd78ac93261d57e28, 0x79f2942d3a5c8143}}, - {{0x97da2f25b6c88de9, 0x251ba7eaacf20169, 0x09b44f87ef4eb4e4, 0x7d90ab1bbc6a7da5}}}, -{{{0x9acca683a7016bfe, 0x90505f4df2c50b6d, 0x6b610d5fcce435aa, 0x19a10d446198ff96}}, - {{0x1a07a3f496b3c397, 0x11ceaa188f4e2532, 0x7d9498d5a7751bf0, 0x19ed161f508dd8a0}}, - {{0x560a2cd687dce6ca, 0x7f3568c48664cf4d, 0x8741e95222803a38, 0x483bdab1595653fc}}}, -{{{0xfa780f148734fa49, 0x106f0b70360534e0, 0x2210776fe3e307bd, 0x3286c109dde6a0fe}}, - {{0xd6cf4d0ab4da80f6, 0x82483e45f8307fe0, 0x05005269ae6f9da4, 0x1c7052909cf7877a}}, - {{0x32ee7de2874e98d4, 0x14c362e9b97e0c60, 0x5781dcde6a60a38a, 0x217dd5eaaa7aa840}}}, -{{{0x9db7c4d0248e1eb0, 0xe07697e14d74bf52, 0x1e6a9b173c562354, 0x7fa7c21f795a4965}}, - {{0x8bdf1fb9be8c0ec8, 0x00bae7f8e30a0282, 0x4963991dad6c4f6c, 0x07058a6e5df6f60a}}, - {{0xe9eb02c4db31f67f, 0xed25fd8910bcfb2b, 0x46c8131f5c5cddb4, 0x33b21c13a0cb9bce}}}, -{{{0x360692f8087d8e31, 0xf4dcc637d27163f7, 0x25a4e62065ea5963, 0x659bf72e5ac160d9}}, - {{0x9aafb9b05ee38c5b, 0xbf9d2d4e071a13c7, 0x8eee6e6de933290a, 0x1c3bab17ae109717}}, - {{0x1c9ab216c7cab7b0, 0x7d65d37407bbc3cc, 0x52744750504a58d5, 0x09f2606b131a2990}}}, -{{{0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7}}, - {{0x7e234c597c6691ae, 0x64889d3d0a85b4c8, 0xdae2c90c354afae7, 0x0a871e070c6a9e1d}}, - {{0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464}}}, -{{{0xf5d255e49e7dd6b7, 0x8016115c610b1eac, 0x3c99975d92e187ca, 0x13815762979125c2}}, - {{0x43fa7947841e7518, 0xe5c6fa59639c46d7, 0xa1065e1de3052b74, 0x7d47c6a2cfb89030}}, - {{0x3fdad0148ef0d6e0, 0x9d3e749a91546f3c, 0x71ec621026bb8157, 0x148cf58d34c9ec80}}}, -{{{0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4}}, - {{0xe2572f7d9ae4756d, 0x56c345bb88f3487f, 0x9fd10b6d6960a88d, 0x278febad4eaea1b9}}, - {{0xb1aa681f8c933966, 0x8c21949c20290c98, 0x39115291219d3c52, 0x4104dd02fe9c677b}}}, -{{{0x72b2bf5e1124422a, 0xa1fa0c3398a33ab5, 0x94cb6101fa52b666, 0x2c863b00afaf53d5}}, - {{0x81214e06db096ab8, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481}}, - {{0xf190a474a0846a76, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8}}}, -{{{0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb}}, - {{0x99b9b3719f18b55d, 0xe465e5faa18c641e, 0x61081136c29f05ed, 0x489b4f867030128b}}, - {{0xd232102d3aeb92ef, 0xe16253b46116a861, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf}}}, -{{{0x30949a108a5bcfd4, 0xdc40dd70bc6473eb, 0x92c294c1307c0d1c, 0x5604a86dcbfa6e74}}, - {{0x155d628c1e9c572e, 0x8a4d86acc5884741, 0x91a352f6515763eb, 0x06a1a6c28867515b}}, - {{0x7288d1d47c1764b6, 0x72541140e0418b51, 0x9f031a6018acf6d1, 0x20989e89fe2742c6}}}, -{{{0x499777fd3a2dcc7f, 0x32857c2ca54fd892, 0xa279d864d207e3a0, 0x0403ed1d0ca67e29}}, - {{0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3}}, - {{0xc94b2d35874ec552, 0xc5e6c8cf98246f8d, 0xf7cb46fa16c035ce, 0x5bd7454308303dcc}}}, -{{{0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83}}, - {{0x85c4932115e7792a, 0xc64c89a2bdcdddc9, 0x9d1e3da8ada3d762, 0x5bb7db123067f82c}}, - {{0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2}}}, -{{{0x50b70bf5d3f0af0b, 0x4feaf48ae32e71f7, 0x60e84ed3a55bbd34, 0x00ed489b3f50d1ed}}, - {{0x3906c72aed261ae5, 0x9ab68fd988e100f7, 0xf5e9059af3360197, 0x0e53dc78bf2b6d47}}, - {{0xb90829bf7971877a, 0x5e4444636d17e631, 0x4d05c52e18276893, 0x27632d9a5a4a4af5}}}, -{{{0xd11ff05154b260ce, 0xd86dc38e72f95270, 0x601fcd0d267cc138, 0x2b67916429e90ccd}}, - {{0xa98285d187eaffdb, 0xa5b4fbbbd8d0a864, 0xb658f27f022663f7, 0x3bbc2b22d99ce282}}, - {{0xb917c952583c0a58, 0x653ff9b80fe4c6f3, 0x9b0da7d7bcdf3c0c, 0x43a0eeb6ab54d60e}}}, -{{{0x396966a46d4a5487, 0xf811a18aac2bb3ba, 0x66e4685b5628b26b, 0x70a477029d929b92}}, - {{0x3ac6322357875fe8, 0xd9d4f4ecf5fbcb8f, 0x8dee8493382bb620, 0x50c5eaa14c799fdc}}, - {{0xdd0edc8bd6f2fb3c, 0x54c63aa79cc7b7a0, 0xae0b032b2c8d9f1a, 0x6f9ce107602967fb}}}, -{{{0xad1054b1cde1c22a, 0xc4a8e90248eb32df, 0x5f3e7b33accdc0ea, 0x72364713fc79963e}}, - {{0x139693063520e0b5, 0x437fcf7c88ea03fe, 0xf7d4c40bd3c959bc, 0x699154d1f893ded9}}, - {{0x315d5c75b4b27526, 0xcccb842d0236daa5, 0x22f0c8a3345fee8e, 0x73975a617d39dbed}}}, -{{{0xe4024df96375da10, 0x78d3251a1830c870, 0x902b1948658cd91c, 0x7e18b10b29b7438a}}, - {{0x6f37f392f4433e46, 0x0e19b9a11f566b18, 0x220fb78a1fd1d662, 0x362a4258a381c94d}}, - {{0x9071d9132b6beb2f, 0x0f26e9ad28418247, 0xeab91ec9bdec925d, 0x4be65bc8f48af2de}}}, -{{{0x78487feba36e7028, 0x5f3f13001dd8ce34, 0x934fb12d4b30c489, 0x056c244d397f0a2b}}, - {{0x1d50fba257c26234, 0x7bd4823adeb0678b, 0xc2b0dc6ea6538af5, 0x5665eec6351da73e}}, - {{0xdb3ee00943bfb210, 0x4972018720800ac2, 0x26ab5d6173bd8667, 0x20b209c2ab204938}}}, -{{{0x549e342ac07fb34b, 0x02d8220821373d93, 0xbc262d70acd1f567, 0x7a92c9fdfbcac784}}, - {{0x1fcca94516bd3289, 0x448d65aa41420428, 0x59c3b7b216a55d62, 0x49992cc64e612cd8}}, - {{0x65bd1bea70f801de, 0x1befb7c0fe49e28a, 0xa86306cdb1b2ae4a, 0x3b7ac0cd265c2a09}}}, -{{{0x822bee438c01bcec, 0x530cb525c0fbc73b, 0x48519034c1953fe9, 0x265cc261e09a0f5b}}, - {{0xf0d54e4f22ed39a7, 0xa2aae91e5608150a, 0xf421b2e9eddae875, 0x31bc531d6b7de992}}, - {{0xdf3d134da980f971, 0x7a4fb8d1221a22a7, 0x3df7d42035aad6d8, 0x2a14edcc6a1a125e}}}, -{{{0xdf48ee0752cfce4e, 0xc3fffaf306ec08b7, 0x05710b2ab95459c4, 0x161d25fa963ea38d}}, - {{0x231a8c570478433c, 0xb7b5270ec281439d, 0xdbaa99eae3d9079f, 0x2c03f5256c2b03d9}}, - {{0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf}}}, -{{{0xbd1f2f46f4dafecf, 0x7cef0114a47fd6f7, 0xd31ffdda4a47b37f, 0x525219a473905785}}, - {{0xd8dd3de66aa91948, 0x485064c22fc0d2cc, 0x9b48246634fdea2f, 0x293e1c4e6c4a2e3a}}, - {{0x376e134b925112e1, 0x703778b5dca15da0, 0xb04589af461c3111, 0x5b605c447f032823}}}, -{{{0xb965805920c47c89, 0xe7f0100c923b8fcc, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee}}, - {{0x3be9fec6f0e7f04c, 0x866a579e75e34962, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5}}, - {{0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, 0xc6cf144178cff668, 0x5e607b2518a43790}}}, -{{{0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, 0xe1b3ff4f66e61d6e, 0x5067acab6ccdd5f7}}, - {{0xa02c431ca596cf14, 0xe3c42d40aed3e400, 0xd24526802e0f26db, 0x201f33139e457068}}, - {{0xfd527f6b08039d51, 0x18b14964017c0006, 0xd5220eb02e25a4a8, 0x397cba8862460375}}}, -{{{0x30c13093f05959b2, 0xe23aa18de9a97976, 0x222fd491721d5e26, 0x2339d320766e6c3a}}, - {{0x7815c3fbc81379e7, 0xa6619420dde12af1, 0xffa9c0f885a8fdd5, 0x771b4022c1e1c252}}, - {{0xd87dd986513a2fa7, 0xf5ac9b71f9d4cf08, 0xd06bc31b1ea283b3, 0x331a189219971a76}}}, -{{{0xf5166f45fb4f80c6, 0x9c36c7de61c775cf, 0xe3d4e81b9041d91c, 0x31167c6b83bdfe21}}, - {{0x26512f3a9d7572af, 0x5bcbe28868074a9e, 0x84edc1c11180f7c4, 0x1ac9619ff649a67b}}, - {{0xf22b3842524b1068, 0x5068343bee9ce987, 0xfc9d71844a6250c8, 0x612436341f08b111}}}, -{{{0xd99d41db874e898d, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40}}, - {{0x8b6349e31a2d2638, 0x9ddfb7009bd3fd35, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445}}, - {{0x2c382f5369614938, 0xdafe409ab72d6d10, 0xe8c83391b646f227, 0x45fe70f50524306c}}}, -{{{0xda4875a6960c0b8c, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4}}, - {{0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245}}, - {{0x084f4a4401a308fd, 0xa82219c376a5caac, 0xdeb8de4643d1bc7d, 0x1d81592d60bd38c6}}}, -{{{0xd833d7beec2a4c38, 0x2c9162830acc20ed, 0xe93a47aa92df7581, 0x702d67a3333c4a81}}, - {{0x3a4a369a2f89c8a1, 0x63137a1d7c8de80d, 0xbcac008a78eda015, 0x2cb8b3a5b483b03f}}, - {{0x36e417cbcb1b90a1, 0x33b3ddaa7f11794e, 0x3f510808885bc607, 0x24141dc0e6a8020d}}}, -{{{0x59f73c773fefee9d, 0xb3f1ef89c1cf989d, 0xe35dfb42e02e545f, 0x5766120b47a1b47c}}, - {{0x91925dccbd83157d, 0x3ca1205322cc8094, 0x28e57f183f90d6e4, 0x1a4714cede2e767b}}, - {{0xdb20ba0fb8b6b7ff, 0xb732c3b677511fa1, 0xa92b51c099f02d89, 0x4f3875ad489ca5f1}}}, -{{{0xc7fc762f4932ab22, 0x7ac0edf72f4c3c1b, 0x5f6b55aa9aa895e8, 0x3680274dad0a0081}}, - {{0x79ed13f6ee73eec0, 0xa5c6526d69110bb1, 0xe48928c38603860c, 0x722a1446fd7059f5}}, - {{0xd0959fe9a8cf8819, 0xd0a995508475a99c, 0x6eac173320b09cc5, 0x628ecf04331b1095}}}, -{{{0x98bcb118a9d0ddbc, 0xee449e3408b4802b, 0x87089226b8a6b104, 0x685f349a45c7915d}}, - {{0x9b41acf85c74ccf1, 0xb673318108265251, 0x99c92aed11adb147, 0x7a47d70d34ecb40f}}, - {{0x60a0c4cbcc43a4f5, 0x775c66ca3677bea9, 0xa17aa1752ff8f5ed, 0x11ded9020e01fdc0}}}, -{{{0x890e7809caefe704, 0x8728296de30e8c6c, 0x4c5cd2a392aeb1c9, 0x194263d15771531f}}, - {{0x471f95b03bea93b7, 0x0552d7d43313abd3, 0xbd9370e2e17e3f7b, 0x7b120f1db20e5bec}}, - {{0x17d2fb3d86502d7a, 0xb564d84450a69352, 0x7da962c8a60ed75d, 0x00d0f85b318736aa}}}, -{{{0x978b142e777c84fd, 0xf402644705a8c062, 0xa67ad51be7e612c7, 0x2f7b459698dd6a33}}, - {{0xa6753c1efd7621c1, 0x69c0b4a7445671f5, 0x971f527405b23c11, 0x387bc74851a8c7cd}}, - {{0x81894b4d4a52a9a8, 0xadd93e12f6b8832f, 0x184d8548b61bd638, 0x3f1c62dbd6c9f6cd}}}, -{{{0x2e8f1f0091910c1f, 0xa4df4fe0bff2e12c, 0x60c6560aee927438, 0x6338283facefc8fa}}, - {{0x3fad3e40148f693d, 0x052656e194eb9a72, 0x2f4dcbfd184f4e2f, 0x406f8db1c482e18b}}, - {{0x9e630d2c7f191ee4, 0x4fbf8301bc3ff670, 0x787d8e4e7afb73c4, 0x50d83d5be8f58fa5}}}, -{{{0x85683916c11a1897, 0x2d69a4efe506d008, 0x39af1378f664bd01, 0x65942131361517c6}}, - {{0xc0accf90b4d3b66d, 0xa7059de561732e60, 0x033d1f7870c6b0ba, 0x584161cd26d946e4}}, - {{0xbbf2b1a072d27ca2, 0xbf393c59fbdec704, 0xe98dbbcee262b81e, 0x02eebd0b3029b589}}}, -{{{0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0}}, - {{0x8765b69f7b85c5e8, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c}}, - {{0x76d20db67178b252, 0x071c34f9d51ed160, 0xf62a4a20b3e41170, 0x7cd682353cffe366}}}, -{{{0x0be1a45bd887fab6, 0x2a846a32ba403b6e, 0xd9921012e96e6000, 0x2838c8863bdc0943}}, - {{0xa665cd6068acf4f3, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff}}, - {{0xd16bb0cf4a465030, 0xfa496b4115c577ab, 0x82cfae8af4ab419d, 0x21dcb8a606a82812}}}, -{{{0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab}}, - {{0x9a8d00fabe7731ba, 0x8203607e629e1889, 0xb2cc023743f3d97f, 0x5d840dbf6c6f678b}}, - {{0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd}}}, -{{{0x4b42432c8a7084fa, 0x898a19e3dfb9e545, 0xbe9f00219c58e45d, 0x1ff177cea16debd1}}, - {{0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, 0x80acffc075aa15fe, 0x0770c9e824e1a9f9}}, - {{0xcf61d99a45b5b5fd, 0x860984e91b3a7924, 0xe7300919303e3e89, 0x39f264fd41500b1e}}}, -{{{0xa7ad3417dbe7e29c, 0xbd94376a2b9c139c, 0xa0e91b8e93597ba9, 0x1712d73468889840}}, - {{0xd19b4aabfe097be1, 0xa46dfce1dfe01929, 0xc3c908942ca6f1ff, 0x65c621272c35f14e}}, - {{0xe72b89f8ce3193dd, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272}}}, -{{{0x605a368a3e9ef8cb, 0xe3e9c022a5504715, 0x553d48b05f24248f, 0x13f416cd647626e5}}, - {{0x42029fdd9a6efdac, 0xb912cebe34a54941, 0x640f64b987bdf37b, 0x4171a4d38598cab4}}, - {{0xfa2758aa99c94c8c, 0x23006f6fb000b807, 0xfbd291ddadda5392, 0x508214fa574bd1ab}}}, -{{{0xc20269153ed6fe4b, 0xa65a6739511d77c4, 0xcbde26462c14af94, 0x22f960ec6faba74b}}, - {{0x461a15bb53d003d6, 0xb2102888bcf3c965, 0x27c576756c683a5a, 0x3a7758a4c86cb447}}, - {{0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494}}}, -{{{0x031408d36d63727f, 0x6a379aefd7c7b533, 0xa9e18fc5ccaee24b, 0x332f35914f8fbed3}}, - {{0x3f244d2aeed7521e, 0x8e3a9028432e9615, 0xe164ba772e9c16d4, 0x3bc187fa47eb98d8}}, - {{0x6d470115ea86c20c, 0x998ab7cb6c46d125, 0xd77832b53a660188, 0x450d81ce906fba03}}}, -{{{0xf8ae4d2ad8453902, 0x7018058ee8db2d1d, 0xaab3995fc7d2c11e, 0x53b16d2324ccca79}}, - {{0x23264d66b2cae0b5, 0x7dbaed33ebca6576, 0x030ebed6f0d24ac8, 0x2a887f78f7635510}}, - {{0x2a23b9e75c012d4f, 0x0c974651cae1f2ea, 0x2fb63273675d70ca, 0x0ba7250b864403f5}}}, -{{{0xbb0d18fd029c6421, 0xbc2d142189298f02, 0x8347f8e68b250e96, 0x7b9f2fe8032d71c9}}, - {{0xdd63589386f86d9c, 0x61699176e13a85a4, 0x2e5111954eaa7d57, 0x32c21b57fb60bdfb}}, - {{0xd87823cd319e0780, 0xefc4cfc1897775c5, 0x4854fb129a0ab3f7, 0x12c49d417238c371}}}, -{{{0x0950b533ffe83769, 0x21861c1d8e1d6bd1, 0xf022d8381302e510, 0x2509200c6391cab4}}, - {{0x09b3a01783799542, 0x626dd08faad5ee3f, 0xba00bceeeb70149f, 0x1421b246a0a444c9}}, - {{0x4aa43a8e8c24a7c7, 0x04c1f540d8f05ef5, 0xadba5e0c0b3eb9dc, 0x2ab5504448a49ce3}}}, -{{{0x2ed227266f0f5dec, 0x9824ee415ed50824, 0x807bec7c9468d415, 0x7093bae1b521e23f}}, - {{0xdc07ac631c5d3afa, 0x58615171f9df8c6c, 0x72a079d89d73e2b0, 0x7301f4ceb4eae15d}}, - {{0x6409e759d6722c41, 0xa674e1cf72bf729b, 0xbc0a24eb3c21e569, 0x390167d24ebacb23}}}, -{{{0x27f58e3bba353f1c, 0x4c47764dbf6a4361, 0xafbbc4e56e562650, 0x07db2ee6aae1a45d}}, - {{0xd7bb054ba2f2120b, 0xe2b9ceaeb10589b7, 0x3fe8bac8f3c0edbe, 0x4cbd40767112cb69}}, - {{0x0b603cc029c58176, 0x5988e3825cb15d61, 0x2bb61413dcf0ad8d, 0x7b8eec6c74183287}}}, -{{{0xe4ca40782cd27cb0, 0xdaf9c323fbe967bd, 0xb29bd34a8ad41e9e, 0x72810497626ede4d}}, - {{0x32fee570fc386b73, 0xda8b0141da3a8cc7, 0x975ffd0ac8968359, 0x6ee809a1b132a855}}, - {{0x9444bb31fcfd863a, 0x2fe3690a3e4e48c5, 0xdc29c867d088fa25, 0x13bd1e38d173292e}}}, -{{{0xd32b4cd8696149b5, 0xe55937d781d8aab7, 0x0bcb2127ae122b94, 0x41e86fcfb14099b0}}, - {{0x223fb5cf1dfac521, 0x325c25316f554450, 0x030b98d7659177ac, 0x1ed018b64f88a4bd}}, - {{0x3630dfa1b802a6b0, 0x880f874742ad3bd5, 0x0af90d6ceec5a4d4, 0x746a247a37cdc5d9}}}, -{{{0xd531b8bd2b7b9af6, 0x5005093537fc5b51, 0x232fcf25c593546d, 0x20a365142bb40f49}}, - {{0x6eccd85278d941ed, 0x2254ae83d22f7843, 0xc522d02e7bbfcdb7, 0x681e3351bff0e4e2}}, - {{0x8b64b59d83034f45, 0x2f8b71f21fa20efb, 0x69249495ba6550e4, 0x539ef98e45d5472b}}}, -{{{0x6e7bb6a1a6205275, 0xaa4f21d7413c8e83, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1}}, - {{0xd074d8961cae743f, 0xf86d18f5ee1c63ed, 0x97bdc55be7f4ed29, 0x4cbad279663ab108}}, - {{0x80d19024a0d71fcd, 0xc525c20afb288af8, 0xb1a3974b5f3a6419, 0x7d7fbcefe2007233}}}, -{{{0xfaef1e6a266b2801, 0x866c68c4d5739f16, 0xf68a2fbc1b03762c, 0x5975435e87b75a8d}}, - {{0xcd7c5dc5f3c29094, 0xc781a29a2a9105ab, 0x80c61d36421c3058, 0x4f9cd196dcd8d4d7}}, - {{0x199297d86a7b3768, 0xd0d058241ad17a63, 0xba029cad5c1c0c17, 0x7ccdd084387a0307}}}, -{{{0xdca6422c6d260417, 0xae153d50948240bd, 0xa9c0c1b4fb68c677, 0x428bd0ed61d0cf53}}, - {{0x9b0c84186760cc93, 0xcdae007a1ab32a99, 0xa88dec86620bda18, 0x3593ca848190ca44}}, - {{0x9213189a5e849aa7, 0xd4d8c33565d8facd, 0x8c52545b53fdbbd1, 0x27398308da2d63e6}}}, -{{{0x42c38d28435ed413, 0xbd50f3603278ccc9, 0xbb07ab1a79da03ef, 0x269597aebe8c3355}}, - {{0xb9a10e4c0a702453, 0x0fa25866d57d1bde, 0xffb9d9b5cd27daf7, 0x572c2945492c33fd}}, - {{0xc77fc745d6cd30be, 0xe4dfe8d3e3baaefb, 0xa22c8830aa5dda0c, 0x7f985498c05bca80}}}, -{{{0x3849ce889f0be117, 0x8005ad1b7b54a288, 0x3da3c39f23fc921c, 0x76c2ec470a31f304}}, - {{0xd35615520fbf6363, 0x08045a45cf4dfba6, 0xeec24fbc873fa0c2, 0x30f2653cd69b12e7}}, - {{0x8a08c938aac10c85, 0x46179b60db276bcb, 0xa920c01e0e6fac70, 0x2f1273f1596473da}}}, -{{{0x4739fc7c8ae01e11, 0xfd5274904a6aab9f, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2}}, - {{0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, 0xead1a69ebc596162, 0x38ac1997edc5f784}}, - {{0x0666b517a751b13b, 0x747d06867e9b858c, 0xacacc011454dde49, 0x22dfcd9cbfe9e69c}}}, -{{{0x8ddbd2e0c30d0cd9, 0xad8e665facbb4333, 0x8f6b258c322a961f, 0x6b2916c05448c1c7}}, - {{0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472}}, - {{0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17}}}, -{{{0xd30a3bd617b28c85, 0xc5d377b739773bea, 0xc6c6e78c1e6a5cbf, 0x0d61b8f78b2ab7c4}}, - {{0x29fc03580dd94500, 0xecd27aa46fbbec93, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5}}, - {{0x56a8d7efe9c136b0, 0xbd07e5cd58e44b20, 0xafe62fda1b57e0ab, 0x191a2af74277e8d2}}}, -{{{0xd550095bab6f4985, 0x04f4cd5b4fbfaf1a, 0x9d8e2ed12a0c7540, 0x2bc24e04b2212286}}, - {{0x09d4b60b2fe09a14, 0xc384f0afdbb1747e, 0x58e2ea8978b5fd6e, 0x519ef577b5e09b0a}}, - {{0x1863d7d91124cca9, 0x7ac08145b88a708e, 0x2bcd7309857031f5, 0x62337a6e8ab8fae5}}}, -{{{0x4bcef17f06ffca16, 0xde06e1db692ae16a, 0x0753702d614f42b0, 0x5f6041b45b9212d0}}, - {{0xd1ab324e1b3a1273, 0x18947cf181055340, 0x3b5d9567a98c196e, 0x7fa00425802e1e68}}, - {{0x7d531574028c2705, 0x80317d69db0d75fe, 0x30fface8ef8c8ddd, 0x7e9de97bb6c3e998}}}, -{{{0x1558967b9e6585a3, 0x97c99ce098e98b92, 0x10af149b6eb3adad, 0x42181fe8f4d38cfa}}, - {{0xf004be62a24d40dd, 0xba0659910452d41f, 0x81c45ee162a44234, 0x4cb829d8a22266ef}}, - {{0x1dbcaa8407b86681, 0x081f001e8b26753b, 0x3cd7ce6a84048e81, 0x78af11633f25f22c}}}, -{{{0x8416ebd40b50babc, 0x1508722628208bee, 0xa3148fafb9c1c36d, 0x0d07daacd32d7d5d}}, - {{0x3241c00e7d65318c, 0xe6bee5dcd0e86de7, 0x118b2dc2fbc08c26, 0x680d04a7fc603dc3}}, - {{0xf9c2414a695aa3eb, 0xdaa42c4c05a68f21, 0x7c6c23987f93963e, 0x210e8cd30c3954e3}}}, -{{{0xac4201f210a71c06, 0x6a65e0aef3bfb021, 0xbc42c35c393632f7, 0x56ea8db1865f0742}}, - {{0x2b50f16137fe6c26, 0xe102bcd856e404d8, 0x12b0f1414c561f6b, 0x51b17bc8d028ec91}}, - {{0xfff5fb4bcf535119, 0xf4989d79df1108a0, 0xbdfcea659a3ba325, 0x18a11f1174d1a6f2}}}, -{{{0x407375ab3f6bba29, 0x9ec3b6d8991e482e, 0x99c80e82e55f92e9, 0x307c13b6fb0c0ae1}}, - {{0xfbd63cdad27a5f2c, 0xf00fc4bc8aa106d7, 0x53fb5c1a8e64a430, 0x04eaabe50c1a2e85}}, - {{0x24751021cb8ab5e7, 0xfc2344495c5010eb, 0x5f1e717b4e5610a1, 0x44da5f18c2710cd5}}}, -{{{0x033cc55ff1b82eb5, 0xb15ae36d411cae52, 0xba40b6198ffbacd3, 0x768edce1532e861f}}, - {{0x9156fe6b89d8eacc, 0xe6b79451e23126a1, 0xbd7463d93944eb4e, 0x726373f6767203ae}}, - {{0xe305ca72eb7ef68a, 0x662cf31f70eadb23, 0x18f026fdb4c45b68, 0x513b5384b5d2ecbd}}}, -{{{0x46d46280c729989e, 0x4b93fbd05368a5dd, 0x63df3f81d1765a89, 0x34cebd64b9a0a223}}, - {{0x5e2702878af34ceb, 0x900b0409b946d6ae, 0x6512ebf7dabd8512, 0x61d9b76988258f81}}, - {{0xa6c5a71349b7d94b, 0xa3f3d15823eb9446, 0x0416fbd277484834, 0x69d45e6f2c70812f}}}, -{{{0xce16f74bc53c1431, 0x2b9725ce2072edde, 0xb8b9c36fb5b23ee7, 0x7e2e0e450b5cc908}}, - {{0x9fe62b434f460efb, 0xded303d4a63607d6, 0xf052210eb7a0da24, 0x237e7dbe00545b93}}, - {{0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3}}}, -{{{0x65ce6f9b3953b61d, 0xc65839eaafa141e6, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e}}, - {{0xea423c1c473b50d6, 0x51e87a1f3b38ef10, 0x9b84bf5fb2c9be95, 0x00731fbc78f89a1c}}, - {{0xe430c71848f81880, 0xbf960c225ecec119, 0xb6dae0836bba15e3, 0x4c4d6f3347e15808}}}, -{{{0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, 0xdbde712bf7ee0cdf, 0x193fddaaa7e47a22}}, - {{0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8}}, - {{0x1fd2c93c37e8876f, 0xa2f61e5a18d1462c, 0x5080f58239241276, 0x6a6fb99ebf0d4969}}}, -{{{0x6a46c1bb560855eb, 0x2416bb38f893f09d, 0xd71d11378f71acc1, 0x75f76914a31896ea}}, - {{0xeeb122b5b6e423c6, 0x939d7010f286ff8e, 0x90a92a831dcf5d8c, 0x136fda9f42c5eb10}}, - {{0xf94cdfb1a305bdd1, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba}}}, -{{{0x4af766385ead2d14, 0xa08ed880ca7c5830, 0x0d13a6e610211e3d, 0x6a071ce17b806c03}}, - {{0x9d5a710143307a7f, 0xb063de9ec47da45f, 0x22bbfe52be927ad3, 0x1387c441fd40426c}}, - {{0xb5d3c3d187978af8, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92}}}, -{{{0xa92f319097564ca8, 0xff7bb84c2275e119, 0x4f55fe37a4875150, 0x221fd4873cf0835a}}, - {{0xa60db7d8b28a47d1, 0xa6bf14d61770a4f1, 0xd4a1f89353ddbd58, 0x6c514a63344243e9}}, - {{0x2322204f3a156341, 0xfb73e0e9ba0a032d, 0xfce0dd4c410f030e, 0x48daa596fb924aaa}}}, -{{{0x6eca8e665ca59cc7, 0xa847254b2e38aca0, 0x31afc708d21e17ce, 0x676dd6fccad84af7}}, - {{0x14f61d5dc84c9793, 0x9941f9e3ef418206, 0xcdf5b88f346277ac, 0x58c837fa0e8a79a9}}, - {{0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, 0xdcc2e77d4935d66a, 0x1c4f73f2c6a57f0a}}}, -{{{0x0e7a4fbd305fa0bb, 0x829d4ce054c663ad, 0xf421c3832fe33848, 0x795ac80d1bf64c42}}, - {{0xb36e706efc7c3484, 0x73dfc9b4c3c1cf61, 0xeb1d79c9781cc7e5, 0x70459adb7daf675c}}, - {{0x1b91db4991b42bb3, 0x572696234b02dcca, 0x9fdf9ee51f8c78dc, 0x5fe162848ce21fd3}}}, -{{{0xe2790aae4d077c41, 0x8b938270db7469a3, 0x6eb632dc8abd16a2, 0x720814ecaa064b72}}, - {{0x315c29c795115389, 0xd7e0e507862f74ce, 0x0c4a762185927432, 0x72de6c984a25a1e4}}, - {{0xae9ab553bf6aa310, 0x050a50a9806d6e1b, 0x92bb7403adff5139, 0x0394d27645be618b}}}, -{{{0x4d572251857eedf4, 0xe3724edde19e93c5, 0x8a71420e0b797035, 0x3b3c833687abe743}}, - {{0xf5396425b23545a4, 0x15a7a27e98fbb296, 0xab6c52bc636fdd86, 0x79d995a8419334ee}}, - {{0xcd8a8ea61195dd75, 0xa504d8a81dd9a82f, 0x540dca81a35879b6, 0x60dd16a379c86a8a}}}, -{{{0x35a2c8487381e559, 0x596ffea6d78082cb, 0xcb9771ebdba7b653, 0x5a08b5019b4da685}}, - {{0x3501d6f8153e47b8, 0xb7a9675414a2f60c, 0x112ee8b6455d9523, 0x4e62a3c18112ea8a}}, - {{0xc8d4ac04516ab786, 0x595af3215295b23d, 0xd6edd234db0230c1, 0x0929efe8825b41cc}}}, -{{{0x5f0601d1cbd0f2d3, 0x736e412f6132bb7f, 0x83604432238dde87, 0x1e3a5272f5c0753c}}, - {{0x8b3172b7ad56651d, 0x01581b7a3fabd717, 0x2dc94df6424df6e4, 0x30376e5d2c29284f}}, - {{0xd2918da78159a59c, 0x6bdc1cd93f0713f3, 0x565f7a934acd6590, 0x53daacec4cb4c128}}}, -{{{0x4ca73bd79cc8a7d6, 0x4d4a738f47e9a9b2, 0xf4cbf12942f5fe00, 0x01a13ff9bdbf0752}}, - {{0x99852bc3852cfdb0, 0x2cc12e9559d6ed0b, 0x70f9e2bf9b5ac27b, 0x4f3b8c117959ae99}}, - {{0x55b6c9c82ff26412, 0x1ac4a8c91fb667a8, 0xd527bfcfeb778bf2, 0x303337da7012a3be}}}, -{{{0x955422228c1c9d7c, 0x01fac1371a9b340f, 0x7e8d9177925b48d7, 0x53f8ad5661b3e31b}}, - {{0x976d3ccbfad2fdd1, 0xcb88839737a640a8, 0x2ff00c1d6734cb25, 0x269ff4dc789c2d2b}}, - {{0x0c003fbdc08d678d, 0x4d982fa37ead2b17, 0xc07e6bcdb2e582f1, 0x296c7291df412a44}}}, -{{{0x7903de2b33daf397, 0xd0ff0619c9a624b3, 0x8a1d252b555b3e18, 0x2b6d581c52e0b7c0}}, - {{0xdfb23205dab8b59e, 0x465aeaa0c8092250, 0xd133c1189a725d18, 0x2327370261f117d1}}, - {{0x3d0543d3623e7986, 0x679414c2c278a354, 0xae43f0cc726196f6, 0x7836c41f8245eaba}}}, -{{{0xe7a254db49e95a81, 0x5192d5d008b0ad73, 0x4d20e5b1d00afc07, 0x5d55f8012cf25f38}}, - {{0xca651e848011937c, 0xc6b0c46e6ef41a28, 0xb7021ba75f3f8d52, 0x119dff99ead7b9fd}}, - {{0x43eadfcbf4b31d4d, 0xc6503f7411148892, 0xfeee68c5060d3b17, 0x329293b3dd4a0ac8}}}, -{{{0x4e59214fe194961a, 0x49be7dc70d71cd4f, 0x9300cfd23b50f22d, 0x4789d446fc917232}}, - {{0x2879852d5d7cb208, 0xb8dedd70687df2e7, 0xdc0bffab21687891, 0x2b44c043677daa35}}, - {{0x1a1c87ab074eb78e, 0xfac6d18e99daf467, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4}}}, -{{{0x0b5d89bc3bfd8bf1, 0xb06b9237c9f3551a, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab}}, - {{0x702bc5c27cae6d11, 0x44c7699b54a48cab, 0xefbc4056ba492eb2, 0x70d77248d9b6676d}}, - {{0xaa8ae84b3ec2a05b, 0x98699ef4ed1781e0, 0x794513e4708e85d1, 0x63755bd3a976f413}}}, -{{{0xb55fa03e2ad10853, 0x356f75909ee63569, 0x9ff9f1fdbe69b890, 0x0d8cc1c48bc16f84}}, - {{0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56}}, - {{0x029402d36eb419a9, 0xf0b44e7e77b460a5, 0xcfa86230d43c4956, 0x70c2dd8a7ad166e7}}}, -{{{0x656194509f6fec0e, 0xee2e7ea946c6518d, 0x9733c1f367e09b5c, 0x2e0fac6363948495}}, - {{0x91d4967db8ed7e13, 0x74252f0ad776817a, 0xe40982e00d852564, 0x32b8613816a53ce5}}, - {{0x79e7f7bee448cd64, 0x6ac83a67087886d0, 0xf89fd4d9a0e4db2e, 0x4179215c735a4f41}}}, -{{{0x8c7094e7d7dced2a, 0x97fb8ac347d39c70, 0xe13be033a906d902, 0x700344a30cd99d76}}, - {{0xe4ae33b9286bcd34, 0xb7ef7eb6559dd6dc, 0x278b141fb3d38e1f, 0x31fa85662241c286}}, - {{0xaf826c422e3622f4, 0xc12029879833502d, 0x9bc1b7e12b389123, 0x24bb2312a9952489}}}, -{{{0xb1a8ed1732de67c3, 0x3cb49418461b4948, 0x8ebd434376cfbcd2, 0x0fee3e871e188008}}, - {{0x41f80c2af5f85c6b, 0x687284c304fa6794, 0x8945df99a3ba1bad, 0x0d1d2af9ffeb5d16}}, - {{0xa9da8aa132621edf, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76}}}, -{{{0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309}}, - {{0xc959c6c57887b6ad, 0x94e19ead5f90feba, 0x16e24e62a342f504, 0x164ed34b18161700}}, - {{0x487ed94c192fe69a, 0x61ae2cea3a911513, 0x877bf6d3b9a4de27, 0x78da0fc61073f3eb}}}, -{{{0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a}}, - {{0xa29f80f1680c3a94, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd}}, - {{0xdfc8468d19267cb8, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760}}}, -{{{0xcaf55ec27c59b23f, 0x99aeed3e154d04f2, 0x68441d72e14141f4, 0x140345133932a0a2}}, - {{0xd91430e0dc028c3c, 0x0eb955a85217c771, 0x4b09e1ed2c99a1fa, 0x42881af2bd6a743c}}, - {{0x7bfec69aab5cad3d, 0xc23e8cd34cb2cfad, 0x685dd14bfb37d6a2, 0x0ad6d64415677a18}}}, -{{{0x781a439e417becb5, 0x4ac5938cd10e0266, 0x5da385110692ac24, 0x11b065a2ade31233}}, - {{0x7914892847927e9f, 0x33dad6ef370aa877, 0x1f8f24fa11122703, 0x5265ac2f2adf9592}}, - {{0x405fdd309afcb346, 0xd9723d4428e63f54, 0x94c01df05f65aaae, 0x43e4dc3ae14c0809}}}, -{{{0xbc12c7f1a938a517, 0x473028ab3180b2e1, 0x3f78571efbcd254a, 0x74e534426ff6f90f}}, - {{0xea6f7ac3adc2c6a3, 0xd0e928f6e9717c94, 0xe2d379ead645eaf5, 0x46dd8785c51ffbbe}}, - {{0x709801be375c8898, 0x4b06dab5e3fd8348, 0x75880ced27230714, 0x2b09468fdd2f4c42}}}, -{{{0x97c749eeb701cb96, 0x83f438d4b6a369c3, 0x62962b8b9a402cd9, 0x6976c7509888df7b}}, - {{0x5b97946582ffa02a, 0xda096a51fea8f549, 0xa06351375f77af9b, 0x1bcfde61201d1e76}}, - {{0x4a4a5490246a59a2, 0xd63ebddee87fdd90, 0xd9437c670d2371fa, 0x69e87308d30f8ed6}}}, -{{{0x435a8bb15656beb0, 0xf8fac9ba4f4d5bca, 0xb9b278c41548c075, 0x3eb0ef76e892b622}}, - {{0x0f80bf028bc80303, 0x6aae16b37a18cefb, 0xdd47ea47d72cd6a3, 0x61943588f4ed39aa}}, - {{0xd26e5c3e91039f85, 0xc0e9e77df6f33aa9, 0xe8968c5570066a93, 0x3c34d1881faaaddd}}}, -{{{0x3f9d2b5ea09f9ec0, 0x1dab3b6fb623a890, 0xa09ba3ea72d926c4, 0x374193513fd8b36d}}, - {{0xbd5b0b8f2fffe0d9, 0x6aa254103ed24fb9, 0x2ac7d7bcb26821c4, 0x605b394b60dca36a}}, - {{0xb4e856e45a9d1ed2, 0xefe848766c97a9a2, 0xb104cf641e5eee7d, 0x2f50b81c88a71c8f}}}, -{{{0x31723c61fc6811bb, 0x9cb450486211800f, 0x768933d347995753, 0x3491a53502752fcd}}, - {{0x2b552ca0a7da522a, 0x3230b336449b0250, 0xf2c4c5bca4b99fb9, 0x7b2c674958074a22}}, - {{0xd55165883ed28cdf, 0x12d84fd2d362de39, 0x0a874ad3e3378e4f, 0x000d2b1f7c763e74}}}, -{{{0x3d420811d06d4a67, 0xbefc048590e0ffe3, 0xf870c6b7bd487bde, 0x6e2a7316319afa28}}, - {{0x9624778c3e94a8ab, 0x0ad6f3cee9a78bec, 0x948ac7810d743c4f, 0x76627935aaecfccc}}, - {{0x56a8ac24d6d59a9f, 0xc8db753e3096f006, 0x477f41e68f4c5299, 0x588d851cf6c86114}}}, -{{{0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650}}, - {{0xcd2a65e777d1f515, 0x548991878faa60f1, 0xb1b73bbcdabc06e5, 0x654878cba97cc9fb}}, - {{0x969ee405055ce6a1, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba}}}, -{{{0xdc4267b1834e2457, 0xb67544b570ce1bc5, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650}}, - {{0xfec7bc0c9b056f85, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9}}, - {{0xc32d36360415171e, 0xcd2bef118998483b, 0x870a6eadd0945110, 0x0bccbb72a2a86561}}}, -{{{0x185e962feab1a9c8, 0x86e7e63565147dcd, 0xb092e031bb5b6df2, 0x4024f0ab59d6b73e}}, - {{0x186d5e4c50fe1296, 0xe0397b82fee89f7e, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2}}, - {{0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701}}}, -{{{0x97f5131594dfd29b, 0x6155985d313f4c6a, 0xeba13f0708455010, 0x676b2608b8d2d322}}, - {{0x21717b0d0f537593, 0x914e690b131e064c, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e}}, - {{0x8138ba651c5b2b47, 0x8671b6ec311b1b80, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0}}}, -{{{0xbf525a1e2bc9c8bd, 0xea5b260826479d81, 0xd511c70edf0155db, 0x1ae23ceb960cf5d0}}, - {{0x6036df5721d34e6a, 0xb1db8827997bb3d0, 0xd3c209c3c8756afa, 0x06e15be54c1dc839}}, - {{0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7}}}, -{{{0xd8173793f266c55c, 0xc8c976c5cc454e49, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9}}, - {{0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8}}, - {{0x77ed3eeec3efc57a, 0x04e05517d4ff4811, 0xea3d7a3ff1a671cb, 0x120633b4947cfe54}}}, -{{{0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185}}, - {{0x82bd31474912100a, 0xde237b6d7e6fbe06, 0xe11e761911ea79c6, 0x07433be3cb393bde}}, - {{0xff7944c05ce997f4, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f}}}, -{{{0x157a316443373409, 0xfab8b7eef4aa81d9, 0xb093fee6f5a64806, 0x2e773654707fa7b6}}, - {{0xaa6202e14e5df981, 0xa20d59175015e1f5, 0x18a275d3bae21d6c, 0x0543618a01600253}}, - {{0x0deabdf4974c23c1, 0xaa6f0a259dce4693, 0x04202cb8a29aba2c, 0x4b1443362d07960d}}}, -{{{0x47b837f753242cec, 0x256dc48cc04212f2, 0xe222fbfbe1d928c5, 0x48ea295bad8a2c07}}, - {{0x299b1c3f57c5715e, 0x96cb929e6b686d90, 0x3004806447235ab3, 0x2c435c24a44d9fe1}}, - {{0x0607c97c80f8833f, 0x0e851578ca25ec5b, 0x54f7450b161ebb6f, 0x7bcb4792a0def80e}}}, -{{{0x8487e3d02bc73659, 0x4baf8445059979df, 0xd17c975adcad6fbf, 0x57369f0bdefc96b6}}, - {{0x1cecd0a0045224c2, 0x757f1b1b69e53952, 0x775b7a925289f681, 0x1b6cc62016736148}}, - {{0xf1a9990175638698, 0x353dd1beeeaa60d3, 0x849471334c9ba488, 0x63fa6e6843ade311}}}, -{{{0xd15c20536597c168, 0x9f73740098d28789, 0x18aee7f13257ba1f, 0x3418bfda07346f14}}, - {{0x2195becdd24b5eb7, 0x5e41f18cc0cd44f9, 0xdf28074441ca9ede, 0x07073b98f35b7d67}}, - {{0xd03c676c4ce530d4, 0x0b64c0473b5df9f4, 0x065cef8b19b3a31e, 0x3084d661533102c9}}}, -{{{0xe1f6b79ebf8469ad, 0x15801004e2663135, 0x9a498330af74181b, 0x3ba2504f049b673c}}, - {{0x9a6ce876760321fd, 0x7fe2b5109eb63ad8, 0x00e7d4ae8ac80592, 0x73d86b7abb6f723a}}, - {{0x0b52b5606dba5ab6, 0xa9134f0fbbb1edab, 0x30a9520d9b04a635, 0x6813b8f37973e5db}}}, -{{{0x9854b054334127c1, 0x105d047882fbff25, 0xdb49f7f944186f4f, 0x1768e838bed0b900}}, - {{0xf194ca56f3157e29, 0x136d35705ef528a5, 0xdd4cef778b0599bc, 0x7d5472af24f833ed}}, - {{0xd0ef874daf33da47, 0x00d3be5db6e339f9, 0x3f2a8a2f9c9ceece, 0x5d1aeb792352435a}}}, -{{{0xf59e6bb319cd63ca, 0x670c159221d06839, 0xb06d565b2150cab6, 0x20fb199d104f12a3}}, - {{0x12c7bfaeb61ba775, 0xb84e621fe263bffd, 0x0b47a5c35c840dcf, 0x7e83be0bccaf8634}}, - {{0x61943dee6d99c120, 0x86101f2e460b9fe0, 0x6bb2f1518ee8598d, 0x76b76289fcc475cc}}}, -{{{0x791b4cc1756286fa, 0xdbced317d74a157c, 0x7e732421ea72bde6, 0x01fe18491131c8e9}}, - {{0x4245f1a1522ec0b3, 0x558785b22a75656d, 0x1d485a2548a1b3c0, 0x60959eccd58fe09f}}, - {{0x3ebfeb7ba8ed7a09, 0x49fdc2bbe502789c, 0x44ebce5d3c119428, 0x35e1eb55be947f4a}}}, -{{{0xdbdae701c5738dd3, 0xf9c6f635b26f1bee, 0x61e96a8042f15ef4, 0x3aa1d11faf60a4d8}}, - {{0x14fd6dfa726ccc74, 0x3b084cfe2f53b965, 0xf33ae4f552a2c8b4, 0x59aab07a0d40166a}}, - {{0x77bcec4c925eac25, 0x1848718460137738, 0x5b374337fea9f451, 0x1865e78ec8e6aa46}}}, -{{{0xccc4b7c7b66e1f7a, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7}}, - {{0x967c54e91c529ccb, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c}}, - {{0xc6317bd320324ce4, 0xa81042e8a4488bc4, 0xb21ef18b4e5a1364, 0x0c2a1c4bcda28dc9}}}, -{{{0xd24dc7d06f1f0447, 0xb2269e3edb87c059, 0xd15b0272fbb2d28f, 0x7c558bd1c6f64877}}, - {{0xedc4814869bd6945, 0x0d6d907dbe1c8d22, 0xc63bd212d55cc5ab, 0x5a6a9b30a314dc83}}, - {{0xd0ec1524d396463d, 0x12bb628ac35a24f0, 0xa50c3a791cbc5fa4, 0x0404a5ca0afbafc3}}}, -{{{0x8c1f40070aa743d6, 0xccbad0cb5b265ee8, 0x574b046b668fd2de, 0x46395bfdcadd9633}}, - {{0x62bc9e1b2a416fd1, 0xb5c6f728e350598b, 0x04343fd83d5d6967, 0x39527516e7f8ee98}}, - {{0x117fdb2d1a5d9a9c, 0x9c7745bcd1005c2a, 0xefd4bef154d56fea, 0x76579a29e822d016}}}, -{{{0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1}}, - {{0x333cb51352b434f2, 0xd832284993de80e1, 0xb5512887750d35ce, 0x02c514bb2a2777c1}}, - {{0x684bd5da8bf1b645, 0xfb8bd37ef6b54b53, 0x313916d7a9b0d253, 0x1160920961548059}}}, -{{{0xb44d166929dacfaa, 0xda529f4c8413598f, 0xe9ef63ca453d5559, 0x351e125bc5698e0b}}, - {{0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042}}, - {{0xd4b49b461af67bbe, 0xd603037ac8ab8961, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a}}}, -{{{0x7a7c8e64ab0168ec, 0xcb5a4a5515edc543, 0x095519d347cd0eda, 0x67d4ac8c343e93b0}}, - {{0x09454b728e217522, 0xaa58e8f4d484b8d8, 0xd358254d7f46903c, 0x44acc043241c5217}}, - {{0x1c7d6bbb4f7a5777, 0x8b35fed4918313e1, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd}}}, -{{{0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff}}, - {{0x81f06756b11be821, 0x0faff82310a3f3dd, 0xf8b2d0556a99465d, 0x097abe38cc8c7f05}}, - {{0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd}}}, -{{{0xf0e268ac61a73b0a, 0xf2fafa103791a5f5, 0xc1e13e826b6d00e9, 0x60fa7ee96fd78f42}}, - {{0x94fecebebd4dd72b, 0xf46a4fda060f2211, 0x124a5977c0c8d1ff, 0x705304b8fb009295}}, - {{0xb63d1d354d296ec6, 0xf3c3053e5fad31d8, 0x670b958cb4bd42ec, 0x21398e0ca16353fd}}}, -{{{0x216ab2ca8da7d2ef, 0x366ad9dd99f42827, 0xae64b9004fdd3c75, 0x403a395b53909e62}}, - {{0x86c5fc16861b7e9a, 0xf6a330476a27c451, 0x01667267a1e93597, 0x05ffb9cd6082dfeb}}, - {{0xa617fa9ff53f6139, 0x60f2b5e513e66cb6, 0xd7a8beefb3448aa4, 0x7a2932856f5ea192}}}, -{{{0x0b39d761b02de888, 0x5f550e7ed2414e1f, 0xa6bfa45822e1a940, 0x050a2f7dfd447b99}}, - {{0xb89c444879639302, 0x4ae4f19350c67f2c, 0xf0b35da8c81af9c6, 0x39d0003546871017}}, - {{0x437c3b33a650db77, 0x6bafe81dbac52bb2, 0xfe99402d2db7d318, 0x2b5b7eec372ba6ce}}}, -{{{0xb3bc4bbd83f50eef, 0x508f0c998c927866, 0x43e76587c8b7e66e, 0x0f7655a3a47f98d9}}, - {{0xa694404d613ac8f4, 0x500c3c2bfa97e72c, 0x874104d21fcec210, 0x1b205fb38604a8ee}}, - {{0x55ecad37d24b133c, 0x441e147d6038c90b, 0x656683a1d62c6fee, 0x0157d5dc87e0ecae}}}, -{{{0xf2a7af510354c13d, 0xd7a0b145aa372b60, 0x2869b96a05a3d470, 0x6528e42d82460173}}, - {{0x95265514d71eb524, 0xe603d8815df14593, 0x147cdf410d4de6b7, 0x5293b1730437c850}}, - {{0x23d0e0814bccf226, 0x92c745cd8196fb93, 0x8b61796c59541e5b, 0x40a44df0c021f978}}}, -{{{0xdaa869894f20ea6a, 0xea14a3d14c620618, 0x6001fccb090bf8be, 0x35f4e822947e9cf0}}, - {{0x86c96e514bc5d095, 0xf20d4098fca6804a, 0x27363d89c826ea5d, 0x39ca36565719cacf}}, - {{0x97506f2f6f87b75c, 0xc624aea0034ae070, 0x1ec856e3aad34dd6, 0x055b0be0e440e58f}}}, -{{{0x6469a17d89735d12, 0xdb6f27d5e662b9f1, 0x9fcba3286a395681, 0x363b8004d269af25}}, - {{0x4d12a04b6ea33da2, 0x57cf4c15e36126dd, 0x90ec9675ee44d967, 0x64ca348d2a985aac}}, - {{0x99588e19e4c4912d, 0xefcc3b4e1ca5ce6b, 0x4522ea60fa5b98d5, 0x7064bbab1de4a819}}}, -{{{0xb919e1515a770641, 0xa9a2e2c74e7f8039, 0x7527250b3df23109, 0x756a7330ac27b78b}}, - {{0xa290c06142542129, 0xf2e2c2aebe8d5b90, 0xcf2458db76abfe1b, 0x02157ade83d626bf}}, - {{0x3e46972a1b9a038b, 0x2e4ee66a7ee03fb4, 0x81a248776edbb4ca, 0x1a944ee88ecd0563}}}, -{{{0xd5a91d1151039372, 0x2ed377b799ca26de, 0xa17202acfd366b6b, 0x0730291bd6901995}}, - {{0xbb40a859182362d6, 0xb99f55778a4d1abb, 0x8d18b427758559f6, 0x26c20fe74d26235a}}, - {{0x648d1d9fe9cc22f5, 0x66bc561928dd577c, 0x47d3ed21652439d1, 0x49d271acedaf8b49}}}, -{{{0x89f5058a382b33f3, 0x5ae2ba0bad48c0b4, 0x8f93b503a53db36e, 0x5aa3ed9d95a232e6}}, - {{0x2798aaf9b4b75601, 0x5eac72135c8dad72, 0xd2ceaa6161b7a023, 0x1bbfb284e98f7d4e}}, - {{0x656777e9c7d96561, 0xcb2b125472c78036, 0x65053299d9506eee, 0x4a07e14e5e8957cc}}}, -{{{0x4ee412cb980df999, 0xa315d76f3c6ec771, 0xbba5edde925c77fd, 0x3f0bac391d313402}}, - {{0x240b58cdc477a49b, 0xfd38dade6447f017, 0x19928d32a7c86aad, 0x50af7aed84afa081}}, - {{0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006}}}, -{{{0x89422f7edfb870fc, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0}}, - {{0xd75aad9ad9f3c18b, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5}}, - {{0xdccbe37a35444483, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64}}}, -{{{0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c}}, - {{0x6bdeeebe6084034b, 0x3199c2b6780fb854, 0x973376abb62d0695, 0x6e3180c98b647d90}}, - {{0xee7ab6e7a128b071, 0xa4c1596d93a88baa, 0xf7b4de82b2216130, 0x363e999ddd97bd18}}}, -{{{0x96a843c135ee1fc4, 0x976eb35508e4c8cf, 0xb42f6801b58cd330, 0x48ee9b78693a052b}}, - {{0x2f1848dce24baec6, 0x769b7255babcaf60, 0x90cb3c6e3cefe931, 0x231f979bc6f9b355}}, - {{0x5c31de4bcc2af3c6, 0xb04bb030fe208d1f, 0xb78d7009c14fb466, 0x079bfa9b08792413}}}, -{{{0xe3903a51da300df4, 0x843964233da95ab0, 0xed3cf12d0b356480, 0x038c77f684817194}}, - {{0xf3c9ed80a2d54245, 0x0aa08b7877f63952, 0xd76dac63d1085475, 0x1ef4fb159470636b}}, - {{0x854e5ee65b167bec, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56}}}, -{{{0xd4c080908a182fcf, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00}}, - {{0x5d46bc450aa4d801, 0xc3af1227a533b9d8, 0x389e3b262b8906c2, 0x200a1e7e382f581b}}, - {{0x518db967eaf93ac5, 0x71bc989b056652c0, 0xfe2b85d9567197f5, 0x050eca52651e4e38}}}, -{{{0xc3431ade453f0c9c, 0xe9f5045eff703b9b, 0xfcd97ac9ed847b3d, 0x4b0ee6c21c58f4c6}}, - {{0x97ac397660e668ea, 0x9b19bbfe153ab497, 0x4cb179b534eca79f, 0x6151c09fa131ae57}}, - {{0x3af55c0dfdf05d96, 0xdd262ee02ab4ee7a, 0x11b2bb8712171709, 0x1fef24fa800f030b}}}, -{{{0xb496123a6b6c6609, 0xa750fe8580ab5938, 0xf471bf39b7c27a5f, 0x507903ce77ac193c}}, - {{0xff91a66a90166220, 0xf22552ae5bf1e009, 0x7dff85d87f90df7c, 0x4f620ffe0c736fb9}}, - {{0x62f90d65dfde3e34, 0xcf28c592b9fa5fad, 0x99c86ef9c6164510, 0x25d448044a256c84}}}, -{{{0xbd68230ec7e9b16f, 0x0eb1b9c1c1c5795d, 0x7943c8c495b6b1ff, 0x2f9faf620bbacf5e}}, - {{0x2c7c4415c9022b55, 0x56a0d241812eb1fe, 0xf02ea1c9d7b65e0d, 0x4180512fd5323b26}}, - {{0xa4ff3e698a48a5db, 0xba6a3806bd95403b, 0x9f7ce1af47d5b65d, 0x15e087e55939d2fb}}}, -{{{0x12207543745c1496, 0xdaff3cfdda38610c, 0xe4e797272c71c34f, 0x39c07b1934bdede9}}, - {{0x8894186efb963f38, 0x48a00e80dc639bd5, 0xa4e8092be96c1c99, 0x5a097d54ca573661}}, - {{0x2d45892b17c9e755, 0xd033fd7289308df8, 0x6c2fe9d9525b8bd9, 0x2edbecf1c11cc079}}}, -{{{0x1616a4e3c715a0d2, 0x53623cb0f8341d4d, 0x96ef5329c7e899cb, 0x3d4e8dbba668baa6}}, - {{0xee0f0fddd087a25f, 0x9c7531555c3e34ee, 0x660c572e8fab3ab5, 0x0854fc44544cd3b2}}, - {{0x61eba0c555edad19, 0x24b533fef0a83de6, 0x3b77042883baa5f8, 0x678f82b898a47e8d}}}, -{{{0xb1491d0bd6900c54, 0x3539722c9d132636, 0x4db928920b362bc9, 0x4d7cd1fea68b69df}}, - {{0x1e09d94057775696, 0xeed1265c3cd951db, 0xfa9dac2b20bce16f, 0x0f7f76e0e8d089f4}}, - {{0x36d9ebc5d485b00c, 0xa2596492e4adb365, 0xc1659480c2119ccd, 0x45306349186e0d5f}}}, -{{{0x94ddd0c1a6cdff1d, 0x55f6f115e84213ae, 0x6c935f85992fcf6a, 0x067ee0f54a37f16f}}, - {{0x96a414ec2b072491, 0x1bb2218127a7b65b, 0x6d2849596e8a4af0, 0x65f3b08ccd27765f}}, - {{0xecb29fff199801f7, 0x9d361d1fa2a0f72f, 0x25f11d2375fd2f49, 0x124cefe80fe10fe2}}}, -{{{0x4c126cf9d18df255, 0xc1d471e9147a63b6, 0x2c6d3c73f3c93b5f, 0x6be3a6a2e3ff86a2}}, - {{0x1518e85b31b16489, 0x8faadcb7db710bfb, 0x39b0bdf4a14ae239, 0x05f4cbea503d20c1}}, - {{0xce040e9ec04145bc, 0xc71ff4e208f6834c, 0xbd546e8dab8847a3, 0x64666aa0a4d2aba5}}}, -{{{0x6841435a7c06d912, 0xca123c21bb3f830b, 0xd4b37b27b1cbe278, 0x1d753b84c76f5046}}, - {{0xb0c53bf73337e94c, 0x7cb5697e11e14f15, 0x4b84abac1930c750, 0x28dd4abfe0640468}}, - {{0x7dc0b64c44cb9f44, 0x18a3e1ace3925dbf, 0x7a3034862d0457c4, 0x4c498bf78a0c892e}}}, -{{{0x37d653fb1aa73196, 0x0f9495303fd76418, 0xad200b09fb3a17b2, 0x544d49292fc8613e}}, - {{0x22d2aff530976b86, 0x8d90b806c2d24604, 0xdca1896c4de5bae5, 0x28005fe6c8340c17}}, - {{0x6aefba9f34528688, 0x5c1bff9425107da1, 0xf75bbbcd66d94b36, 0x72e472930f316dfa}}}, -{{{0x2695208c9781084f, 0xb1502a0b23450ee1, 0xfd9daea603efde02, 0x5a9d2e8c2733a34c}}, - {{0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438}}, - {{0x765305da03dbf7e5, 0xa4daf2491434cdbd, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543}}}, -{{{0x8d356b23c3d330b2, 0xf21c8b9bb0471b06, 0xb36c316c6e42b83c, 0x07d79c7e8beab10d}}, - {{0xd7ef93bb07af9753, 0x583ed0cf3db766a7, 0xce6998bf6e0b1ec5, 0x47b7ffd25dd40452}}, - {{0x87fbfb9cbc08dd12, 0x8a066b3ae1eec29b, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6}}}, -{{{0x80d253a6bccba34a, 0x3e61c3a13838219b, 0x90c3b6019882e396, 0x1c3d05775d0ee66f}}, - {{0xcda86f40216bc059, 0x1fbb231d12bcd87e, 0xb4956a9e17c70990, 0x38750c3b66d12e55}}, - {{0x692ef1409422e51a, 0xcbc0c73c2b5df671, 0x21014fe7744ce029, 0x0621e2c7d330487c}}}, -{{{0xaf9860cc8259838d, 0x90ea48c1c69f9adc, 0x6526483765581e30, 0x0007d6097bd3a5bc}}, - {{0xb7ae1796b0dbf0f3, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d}}, - {{0xc0bf1d950842a94b, 0xb2d3c363588f2e3e, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86}}}, -{{{0xeceea2ef5da27ae1, 0x597c3a1455670174, 0xc9a62a126609167a, 0x252a5f2e81ed8f70}}, - {{0x90034704cc9d28c7, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a}}, - {{0x0d2894265066e80d, 0xfcc3f785307c8c6b, 0x1b53da780c1112fd, 0x079c170bd843b388}}}, -{{{0x0506ece464fa6fff, 0xbee3431e6205e523, 0x3579422451b8ea42, 0x6dec05e34ac9fb00}}, - {{0xcdd6cd50c0d5d056, 0x9af7686dbb03573b, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc}}, - {{0x94b625e5f155c1b3, 0x417bf3a7997b7b91, 0xc22cbddc6d6b2600, 0x51445e14ddcd52f4}}}, -{{{0x57502b4b3b144951, 0x8e67ff6b444bbcb3, 0xb8bd6927166385db, 0x13186f31e39295c8}}, - {{0x893147ab2bbea455, 0x8c53a24f92079129, 0x4b49f948be30f7a7, 0x12e990086e4fd43d}}, - {{0xf10c96b37fdfbb2e, 0x9f9a935e121ceaf9, 0xdf1136c43a5b983f, 0x77b2e3f05d3e99af}}}, -{{{0xfd0d75879cf12657, 0xe82fef94e53a0e29, 0xcc34a7f05bbb4be7, 0x0b251172a50c38a2}}, - {{0x9532f48fcc5cd29b, 0x2ba851bea3ce3671, 0x32dacaa051122941, 0x478d99d9350004f2}}, - {{0x1d5ad94890bb02c0, 0x50e208b10ec25115, 0xa26a22894ef21702, 0x4dc923343b524805}}}, -{{{0xe3828c400f8086b6, 0x3f77e6f7979f0dc8, 0x7ef6de304df42cb4, 0x5265797cb6abd784}}, - {{0x3ad3e3ebf36c4975, 0xd75d25a537862125, 0xe873943da025a516, 0x6bbc7cb4c411c847}}, - {{0x3c6f9cd1d4a50d56, 0xb6244077c6feab7e, 0x6ff9bf483580972e, 0x00375883b332acfb}}}, -{{{0x0001b2cd28cb0940, 0x63fb51a06f1c24c9, 0xb5ad8691dcd5ca31, 0x67238dbd8c450660}}, - {{0xc98bec856c75c99c, 0xe44184c000e33cf4, 0x0a676b9bba907634, 0x669e2cb571f379d7}}, - {{0xcb116b73a49bd308, 0x025aad6b2392729e, 0xb4793efa3f55d9b1, 0x72a1056140678bb9}}}, -{{{0xa2b6812b1cc9249d, 0x62866eee21211f58, 0x2cb5c5b85df10ece, 0x03a6b259e263ae00}}, - {{0x0d8d2909e2e505b6, 0x98ca78abc0291230, 0x77ef5569a9b12327, 0x7c77897b81439b47}}, - {{0xf1c1b5e2de331cb5, 0x5a9f5d8e15fca420, 0x9fa438f17bd932b1, 0x2a381bf01c6146e7}}}, -{{{0xac9b9879cfc811c1, 0x8b7d29813756e567, 0x50da4e607c70edfc, 0x5dbca62f884400b6}}, - {{0xf7c0be32b534166f, 0x27e6ca6419cf70d4, 0x934df7d7a957a759, 0x5701461dabdec2aa}}, - {{0x2c6747402c915c25, 0x1bdcd1a80b0d340a, 0x5e5601bd07b43f5f, 0x2555b4e05539a242}}}, -{{{0x6fc09f5266ddd216, 0xdce560a7c8e37048, 0xec65939da2df62fd, 0x7a869ae7e52ed192}}, - {{0x78409b1d87e463d4, 0xad4da95acdfb639d, 0xec28773755259b9c, 0x69c806e9c31230ab}}, - {{0x7b48f57414bb3f22, 0x68c7cee4aedccc88, 0xed2f936179ed80be, 0x25d70b885f77bc4b}}}, -{{{0x4151c3d9762bf4de, 0x083f435f2745d82b, 0x29775a2e0d23ddd5, 0x138e3a6269a5db24}}, - {{0x98459d29bb1ae4d4, 0x56b9c4c739f954ec, 0x832743f6c29b4b3e, 0x21ea8e2798b6878a}}, - {{0x87bef4b46a5a7b9c, 0xd2299d1b5fc1d062, 0x82409818dd321648, 0x5c5abeb1e5a2e03d}}}, -{{{0x14722af4b73c2ddb, 0xbc470c5f5a05060d, 0x00943eac2581b02e, 0x0e434b3b1f499c8f}}, - {{0x02cde6de1306a233, 0x7b5a52a2116f8ec7, 0xe1c681f4c1163b5b, 0x241d350660d32643}}, - {{0x6be4404d0ebc52c7, 0xae46233bb1a791f5, 0x2aec170ed25db42b, 0x1d8dfd966645d694}}}, -{{{0x296fa9c59c2ec4de, 0xbc8b61bf4f84f3cb, 0x1c7706d917a8f908, 0x63b795fc7ad3255d}}, - {{0xd598639c12ddb0a4, 0xa5d19f30c024866b, 0xd17c2f0358fce460, 0x07a195152e095e8a}}, - {{0xa8368f02389e5fc8, 0x90433b02cf8de43b, 0xafa1fd5dc5412643, 0x3e8fe83d032f0137}}}, -{{{0x2f8b15b90570a294, 0x94f2427067084549, 0xde1c5ae161bbfd84, 0x75ba3b797fac4007}}, - {{0x08704c8de8efd13c, 0xdfc51a8e33e03731, 0xa59d5da51260cde3, 0x22d60899a6258c86}}, - {{0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, 0xb38847bceb401260, 0x0904d07b87779e5e}}}, -{{{0xb4ce1fd4ddba919c, 0xcf31db3ec74c8daa, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07}}, - {{0xf4322d6648f940b9, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c}}, - {{0xf834749c5ba295a0, 0xd6947c5bca37d25a, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac}}}, -{{{0x362ab9e3f53533eb, 0x338568d56eb93d40, 0x9e0e14521d5a5572, 0x1d24a86d83741318}}, - {{0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754}}, - {{0xf4ec7648ffd4ce1f, 0xe045eaf054ac8c1c, 0x88d225821d09357c, 0x43b261dc9aeb4859}}}, -{{{0xe55b1e1988bb79bb, 0xa09ed07dc17a359d, 0xb02c2ee2603dea33, 0x326055cf5b276bc2}}, - {{0x19513d8b6c951364, 0x94fe7126000bf47b, 0x028d10ddd54f9567, 0x02b4d5e242940964}}, - {{0xb4a155cb28d18df2, 0xeacc4646186ce508, 0xc49cf4936c824389, 0x27a6c809ae5d3410}}}, -{{{0x8ba6ebcd1f0db188, 0x37d3d73a675a5be8, 0xf22edfa315f5585a, 0x2cb67174ff60a17e}}, - {{0xcd2c270ac43d6954, 0xdd4a3e576a66cab2, 0x79fa592469d7036c, 0x221503603d8c2599}}, - {{0x59eecdf9390be1d0, 0xa9422044728ce3f1, 0x82891c667a94f0f4, 0x7b1df4b73890f436}}}, -{{{0xe492f2e0b3b2a224, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992}}, - {{0x5f2e221807f8f58c, 0xe3555c9fd49409d4, 0xb2aaa88d1fb6a630, 0x68698245d352e03d}}, - {{0xdbb15d852a18187a, 0xf3e4aad386ddacd7, 0x44bae2810ff6c482, 0x46cf4c473daf01cf}}}, -{{{0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40}}, - {{0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb}}, - {{0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716}}}, -{{{0x7afcd613efa9d697, 0x0cc45aa41c067959, 0xa56fe104c1fada96, 0x3a73b70472e40365}}, - {{0x7b26e56b9e2d4734, 0xc4c7132b81c61675, 0xef5c9525ec9cde7f, 0x39c80b16e71743ad}}, - {{0x0f196e0d1b826c68, 0xf71ff0e24960e3db, 0x6113167023b7436c, 0x0cf0ea5877da7282}}}, -{{{0x196c80a4ddd4ccbd, 0x22e6f55d95f2dd9d, 0xc75e33c740d6c71b, 0x7bb51279cb3c042f}}, - {{0xe332ced43ba6945a, 0xde0b1361e881c05d, 0x1ad40f095e67ed3b, 0x5da8acdab8c63d5d}}, - {{0xc4b6664a3a70159f, 0x76194f0f0a904e14, 0xa5614c39a4096c13, 0x6cd0ff50979feced}}}, -{{{0xc0e067e78f4428ac, 0x14835ab0a61135e3, 0xf21d14f338062935, 0x6390a4c8df04849c}}, - {{0x7fecfabdb04ba18e, 0xd0fc7bfc3bddbcf7, 0xa41d486e057a131c, 0x641a4391f2223a61}}, - {{0xc5c6b95aa606a8db, 0x914b7f9eb06825f1, 0x2a731f6b44fc9eff, 0x30ddf38562705cfc}}}, -{{{0x4e3dcbdad1bff7f9, 0xc9118e8220645717, 0xbacccebc0f189d56, 0x1b4822e9d4467668}}, - {{0x33bef2bd68bcd52c, 0xc649dbb069482ef2, 0xb5b6ee0c41cb1aee, 0x5c294d270212a7e5}}, - {{0xab360a7f25563781, 0x2512228a480f7958, 0xc75d05276114b4e3, 0x222d9625d976fe2a}}}, -{{{0x1c717f85b372ace1, 0x81930e694638bf18, 0x239cad056bc08b58, 0x0b34271c87f8fff4}}, - {{0x0f94be7e0a344f85, 0xeb2faa8c87f22c38, 0x9ce1e75e4ee16f0f, 0x43e64e5418a08dea}}, - {{0x8155e2521a35ce63, 0xbe100d4df912028e, 0xbff80bf8a57ddcec, 0x57342dc96d6bc6e4}}}, -{{{0xefeef065c8ce5998, 0xbf029510b5cbeaa2, 0x8c64a10620b7c458, 0x35134fb231c24855}}, - {{0xf3c3bcb71e707bf6, 0x351d9b8c7291a762, 0x00502e6edad69a33, 0x522f521f1ec8807f}}, - {{0x272c1f46f9a3902b, 0xc91ba3b799657bcc, 0xae614b304f8a1c0e, 0x7afcaad70b99017b}}}, -{{{0xc25ded54a4b8be41, 0x902d13e11bb0e2dd, 0x41f43233cde82ab2, 0x1085faa5c3aae7cb}}, - {{0xa88141ecef842b6b, 0x55e7b14797abe6c5, 0x8c748f9703784ffe, 0x5b50a1f7afcd00b7}}, - {{0x9b840f66f1361315, 0x18462242701003e9, 0x65ed45fae4a25080, 0x0a2862393fda7320}}}, -{{{0x46ab13c8347cbc9d, 0x3849e8d499c12383, 0x4cea314087d64ac9, 0x1f354134b1a29ee7}}, - {{0x960e737b6ecb9d17, 0xfaf24948d67ceae1, 0x37e7a9b4d55e1b89, 0x5cb7173cb46c59eb}}, - {{0x4a89e68b82b7abf0, 0xf41cd9279ba6b7b9, 0x16e6c210e18d876f, 0x7cacdb0f7f1b09c6}}}, -{{{0x9062b2e0d91a78bc, 0x47c9889cc8509667, 0x9df54a66405070b8, 0x7369e6a92493a1bf}}, - {{0xe1014434dcc5caed, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4}}, - {{0x9d673ffb13986864, 0x3ca5fbd9415dc7b8, 0xe04ecc3bdf273b5e, 0x1420683db54e4cd2}}}, -{{{0xb478bd1e249dd197, 0x620c35005e58c102, 0xfb02d32fccbaac5c, 0x60b63bebf508a72d}}, - {{0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, 0xd3b0da49a66bde53, 0x31e83b4161d081c1}}, - {{0x97e8c7129e062b4f, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317}}}, -{{{0x5879101065c23d58, 0x8b9d086d5094819c, 0xe2402fa912c55fa7, 0x669a6564570891d4}}, - {{0x3076b5e37df58c52, 0xd73ab9dde799cc36, 0xbd831ce34913ee20, 0x1a56fbaa62ba0133}}, - {{0x943e6b505c9dc9ec, 0x302557bba77c371a, 0x9873ae5641347651, 0x13c4836799c58a5c}}}, -{{{0x423a5d465ab3e1b9, 0xfc13c187c7f13f61, 0x19f83664ecb5b9b6, 0x66f80c93a637b607}}, - {{0xc4dcfb6a5d8bd080, 0xdeebc4ec571a4842, 0xd4b2e883b8e55365, 0x50bdc87dc8e5b827}}, - {{0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae}}}, -{{{0x8fa47ff83362127d, 0xbc9f6ac471cd7c15, 0x6e71454349220c8b, 0x0e645912219f732e}}, - {{0xc297e60008bac89a, 0x7d4cea11eae1c3e0, 0xf3e38be19fe7977c, 0x3a3a450f63a305cd}}, - {{0x078f2f31d8394627, 0x389d3183de94a510, 0xd1e36c6d17996f80, 0x318c8d9393a9a87b}}}, -{{{0xf2745d032afffe19, 0x0c9f3c497f24db66, 0xbc98d3e3ba8598ef, 0x224c7c679a1d5314}}, - {{0x5d669e29ab1dd398, 0xfc921658342d9e3b, 0x55851dfdf35973cd, 0x509a41c325950af6}}, - {{0xbdc06edca6f925e9, 0x793ef3f4641b1f33, 0x82ec12809d833e89, 0x05bff02328a11389}}}, -{{{0x3632137023cae00b, 0x544acf0ad1accf59, 0x96741049d21a1c88, 0x780b8cc3fa2a44a7}}, - {{0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea}}, - {{0x1ef38abc234f305f, 0x9a577fbd1405de08, 0x5e82a51434e62a0d, 0x5ff418726271b7a1}}}, -{{{0x398e080c1789db9d, 0xa7602025f3e778f5, 0xfa98894c06bd035d, 0x106a03dc25a966be}}, - {{0xe5db47e813b69540, 0xf35d2a3b432610e1, 0xac1f26e938781276, 0x29d4db8ca0a0cb69}}, - {{0xd9ad0aaf333353d0, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa}}}, -{{{0xdfdacbee4324c0e9, 0x054442883f955bb7, 0xdef7aaa8ea31609f, 0x68aee70642287cff}}, - {{0xf68fe2e8809de054, 0xe3bc096a9c82bad1, 0x076353d40aadbf45, 0x7b9b1fb5dea1959e}}, - {{0xf01cc8f17471cc0c, 0x95242e37579082bb, 0x27776093d3e46b5f, 0x2d13d55a28bd85fb}}}, -{{{0xfac5d2065b35b8da, 0xa8da8a9a85624bb7, 0xccd2ca913d21cd0f, 0x6b8341ee8bf90d58}}, - {{0xbf019cce7aee7a52, 0xa8ded2b6e454ead3, 0x3c619f0b87a8bb19, 0x3619b5d7560916d8}}, - {{0x3579f26b0282c4b2, 0x64d592f24fafefae, 0xb7cded7b28c8c7c0, 0x6a927b6b7173a8d7}}}, -{{{0x1f6db24f986e4656, 0x1021c02ed1e9105b, 0xf8ff3fff2cc0a375, 0x1d2a6bf8c6c82592}}, - {{0x8d7040863ece88eb, 0xf0e307a980eec08c, 0xac2250610d788fda, 0x056d92a43a0d478d}}, - {{0x1b05a196fc3da5a1, 0x77d7a8c243b59ed0, 0x06da3d6297d17918, 0x66fbb494f12353f7}}}, -{{{0x751a50b9d85c0fb8, 0xd1afdc258bcf097b, 0x2f16a6a38309a969, 0x14ddff9ee5b00659}}, - {{0xd6d70996f12309d6, 0xdbfb2385e9c3d539, 0x46d602b0f7552411, 0x270a0b0557843e0c}}, - {{0x61ff0640a7862bcc, 0x81cac09a5f11abfe, 0x9047830455d12abb, 0x19a4bde1945ae873}}}, -{{{0x9b9f26f520a6200a, 0x64804443cf13eaf8, 0x8a63673f8631edd3, 0x72bbbce11ed39dc1}}, - {{0x40c709dec076c49f, 0x657bfaf27f3e53f6, 0x40662331eca042c4, 0x14b375487eb4df04}}, - {{0xae853c94ab66dc47, 0xeb62343edf762d6e, 0xf08e0e186fb2f7d1, 0x4f0b1c02700ab37a}}}, -{{{0xe1706787d81951fa, 0xa10a2c8eb290c77b, 0xe7382fa03ed66773, 0x0a4d84710bcc4b54}}, - {{0x79fd21ccc1b2e23f, 0x4ae7c281453df52a, 0xc8172ec9d151486b, 0x68abe9443e0a7534}}, - {{0xda12c6c407831dcb, 0x0da230d74d5c510d, 0x4ab1531e6bd404e1, 0x4106b166bcf440ef}}}, -{{{0x02e57a421cd23668, 0x4ad9fb5d0eaef6fd, 0x954e6727b1244480, 0x7f792f9d2699f331}}, - {{0xa485ccd539e4ecf2, 0x5aa3f3ad0555bab5, 0x145e3439937df82d, 0x1238b51e1214283f}}, - {{0x0b886b925fd4d924, 0x60906f7a3626a80d, 0xecd367b4b98abd12, 0x2876beb1def344cf}}}, -{{{0xdc84e93563144691, 0x632fe8a0d61f23f4, 0x4caa800612a9a8d5, 0x48f9dbfa0e9918d3}}, - {{0xd594b3333a8a85f8, 0x4ea37689e78d7d58, 0x73bf9f455e8e351f, 0x5507d7d2bc41ebb4}}, - {{0x1ceb2903299572fc, 0x7c8ccaa29502d0ee, 0x91bfa43411cce67b, 0x5784481964a831e7}}}, -{{{0xda7c2b256768d593, 0x98c1c0574422ca13, 0xf1a80bd5ca0ace1d, 0x29cdd1adc088a690}}, - {{0xd6cfd1ef5fddc09c, 0xe82b3efdf7575dce, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b}}, - {{0x0ff2f2f9d956e148, 0xade797759f356b2e, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b}}}, -{{{0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149}}, - {{0xa95d9a5fd67ff163, 0xe92be69d4cc75681, 0xb7f8024cde20f257, 0x204f2a20fb072df5}}, - {{0xc8143b3d30ebb079, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f}}}, -{{{0x3efa367f2cb61575, 0xf5f96f761cd6026c, 0xe8c7142a65b52562, 0x3dcb65ea53030acd}}, - {{0x192ea9550bb8245a, 0xc8e6fba88f9050d1, 0x7986ea2d88a4c935, 0x241c5f91de018668}}, - {{0x28d8172940de6caa, 0x8fbf2cf022d9733a, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5}}}, -{{{0xcdff20ab8362fa4a, 0x57e118d4e21a3e6e, 0xe3179617fc39e62b, 0x0d9a53efbc1769fd}}, - {{0x0358c34e04f410ce, 0xb6135b5a276e0685, 0x5d9670c7ebb91521, 0x04d654f321db889c}}, - {{0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7}}}, -{{{0xf4a718025fb15f95, 0x3df65f346b5c1b8f, 0xcdfcf08500e01112, 0x11b50c4cddd31848}}, - {{0x24c3b291af372a4b, 0x93da8270718147f2, 0xdd84856486899ef2, 0x4a96314223e0ee33}}, - {{0xa6e8274408a4ffd6, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51}}}, -{{{0xa71fce5ae2242584, 0x26ea725692f58a9e, 0xd21a09d71cea3cf4, 0x73fcdd14b71c01e6}}, - {{0x30e2616ec49d0b6f, 0xe456718fcaec2317, 0x48eb409bf26b4fa6, 0x3042cee561595f37}}, - {{0x427e7079449bac41, 0x855ae36dbce2310a, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6}}}, -{{{0x64fcb3ae34dcb9ce, 0x97500323e348d0ad, 0x45b3f07d62c6381b, 0x61545379465a6788}}, - {{0xc9bd78f6570eac28, 0xe55b0b3227919ce1, 0x65fc3eaba19b91ed, 0x25c425e5d6263690}}, - {{0x3f3e06a6f1d7de6e, 0x3ef976278e062308, 0x8c14f6264e8a6c77, 0x6539a08915484759}}}, -{{{0xe9d21f74c3d2f773, 0xc150544125c46845, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c}}, - {{0xddc4dbd414bb4a19, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90}}, - {{0xd486d1b1cafde0c6, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a}}}, -{{{0x16faa8fb532f7428, 0xdbd42ea046a4e272, 0x5337653b8b9ea480, 0x4065947223973f03}}, - {{0xf7c0a19c1a54a044, 0x4a1c5e2477bd9fbb, 0xa6e3ca115af22972, 0x1819bb953f2e9e0d}}, - {{0x498fbb795e042e84, 0x7d0dd89a7698b714, 0x8bfb0ba427fe6295, 0x36ba82e721200524}}}, -{{{0xd60ecbb74245ec41, 0xfd9be89e34348716, 0xc9240afee42284de, 0x4472f648d0531db4}}, - {{0xc8d69d0a57274ed5, 0x45ba803260804b17, 0xdf3cda102255dfac, 0x77d221232709b339}}, - {{0x498a6d7064ad94d8, 0xa5b5c8fd9af62263, 0x8ca8ed0545c141f4, 0x2c63bec3662d358c}}}, -{{{0x7fe60d8bea787955, 0xb9dc117eb5f401b7, 0x91c7c09a19355cce, 0x22692ef59442bedf}}, - {{0x9a518b3a8586f8bf, 0x9ee71af6cbb196f0, 0xaa0625e6a2385cf2, 0x1deb2176ddd7c8d1}}, - {{0x8563d19a2066cf6c, 0x401bfd8c4dcc7cd7, 0xd976a6becd0d8f62, 0x67cfd773a278b05e}}}, -{{{0x8dec31faef3ee475, 0x99dbff8a9e22fd92, 0x512d11594e26cab1, 0x0cde561eec4310b9}}, - {{0x2d5fa9855a4e586a, 0x65f8f7a449beab7e, 0xaa074dddf21d33d3, 0x185cba721bcb9dee}}, - {{0x93869da3f4e3cb41, 0xbf0392f540f7977e, 0x026204fcd0463b83, 0x3ec91a769eec6eed}}}, -{{{0x1e9df75bf78166ad, 0x4dfda838eb0cd7af, 0xba002ed8c1eaf988, 0x13fedb3e11f33cfc}}, - {{0x0fad2fb7b0a3402f, 0x46615ecbfb69f4a8, 0xf745bcc8c5f8eaa6, 0x7a5fa8794a94e896}}, - {{0x52958faa13cd67a1, 0x965ee0818bdbb517, 0x16e58daa2e8845b3, 0x357d397d5499da8f}}}, -{{{0x1ebfa05fb0bace6c, 0xc934620c1caf9a1e, 0xcc771cc41d82b61a, 0x2d94a16aa5f74fec}}, - {{0x481dacb4194bfbf8, 0x4d77e3f1bae58299, 0x1ef4612e7d1372a0, 0x3a8d867e70ff69e1}}, - {{0x6f58cd5d55aff958, 0xba3eaa5c75567721, 0x75c123999165227d, 0x69be1343c2f2b35e}}}, -{{{0x0e091d5ee197c92a, 0x4f51019f2945119f, 0x143679b9f034e99c, 0x7d88112e4d24c696}}, - {{0x82bbbdac684b8de3, 0xa2f4c7d03fca0718, 0x337f92fbe096aaa8, 0x200d4d8c63587376}}, - {{0x208aed4b4893b32b, 0x3efbf23ebe59b964, 0xd762deb0dba5e507, 0x69607bd681bd9d94}}}, -{{{0xf6be021068de1ce1, 0xe8d518e70edcbc1f, 0xe3effdd01b5505a5, 0x35f63353d3ec3fd0}}, - {{0x3b7f3bd49323a902, 0x7c21b5566b2c6e53, 0xe5ba8ff53a7852a7, 0x28bc77a5838ece00}}, - {{0x63ba78a8e25d8036, 0x63651e0094333490, 0x48d82f20288ce532, 0x3a31abfa36b57524}}}, -{{{0x239e9624089c0a2e, 0xc748c4c03afe4738, 0x17dbed2a764fa12a, 0x639b93f0321c8582}}, - {{0xc08f788f3f78d289, 0xfe30a72ca1404d9f, 0xf2778bfccf65cc9d, 0x7ee498165acb2021}}, - {{0x7bd508e39111a1c3, 0x2b2b90d480907489, 0xe7d2aec2ae72fd19, 0x0edf493c85b602a6}}}, -{{{0xaecc8158599b5a68, 0xea574f0febade20e, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4}}, - {{0x6767c4d284764113, 0xa090403ff7f5f835, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369}}, - {{0x4dc22f818b465cf8, 0x71a0f35a1480eff8, 0xaee8bfad04c7d657, 0x355bb12ab26176f4}}}, -{{{0xa71e64cc7493bbf4, 0xe5bd84d9eca3b0c3, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312}}, - {{0xa301dac75a8c7318, 0xed90039db3ceaa11, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e}}, - {{0xa48859c41b7f6c32, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4}}}, -{{{0x5144539771ec4f48, 0xf805b17dc98c5d6e, 0xf762c11a47c3c66b, 0x00b89b85764699dc}}, - {{0xfbe65d50c85066b0, 0x62ecc4b0b3a299b0, 0xe53754ea441ae8e0, 0x08fea02ce8d48d5f}}, - {{0x824ddd7668deead0, 0xc86445204b685d23, 0xb514cfcd5d89d665, 0x473829a74f75d537}}}, -{{{0x82d2da754679c418, 0xe63bd7d8b2618df0, 0x355eef24ac47eb0a, 0x2078684c4833c6b4}}, - {{0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390}}, - {{0x3b48cf217a78820c, 0xf76a0ab281273e97, 0xa96c65a78c8eed7b, 0x7411a6054f8a433f}}}, -{{{0x4d659d32b99dc86d, 0x044cdc75603af115, 0xb34c712cdcc2e488, 0x7c136574fb8134ff}}, - {{0x579ae53d18b175b4, 0x68713159f392a102, 0x8455ecba1eef35f5, 0x1ec9a872458c398f}}, - {{0xb8e6a4d400a2509b, 0x9b81d7020bc882b4, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460}}}, -{{{0xab895770b635dcf2, 0x02dfef6cf66c1fbc, 0x85530268beb6d187, 0x249929fccc879e74}}, - {{0x85c298d459393046, 0x8f7e35985ff659ec, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720}}, - {{0xa3d0a0f116959029, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7}}}, -{{{0x528993434934d643, 0xb9dbf806a51222f5, 0x8f6d878fc3f41c22, 0x37676a2a4d9d9730}}, - {{0x6646b5f477e285d6, 0x40e8ff676c8f6193, 0xa6ec7311abb594dd, 0x7ec846f3658cec4d}}, - {{0x9b5e8f3f1da22ec7, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5}}}, -{{{0x591e4a5610628564, 0x2a4bb87ca8b4df34, 0xde2a2572e7a38e43, 0x3cbdabd9fee5046e}}, - {{0x81aebbdd2cd13070, 0x962e4325f85a0e9e, 0xde9391aacadffecb, 0x53177fda52c230e6}}, - {{0xa7bc970650b9de79, 0x3d12a7fbc301b59b, 0x02652e68d36ae38c, 0x79d739835a6199dc}}}, -{{{0xd9354df64131c1bd, 0x758094a186ec5822, 0x4464ee12e459f3c2, 0x6c11fce4cb133282}}, - {{0x21c9d9920d591737, 0x9bea41d2e9b46cd6, 0xe20e84200d89bfca, 0x79d99f946eae5ff8}}, - {{0xf17b483568673205, 0x387deae83caad96c, 0x61b471fd56ffe386, 0x31741195b745a599}}}, -{{{0xe8d10190b77a360b, 0x99b983209995e702, 0xbd4fdff8fa0247aa, 0x2772e344e0d36a87}}, - {{0x17f8ba683b02a047, 0x50212096feefb6c8, 0x70139be21556cbe2, 0x203e44a11d98915b}}, - {{0xd6863eba37b9e39f, 0x105bc169723b5a23, 0x104f6459a65c0762, 0x567951295b4d38d4}}}, -{{{0x535fd60613037524, 0xe210adf6b0fbc26a, 0xac8d0a9b23e990ae, 0x47204d08d72fdbf9}}, - {{0x07242eb30d4b497f, 0x1ef96306b9bccc87, 0x37950934d8116f45, 0x05468d6201405b04}}, - {{0x00f565a9f93267de, 0xcecfd78dc0d58e8a, 0xa215e2dcf318e28e, 0x4599ee919b633352}}}, -{{{0xd3c220ca70e0e76b, 0xb12bea58ea9f3094, 0x294ddec8c3271282, 0x0c3539e1a1d1d028}}, - {{0xac746d6b861ae579, 0x31ab0650f6aea9dc, 0x241d661140256d4c, 0x2f485e853d21a5de}}, - {{0x329744839c0833f3, 0x6fe6257fd2abc484, 0x5327d1814b358817, 0x65712585893fe9bc}}}, -{{{0x9c102fb732a61161, 0xe48e10dd34d520a8, 0x365c63546f9a9176, 0x32f6fe4c046f6006}}, - {{0x81c29f1bd708ee3f, 0xddcb5a05ae6407d0, 0x97aec1d7d2a3eba7, 0x1590521a91d50831}}, - {{0x40a3a11ec7910acc, 0x9013dff8f16d27ae, 0x1a9720d8abb195d4, 0x1bb9fe452ea98463}}}, -{{{0xe9d1d950b3d54f9e, 0x2d5f9cbee00d33c1, 0x51c2c656a04fc6ac, 0x65c091ee3c1cbcc9}}, - {{0xcf5e6c95cc36747c, 0x294201536b0bc30d, 0x453ac67cee797af0, 0x5eae6ab32a8bb3c9}}, - {{0x7083661114f118ea, 0x2b37b87b94349cad, 0x7273f51cb4e99f40, 0x78a2a95823d75698}}}, -{{{0xa2b072e95c8c2ace, 0x69cffc96651e9c4b, 0x44328ef842e7b42b, 0x5dd996c122aadeb3}}, - {{0xb4f23c425ef83207, 0xabf894d3c9a934b5, 0xd0708c1339fd87f7, 0x1876789117166130}}, - {{0x925b5ef0670c507c, 0x819bc842b93c33bf, 0x10792e9a70dd003f, 0x59ad4b7a6e28dc74}}}, -{{{0x5f3a7562eb3dbe47, 0xf7ea38548ebda0b8, 0x00c3e53145747299, 0x1304e9e71627d551}}, - {{0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa}}, - {{0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, 0xda0fe1fff979c60a, 0x4468de2d7c2dd693}}}, -{{{0x51bb355e9419469e, 0x33e6dc4c23ddc754, 0x93a5b6d6447f9962, 0x6cce7c6ffb44bd63}}, - {{0x4b9ad8c6f86307ce, 0x21113531435d0c28, 0xd4a866c5657a772c, 0x5da6427e63247352}}, - {{0x1a94c688deac22ca, 0xb9066ef7bbae1ff8, 0x88ad8c388d59580f, 0x58f29abfe79f2ca8}}}, -{{{0xe90ecfab8de73e68, 0x54036f9f377e76a5, 0xf0495b0bbe015982, 0x577629c4a7f41e36}}, - {{0x4b5a64bf710ecdf6, 0xb14ce538462c293c, 0x3643d056d50b3ab9, 0x6af93724185b4870}}, - {{0x3220024509c6a888, 0xd2e036134b558973, 0x83e236233c33289f, 0x701f25bb0caec18f}}}, -{{{0xc3a8b0f8e4616ced, 0xf700660e9e25a87d, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9}}, - {{0x9d18f6d97cbec113, 0x844a06e674bfdbe4, 0x20f5b522ac4e60d6, 0x720a5bc050955e51}}, - {{0x0c3f09439b805a35, 0xe84e8b376242abfc, 0x691417f35c229346, 0x0e9b9cbb144ef0ec}}}, -{{{0xfbbad48ffb5720ad, 0xee81916bdbf90d0e, 0xd4813152635543bf, 0x221104eb3f337bd8}}, - {{0x8dee9bd55db1beee, 0xc9c3ab370a723fb9, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde}}, - {{0x9e3c1743f2bc8c14, 0x2eda26fcb5856c3b, 0xccb82f0e68a7fb97, 0x4167a4e6bc593244}}}, -{{{0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a}}, - {{0xc2be2665f8ce8fee, 0xe967ff14e880d62c, 0xf12e6e7e2f364eee, 0x34b33370cb7ed2f6}}, - {{0xcdc591ee8681d6cc, 0xce02109ced85a753, 0xed7485c158808883, 0x1176fc6e2dfe65e4}}}, -{{{0xb4af6cd05b9c619b, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34}}, - {{0xdb90e28949770eb8, 0x98fbcc2aacf440a3, 0x21354ffeded7879b, 0x1f6a3e54f26906b6}}, - {{0x60a4c199d30734ea, 0x40c085b631165cd6, 0xe2333e23f7598295, 0x4f2fad0116b900d1}}}, -{{{0x44beb24194ae4e54, 0x5f541c511857ef6c, 0xa61e6b2d368d0498, 0x445484a4972ef7ab}}, - {{0x962cd91db73bb638, 0xe60577aafc129c08, 0x6f619b39f3b61689, 0x3451995f2944ee81}}, - {{0x9152fcd09fea7d7c, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7}}}, -{{{0x9b2a426e3b646025, 0x32127190385ce4cf, 0xa25cffc2dd6dea45, 0x06409010bea8de75}}, - {{0xd67cded679d34aa0, 0xcc0b9ec0cc4db39f, 0xa535a456e35d190f, 0x2e05d9eaf61f6fef}}, - {{0xc447901ad61beb59, 0x661f19bce5dc880a, 0x24685482b7ca6827, 0x293c778cefe07f26}}}, -{{{0x86809e7007069096, 0xaad75b15e4e50189, 0x07f35715a21a0147, 0x0487f3f112815d5e}}, - {{0x16c795d6a11ff200, 0xcb70d0e2b15815c9, 0x89f293209b5395b5, 0x50b8c2d031e47b4f}}, - {{0x48350c08068a4962, 0x6ffdd05351092c9a, 0x17af4f4aaf6fc8dd, 0x4b0553b53cdba58b}}}, -{{{0x9c65fcbe1b32ff79, 0xeb75ea9f03b50f9b, 0xfced2a6c6c07e606, 0x35106cd551717908}}, - {{0xbf05211b27c152d4, 0x5ec26849bd1af639, 0x5e0b2caa8e6fab98, 0x054c8bdd50bd0840}}, - {{0x38a0b12f1dcf073d, 0x4b60a8a3b7f6a276, 0xfed5ac25d3404f9a, 0x72e82d5e5505c229}}}, -{{{0x6b0b697ff0d844c8, 0xbb12f85cd979cb49, 0xd2a541c6c1da0f1f, 0x7b7c242958ce7211}}, - {{0x00d9cdfd69771d02, 0x410276cd6cfbf17e, 0x4c45306c1cb12ec7, 0x2857bf1627500861}}, - {{0x9f21903f0101689e, 0xd779dfd3bf861005, 0xa122ee5f3deb0f1b, 0x510df84b485a00d4}}}, -{{{0xa54133bb9277a1fa, 0x74ec3b6263991237, 0x1a3c54dc35d2f15a, 0x2d347144e482ba3a}}, - {{0x24b3c887c70ac15e, 0xb0f3a557fb81b732, 0x9b2cde2fe578cc1b, 0x4cf7ed0703b54f8e}}, - {{0x6bd47c6598fbee0f, 0x9e4733e2ab55be2d, 0x1093f624127610c5, 0x4e05e26ad0a1eaa4}}}, -{{{0xda9b6b624b531f20, 0x429a760e77509abb, 0xdbe9f522e823cb80, 0x618f1856880c8f82}}, - {{0x1833c773e18fe6c0, 0xe3c4711ad3c87265, 0x3bfd3c4f0116b283, 0x1955875eb4cd4db8}}, - {{0x6da6de8f0e399799, 0x7ad61aa440fda178, 0xb32cd8105e3563dd, 0x15f6beae2ae340ae}}}, -{{{0x862bcb0c31ec3a62, 0x810e2b451138f3c2, 0x788ec4b839dac2a4, 0x28f76867ae2a9281}}, - {{0xba9a0f7b9245e215, 0xf368612dd98c0dbb, 0x2e84e4cbf220b020, 0x6ba92fe962d90eda}}, - {{0x3e4df9655884e2aa, 0xbd62fbdbdbd465a5, 0xd7596caa0de9e524, 0x6e8042ccb2b1b3d7}}}, -{{{0xf10d3c29ce28ca6e, 0xbad34540fcb6093d, 0xe7426ed7a2ea2d3f, 0x08af9d4e4ff298b9}}, - {{0x1530653616521f7e, 0x660d06b896203dba, 0x2d3989bc545f0879, 0x4b5303af78ebd7b0}}, - {{0x72f8a6c3bebcbde8, 0x4f0fca4adc3a8e89, 0x6fa9d4e8c7bfdf7a, 0x0dcf2d679b624eb7}}}, -{{{0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e}}, - {{0x753941be5a45f06e, 0xd07caeed6d9c5f65, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9}}, - {{0x27f2af18073f3e6a, 0xfd3fe519d7521069, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7}}}, -{{{0xb4e37f405307a693, 0xaba714d72f336795, 0xd6fbd0a773761099, 0x5fdf48c58171cbc9}}, - {{0x1d9db7b9f43b29c9, 0xd605824a4f518f75, 0xf2c072bd312f9dc4, 0x1f24ac855a1545b0}}, - {{0x24d608328e9505aa, 0x4748c1d10c1420ee, 0xc7ffe45c06fb25a2, 0x00ba739e2ae395e6}}}, -{{{0x592e98de5c8790d6, 0xe5bfb7d345c2a2df, 0x115a3b60f9b49922, 0x03283a3e67ad78f3}}, - {{0xae4426f5ea88bb26, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226}}, - {{0x48241dc7be0cb939, 0x32f19b4d8b633080, 0xd3dfc90d02289308, 0x05e1296846271945}}}, -{{{0xba82eeb32d9c495a, 0xceefc8fcf12bb97c, 0xb02dabae93b5d1e0, 0x39c00c9c13698d9b}}, - {{0xadbfbbc8242c4550, 0xbcc80cecd03081d9, 0x843566a6f5c8df92, 0x78cf25d38258ce4c}}, - {{0x15ae6b8e31489d68, 0xaa851cab9c2bf087, 0xc9a75a97f04efa05, 0x006b52076b3ff832}}}, -{{{0x29e0cfe19d95781c, 0xb681df18966310e2, 0x57df39d370516b39, 0x4d57e3443bc76122}}, - {{0xf5cb7e16b9ce082d, 0x3407f14c417abc29, 0xd4b36bce2bf4a7ab, 0x7de2e9561a9f75ce}}, - {{0xde70d4f4b6a55ecb, 0x4801527f5d85db99, 0xdbc9c440d3ee9a81, 0x6b2a90af1a6029ed}}}, -{{{0x6923f4fc9ae61e97, 0x5735281de03f5fd1, 0xa764ae43e6edd12d, 0x5fd8f4e9d12d3e4a}}, - {{0x77ebf3245bb2d80a, 0xd8301b472fb9079b, 0xc647e6f24cee7333, 0x465812c8276c2109}}, - {{0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790}}}, -{{{0xc8c05eccd24da8fd, 0xa1cf1aac05dfef83, 0xdbbeeff27df9cd61, 0x3b5556a37b471e99}}, - {{0xf7fca42c7ad58195, 0x3214286e4333f3cc, 0xb6c29d0d340b979d, 0x31771a48567307e1}}, - {{0x32b0c524e14dd482, 0xedb351541a2ba4b6, 0xa3d16048282b5af3, 0x4fc079d27a7336eb}}}, -{{{0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, 0xffffc09c7880e453, 0x124567cecaf98e92}}, - {{0xdc348b440c86c50d, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08}}, - {{0x3ff9ab860ac473b4, 0xf0911dee0113e435, 0x4ae75060ebc6c4af, 0x3f8612966c87000d}}}, -{{{0x0c9c5303f7957be4, 0xa3c31a20e085c145, 0xb0721d71d0850050, 0x0aba390eab0bf2da}}, - {{0x529fdffe638c7bf3, 0xdf2b9e60388b4995, 0xe027b34f1bad0249, 0x7bc92fc9b9fa74ed}}, - {{0x9f97ef2e801ad9f9, 0x83697d5479afda3a, 0xe906b3ffbd596b50, 0x02672b37dd3fb8e0}}}, -{{{0x48b2ca8b260885e4, 0xa4286bec82b34c1c, 0x937e1a2617f58f74, 0x741d1fcbab2ca2a5}}, - {{0xee9ba729398ca7f5, 0xeb9ca6257a4849db, 0x29eb29ce7ec544e1, 0x232ca21ef736e2c8}}, - {{0xbf61423d253fcb17, 0x08803ceafa39eb14, 0xf18602df9851c7af, 0x0400f3a049e3414b}}}, -{{{0xabce0476ba61c55b, 0x36a3d6d7c4d39716, 0x6eb259d5e8d82d09, 0x0c9176e984d756fb}}, - {{0x2efba412a06e7b06, 0x146785452c8d2560, 0xdf9713ebd67a91c7, 0x32830ac7157eadf3}}, - {{0x0e782a7ab73769e8, 0x04a05d7875b18e2c, 0x29525226ebcceae1, 0x0d794f8383eba820}}}, -{{{0xff35f5cb9e1516f4, 0xee805bcf648aae45, 0xf0d73c2bb93a9ef3, 0x097b0bf22092a6c2}}, - {{0x7be44ce7a7a2e1ac, 0x411fd93efad1b8b7, 0x1734a1d70d5f7c9b, 0x0d6592233127db16}}, - {{0xc48bab1521a9d733, 0xa6c2eaead61abb25, 0x625c6c1cc6cb4305, 0x7fc90fea93eb3a67}}}, -{{{0x0408f1fe1f5c5926, 0x1a8f2f5e3b258bf4, 0x40a951a2fdc71669, 0x6598ee93c98b577e}}, - {{0xc527deb59c7cb23d, 0x955391695328404e, 0xd64392817ccf2c7a, 0x6ce97dabf7d8fa11}}, - {{0x25b5a8e50ef7c48f, 0xeb6034116f2ce532, 0xc5e75173e53de537, 0x73119fa08c12bb03}}}, -{{{0xed30129453f1a4cb, 0xbce621c9c8f53787, 0xfacb2b1338bee7b9, 0x3025798a9ea8428c}}, - {{0x7845b94d21f4774d, 0xbf62f16c7897b727, 0x671857c03c56522b, 0x3cd6a85295621212}}, - {{0x3fecde923aeca999, 0xbdaa5b0062e8c12f, 0x67b99dfc96988ade, 0x3f52c02852661036}}}, -{{{0xffeaa48e2a1351c6, 0x28624754fa7f53d7, 0x0b5ba9e57582ddf1, 0x60c0104ba696ac59}}, - {{0x9258bf99eec416c6, 0xac8a5017a9d2f671, 0x629549ab16dea4ab, 0x05d0e85c99091569}}, - {{0x051de020de9cbe97, 0xfa07fc56b50bcf74, 0x378cec9f0f11df65, 0x36853c69ab96de4d}}}, -{{{0x36d9b8de78f39b2d, 0x7f42ed71a847b9ec, 0x241cd1d679bd3fde, 0x6a704fec92fbce6b}}, - {{0x4433c0b0fac5e7be, 0x724bae854c08dcbe, 0xf1f24cc446978f9b, 0x4a0aff6d62825fc8}}, - {{0xe917fb9e61095301, 0xc102df9402a092f8, 0xbf09e2f5fa66190b, 0x681109bee0dcfe37}}}, -{{{0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d}}, - {{0x9c18fcfa36048d13, 0x29159db373899ddd, 0xdc9f350b9f92d0aa, 0x26f57eee878a19d4}}, - {{0x0cab2cd55687efb1, 0x5180d162247af17b, 0x85c15a344f5a2467, 0x4041943d9dba3069}}}, -{{{0xc3c0eeba43ebcc96, 0x8d749c9c26ea9caf, 0xd9fa95ee1c77ccc6, 0x1420a1d97684340f}}, - {{0x4b217743a26caadd, 0x47a6b424648ab7ce, 0xcb1d4f7a03fbc9e3, 0x12d931429800d019}}, - {{0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012}}}, -{{{0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae}}, - {{0x33cf3030a49866b1, 0x251f73d2215f4859, 0xab82aa4051def4f6, 0x5ff191d56f9a23f6}}, - {{0x819ed433ac2d9068, 0x2883ab795fc98523, 0xef4572805593eb3d, 0x020c526a758f36cb}}}, -{{{0x779834f89ed8dbbc, 0xc8f2aaf9dc7ca46c, 0xa9524cdca3e1b074, 0x02aacc4615313877}}, - {{0xe931ef59f042cc89, 0x2c589c9d8e124bb6, 0xadc8e18aaec75997, 0x452cfe0a5602c50c}}, - {{0x86a0f7a0647877df, 0xbbc464270e607c9f, 0xab17ea25f1fb11c9, 0x4cfb7d7b304b877b}}}, -{{{0x72b43d6cb89b75fe, 0x54c694d99c6adc80, 0xb8c3aa373ee34c9f, 0x14b4622b39075364}}, - {{0xe28699c29789ef12, 0x2b6ecd71df57190d, 0xc343c857ecc970d0, 0x5b1d4cbc434d3ac5}}, - {{0xb6fb2615cc0a9f26, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1}}}, -{{{0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, 0x9a2acc2182300f67, 0x3a6ae249d806aaf9}}, - {{0x2e12ae444f54a701, 0xfcfe3ef0a9cbd7de, 0xcebf890d75835de0, 0x1d8062e9e7614554}}, - {{0x657ada85a9907c5a, 0x1a0ea8b591b90f62, 0x8d0e1dfbdf34b4e9, 0x298b8ce8aef25ff3}}}, -{{{0x2a927953eff70cb2, 0x4b89c92a79157076, 0x9418457a30a7cf6a, 0x34b8a8404d5ce485}}, - {{0x837a72ea0a2165de, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc}}, - {{0xc26eecb583693335, 0xd5a813df63b5fefd, 0xa293aa9aa4b22573, 0x71d62bdd465e1c6a}}}, -{{{0x6533cc28d378df80, 0xf6db43790a0fa4b4, 0xe3645ff9f701da5a, 0x74d5f317f3172ba4}}, - {{0xcd2db5dab1f75ef5, 0xd77f95cf16b065f5, 0x14571fea3f49f085, 0x1c333621262b2b3d}}, - {{0xa86fe55467d9ca81, 0x398b7c752b298c37, 0xda6d0892e3ac623b, 0x4aebcc4547e9d98c}}}, -{{{0x53175a7205d21a77, 0xb0c04422d3b934d4, 0xadd9f24bdd5deadc, 0x074f46e69f10ff8c}}, - {{0x0de9b204a059a445, 0xe15cb4aa4b17ad0f, 0xe1bbec521f79c557, 0x2633f1b9d071081b}}, - {{0xc1fb4177018b9910, 0xa6ea20dc6c0fe140, 0xd661f3e74354c6ff, 0x5ecb72e6f1a3407a}}}, -{{{0xa515a31b2259fb4e, 0x0960f3972bcac52f, 0xedb52fec8d3454cb, 0x382e2720c476c019}}, - {{0xfeeae106e8e86997, 0x9863337f98d09383, 0x9470480eaa06ebef, 0x038b6898d4c5c2d0}}, - {{0xf391c51d8ace50a6, 0x3142d0b9ae2d2948, 0xdb4d5a1a7f24ca80, 0x21aeba8b59250ea8}}}, -{{{0x24f13b34cf405530, 0x3c44ea4a43088af7, 0x5dd5c5170006a482, 0x118eb8f8890b086d}}, - {{0x53853600f0087f23, 0x4c461879da7d5784, 0x6af303deb41f6860, 0x0a3c16c5c27c18ed}}, - {{0x17e49c17cc947f3d, 0xccc6eda6aac1d27b, 0xdf6092ceb0f08e56, 0x4909b3e22c67c36b}}}, -{{{0x9c9c85ea63fe2e89, 0xbe1baf910e9412ec, 0x8f7baa8a86fbfe7b, 0x0fb17f9fef968b6c}}, - {{0x59a16676706ff64e, 0x10b953dd0d86a53d, 0x5848e1e6ce5c0b96, 0x2d8b78e712780c68}}, - {{0x79d5c62eafc3902b, 0x773a215289e80728, 0xc38ae640e10120b9, 0x09ae23717b2b1a6d}}}, -{{{0xbb6a192a4e4d083c, 0x34ace0630029e192, 0x98245a59aafabaeb, 0x6d9c8a9ada97faac}}, - {{0x10ab8fa1ad32b1d0, 0xe9aced1be2778b24, 0xa8856bc0373de90f, 0x66f35ddddda53996}}, - {{0xd27d9afb24997323, 0x1bb7e07ef6f01d2e, 0x2ba7472df52ecc7f, 0x03019b4f646f9dc8}}}, -{{{0x04a186b5565345cd, 0xeee76610bcc4116a, 0x689c73b478fb2a45, 0x387dcbff65697512}}, - {{0xaf09b214e6b3dc6b, 0x3f7573b5ad7d2f65, 0xd019d988100a23b0, 0x392b63a58b5c35f7}}, - {{0x4093addc9c07c205, 0xc565be15f532c37e, 0x63dbecfd1583402a, 0x61722b4aef2e032e}}}, -{{{0x0012aafeecbd47af, 0x55a266fb1cd46309, 0xf203eb680967c72c, 0x39633944ca3c1429}}, - {{0xd6b07a5581cb0e3c, 0x290ff006d9444969, 0x08680b6a16dcda1f, 0x5568d2b75a06de59}}, - {{0x8d0cb88c1b37cfe1, 0x05b6a5a3053818f3, 0xf2e9bc04b787d959, 0x6beba1249add7f64}}}, -{{{0x1d06005ca5b1b143, 0x6d4c6bb87fd1cda2, 0x6ef5967653fcffe7, 0x097c29e8c1ce1ea5}}, - {{0x5c3cecb943f5a53b, 0x9cc9a61d06c08df2, 0xcfba639a85895447, 0x5a845ae80df09fd5}}, - {{0x4ce97dbe5deb94ca, 0x38d0a4388c709c48, 0xc43eced4a169d097, 0x0a1249fff7e587c3}}}, -{{{0x12f0071b276d01c9, 0xe7b8bac586c48c70, 0x5308129b71d6fba9, 0x5d88fbf95a3db792}}, - {{0x0b408d9e7354b610, 0x806b32535ba85b6e, 0xdbe63a034a58a207, 0x173bd9ddc9a1df2c}}, - {{0x2b500f1efe5872df, 0x58d6582ed43918c1, 0xe6ed278ec9673ae0, 0x06e1cd13b19ea319}}}, -{{{0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266}}, - {{0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13}}, - {{0xf7e644395d3d800b, 0x95a8d555c901edf6, 0x68cd7830592c6339, 0x30d0fded2e51307e}}}, -{{{0xe0594d1af21233b3, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868}}, - {{0x9cb4971e68b84750, 0xa09572296664bbcf, 0x5c8de72672fa412b, 0x4615084351c589d9}}, - {{0xbc9019c0aeb9a02e, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe}}}, -{{{0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, 0x98183da2130fb545, 0x5631deddae8f13cd}}, - {{0x9c688eb69ecc01bf, 0xf0bc83ada644896f, 0xca2d955f5f7a9fe2, 0x4ea8b4038df28241}}, - {{0x2aed460af1cad202, 0x46305305a48cee83, 0x9121774549f11a5f, 0x24ce0930542ca463}}}, -{{{0x1fe890f5fd06c106, 0xb5c468355d8810f2, 0x827808fe6e8caf3e, 0x41d4e3c28a06d74b}}, - {{0x3fcfa155fdf30b85, 0xd2f7168e36372ea4, 0xb2e064de6492f844, 0x549928a7324f4280}}, - {{0xf26e32a763ee1a2e, 0xae91e4b7d25ffdea, 0xbc3bd33bd17f4d69, 0x491b66dec0dcff6a}}}, -{{{0x98f5b13dc7ea32a7, 0xe3d5f8cc7e16db98, 0xac0abf52cbf8d947, 0x08f338d0c85ee4ac}}, - {{0x75f04a8ed0da64a1, 0xed222caf67e2284b, 0x8234a3791f7b7ba4, 0x4cf6b8b0b7018b67}}, - {{0xc383a821991a73bd, 0xab27bc01df320c7a, 0xc13d331b84777063, 0x530d4a82eb078a99}}}, -{{{0x004c3630e1f94825, 0x7e2d78268cab535a, 0xc7482323cc84ff8b, 0x65ea753f101770b9}}, - {{0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b}}, - {{0x3d66fc3ee2096363, 0x81d62c7f61b5cb6b, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db}}}, -{{{0x5ce6259a3b24b8a2, 0xb8577acc45afa0b8, 0xcccbe6e88ba07037, 0x3d143c51127809bf}}, - {{0xf5c86162f1cf795f, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf}}, - {{0x126d279179154557, 0xd5e48f5cfc783a0a, 0x36bdb6e8df179bac, 0x2ef517885ba82859}}}, -{{{0x88bd438cd11e0d4a, 0x30cb610d43ccf308, 0xe09a0e3791937bcc, 0x4559135b25b1720c}}, - {{0x1ea436837c6da1e9, 0xf9c189af1fb9bdbe, 0x303001fcce5dd155, 0x28a7c99ebc57be52}}, - {{0xb8fd9399e8d19e9d, 0x908191cb962423ff, 0xb2b948d747c742a3, 0x37f33226d7fb44c4}}}, -{{{0x0dae8767b55f6e08, 0x4a43b3b35b203a02, 0xe3725a6e80af8c79, 0x0f7a7fd1705fa7a3}}, - {{0x33912553c821b11d, 0x66ed42c241e301df, 0x066fcc11104222fd, 0x307a3b41c192168f}}, - {{0x8eeb5d076eb55ce0, 0x2fc536bfaa0d925a, 0xbe81830fdcb6c6e8, 0x556c7045827baf52}}}, -{{{0x8e2b517302e9d8b7, 0xe3e52269248714e8, 0xbd4fbd774ca960b5, 0x6f4b4199c5ecada9}}, - {{0xb94b90022bf44406, 0xabd4237eff90b534, 0x7600a960faf86d3a, 0x2f45abdac2322ee3}}, - {{0x61af4912c8ef8a6a, 0xe58fa4fe43fb6e5e, 0xb5afcc5d6fd427cf, 0x6a5393281e1e11eb}}}, -{{{0xf3da5139a5d1ee89, 0x8145457cff936988, 0x3f622fed00e188c4, 0x0f513815db8b5a3d}}, - {{0x0fff04fe149443cf, 0x53cac6d9865cddd7, 0x31385b03531ed1b7, 0x5846a27cacd1039d}}, - {{0x4ff5cdac1eb08717, 0x67e8b29590f2e9bc, 0x44093b5e237afa99, 0x0d414bed8708b8b2}}}, -{{{0xcfb68265fd0e75f6, 0xe45b3e28bb90e707, 0x7242a8de9ff92c7a, 0x685b3201933202dd}}, - {{0x81886a92294ac9e8, 0x23162b45d55547be, 0x94cfbc4403715983, 0x50eb8fdb134bc401}}, - {{0xc0b73ec6d6b330cd, 0x84e44807132faff1, 0x732b7352c4a5dee1, 0x5d7c7cf1aa7cd2d2}}}, -{{{0xaf3b46bf7a4aafa2, 0xb78705ec4d40d411, 0x114f0c6aca7c15e3, 0x3f364faaa9489d4d}}, - {{0x33d1013e9b73a562, 0x925cef5748ec26e1, 0xa7fce614dd468058, 0x78b0fad41e9aa438}}, - {{0xbf56a431ed05b488, 0xa533e66c9c495c7e, 0xe8652baf87f3651a, 0x0241800059d66c33}}}, -{{{0xceb077fea37a5be4, 0xdb642f02e5a5eeb7, 0xc2e6d0c5471270b8, 0x4771b65538e4529c}}, - {{0x28350c7dcf38ea01, 0x7c6cdbc0b2917ab6, 0xace7cfbe857082f7, 0x4d2845aba2d9a1e0}}, - {{0xbb537fe0447070de, 0xcba744436dd557df, 0xd3b5a3473600dbcb, 0x4aeabbe6f9ffd7f8}}}, -{{{0x4630119e40d8f78c, 0xa01a9bc53c710e11, 0x486d2b258910dd79, 0x1e6c47b3db0324e5}}, - {{0x6a2134bcc4a9c8f2, 0xfbf8fd1c8ace2e37, 0x000ae3049911a0ba, 0x046e3a616bc89b9e}}, - {{0x14e65442f03906be, 0x4a019d54e362be2a, 0x68ccdfec8dc230c7, 0x7cfb7e3faf6b861c}}}, -{{{0x4637974e8c58aedc, 0xb9ef22fbabf041a4, 0xe185d956e980718a, 0x2f1b78fab143a8a6}}, - {{0x96eebffb305b2f51, 0xd3f938ad889596b8, 0xf0f52dc746d5dd25, 0x57968290bb3a0095}}, - {{0xf71ab8430a20e101, 0xf393658d24f0ec47, 0xcf7509a86ee2eed1, 0x7dc43e35dc2aa3e1}}}, -{{{0x85966665887dd9c3, 0xc90f9b314bb05355, 0xc6e08df8ef2079b1, 0x7ef72016758cc12f}}, - {{0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99}}, - {{0xc1df18c5a907e3d9, 0x57b3371dce4c6359, 0xca704534b201bb49, 0x7f79823f9c30dd2e}}}, -{{{0x8334d239a3b513e8, 0xc13670d4b91fa8d8, 0x12b54136f590bd33, 0x0a4e0373d784d9b4}}, - {{0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0}}, - {{0x2eb3d6a15b7d2919, 0xb0b4f6a0d53a8235, 0x7156ce4389a45d47, 0x071a7d0ace18346c}}}, -{{{0xd3072daac887ba0b, 0x01262905bfa562ee, 0xcf543002c0ef768b, 0x2c3bcc7146ea7e9c}}, - {{0xcc0c355220e14431, 0x0d65950709b15141, 0x9af5621b209d5f36, 0x7c69bcf7617755d3}}, - {{0x07f0d7eb04e8295f, 0x10db18252f50f37d, 0xe951a9a3171798d7, 0x6f5a9a7322aca51d}}}, -{{{0x8ba1000c2f41c6c5, 0xc49f79c10cfefb9b, 0x4efa47703cc51c9f, 0x494e21a2e147afca}}, - {{0xe729d4eba3d944be, 0x8d9e09408078af9e, 0x4525567a47869c03, 0x02ab9680ee8d3b24}}, - {{0xefa48a85dde50d9a, 0x219a224e0fb9a249, 0xfa091f1dd91ef6d9, 0x6b5d76cbea46bb34}}}, -{{{0x8857556cec0cd994, 0x6472dc6f5cd01dba, 0xaf0169148f42b477, 0x0ae333f685277354}}, - {{0xe0f941171e782522, 0xf1e6ae74036936d3, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e}}, - {{0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075}}}, -{{{0x7f910fcc7ed9affe, 0x545cb8a12465874b, 0xa8397ed24b0c4704, 0x50510fc104f50993}}, - {{0x0adb7f355f17c824, 0x74b923c3d74299a4, 0xd57c3e8bcbf8eaf7, 0x0ad3e2d34cdedc3d}}, - {{0x6f0c0fc5336e249d, 0x745ede19c331cfd9, 0xf2d6fd0009eefe1c, 0x127c158bf0fa1ebe}}}, -{{{0xf6197c422e9879a2, 0xa44addd452ca3647, 0x9b413fc14b4eaccb, 0x354ef87d07ef4f68}}, - {{0xdea28fc4ae51b974, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95}}, - {{0xfee3b52260c5d975, 0x50352efceb41b0b8, 0x8808ac30a9f6653c, 0x302d92d20539236d}}}, -{{{0x4c59023fcb3efb7c, 0x6c2fcb99c63c2a94, 0xba4190e2c3c7e084, 0x0e545daea51874d9}}, - {{0x957b8b8b0df53c30, 0x2a1c770a8e60f098, 0xbbc7a670345796de, 0x22a48f9a90c99bc9}}, - {{0x6b7dc0dc8d3fac58, 0x5497cd6ce6e42bfd, 0x542f7d1bf400d305, 0x4159f47f048d9136}}}, -{{{0x20ad660839e31e32, 0xf81e1bd58405be50, 0xf8064056f4dabc69, 0x14d23dd4ce71b975}}, - {{0x748515a8bbd24839, 0x77128347afb02b55, 0x50ba2ac649a2a17f, 0x060525513ad730f1}}, - {{0xf2398e098aa27f82, 0x6d7982bb89a1b024, 0xfa694084214dd24c, 0x71ab966fa32301c3}}}, -{{{0x2dcbd8e34ded02fc, 0x1151f3ec596f22aa, 0xbca255434e0328da, 0x35768fbe92411b22}}, - {{0xb1088a0702809955, 0x43b273ea0b43c391, 0xca9b67aefe0686ed, 0x605eecbf8335f4ed}}, - {{0x83200a656c340431, 0x9fcd71678ee59c2f, 0x75d4613f71300f8a, 0x7a912faf60f542f9}}}, -{{{0xb204585e5edc1a43, 0x9f0e16ee5897c73c, 0x5b82c0ae4e70483c, 0x624a170e2bddf9be}}, - {{0x253f4f8dfa2d5597, 0x25e49c405477130c, 0x00c052e5996b1102, 0x33cb966e33bb6c4a}}, - {{0x597028047f116909, 0x828ac41c1e564467, 0x70417dbde6217387, 0x721627aefbac4384}}}, -{{{0x97d03bc38736add5, 0x2f1422afc532b130, 0x3aa68a057101bbc4, 0x4c946cf7e74f9fa7}}, - {{0xfd3097bc410b2f22, 0xf1a05da7b5cfa844, 0x61289a1def57ca74, 0x245ea199bb821902}}, - {{0xaedca66978d477f8, 0x1898ba3c29117fe1, 0xcf73f983720cbd58, 0x67da12e6b8b56351}}}, -{{{0x7067e187b4bd6e07, 0x6e8f0203c7d1fe74, 0x93c6aa2f38c85a30, 0x76297d1f3d75a78a}}, - {{0x2b7ef3d38ec8308c, 0x828fd7ec71eb94ab, 0x807c3b36c5062abd, 0x0cb64cb831a94141}}, - {{0x3030fc33534c6378, 0xb9635c5ce541e861, 0x15d9a9bed9b2c728, 0x49233ea3f3775dcb}}}, -{{{0x629398fa8dbffc3a, 0xe12fe52dd54db455, 0xf3be11dfdaf25295, 0x628b140dce5e7b51}}, - {{0x7b3985fe1c9f249b, 0x4fd6b2d5a1233293, 0xceb345941adf4d62, 0x6987ff6f542de50c}}, - {{0x47e241428f83753c, 0x6317bebc866af997, 0xdabb5b433d1a9829, 0x074d8d245287fb2d}}}, -{{{0x8337d9cd440bfc31, 0x729d2ca1af318fd7, 0xa040a4a4772c2070, 0x46002ef03a7349be}}, - {{0x481875c6c0e31488, 0x219429b2e22034b4, 0x7223c98a31283b65, 0x3420d60b342277f9}}, - {{0xfaa23adeaffe65f7, 0x78261ed45be0764c, 0x441c0a1e2f164403, 0x5aea8e567a87d395}}}, -{{{0x7813c1a2bca4283d, 0xed62f091a1863dd9, 0xaec7bcb8c268fa86, 0x10e5d3b76f1cae4c}}, - {{0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060}}, - {{0x5453bfd653da8e67, 0xe9dc1eec24a9f641, 0xbf87263b03578a23, 0x45b46c51361cba72}}}, -{{{0xa9402abf314f7fa1, 0xe257f1dc8e8cf450, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b}}, - {{0xce9d4ddd8a7fe3e4, 0xab13645676620e30, 0x4b594f7bb30e9958, 0x5c1c0aef321229df}}, - {{0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb}}}, -{{{0x8ddbf6aa5344a32e, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03}}, - {{0x61117e44985bfb83, 0xfce0462a71963136, 0x83ac3448d425904b, 0x75685abe5ba43d64}}, - {{0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, 0xdf7275107af66569, 0x135529b623b0e6aa}}}, -{{{0x18f0dbd7add1d518, 0x979f7888cfc11f11, 0x8732e1f07114759b, 0x79b5b81a65ca3a01}}, - {{0xf5c716bce22e83fe, 0xb42beb19e80985c1, 0xec9da63714254aae, 0x5972ea051590a613}}, - {{0x0fd4ac20dc8f7811, 0x9a9ad294ac4d4fa8, 0xc01b2d64b3360434, 0x4f7e9c95905f3bdb}}}, -{{{0x62674bbc5781302e, 0xd8520f3989addc0f, 0x8c2999ae53fbd9c6, 0x31993ad92e638e4c}}, - {{0x71c8443d355299fe, 0x8bcd3b1cdbebead7, 0x8092499ef1a49466, 0x1942eec4a144adc8}}, - {{0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75}}}, -{{{0x2db7937ff7f927c2, 0xdb741f0617d0a635, 0x5982f3a21155af76, 0x4cf6e218647c2ded}}, - {{0xcf361acd3c1c793a, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13}}, - {{0xb119227cc28d5bb6, 0x07e24ebc774dffab, 0xa83c78cee4a32c89, 0x121a307710aa24b6}}}, -{{{0xe4db5d5e9f034a97, 0xe153fc093034bc2d, 0x460546919551d3b1, 0x333fc76c7a40e52d}}, - {{0xd659713ec77483c9, 0x88bfe077b82b96af, 0x289e28231097bcd3, 0x527bb94a6ced3a9b}}, - {{0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7}}}, -{{{0x812aa0416270220d, 0x995a89faf9245b4e, 0xffadc4ce5072ef05, 0x23bc2103aa73eb73}}, - {{0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf}}, - {{0xcaee792603589e05, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a}}}, -{{{0xb5a2d50c7ec20d3e, 0xc64bdd6ea0c97263, 0x56e89052c1ff734d, 0x4929c6f72b2ffaba}}, - {{0x358ecba293a36247, 0xaf8f9862b268fd65, 0x412f7e9968a01c89, 0x5786f312cd754524}}, - {{0x337788ffca14032c, 0xf3921028447f1ee3, 0x8b14071f231bccad, 0x4c817b4bf2344783}}}, -{{{0x0ff853852871b96e, 0xe13e9fab60c3f1bb, 0xeefd595325344402, 0x0a37c37075b7744b}}, - {{0x413ba057a40b4484, 0xba4c2e1a4f5f6a43, 0x614ba0a5aee1d61c, 0x78a1531a8b05dc53}}, - {{0x6cbdf1703ad0562b, 0x8ecf4830c92521a3, 0xdaebd303fd8424e7, 0x72ad82a42e5ec56f}}}, -{{{0x3f9e8e35bafb65f6, 0x39d69ec8f27293a1, 0x6cb8cd958cf6a3d0, 0x1734778173adae6d}}, - {{0xc368939167024bc3, 0x8e69d16d49502fda, 0xfcf2ec3ce45f4b29, 0x065f669ea3b4cbc4}}, - {{0x8a00aec75532db4d, 0xb869a4e443e31bb1, 0x4a0f8552d3a7f515, 0x19adeb7c303d7c08}}}, -{{{0xc720cb6153ead9a3, 0x55b2c97f512b636e, 0xb1e35b5fd40290b1, 0x2fd9ccf13b530ee2}}, - {{0x9d05ba7d43c31794, 0x2470c8ff93322526, 0x8323dec816197438, 0x2852709881569b53}}, - {{0x07bd475b47f796b8, 0xd2c7b013542c8f54, 0x2dbd23f43b24f87e, 0x6551afd77b0901d6}}}, -{{{0x4546baaf54aac27f, 0xf6f66fecb2a45a28, 0x582d1b5b562bcfe8, 0x44b123f3920f785f}}, - {{0x68a24ce3a1d5c9ac, 0xbb77a33d10ff6461, 0x0f86ce4425d3166e, 0x56507c0950b9623b}}, - {{0x1206f0b7d1713e63, 0x353fe3d915bafc74, 0x194ceb970ad9d94d, 0x62fadd7cf9d03ad3}}}, -{{{0xc6b5967b5598a074, 0x5efe91ce8e493e25, 0xd4b72c4549280888, 0x20ef1149a26740c2}}, - {{0x3cd7bc61e7ce4594, 0xcd6b35a9b7dd267e, 0xa080abc84366ef27, 0x6ec7c46f59c79711}}, - {{0x2f07ad636f09a8a2, 0x8697e6ce24205e7d, 0xc0aefc05ee35a139, 0x15e80958b5f9d897}}}, -{{{0x25a5ef7d0c3e235b, 0x6c39c17fbe134ee7, 0xc774e1342dc5c327, 0x021354b892021f39}}, - {{0x4dd1ed355bb061c4, 0x42dc0cef941c0700, 0x61305dc1fd86340e, 0x56b2cc930e55a443}}, - {{0x1df79da6a6bfc5a2, 0x02f3a2749fde4369, 0xb323d9f2cda390a7, 0x7be0847b8774d363}}}, -{{{0x8c99cc5a8b3f55c3, 0x0611d7253fded2a0, 0xed2995ff36b70a36, 0x1f699a54d78a2619}}, - {{0x1466f5af5307fa11, 0x817fcc7ded6c0af2, 0x0a6de44ec3a4a3fb, 0x74071475bc927d0b}}, - {{0xe77292f373e7ea8a, 0x296537d2cb045a31, 0x1bd0653ed3274fde, 0x2f9a2c4476bd2966}}}, -{{{0xeb18b9ab7f5745c6, 0x023a8aee5787c690, 0xb72712da2df7afa9, 0x36597d25ea5c013d}}, - {{0xa2b4dae0b5511c9a, 0x7ac860292bffff06, 0x981f375df5504234, 0x3f6bd725da4ea12d}}, - {{0x734d8d7b106058ac, 0xd940579e6fc6905f, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0}}}, -{{{0x78c2373c695c690d, 0xdd252e660642906e, 0x951d44444ae12bd2, 0x4235ad7601743956}}, - {{0x6dae4a51a77cfa9b, 0x82263654e7a38650, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba}}, - {{0x6258cb0d078975f5, 0x492942549189f298, 0xa0cab423e2e36ee4, 0x0e7ce2b0cdf066a1}}}, -{{{0xc494643ac48c85a3, 0xfd361df43c6139ad, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a}}, - {{0xfea6fedfd94b70f9, 0xf130c051c1fcba2d, 0x4882d47e7f2fab89, 0x615256138aeceeb5}}, - {{0x2abbf64e4870cb0d, 0xcd65bcf0aa458b6b, 0x9abe4eba75e8985d, 0x7f0bc810d514dee4}}}, -{{{0xb9006ba426f4136f, 0x8d67369e57e03035, 0xcbc8dfd94f463c28, 0x0d1f8dbcf8eedbf5}}, - {{0x83ac9dad737213a0, 0x9ff6f8ba2ef72e98, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75}}, - {{0xba1693313ed081dc, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3}}}, -{{{0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1}}, - {{0x16561f696a0aa75c, 0xc1bf725c5852bd6a, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026}}, - {{0x00120753afbd232e, 0xe92bceb8fdd8f683, 0xf81669b384e72b91, 0x33fad52b2368a066}}}, -{{{0x540649c6c5e41e16, 0x0af86430333f7735, 0xb2acfcd2f305e746, 0x16c0f429a256dca7}}, - {{0x8d2cc8d0c422cfe8, 0x072b4f7b05a13acb, 0xa3feb6e6ecf6a56f, 0x3cc355ccb90a71e2}}, - {{0xe9b69443903e9131, 0xb8a494cb7a5637ce, 0xc87cd1a4baba9244, 0x631eaf426bae7568}}}, -{{{0xb3e90410da66fe9f, 0x85dd4b526c16e5a6, 0xbc3d97611ef9bf83, 0x5599648b1ea919b5}}, - {{0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5}}, - {{0xd6026344858f7b19, 0x14ab352fa1ea514a, 0x8900441a2090a9d7, 0x7b04715f91253b26}}}, -{{{0x83edbd28acf6ae43, 0x86357c8b7d5c7ab4, 0xc0404769b7eb2c44, 0x59b37bf5c2f6583f}}, - {{0xb376c280c4e6bac6, 0x970ed3dd6d1d9b0b, 0xb09a9558450bf944, 0x48d0acfa57cde223}}, - {{0xb60f26e47dabe671, 0xf1d1a197622f3a37, 0x4208ce7ee9960394, 0x16234191336d3bdb}}}, -{{{0xf19aeac733a63aef, 0x2c7fba5d4442454e, 0x5da87aa04795e441, 0x413051e1a4e0b0f5}}, - {{0x852dd1fd3d578bbe, 0x2b65ce72c3286108, 0x658c07f4eace2273, 0x0933f804ec38ab40}}, - {{0xa7ab69798d496476, 0x8121aadefcb5abc8, 0xa5dc12ef7b539472, 0x07fd47065e45351a}}}, -{{{0xc8583c3d258d2bcd, 0x17029a4daf60b73f, 0xfa0fc9d6416a3781, 0x1c1e5fba38b3fb23}}, - {{0x304211559ae8e7c3, 0xf281b229944882a5, 0x8a13ac2e378250e4, 0x014afa0954ba48f4}}, - {{0xcb3197001bb3666c, 0x330060524bffecb9, 0x293711991a88233c, 0x291884363d4ed364}}}, -{{{0x033c6805dc4babfa, 0x2c15bf5e5596ecc1, 0x1bc70624b59b1d3b, 0x3ede9850a19f0ec5}}, - {{0xfb9d37c3bc1ab6eb, 0x02be14534d57a240, 0xf4d73415f8a5e1f6, 0x5964f4300ccc8188}}, - {{0xe44a23152d096800, 0x5c08c55970866996, 0xdf2db60a46affb6e, 0x579155c1f856fd89}}}, -{{{0x96324edd12e0c9ef, 0x468b878df2420297, 0x199a3776a4f573be, 0x1e7fbcf18e91e92a}}, - {{0xb5f16b630817e7a6, 0x808c69233c351026, 0x324a983b54cef201, 0x53c092084a485345}}, - {{0xd2d41481f1cbafbf, 0x231d2db6716174e5, 0x0b7d7656e2a55c98, 0x3e955cd82aa495f6}}}, -{{{0xe48f535e3ed15433, 0xd075692a0d7270a3, 0x40fbd21daade6387, 0x14264887cf4495f5}}, - {{0xab39f3ef61bb3a3f, 0x8eb400652eb9193e, 0xb5de6ecc38c11f74, 0x654d7e9626f3c49f}}, - {{0xe564cfdd5c7d2ceb, 0x82eeafded737ccb9, 0x6107db62d1f9b0ab, 0x0b6baac3b4358dbb}}}, -{{{0x7ae62bcb8622fe98, 0x47762256ceb891af, 0x1a5a92bcf2e406b4, 0x7d29401784e41501}}, - {{0x204abad63700a93b, 0xbe0023d3da779373, 0xd85f0346633ab709, 0x00496dc490820412}}, - {{0x1c74b88dc27e6360, 0x074854268d14850c, 0xa145fb7b3e0dcb30, 0x10843f1b43803b23}}}, -{{{0xc5f90455376276dd, 0xce59158dd7645cd9, 0x92f65d511d366b39, 0x11574b6e526996c4}}, - {{0xd56f672de324689b, 0xd1da8aedb394a981, 0xdd7b58fe9168cfed, 0x7ce246cd4d56c1e8}}, - {{0xb8f4308e7f80be53, 0x5f3cb8cb34a9d397, 0x18a961bd33cc2b2c, 0x710045fb3a9af671}}}, -{{{0x73f93d36101b95eb, 0xfaef33794f6f4486, 0x5651735f8f15e562, 0x7fa3f19058b40da1}}, - {{0xa03fc862059d699e, 0x2370cfa19a619e69, 0xc4fe3b122f823deb, 0x1d1b056fa7f0844e}}, - {{0x1bc64631e56bf61f, 0xd379ab106e5382a3, 0x4d58c57e0540168d, 0x566256628442d8e4}}}, -{{{0xb9e499def6267ff6, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006}}, - {{0xdd499cd61ff38640, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231}}, - {{0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc}}}, -{{{0x0b6e5517fd181bae, 0x9022629f2bb963b4, 0x5509bce932064625, 0x578edd74f63c13da}}, - {{0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd}}, - {{0x997276c6492b0c3d, 0x47ccc2c4dfe205fc, 0xdcd29b84dd623a3c, 0x3ec2ab590288c7a2}}}, -{{{0xa1a0d27be4d87bb9, 0xa98b4deb61391aed, 0x99a0ddd073cb9b83, 0x2dd5c25a200fcace}}, - {{0xa7213a09ae32d1cb, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e}}, - {{0xe2abd5e9792c887e, 0x1a020018cb926d5d, 0xbfba69cdbaae5f1e, 0x730548b35ae88f5f}}}, -{{{0xc43551a3cba8b8ee, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca}}, - {{0x805b094ba1d6e334, 0xbf3ef17709353f19, 0x423f06cb0622702b, 0x585a2277d87845dd}}, - {{0xa18a5f8233d48962, 0x6698c4b5ec78257f, 0xa78e6fa5373e41ff, 0x7656278950ef981f}}}, -{{{0x38c3cf59d51fc8c0, 0x9bedd2fd0506b6f2, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6}}, - {{0xe17073a3ea86cf9d, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616}}, - {{0xf2612f5c6f136c7c, 0xafead107f6dd11be, 0x527e9ad213de6f33, 0x1e79cb358188f75d}}}, -{{{0x013436c3eef7e3f1, 0x828b6a7ffe9e10f8, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831}}, - {{0x77e953d8f5e08181, 0x84a50c44299dded9, 0xdc6c2d0c864525e5, 0x478ab52d39d1f2f4}}, - {{0x66a6a4d39252d159, 0xe5dde1bc871ac807, 0xb82c6b40a6c1c96f, 0x16d87a411a212214}}}, -{{{0xb3bd7e5a42066215, 0x879be3cd0c5a24c1, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6}}, - {{0xfba4d5e2d54e0583, 0xe21fafd72ebd99fa, 0x497ac2736ee9778f, 0x1f990b577a5a6dde}}, - {{0xa3344ead1be8f7d6, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e}}}, -{{{0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd}}, - {{0xd8ac9929943c6fe4, 0xb5f9f161a38392a2, 0x2699db13bec89af3, 0x7dcf843ce405f074}}, - {{0x6c90d6484a4732c0, 0xd52143fdca563299, 0xb3be28c3915dc6e1, 0x6739687e7327191b}}}, -{{{0x9f65c5ea200814cf, 0x840536e169a31740, 0x8b0ed13925c8b4ad, 0x0080dbafe936361d}}, - {{0x8ce5aad0c9cb971f, 0x1156aaa99fd54a29, 0x41f7247015af9b78, 0x1fe8cca8420f49aa}}, - {{0x72a1848f3c0cc82a, 0x38c560c2877c9e54, 0x5004e228ce554140, 0x042418a103429d71}}}, -{{{0x899dea51abf3ff5f, 0x9b93a8672fc2d8ba, 0x2c38cb97be6ebd5c, 0x114d578497263b5d}}, - {{0x58e84c6f20816247, 0x8db2b2b6e36fd793, 0x977182561d484d85, 0x0822024f8632abd7}}, - {{0xb301bb7c6b1beca3, 0x55393f6dc6eb1375, 0x910d281097b6e4eb, 0x1ad4548d9d479ea3}}}, -{{{0xcd5a7da0389a48fd, 0xb38fa4aa9a78371e, 0xc6d9761b2cdb8e6c, 0x35cf51dbc97e1443}}, - {{0xa06fe66d0fe9fed3, 0xa8733a401c587909, 0x30d14d800df98953, 0x41ce5876c7b30258}}, - {{0x59ac3bc5d670c022, 0xeae67c109b119406, 0x9798bdf0b3782fda, 0x651e3201fd074092}}}, -{{{0xd63d8483ef30c5cf, 0x4cd4b4962361cc0c, 0xee90e500a48426ac, 0x0af51d7d18c14eeb}}, - {{0xa57ba4a01efcae9e, 0x769f4beedc308a94, 0xd1f10eeb3603cb2e, 0x4099ce5e7e441278}}, - {{0x1ac98e4f8a5121e9, 0x7dae9544dbfa2fe0, 0x8320aa0dd6430df9, 0x667282652c4a2fb5}}}, -{{{0x874621f4d86bc9ab, 0xb54c7bbe56fe6fea, 0x077a24257fadc22c, 0x1ab53be419b90d39}}, - {{0xada8b6e02946db23, 0x1c0ce51a7b253ab7, 0x8448c85a66dd485b, 0x7f1fc025d0675adf}}, - {{0xd8ee1b18319ea6aa, 0x004d88083a21f0da, 0x3bd6aa1d883a4f4b, 0x4db9a3a6dfd9fd14}}}, -{{{0x8ce7b23bb99c0755, 0x35c5d6edc4f50f7a, 0x7e1e2ed2ed9b50c3, 0x36305f16e8934da1}}, - {{0xd95b00bbcbb77c68, 0xddbc846a91f17849, 0x7cf700aebe28d9b3, 0x5ce1285c85d31f3e}}, - {{0x31b6972d98b0bde8, 0x7d920706aca6de5b, 0xe67310f8908a659f, 0x50fac2a6efdf0235}}}, -{{{0xf3d3a9f35b880f5a, 0xedec050cdb03e7c2, 0xa896981ff9f0b1a2, 0x49a4ae2bac5e34a4}}, - {{0x295b1c86f6f449bc, 0x51b2e84a1f0ab4dd, 0xc001cb30aa8e551d, 0x6a28d35944f43662}}, - {{0x28bb12ee04a740e0, 0x14313bbd9bce8174, 0x72f5b5e4e8c10c40, 0x7cbfb19936adcd5b}}}, -{{{0xa311ddc26b89792d, 0x1b30b4c6da512664, 0x0ca77b4ccf150859, 0x1de443df1b009408}}, - {{0x8e793a7acc36e6e0, 0xf9fab7a37d586eed, 0x3a4f9692bae1f4e4, 0x1c14b03eff5f447e}}, - {{0x19647bd114a85291, 0x57b76cb21034d3af, 0x6329db440f9d6dfa, 0x5ef43e586a571493}}}, -{{{0xef782014385675a6, 0xa2649f30aafda9e8, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3}}, - {{0xa66dcc9dc80c1ac0, 0x97a05cf41b38a436, 0xa7ebf3be95dbd7c6, 0x7da0b8f68d7e7dab}}, - {{0xd40f1953c3b5da76, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b}}}, -{{{0x8f6301cf70a13d11, 0xcfceb815350dd0c4, 0xf70297d4a4bca47e, 0x3669b656e44d1434}}, - {{0x9e9628d3a0a643b9, 0xb5c3cb00e6c32064, 0x9b5302897c2dec32, 0x43e37ae2d5d1c70c}}, - {{0x387e3f06eda6e133, 0x67301d5199a13ac0, 0xbd5ad8f836263811, 0x6a21e6cd4fd5e9be}}}, -{{{0xf1c6170a3046e65f, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57}}, - {{0xef4129126699b2e3, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36}}, - {{0xa6db088d5ef8790b, 0x5278f0dc610937e5, 0xac0349d261a16eb8, 0x0eafb03790e52179}}}, -{{{0x960555c13748042f, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661}}, - {{0x5140805e0f75ae1d, 0xec02fbe32662cc30, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3}}, - {{0x9cf289b9bba543ee, 0xf3760e9d5ac97142, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f}}}, -{{{0x524c299c18d0936d, 0xc86bb56c8a0c1a0c, 0xa375052edb4a8631, 0x5c0efde4bc754562}}, - {{0x7585d4263af77a3c, 0xdfae7b11fee9144d, 0xa506708059f7193d, 0x14f29a5383922037}}, - {{0xdf717edc25b2d7f5, 0x21f970db99b53040, 0xda9234b7c3ed4c62, 0x5e72365c7bee093e}}}, -{{{0x575bfc074571217f, 0x3779675d0694d95b, 0x9a0a37bbf4191e33, 0x77f1104c47b4eabc}}, - {{0x7d9339062f08b33e, 0x5b9659e5df9f32be, 0xacff3dad1f9ebdfd, 0x70b20555cb7349b7}}, - {{0xbe5113c555112c4c, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a}}}, -{{{0xb67d22d93ecebde8, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372}}, - {{0x18930b093e4b1928, 0x7de3e10e73f3f640, 0xf43217da73395d6f, 0x6f8aded6ca379c3e}}, - {{0xe340123dfdb7b29a, 0x487b97e1a21ab291, 0xf9967d02fde6949e, 0x780de72ec8d3de97}}}, -{{{0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4}}, - {{0x671feaf300f42772, 0x8f72eb2a2a8c41aa, 0x29a17fd797373292, 0x1defc6ad32b587a6}}, - {{0xaf5bbe1aef5195a7, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867}}}, -{{{0x7906ee72f7bd2e6b, 0x05d270d6109abf4e, 0x8d5cfe45b941a8a4, 0x44c218671c974287}}, - {{0x745f9d56296bc318, 0x993580d4d8152e65, 0xb0e5b13f5839e9ce, 0x51fc2b28d43921c0}}, - {{0x1b8fd11795e2a98c, 0x1c4e5ee12b6b6291, 0x5b30e7107424b572, 0x6e6b9de84c4f4ac6}}}, -{{{0xdff25fce4b1de151, 0xd841c0c7e11c4025, 0x2554b3c854749c87, 0x2d292459908e0df9}}, - {{0x6b7c5f10f80cb088, 0x736b54dc56e42151, 0xc2b620a5c6ef99c4, 0x5f4c802cc3a06f42}}, - {{0x9b65c8f17d0752da, 0x881ce338c77ee800, 0xc3b514f05b62f9e3, 0x66ed5dd5bec10d48}}}, -{{{0x7d38a1c20bb2089d, 0x808334e196ccd412, 0xc4a70b8c6c97d313, 0x2eacf8bc03007f20}}, - {{0xf0adf3c9cbca047d, 0x81c3b2cbf4552f6b, 0xcfda112d44735f93, 0x1f23a0c77e20048c}}, - {{0xf235467be5bc1570, 0x03d2d9020dbab38c, 0x27529aa2fcf9e09e, 0x0840bef29d34bc50}}}, -{{{0x796dfb35dc10b287, 0x27176bcd5c7ff29d, 0x7f3d43e8c7b24905, 0x0304f5a191c54276}}, - {{0xcd54e06b7f37e4eb, 0x8cc15f87f5e96cca, 0xb8248bb0d3597dce, 0x246affa06074400c}}, - {{0x37d88e68fbe45321, 0x86097548c0d75032, 0x4e9b13ef894a0d35, 0x25a83cac5753d325}}}, -{{{0x10222f48eed8165e, 0x623fc1234b8bcf3a, 0x1e145c09c221e8f0, 0x7ccfa59fca782630}}, - {{0x9f0f66293952b6e2, 0x33db5e0e0934267b, 0xff45252bd609fedc, 0x06be10f5c506e0c9}}, - {{0x1a9615a9b62a345f, 0x22050c564a52fecc, 0xa7a2788528bc0dfe, 0x5e82770a1a1ee71d}}}, -{{{0x35425183ad896a5c, 0xe8673afbe78d52f6, 0x2c66f25f92a35f64, 0x09d04f3b3b86b102}}, - {{0xe802e80a42339c74, 0x34175166a7fffae5, 0x34865d1f1c408cae, 0x2cca982c605bc5ee}}, - {{0xfd2d5d35197dbe6e, 0x207c2eea8be4ffa3, 0x2613d8db325ae918, 0x7a325d1727741d3e}}}, -{{{0xd036b9bbd16dfde2, 0xa2055757c497a829, 0x8e6cc966a7f12667, 0x4d3b1a791239c180}}, - {{0xecd27d017e2a076a, 0xd788689f1636495e, 0x52a61af0919233e5, 0x2a479df17bb1ae64}}, - {{0x9e5eee8e33db2710, 0x189854ded6c43ca5, 0xa41c22c592718138, 0x27ad5538a43a5e9b}}}, -{{{0x2746dd4b15350d61, 0xd03fcbc8ee9521b7, 0xe86e365a138672ca, 0x510e987f7e7d89e2}}, - {{0xcb5a7d638e47077c, 0x8db7536120a1c059, 0x549e1e4d8bedfdcc, 0x080153b7503b179d}}, - {{0xdda69d930a3ed3e3, 0x3d386ef1cd60a722, 0xc817ad58bdaa4ee6, 0x23be8d554fe7372a}}}, -{{{0x95fe919a74ef4fad, 0x3a827becf6a308a2, 0x964e01d309a47b01, 0x71c43c4f5ba3c797}}, - {{0xbc1ef4bd567ae7a9, 0x3f624cb2d64498bd, 0xe41064d22c1f4ec8, 0x2ef9c5a5ba384001}}, - {{0xb6fd6df6fa9e74cd, 0xf18278bce4af267a, 0x8255b3d0f1ef990e, 0x5a758ca390c5f293}}}, -{{{0xa2b72710d9462495, 0x3aa8c6d2d57d5003, 0xe3d400bfa0b487ca, 0x2dbae244b3eb72ec}}, - {{0x8ce0918b1d61dc94, 0x8ded36469a813066, 0xd4e6a829afe8aad3, 0x0a738027f639d43f}}, - {{0x980f4a2f57ffe1cc, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c}}}, -{{{0xe765318832b0ba78, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07}}, - {{0x2e3d702f5e3dd90e, 0x9e3f0918e4d25386, 0x5e773ef6024da96a, 0x3c004b0c4afa3332}}, - {{0x9aa946ac06f4b82b, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217}}}, -{{{0xc7a75d4b4697c544, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714}}, - {{0xb5c742583e760ef3, 0x75dc52b9ee0ab990, 0xbf1427c2072b923f, 0x73420b2d6ff0d9f0}}, - {{0xaf2cf6cb9e851e06, 0x8f593913c62238c4, 0xda8ab89699fbf373, 0x3db5632fea34bc9e}}}, -{{{0xf46eee2bf75dd9d8, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13}}, - {{0x2e4990b1829825d5, 0xedeaeb873e9a8991, 0xeef03d394c704af8, 0x59197ea495df2b0e}}, - {{0x04e16019e4e55aae, 0xe77b437a7e2f92e9, 0xc7ce2dc16f159aa4, 0x45eafdc1f4d70cc0}}}, -{{{0x698401858045d72b, 0x4c22faa2cf2f0651, 0x941a36656b222dc6, 0x5a5eebc80362dade}}, - {{0xb60e4624cfccb1ed, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940}}, - {{0xb7a7bfd10a4e8dc6, 0xbe57007e44c9b339, 0x60c1207f1557aefa, 0x26058891266218db}}}, -{{{0x59f704a68360ff04, 0xc3d93fde7661e6f4, 0x831b2a7312873551, 0x54ad0c2e4e615d57}}, - {{0x4c818e3cc676e542, 0x5e422c9303ceccad, 0xec07cccab4129f08, 0x0dedfa10b24443b8}}, - {{0xee3b67d5b82b522a, 0x36f163469fa5c1eb, 0xa5b4d2f26ec19fd3, 0x62ecb2baa77a9408}}}, -{{{0xe5ed795261152b3d, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be}}, - {{0x92072836afb62874, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98}}, - {{0x0dc62d361a3231da, 0xfa47583294200270, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c}}}, -{{{0x3f50a50a4ffb81ef, 0xb1e035093bf420bf, 0x9baa8e1cc6aa2cd0, 0x32239861fa237a40}}, - {{0xfb735ac2004a35d1, 0x31de0f433a6607c3, 0x7b8591bfc528d599, 0x55be9a25f5bb050c}}, - {{0x0d005acd33db3dbf, 0x0111b37c80ac35e2, 0x4892d66c6f88ebeb, 0x770eadb16508fbcd}}}, -{{{0x8451f9e05e4e89dd, 0xc06302ffbc793937, 0x5d22749556a6495c, 0x09a6755ca05603fb}}, - {{0xf1d3b681a05071b9, 0x2207659a3592ff3a, 0x5f0169297881e40e, 0x16bedd0e86ba374e}}, - {{0x5ecccc4f2c2737b5, 0x43b79e0c2dccb703, 0x33e008bc4ec43df3, 0x06c1b840f07566c0}}}, -{{{0x7688a5c6a388f877, 0x02a96c14deb2b6ac, 0x64c9f3431b8c2af8, 0x3628435554a1eed6}}, - {{0x69ee9e7f9b02805c, 0xcbff828a547d1640, 0x3d93a869b2430968, 0x46b7b8cd3fe26972}}, - {{0xe9812086fe7eebe0, 0x4cba6be72f515437, 0x1d04168b516efae9, 0x5ea1391043982cb9}}}, -{{{0x49125c9cf4702ee1, 0x4520b71f8b25b32d, 0x33193026501fef7e, 0x656d8997c8d2eb2b}}, - {{0x6f2b3be4d5d3b002, 0xafec33d96a09c880, 0x035f73a4a8bcc4cc, 0x22c5b9284662198b}}, - {{0xcb58c8fe433d8939, 0x89a0cb2e6a8d7e50, 0x79ca955309fbbe5a, 0x0c626616cd7fc106}}}, -{{{0x1ffeb80a4879b61f, 0x6396726e4ada21ed, 0x33c7b093368025ba, 0x471aa0c6f3c31788}}, - {{0x8fdfc379fbf454b1, 0x45a5a970f1a4b771, 0xac921ef7bad35915, 0x42d088dca81c2192}}, - {{0x8fda0f37a0165199, 0x0adadb77c8a0e343, 0x20fbfdfcc875e820, 0x1cf2bea80c2206e7}}}, -{{{0xc2ddf1deb36202ac, 0x92a5fe09d2e27aa5, 0x7d1648f6fc09f1d3, 0x74c2cc0513bc4959}}, - {{0x982d6e1a02c0412f, 0x90fa4c83db58e8fe, 0x01c2f5bcdcb18bc0, 0x686e0c90216abc66}}, - {{0x1fadbadba54395a7, 0xb41a02a0ae0da66a, 0xbf19f598bba37c07, 0x6a12b8acde48430d}}}, -{{{0xf8daea1f39d495d9, 0x592c190e525f1dfc, 0xdb8cbd04c9991d1b, 0x11f7fda3d88f0cb7}}, - {{0x793bdd801aaeeb5f, 0x00a2a0aac1518871, 0xe8a373a31f2136b4, 0x48aab888fc91ef19}}, - {{0x041f7e925830f40e, 0x002d6ca979661c06, 0x86dc9ff92b046a2e, 0x760360928b0493d1}}}, -{{{0x21bb41c6120cf9c6, 0xeab2aa12decda59b, 0xc1a72d020aa48b34, 0x215d4d27e87d3b68}}, - {{0xb43108e5695a0b05, 0x6cb00ee8ad37a38b, 0x5edad6eea3537381, 0x3f2602d4b6dc3224}}, - {{0xc8b247b65bcaf19c, 0x49779dc3b1b2c652, 0x89a180bbd5ece2e2, 0x13f098a3cec8e039}}}, -{{{0x9adc0ff9ce5ec54b, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b}}, - {{0xf3aa57a22796bb14, 0x883abab79b07da21, 0xe54be21831a0391c, 0x5ee7fb38d83205f9}}, - {{0x538dfdcb41446a8e, 0xa5acfda9434937f9, 0x46af908d263c8c78, 0x61d0633c9bca0d09}}}, -{{{0x63744935ffdb2566, 0xc5bd6b89780b68bb, 0x6f1b3280553eec03, 0x6e965fd847aed7f5}}, - {{0xada328bcf8fc73df, 0xee84695da6f037fc, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc}}, - {{0x9ad2b953ee80527b, 0xe88f19aafade6d8d, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc}}}, -{{{0xebb355406a3126c2, 0xd26383a868c8c393, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147}}, - {{0xd1997dae8e9f7374, 0xa032a2f8cfbb0816, 0xcd6cba126d445f0a, 0x1ba811460accb834}}, - {{0x708169fb0c429954, 0xe14600acd76ecf67, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2}}}, -{{{0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd}}, - {{0xc845dfa56de66fde, 0xe152a5002c40483a, 0xe9d2e163c7b4f632, 0x30f4452edcbc1b65}}, - {{0x856d2782c5759740, 0xfa134569f99cbecc, 0x8844fc73c0ea4e71, 0x632d9a1a593f2469}}}, -{{{0xf6bb6b15b807cba6, 0x1823c7dfbc54f0d7, 0xbb1d97036e29670b, 0x0b24f48847ed4a57}}, - {{0xbf09fd11ed0c84a7, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2}}, - {{0xdcdad4be511beac7, 0xa4538075ed26ccf2, 0xe19cff9f005f9a65, 0x34fcf74475481f63}}}, -{{{0xc197e04c789767ca, 0xb8714dcb38d9467d, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7}}, - {{0xa5bb1dab78cfaa98, 0x5ceda267190b72f2, 0x9309c9110a92608e, 0x0119a3042fb374b0}}, - {{0x67a2d89ce8c2177d, 0x669da5f66895d0c1, 0xf56598e5b282a2b0, 0x56c088f1ede20a73}}}, -{{{0x336d3d1110a86e17, 0xd7f388320b75b2fa, 0xf915337625072988, 0x09674c6b99108b87}}, - {{0x581b5fac24f38f02, 0xa90be9febae30cbd, 0x9a2169028acf92f0, 0x038b7ea48359038f}}, - {{0x9f4ef82199316ff8, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65}}}, -{{{0xb16c62f587e593fb, 0x4999eddeca5d3e71, 0xb491c1e014cc3e6d, 0x08f5114789a8dba8}}, - {{0x3304fb0e63066222, 0xfb35068987acba3f, 0xbd1924778c1061a3, 0x3058ad43d1838620}}, - {{0x323c0ffde57663d0, 0x05c3df38a22ea610, 0xbdc78abdac994f9a, 0x26549fa4efe3dc99}}}, -{{{0x738b38d787ce8f89, 0xb62658e24179a88d, 0x30738c9cf151316d, 0x49128c7f727275c9}}, - {{0x04dbbc17f75396b9, 0x69e6a2d7d2f86746, 0xc6409d99f53eabc6, 0x606175f6332e25d2}}, - {{0x4021370ef540e7dd, 0x0910d6f5a1f1d0a5, 0x4634aacd5b06b807, 0x6a39e6356944f235}}}, -{{{0x96cd5640df90f3e7, 0x6c3a760edbfa25ea, 0x24f3ef0959e33cc4, 0x42889e7e530d2e58}}, - {{0x1da1965774049e9d, 0xfbcd6ea198fe352b, 0xb1cbcd50cc5236a6, 0x1f5ec83d3f9846e2}}, - {{0x8efb23c3328ccb75, 0xaf42a207dd876ee9, 0x20fbdadc5dfae796, 0x241e246b06bf9f51}}}, -{{{0x29e68e57ad6e98f6, 0x4c9260c80b462065, 0x3f00862ea51ebb4b, 0x5bc2c77fb38d9097}}, - {{0x7eaafc9a6280bbb8, 0x22a70f12f403d809, 0x31ce40bb1bfc8d20, 0x2bc65635e8bd53ee}}, - {{0xe8d5dc9fa96bad93, 0xe58fb17dde1947dc, 0x681532ea65185fa3, 0x1fdd6c3b034a7830}}}, -{{{0x0a64e28c55dc18fe, 0xe3df9e993399ebdd, 0x79ac432370e2e652, 0x35ff7fc33ae4cc0e}}, - {{0x9c13a6a52dd8f7a9, 0x2dbb1f8c3efdcabf, 0x961e32405e08f7b5, 0x48c8a121bbe6c9e5}}, - {{0xfc415a7c59646445, 0xd224b2d7c128b615, 0x6035c9c905fbb912, 0x42d7a91274429fab}}}, -{{{0x4e6213e3eaf72ed3, 0x6794981a43acd4e7, 0xff547cde6eb508cb, 0x6fed19dd10fcb532}}, - {{0xa9a48947933da5bc, 0x4a58920ec2e979ec, 0x96d8800013e5ac4c, 0x453692d74b48b147}}, - {{0xdd775d99a8559c6f, 0xf42a2140df003e24, 0x5223e229da928a66, 0x063f46ba6d38f22c}}}, -{{{0xd2d242895f536694, 0xca33a2c542939b2c, 0x986fada6c7ddb95c, 0x5a152c042f712d5d}}, - {{0x39843cb737346921, 0xa747fb0738c89447, 0xcb8d8031a245307e, 0x67810f8e6d82f068}}, - {{0x3eeb8fbcd2287db4, 0x72c7d3a301a03e93, 0x5473e88cbd98265a, 0x7324aa515921b403}}}, -{{{0x857942f46c3cbe8e, 0xa1d364b14730c046, 0x1c8ed914d23c41bf, 0x0838e161eef6d5d2}}, - {{0xad23f6dae82354cb, 0x6962502ab6571a6d, 0x9b651636e38e37d1, 0x5cac5005d1a3312f}}, - {{0x8cc154cce9e39904, 0x5b3a040b84de6846, 0xc4d8a61cb1be5d6e, 0x40fb897bd8861f02}}}, -{{{0x84c5aa9062de37a1, 0x421da5000d1d96e1, 0x788286306a9242d9, 0x3c5e464a690d10da}}, - {{0xe57ed8475ab10761, 0x71435e206fd13746, 0x342f824ecd025632, 0x4b16281ea8791e7b}}, - {{0xd1c101d50b813381, 0xdee60f1176ee6828, 0x0cb68893383f6409, 0x6183c565f6ff484a}}}, -{{{0x741d5a461e6bf9d6, 0x2305b3fc7777a581, 0xd45574a26474d3d9, 0x1926e1dc6401e0ff}}, - {{0xdb468549af3f666e, 0xd77fcf04f14a0ea5, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85}}, - {{0xe07f4e8aea17cea0, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15}}}, -{{{0xcc8055947d599832, 0x1e4656da37f15520, 0x99f6f7744e059320, 0x773563bc6a75cf33}}, - {{0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5}}, - {{0x06b1e90863139cb3, 0xa493da67c5a03ecd, 0x8d77cec8ad638932, 0x1f426b701b864f44}}}, -{{{0xefc9264c41911c01, 0xf1a3b7b817a22c25, 0x5875da6bf30f1447, 0x4e1af5271d31b090}}, - {{0xf17e35c891a12552, 0xb76b8153575e9c76, 0xfa83406f0d9b723e, 0x0b76bb1b3fa7e438}}, - {{0x08b8c1f97f92939b, 0xbe6771cbd444ab6e, 0x22e5646399bb8017, 0x7b6dd61eb772a955}}}, -{{{0xb7adc1e850f33d92, 0x7998fa4f608cd5cf, 0xad962dbd8dfc5bdb, 0x703e9bceaf1d2f4f}}, - {{0x5730abf9ab01d2c7, 0x16fb76dc40143b18, 0x866cbe65a0cbb281, 0x53fa9b659bff6afe}}, - {{0x6c14c8e994885455, 0x843a5d6665aed4e5, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50}}}, -{{{0x1c4bd16733e248f3, 0xbd9e128715bf0a5f, 0xd43f8cf0a10b0376, 0x53b09b5ddf191b13}}, - {{0xc3877c60d2e7e3f2, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577}}, - {{0xf306a7235946f1cc, 0x921718b5cce5d97d, 0x28cdd24781b4e975, 0x51caf30c6fcdd907}}}, -{{{0xa60ba7427674e00a, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa}}, - {{0x737af99a18ac54c7, 0x903378dcc51cb30f, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a}}, - {{0xa99ec0cb1f0d01cf, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea}}}, -{{{0xb5dc2ddf2845ab2c, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1}}, - {{0x3c42fe5ebf93cb8e, 0xbedfa85136d4565f, 0xe0f0859e884220e8, 0x7dd73f960725d128}}, - {{0xb10d24fe68059829, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4}}}, -{{{0x83847d429917135f, 0xad1b911f567d03d7, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a}}, - {{0x7041d560b691c301, 0x85201b3fadd7e71e, 0x16c2e16311335585, 0x2aa55e3d010828b1}}, - {{0xed5192e60c07444f, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664}}}, -{{{0xcbb5b5556c032bff, 0xdf7191b729297a3a, 0xc1ff7326aded81bb, 0x71ade8bb68be03f5}}, - {{0x1e6284c5806b467c, 0xc5f6997be75d607b, 0x8b67d958b378d262, 0x3d88d66a81cd8b70}}, - {{0x8b767a93204ed789, 0x762fcacb9fa0ae2a, 0x771febcc6dce4887, 0x343062158ff05fb3}}}, -{{{0xe05da1a7e1f5bf49, 0x26457d6dd4736092, 0x77dcb07773cc32f6, 0x0a5d94969cdd5fcd}}, - {{0xfce219072a7b31b4, 0x4d7adc75aa578016, 0x0ec276a687479324, 0x6d6d9d5d1fda4beb}}, - {{0x22b1a58ae9b08183, 0xfd95d071c15c388b, 0xa9812376850a0517, 0x33384cbabb7f335e}}}, -{{{0x3c6fa2680ca2c7b5, 0x1b5082046fb64fda, 0xeb53349c5431d6de, 0x5278b38f6b879c89}}, - {{0x33bc627a26218b8d, 0xea80b21fc7a80c61, 0x9458b12b173e9ee6, 0x076247be0e2f3059}}, - {{0x52e105f61416375a, 0xec97af3685abeba4, 0x26e6b50623a67c36, 0x5cf0e856f3d4fb01}}}, -{{{0xf6c968731ae8cab4, 0x5e20741ecb4f92c5, 0x2da53be58ccdbc3e, 0x2dddfea269970df7}}, - {{0xbeaece313db342a8, 0xcba3635b842db7ee, 0xe88c6620817f13ef, 0x1b9438aa4e76d5c6}}, - {{0x8a50777e166f031a, 0x067b39f10fb7a328, 0x1925c9a6010fbd76, 0x6df9b575cc740905}}}, -{{{0x42c1192927f6bdcf, 0x8f91917a403d61ca, 0xdc1c5a668b9e1f61, 0x1596047804ec0f8d}}, - {{0xecdfc35b48cade41, 0x6a88471fb2328270, 0x740a4a2440a01b6a, 0x471e5796003b5f29}}, - {{0xda96bbb3aced37ac, 0x7a2423b5e9208cea, 0x24cc5c3038aebae2, 0x50c356afdc5dae2f}}}, -{{{0x09dcbf4341c30318, 0xeeba061183181dce, 0xc179c0cedc1e29a1, 0x1dbf7b89073f35b0}}, - {{0xcfed9cdf1b31b964, 0xf486a9858ca51af3, 0x14897265ea8c1f84, 0x784a53dd932acc00}}, - {{0x2d99f9df14fc4920, 0x76ccb60cc4499fe5, 0xa4132cbbe5cf0003, 0x3f93d82354f000ea}}}, -{{{0x8183e7689e04ce85, 0x678fb71e04465341, 0xad92058f6688edac, 0x5da350d3532b099a}}, - {{0xeaac12d179e14978, 0xff923ff3bbebff5e, 0x4af663e40663ce27, 0x0fd381a811a5f5ff}}, - {{0xf256aceca436df54, 0x108b6168ae69d6e8, 0x20d986cb6b5d036c, 0x655957b9fee2af50}}}, -{{{0xaea8b07fa902030f, 0xf88c766af463d143, 0x15b083663c787a60, 0x08eab1148267a4a8}}, - {{0xbdc1409bd002d0ac, 0x66660245b5ccd9a6, 0x82317dc4fade85ec, 0x02fe934b6ad7df0d}}, - {{0xef5cf100cfb7ea74, 0x22897633a1cb42ac, 0xd4ce0c54cef285e2, 0x30408c048a146a55}}}, -{{{0x739d8845832fcedb, 0xfa38d6c9ae6bf863, 0x32bc0dcab74ffef7, 0x73937e8814bce45e}}, - {{0xbb2e00c9193b877f, 0xece3a890e0dc506b, 0xecf3b7c036de649f, 0x5f46040898de9e1a}}, - {{0xb9037116297bf48d, 0xa9d13b22d4f06834, 0xe19715574696bdc6, 0x2cf8a4e891d5e835}}}, -{{{0x6d93fd8707110f67, 0xdd4c09d37c38b549, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09}}, - {{0x2cb5487e17d06ba2, 0x24d2381c3950196b, 0xd7659c8185978a30, 0x7a6f7f2891d6a4f6}}, - {{0x7d09fd8d6a9aef49, 0xf0ee60be5b3db90b, 0x4c21b52c519ebfd4, 0x6011aadfc545941d}}}, -{{{0x5f67926dcf95f83c, 0x7c7e856171289071, 0xd6a1e7f3998f7a5b, 0x6fc5cc1b0b62f9e0}}, - {{0x63ded0c802cbf890, 0xfbd098ca0dff6aaa, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e}}, - {{0xd1ef5528b29879cb, 0xdd1aae3cd47e9092, 0x127e0442189f2352, 0x15596b3ae57101f1}}}, -{{{0x462739d23f9179a2, 0xff83123197d6ddcf, 0x1307deb553f2148a, 0x0d2237687b5f4dda}}, - {{0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138}}, - {{0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c}}}, -{{{0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, 0xaac014de22efe4a3, 0x4627e9cefebd6a5c}}, - {{0x3207a4732787ccdf, 0x17e31908f213e3f8, 0xd5b2ecd7f60d964e, 0x746f6336c2600be9}}, - {{0x3f4af345ab6c971c, 0xe288eb729943731f, 0x33596a8a0344186d, 0x7b4917007ed66293}}}, -{{{0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b}}, - {{0x54341b28dd53a2dd, 0xaa17905bdf42fc3f, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d}}, - {{0xc20232cda2b4e554, 0x9ed0fd42115d187f, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c}}}, -{{{0xa287ec4b5d0b2fbb, 0x415c5790074882ca, 0xe044a61ec1d0815c, 0x26334f0a409ef5e0}}, - {{0xace532bf458d72e1, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03}}, - {{0xb6c8f04adf62a3c0, 0x3ef000ef076da45d, 0x9c9cb95849f0d2a9, 0x1cc37f43441b2fae}}}, -{{{0x508f565a5cc7324f, 0xd061c4c0e506a922, 0xfb18abdb5c45ac19, 0x6c6809c10380314a}}, - {{0xd76656f1c9ceaeb9, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838}}, - {{0xd2d55112e2da6ac8, 0xe9bd0331b1e851ed, 0x960746dd8ec67262, 0x05911b9f6ef7c5d0}}}, -{{{0xe9dcd756b637ff2d, 0xec4c348fc987f0c4, 0xced59285f3fbc7b7, 0x3305354793e1ea87}}, - {{0x01c18980c5fe9f94, 0xcd656769716fd5c8, 0x816045c3d195a086, 0x6e2b7f3266cc7982}}, - {{0xcc802468f7c3568f, 0x9de9ba8219974cb3, 0xabb7229cb5b81360, 0x44e2017a6fbeba62}}}, -{{{0xc4c2a74354dab774, 0x8e5d4c3c4eaf031a, 0xb76c23d242838f17, 0x749a098f68dce4ea}}, - {{0x87f82cf3b6ca6ecd, 0x580f893e18f4a0c2, 0x058930072604e557, 0x6cab6ac256d19c1d}}, - {{0xdcdfe0a02cc1de60, 0x032665ff51c5575b, 0x2c0c32f1073abeeb, 0x6a882014cd7b8606}}}, -{{{0xa52a92fea4747fb5, 0xdc12a4491fa5ab89, 0xd82da94bb847a4ce, 0x4d77edce9512cc4e}}, - {{0xd111d17caf4feb6e, 0x050bba42b33aa4a3, 0x17514c3ceeb46c30, 0x54bedb8b1bc27d75}}, - {{0x77c8e14577e2189c, 0xa3e46f6aff99c445, 0x3144dfc86d335343, 0x3a96559e7c4216a9}}}, -{{{0x12550d37f42ad2ee, 0x8b78e00498a1fbf5, 0x5d53078233894cb2, 0x02c84e4e3e498d0c}}, - {{0x4493896880baaa52, 0x4c98afc4f285940e, 0xef4aa79ba45448b6, 0x5278c510a57aae7f}}, - {{0xa54dd074294c0b94, 0xf55d46b8df18ffb6, 0xf06fecc58dae8366, 0x588657668190d165}}}, -{{{0xd47712311aef7117, 0x50343101229e92c7, 0x7a95e1849d159b97, 0x2449959b8b5d29c9}}, - {{0xbf5834f03de25cc3, 0xb887c8aed6815496, 0x5105221a9481e892, 0x6760ed19f7723f93}}, - {{0x669ba3b7ac35e160, 0x2eccf73fba842056, 0x1aec1f17c0804f07, 0x0d96bc031856f4e7}}}, -{{{0x3318be7775c52d82, 0x4cb764b554d0aab9, 0xabcf3d27cc773d91, 0x3bf4d1848123288a}}, - {{0xb1d534b0cc7505e1, 0x32cd003416c35288, 0xcb36a5800762c29d, 0x5bfe69b9237a0bf8}}, - {{0x183eab7e78a151ab, 0xbbe990c999093763, 0xff717d6e4ac7e335, 0x4c5cddb325f39f88}}}, -{{{0xc0f6b74d6190a6eb, 0x20ea81a42db8f4e4, 0xa8bd6f7d97315760, 0x33b1d60262ac7c21}}, - {{0x57750967e7a9f902, 0x2c37fdfc4f5b467e, 0xb261663a3177ba46, 0x3a375e78dc2d532b}}, - {{0x8141e72f2d4dddea, 0xe6eafe9862c607c8, 0x23c28458573cafd0, 0x46b9476f4ff97346}}}, -{{{0x0c1ffea44f901e5c, 0x2b0b6fb72184b782, 0xe587ff910114db88, 0x37130f364785a142}}, - {{0x1215505c0d58359f, 0x2a2013c7fc28c46b, 0x24a0a1af89ea664e, 0x4400b638a1130e1f}}, - {{0x3a01b76496ed19c3, 0x31e00ab0ed327230, 0x520a885783ca15b1, 0x06aab9875accbec7}}}, -{{{0xc1339983f5df0ebb, 0xc0f3758f512c4cac, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62}}, - {{0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17}}, - {{0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d}}}, -{{{0x0e2c52036b1782fc, 0x64816c816cad83b4, 0xd0dcbdd96964073e, 0x13d99df70164c520}}, - {{0xa12ff6d93bdab31d, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43}}, - {{0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80}}}, -{{{0x990f7ad6a33ec4e2, 0x6608f938be2ee08e, 0x9ca143c563284515, 0x4cf38a1fec2db60d}}, - {{0xffd52b40ff6d69aa, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d}}, - {{0xa0aaaa650dfa5ce7, 0xf9c49e2a48b5478c, 0x4f09cc7d7003725b, 0x373cad3a26091abe}}}, -{{{0xb294634d82c9f57c, 0x1fcbfde124934536, 0x9e9c4db3418cdb5a, 0x0040f3d9454419fc}}, - {{0xf1bea8fb89ddbbad, 0x3bcb2cbc61aeaecb, 0x8f58a7bb1f9b8d9d, 0x21547eda5112a686}}, - {{0xdefde939fd5986d3, 0xf4272c89510a380c, 0xb72ba407bb3119b9, 0x63550a334a254df4}}}, -{{{0x6507d6edb569cf37, 0x178429b00ca52ee1, 0xea7c0090eb6bd65d, 0x3eea62c7daf78f51}}, - {{0x9bba584572547b49, 0xf305c6fae2c408e0, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a}}, - {{0x9d24c713e693274e, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd}}}, -{{{0xbc0235e8202f3f27, 0xc75c00e264f975b0, 0x91a4e9d5a38c2416, 0x17b6e7f68ab789f9}}, - {{0x1e56d317e820107c, 0xc5266844840ae965, 0xc1e0a1c6320ffc7a, 0x5373669c91611472}}, - {{0x5d2814ab9a0e5257, 0x908f2084c9cab3fc, 0xafcaf5885b2d1eca, 0x1cb4b5a678f87d11}}}, -{{{0xb664c06b394afc6c, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2}}, - {{0x6b74aa62a2a007e7, 0xf311e0b0f071c7b1, 0x5707e438000be223, 0x2dc0fd2d82ef6eac}}, - {{0x982eff841119744e, 0xf9695e962b074724, 0xc58ac14fbfc953fb, 0x3c31be1b369f1cf5}}}, -{{{0xb0f4864d08948aee, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb}}, - {{0xc168bc93f9cb4272, 0xaeb8711fc7cedb98, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb}}, - {{0xf79619d7a26d808a, 0xbb1fd49e1d9e156d, 0x73d7c36cdba1df27, 0x26b44cd91f28777d}}}, -{{{0x300a9035393aa6d8, 0x2b501131a12bb1cd, 0x7b1ff677f093c222, 0x4309c1f8cab82bad}}, - {{0xaf44842db0285f37, 0x8753189047efc8df, 0x9574e091f820979a, 0x0e378d6069615579}}, - {{0xd9fa917183075a55, 0x4bdb5ad26b009fdc, 0x7829ad2cd63def0e, 0x078fc54975fd3877}}}, -{{{0x87dfbd1428878f2d, 0x134636dd1e9421a1, 0x4f17c951257341a3, 0x5df98d4bad296cb8}}, - {{0xe2004b5bb833a98a, 0x44775dec2d4c3330, 0x3aa244067eace913, 0x272630e3d58e00a9}}, - {{0xf3678fd0ecc90b54, 0xf001459b12043599, 0x26725fbc3758b89b, 0x4325e4aa73a719ae}}}, -{{{0x657dc6ef433c3493, 0x65375e9f80dbf8c3, 0x47fd2d465b372dae, 0x4966ab79796e7947}}, - {{0xed24629acf69f59d, 0x2a4a1ccedd5abbf4, 0x3535ca1f56b2d67b, 0x5d8c68d043b1b42d}}, - {{0xee332d4de3b42b0a, 0xd84e5a2b16a4601c, 0x78243877078ba3e4, 0x77ed1eb4184ee437}}}, -{{{0xbfd4e13f201839a0, 0xaeefffe23e3df161, 0xb65b04f06b5d1fe3, 0x52e085fb2b62fbc0}}, - {{0x185d43f89e92ed1a, 0xb04a1eeafe4719c6, 0x499fbe88a6f03f4f, 0x5d8b0d2f3c859bdd}}, - {{0x124079eaa54cf2ba, 0xd72465eb001b26e7, 0x6843bcfdc97af7fd, 0x0524b42b55eacd02}}}, -{{{0xfd0d5dbee45447b0, 0x6cec351a092005ee, 0x99a47844567579cb, 0x59d242a216e7fa45}}, - {{0xbc18dcad9b829eac, 0x23ae7d28b5f579d0, 0xc346122a69384233, 0x1a6110b2e7d4ac89}}, - {{0x4f833f6ae66997ac, 0x6849762a361839a4, 0x6985dec1970ab525, 0x53045e89dcb1f546}}}, -{{{0xcb8bb346d75353db, 0xfcfcb24bae511e22, 0xcba48d40d50ae6ef, 0x26e3bae5f4f7cb5d}}, - {{0x84da3cde8d45fe12, 0xbd42c218e444e2d2, 0xa85196781f7e3598, 0x7642c93f5616e2b2}}, - {{0x2323daa74595f8e4, 0xde688c8b857abeb4, 0x3fc48e961c59326e, 0x0b2e73ca15c9b8ba}}}, -{{{0xd6bb4428c17f5026, 0x9eb27223fb5a9ca7, 0xe37ba5031919c644, 0x21ce380db59a6602}}, - {{0x0e3fbfaf79c03a55, 0x3077af054cbb5acf, 0xd5c55245db3de39f, 0x015e68c1476a4af7}}, - {{0xc1d5285220066a38, 0x95603e523570aef3, 0x832659a7226b8a4d, 0x5dd689091f8eedc9}}}, -{{{0xcbac84debfd3c856, 0x1624c348b35ff244, 0xb7f88dca5d9cad07, 0x3b0e574da2c2ebe8}}, - {{0x1d022591a5313084, 0xca2d4aaed6270872, 0x86a12b852f0bfd20, 0x56e6c439ad7da748}}, - {{0xc704ff4942bdbae6, 0x5e21ade2b2de1f79, 0xe95db3f35652fad8, 0x0822b5378f08ebc1}}}, -{{{0x51f048478f387475, 0xb25dbcf49cbecb3c, 0x9aab1244d99f2055, 0x2c709e6c1c10a5d6}}, - {{0xe1b7f29362730383, 0x4b5279ffebca8a2c, 0xdafc778abfd41314, 0x7deb10149c72610f}}, - {{0xcb62af6a8766ee7a, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea}}}, -{{{0x34ad500a4bc130ad, 0x8d38db493d0bd49c, 0xa25c3d98500a89be, 0x2f1f3f87eeba3b09}}, - {{0x2f2d09d50ab8f2f9, 0xacb9218dc55923df, 0x4a8f342673766cb9, 0x4cb13bd738f719f5}}, - {{0xf7848c75e515b64a, 0xa59501badb4a9038, 0xc20d313f3f751b50, 0x19a1e353c0ae2ee8}}}, -{{{0x7d1c7560bafa05c3, 0xb3e1a0a0c6e55e61, 0xe3529718c0d66473, 0x41546b11c20c3486}}, - {{0xb42172cdd596bdbd, 0x93e0454398eefc40, 0x9fb15347b44109b5, 0x736bd3990266ae34}}, - {{0x85532d509334b3b4, 0x46fd114b60816573, 0xcc5f5f30425c8375, 0x412295a2b87fab5c}}}, -{{{0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34}}, - {{0x2e655261e293eac6, 0x845a92032133acdb, 0x460975cb7900996b, 0x0760bb8d195add80}}, - {{0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2}}}, -{{{0xf3df2f643a78c0b2, 0x4c3e971ef22e027c, 0xec7d1c5e49c1b5a3, 0x2012c18f0922dd2d}}, - {{0x11fc69656571f2d3, 0xc6c9e845530e737a, 0xe33ae7a2d4fe5035, 0x01b9c7b62e6dd30b}}, - {{0x880b55e55ac89d29, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8}}}, -{{{0x283499dc881f2533, 0x9d0525da779323b6, 0x897addfb673441f4, 0x32b79d71163a168d}}, - {{0xe27314d289cc2c4b, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e}}, - {{0xcc85f8d9edfcb36a, 0x22bcc28f3746e5f9, 0xe49de338f9e5d3cd, 0x480a5efbc13e2dcc}}}, -{{{0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31}}, - {{0xb6614ce442ce221f, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06}}, - {{0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, 0xf0af66134ea278d6, 0x545b585d14dda094}}}, -{{{0x67bf275ea0d43a0f, 0xade68e34089beebe, 0x4289134cd479e72e, 0x0f62f9c332ba5454}}, - {{0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071}}, - {{0xfcb46589d63b5f39, 0x5cae6a3f57cbcf61, 0xfebac2d2953afa05, 0x1c0fa01a36371436}}}, -{{{0xe7547449bc7cd692, 0x0f9abeaae6f73ddf, 0x4af01ca700837e29, 0x63ab1b5d3f1bc183}}, - {{0xc11ee5e854c53fae, 0x6a0b06c12b4f3ff4, 0x33540f80e0b67a72, 0x15f18fc3cd07e3ef}}, - {{0x32750763b028f48c, 0x06020740556a065f, 0xd53bd812c3495b58, 0x08706c9b865f508d}}}, -{{{0xf37ca2ab3d343dff, 0x1a8c6a2d80abc617, 0x8e49e035d4ccffca, 0x48b46beebaa1d1b9}}, - {{0xcc991b4138b41246, 0x243b9c526f9ac26b, 0xb9ef494db7cbabbd, 0x5fba433dd082ed00}}, - {{0x9c49e355c9941ad0, 0xb9734ade74498f84, 0x41c3fed066663e5c, 0x0ecfedf8e8e710b3}}}, -{{{0x76430f9f9cd470d9, 0xb62acc9ba42f6008, 0x1898297c59adad5e, 0x7789dd2db78c5080}}, - {{0x744f7463e9403762, 0xf79a8dee8dfcc9c9, 0x163a649655e4cde3, 0x3b61788db284f435}}, - {{0xb22228190d6ef6b2, 0xa94a66b246ce4bfa, 0x46c1a77a4f0b6cc7, 0x4236ccffeb7338cf}}}, -{{{0x8497404d0d55e274, 0x6c6663d9c4ad2b53, 0xec2fb0d9ada95734, 0x2617e120cdb8f73c}}, - {{0x3bd82dbfda777df6, 0x71b177cc0b98369e, 0x1d0e8463850c3699, 0x5a71945b48e2d1f1}}, - {{0x6f203dd5405b4b42, 0x327ec60410b24509, 0x9c347230ac2a8846, 0x77de29fc11ffeb6a}}}, -{{{0xb0ac57c983b778a8, 0x53cdcca9d7fe912c, 0x61c2b854ff1f59dc, 0x3a1a2cf0f0de7dac}}, - {{0x835e138fecced2ca, 0x8c9eaf13ea963b9a, 0xc95fbfc0b2160ea6, 0x575e66f3ad877892}}, - {{0x99803a27c88fcb3a, 0x345a6789275ec0b0, 0x459789d0ff6c2be5, 0x62f882651e70a8b2}}}, -{{{0x085ae2c759ff1be4, 0x149145c93b0e40b7, 0xc467e7fa7ff27379, 0x4eeecf0ad5c73a95}}, - {{0x6d822986698a19e0, 0xdc9821e174d78a71, 0x41a85f31f6cb1f47, 0x352721c2bcda9c51}}, - {{0x48329952213fc985, 0x1087cf0d368a1746, 0x8e5261b166c15aa5, 0x2d5b2d842ed24c21}}}, -{{{0x02cfebd9ebd3ded1, 0xd45b217739021974, 0x7576f813fe30a1b7, 0x5691b6f9a34ef6c2}}, - {{0x5eb7d13d196ac533, 0x377234ecdb80be2b, 0xe144cffc7cf5ae24, 0x5226bcf9c441acec}}, - {{0x79ee6c7223e5b547, 0x6f5f50768330d679, 0xed73e1e96d8adce9, 0x27c3da1e1d8ccc03}}}, -{{{0x7eb9efb23fe24c74, 0x3e50f49f1651be01, 0x3ea732dc21858dea, 0x17377bd75bb810f9}}, - {{0x28302e71630ef9f6, 0xc2d4a2032b64cee0, 0x090820304b6292be, 0x5fca747aa82adf18}}, - {{0x232a03c35c258ea5, 0x86f23a2c6bcb0cf1, 0x3dad8d0d2e442166, 0x04a8933cab76862b}}}, -{{{0xd2c604b622943dff, 0xbc8cbece44cfb3a0, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf}}, - {{0x69082b0e8c936a50, 0xf9c9a035c1dac5b6, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140}}, - {{0xa003febdb9be82f0, 0x2089c1af3a44ac90, 0xf8499f911954fa8e, 0x1fba218aef40ab42}}}, -{{{0xab549448fac8f53e, 0x81f6e89a7ba63741, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42}}, - {{0x4f3e57043e7b0194, 0xa81d3eee08daaf7f, 0xc839c6ab99dcdef1, 0x6c535d13ff7761d5}}, - {{0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b}}}, -{{{0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351}}, - {{0x915f7ff576f121a7, 0xc34a32272fcd87e3, 0xccba2fde4d1be526, 0x6bba828f8969899b}}, - {{0xe2d1bc6690fe3901, 0x4cb54a18a0997ad5, 0x971d6914af8460d4, 0x559d504f7f6b7be4}}}, -{{{0xa7738378b3eb54d5, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217}}, - {{0x9c4891e7f6d266fd, 0x0744a19b0307781b, 0x88388f1d6061e23b, 0x123ea6a3354bd50e}}, - {{0x118d189041e32d96, 0xb9ede3c2d8315848, 0x1eab4271d83245d9, 0x4a3961e2c918a154}}}, -{{{0x71dc3be0f8e6bba0, 0xd6cef8347effe30a, 0xa992425fe13a476a, 0x2cd6bce3fb1db763}}, - {{0x0327d644f3233f1e, 0x499a260e34fcf016, 0x83b5a716f2dab979, 0x68aceead9bd4111f}}, - {{0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597}}}, -{{{0x6129bfe104aa6397, 0x8f960008a4a7fccb, 0x3f8bc0897d909458, 0x709fa43edcb291a9}}, - {{0x882acbebfd022790, 0x89af3305c4115760, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b}}, - {{0xeb0a5d8c63fd2aca, 0xd22bc1662e694eff, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f}}}, -{{{0x461307b32eed3e33, 0xae042f33a45581e7, 0xc94449d3195f0366, 0x0b7d5d8a6c314858}}, - {{0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1}}, - {{0x25d448327b95d543, 0x70d38300a3340f1d, 0xde1c531c60e1c52b, 0x272224512c7de9e4}}}, -{{{0x1abc92af49c5342e, 0xffeed811b2e6fad0, 0xefa28c8dfcc84e29, 0x11b5df18a44cc543}}, - {{0xbf7bbb8a42a975fc, 0x8c5c397796ada358, 0xe27fc76fcdedaa48, 0x19735fd7f6bc20a6}}, - {{0xe3ab90d042c84266, 0xeb848e0f7f19547e, 0x2503a1d065a497b9, 0x0fef911191df895f}}}, -{{{0xb1507ca1ab1c6eb9, 0xbd448f3e16b687b3, 0x3455fb7f2c7a91ab, 0x7579229e2f2adec1}}, - {{0x6ab5dcb85b1c16b7, 0x94c0fce83c7b27a5, 0xa4b11c1a735517be, 0x499238d0ba0eafaa}}, - {{0xecf46e527aba8b57, 0x15a08c478bd1647b, 0x7af1c6a65f706fef, 0x6345fa78f03a30d5}}}, -{{{0xdf02f95f1015e7a1, 0x790ec41da9b40263, 0x4d3a0ea133ea1107, 0x54f70be7e33af8c9}}, - {{0x93d3cbe9bdd8f0a4, 0xdb152c1bfd177302, 0x7dbddc6d7f17a875, 0x3e1a71cc8f426efe}}, - {{0xc83ca3e390babd62, 0x80ede3670291c833, 0xc88038ccd37900c4, 0x2c5fc0231ec31fa1}}}, -{{{0xfeba911717038b4f, 0xe5123721c9deef81, 0x1c97e4e75d0d8834, 0x68afae7a23dc3bc6}}, - {{0xc422e4d102456e65, 0x87414ac1cad47b91, 0x1592e2bba2b6ffdd, 0x75d9d2bff5c2100f}}, - {{0x5bd9b4763626e81c, 0x89966936bca02edd, 0x0a41193d61f077b3, 0x3097a24200ce5471}}}, -{{{0x57427734c7f8b84c, 0xf141a13e01b270e9, 0x02d1adfeb4e564a6, 0x4bb23d92ce83bd48}}, - {{0xa162e7246695c486, 0x131d633435a89607, 0x30521561a0d12a37, 0x56704bada6afb363}}, - {{0xaf6c4aa752f912b9, 0x5e665f6cd86770c8, 0x4c35ac83a3c8cd58, 0x2b7a29c010a58a7e}}}, -{{{0xc4007f77d0c1cec3, 0x8d1020b6bac492f8, 0x32ec29d57e69daaf, 0x599408759d95fce0}}, - {{0x33810a23bf00086e, 0xafce925ee736ff7c, 0x3d60e670e24922d4, 0x11ce9e714f96061b}}, - {{0x219ef713d815bac1, 0xf141465d485be25c, 0x6d5447cc4e513c51, 0x174926be5ef44393}}}, -{{{0xb5deb2f9fc5bd5bb, 0x92daa72ae1d810e1, 0xafc4cfdcb72a1c59, 0x497d78813fc22a24}}, - {{0x3ef5d41593ea022e, 0x5cbcc1a20ed0eed6, 0x8fd24ecf07382c8c, 0x6fa42ead06d8e1ad}}, - {{0xe276824a1f73371f, 0x7f7cf01c4f5b6736, 0x7e201fe304fa46e7, 0x785a36a357808c96}}}, -{{{0x825fbdfd63014d2b, 0xc852369c6ca7578b, 0x5b2fcd285c0b5df0, 0x12ab214c58048c8f}}, - {{0x070442985d517bc3, 0x6acd56c7ae653678, 0x00a27983985a7763, 0x5167effae512662b}}, - {{0xbd4ea9e10f53c4b6, 0x1673dc5f8ac91a14, 0xa8f81a4e2acc1aba, 0x33a92a7924332a25}}}, -{{{0x9dd1f49927996c02, 0x0cb3b058e04d1752, 0x1f7e88967fd02c3e, 0x2f964268cb8b3eb1}}, - {{0x7ba95ba0218f2ada, 0xcff42287330fb9ca, 0xdada496d56c6d907, 0x5380c296f4beee54}}, - {{0x9d4f270466898d0a, 0x3d0987990aff3f7a, 0xd09ef36267daba45, 0x7761455e7b1c669c}}} \ No newline at end of file diff --git a/ext/ed25519-amd64-asm/ge25519_base_niels_smalltables.data b/ext/ed25519-amd64-asm/ge25519_base_niels_smalltables.data deleted file mode 100644 index a31f6f2f0..000000000 --- a/ext/ed25519-amd64-asm/ge25519_base_niels_smalltables.data +++ /dev/null @@ -1,768 +0,0 @@ -{{{0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267}}, - {{0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65}}, - {{0xdbbd15674b6fbb59, 0x41e13f00eea2a5ea, 0xcdd49d1cc957c6fa, 0x4f0ebe1faf16ecca}}}, -{{{0x8a99a56042b4d5a8, 0x8f2b810c4e60acf6, 0xe09e236bb16e37aa, 0x6bb595a669c92555}}, - {{0x9224e7fc933c71d7, 0x9f469d967a0ff5b5, 0x5aa69a65e1d60702, 0x590c063fa87d2e2e}}, - {{0x6e347eaadad36802, 0xbaf3599383ee4805, 0x3bcabe10e6076826, 0x49314f0a165ed1b8}}}, -{{{0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62}}, - {{0xaf25b0a84cee9730, 0x025a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4}}, - {{0x9bf211f4f1674834, 0xb84e6b17f62df895, 0xd7de6f075b722a4e, 0x549a04b963bb2a21}}}, -{{{0x95fe050a056818bf, 0x327e89715660faa9, 0xc3e8e3cd06a05073, 0x27933f4c7445a49a}}, - {{0x287351b98efc099f, 0x6765c6f47dfd2538, 0xca348d3dfb0a9265, 0x680e910321e58727}}, - {{0xbf1e45ece51426b0, 0xe32bc63d6dba0f94, 0xe42974d58cf852c0, 0x44f079b1b0e64c18}}}, -{{{0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3}}, - {{0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb}}, - {{0xc832a179e7d003b3, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98}}}, -{{{0x499806b67b7d8ca4, 0x575be28427d22739, 0xbb085ce7204553b9, 0x38b64c41ae417884}}, - {{0x3a0ceeeb77157131, 0x9b27158900c8af88, 0x8065b668da59a736, 0x51e57bb6a2cc38bd}}, - {{0x8f9dad91689de3a4, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f}}}, -{{{0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0}}, - {{0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e}}, - {{0x217a8aacab0fda36, 0xa528c6543d3549c8, 0x37d05b8b13ab7568, 0x233cef623a2cbc37}}}, -{{{0xe2a75dedf39234d9, 0x963d7680e1b558f9, 0x2c2741ac6e3c23fb, 0x3a9024a1320e01c3}}, - {{0x59b7596604dd3e8f, 0x6cb30377e288702c, 0xb1339c665ed9c323, 0x0915e76061bce52f}}, - {{0xdf7de835a834a37e, 0x8be19cda689857ea, 0x2c1185367167b326, 0x589eb3d9dbefd5c2}}}, -{{{0xed5b635449aa515e, 0xa865c49f0bc6823a, 0x850c1fe95b42d1c4, 0x30d76d6f03d315b9}}, - {{0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39}}, - {{0x6c4444172106e4c7, 0xfb53d680928d7f69, 0xb4739ea4694d3f26, 0x10c697112e864bb0}}}, -{{{0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09}}, - {{0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef}}, - {{0x3f13e128cc586604, 0x6f5873ecb459747e, 0xa0b63dedcc1268f5, 0x566d78634586e22c}}}, -{{{0x1637a49f9cc10834, 0xbc8e56d5a89bc451, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9}}, - {{0xa1054285c65a2fd0, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a}}, - {{0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c}}}, -{{{0xff437b8497dd95c2, 0x6c744e30aa4eb5a7, 0x9e0c5d613c85e88b, 0x2fd9c71e5f758173}}, - {{0x21e70b2f4e71ecb8, 0xe656ddb940a477e3, 0xbf6556cece1d4f80, 0x05fc3bc4535d7b7e}}, - {{0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04}}}, -{{{0x2fba99fd40d1add9, 0xb307166f96f4d027, 0x4363f05215f03bae, 0x1fbea56c3b18f999}}, - {{0x634095cb14246590, 0xef12144016c15535, 0x9e38140c8910bc60, 0x6bf5905730907c8c}}, - {{0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56}}}, -{{{0x513fee0b0a9d5294, 0x8f98e75c0fdf5a66, 0xd4618688bfe107ce, 0x3fa00a7e71382ced}}, - {{0xb1146720772f5ee4, 0xe8f894b196079ace, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4}}, - {{0x3c69232d963ddb34, 0x1dde87dab4973858, 0xaad7d1f9a091f285, 0x12b5fe2fa048edb6}}}, -{{{0x71f0fbc496fce34d, 0x73b9826badf35bed, 0xd2047261ff28c561, 0x749b76f96fb1206f}}, - {{0xdf2b7c26ad6f1e92, 0x4b66d323504b8913, 0x8c409dc0751c8bc3, 0x6f7e93c20796c7b8}}, - {{0x1f5af604aea6ae05, 0xc12351f1bee49c99, 0x61a808b5eeff6b66, 0x0fcec10f01e02151}}}, -{{{0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3}}, - {{0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a}}, - {{0x08b1b7548c1af8f0, 0xce0f7a7c246299b4, 0xf760b0f91e06d939, 0x41bb887b726d1213}}}, -{{{0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7}}, - {{0x7e234c597c6691ae, 0x64889d3d0a85b4c8, 0xdae2c90c354afae7, 0x0a871e070c6a9e1d}}, - {{0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464}}}, -{{{0xf5d255e49e7dd6b7, 0x8016115c610b1eac, 0x3c99975d92e187ca, 0x13815762979125c2}}, - {{0x43fa7947841e7518, 0xe5c6fa59639c46d7, 0xa1065e1de3052b74, 0x7d47c6a2cfb89030}}, - {{0x3fdad0148ef0d6e0, 0x9d3e749a91546f3c, 0x71ec621026bb8157, 0x148cf58d34c9ec80}}}, -{{{0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4}}, - {{0xe2572f7d9ae4756d, 0x56c345bb88f3487f, 0x9fd10b6d6960a88d, 0x278febad4eaea1b9}}, - {{0xb1aa681f8c933966, 0x8c21949c20290c98, 0x39115291219d3c52, 0x4104dd02fe9c677b}}}, -{{{0x72b2bf5e1124422a, 0xa1fa0c3398a33ab5, 0x94cb6101fa52b666, 0x2c863b00afaf53d5}}, - {{0x81214e06db096ab8, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481}}, - {{0xf190a474a0846a76, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8}}}, -{{{0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb}}, - {{0x99b9b3719f18b55d, 0xe465e5faa18c641e, 0x61081136c29f05ed, 0x489b4f867030128b}}, - {{0xd232102d3aeb92ef, 0xe16253b46116a861, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf}}}, -{{{0x30949a108a5bcfd4, 0xdc40dd70bc6473eb, 0x92c294c1307c0d1c, 0x5604a86dcbfa6e74}}, - {{0x155d628c1e9c572e, 0x8a4d86acc5884741, 0x91a352f6515763eb, 0x06a1a6c28867515b}}, - {{0x7288d1d47c1764b6, 0x72541140e0418b51, 0x9f031a6018acf6d1, 0x20989e89fe2742c6}}}, -{{{0x499777fd3a2dcc7f, 0x32857c2ca54fd892, 0xa279d864d207e3a0, 0x0403ed1d0ca67e29}}, - {{0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3}}, - {{0xc94b2d35874ec552, 0xc5e6c8cf98246f8d, 0xf7cb46fa16c035ce, 0x5bd7454308303dcc}}}, -{{{0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83}}, - {{0x85c4932115e7792a, 0xc64c89a2bdcdddc9, 0x9d1e3da8ada3d762, 0x5bb7db123067f82c}}, - {{0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2}}}, -{{{0xdf48ee0752cfce4e, 0xc3fffaf306ec08b7, 0x05710b2ab95459c4, 0x161d25fa963ea38d}}, - {{0x231a8c570478433c, 0xb7b5270ec281439d, 0xdbaa99eae3d9079f, 0x2c03f5256c2b03d9}}, - {{0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf}}}, -{{{0xbd1f2f46f4dafecf, 0x7cef0114a47fd6f7, 0xd31ffdda4a47b37f, 0x525219a473905785}}, - {{0xd8dd3de66aa91948, 0x485064c22fc0d2cc, 0x9b48246634fdea2f, 0x293e1c4e6c4a2e3a}}, - {{0x376e134b925112e1, 0x703778b5dca15da0, 0xb04589af461c3111, 0x5b605c447f032823}}}, -{{{0xb965805920c47c89, 0xe7f0100c923b8fcc, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee}}, - {{0x3be9fec6f0e7f04c, 0x866a579e75e34962, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5}}, - {{0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, 0xc6cf144178cff668, 0x5e607b2518a43790}}}, -{{{0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, 0xe1b3ff4f66e61d6e, 0x5067acab6ccdd5f7}}, - {{0xa02c431ca596cf14, 0xe3c42d40aed3e400, 0xd24526802e0f26db, 0x201f33139e457068}}, - {{0xfd527f6b08039d51, 0x18b14964017c0006, 0xd5220eb02e25a4a8, 0x397cba8862460375}}}, -{{{0x30c13093f05959b2, 0xe23aa18de9a97976, 0x222fd491721d5e26, 0x2339d320766e6c3a}}, - {{0x7815c3fbc81379e7, 0xa6619420dde12af1, 0xffa9c0f885a8fdd5, 0x771b4022c1e1c252}}, - {{0xd87dd986513a2fa7, 0xf5ac9b71f9d4cf08, 0xd06bc31b1ea283b3, 0x331a189219971a76}}}, -{{{0xf5166f45fb4f80c6, 0x9c36c7de61c775cf, 0xe3d4e81b9041d91c, 0x31167c6b83bdfe21}}, - {{0x26512f3a9d7572af, 0x5bcbe28868074a9e, 0x84edc1c11180f7c4, 0x1ac9619ff649a67b}}, - {{0xf22b3842524b1068, 0x5068343bee9ce987, 0xfc9d71844a6250c8, 0x612436341f08b111}}}, -{{{0xd99d41db874e898d, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40}}, - {{0x8b6349e31a2d2638, 0x9ddfb7009bd3fd35, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445}}, - {{0x2c382f5369614938, 0xdafe409ab72d6d10, 0xe8c83391b646f227, 0x45fe70f50524306c}}}, -{{{0xda4875a6960c0b8c, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4}}, - {{0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245}}, - {{0x084f4a4401a308fd, 0xa82219c376a5caac, 0xdeb8de4643d1bc7d, 0x1d81592d60bd38c6}}}, -{{{0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0}}, - {{0x8765b69f7b85c5e8, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c}}, - {{0x76d20db67178b252, 0x071c34f9d51ed160, 0xf62a4a20b3e41170, 0x7cd682353cffe366}}}, -{{{0x0be1a45bd887fab6, 0x2a846a32ba403b6e, 0xd9921012e96e6000, 0x2838c8863bdc0943}}, - {{0xa665cd6068acf4f3, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff}}, - {{0xd16bb0cf4a465030, 0xfa496b4115c577ab, 0x82cfae8af4ab419d, 0x21dcb8a606a82812}}}, -{{{0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab}}, - {{0x9a8d00fabe7731ba, 0x8203607e629e1889, 0xb2cc023743f3d97f, 0x5d840dbf6c6f678b}}, - {{0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd}}}, -{{{0x4b42432c8a7084fa, 0x898a19e3dfb9e545, 0xbe9f00219c58e45d, 0x1ff177cea16debd1}}, - {{0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, 0x80acffc075aa15fe, 0x0770c9e824e1a9f9}}, - {{0xcf61d99a45b5b5fd, 0x860984e91b3a7924, 0xe7300919303e3e89, 0x39f264fd41500b1e}}}, -{{{0xa7ad3417dbe7e29c, 0xbd94376a2b9c139c, 0xa0e91b8e93597ba9, 0x1712d73468889840}}, - {{0xd19b4aabfe097be1, 0xa46dfce1dfe01929, 0xc3c908942ca6f1ff, 0x65c621272c35f14e}}, - {{0xe72b89f8ce3193dd, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272}}}, -{{{0x605a368a3e9ef8cb, 0xe3e9c022a5504715, 0x553d48b05f24248f, 0x13f416cd647626e5}}, - {{0x42029fdd9a6efdac, 0xb912cebe34a54941, 0x640f64b987bdf37b, 0x4171a4d38598cab4}}, - {{0xfa2758aa99c94c8c, 0x23006f6fb000b807, 0xfbd291ddadda5392, 0x508214fa574bd1ab}}}, -{{{0xc20269153ed6fe4b, 0xa65a6739511d77c4, 0xcbde26462c14af94, 0x22f960ec6faba74b}}, - {{0x461a15bb53d003d6, 0xb2102888bcf3c965, 0x27c576756c683a5a, 0x3a7758a4c86cb447}}, - {{0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494}}}, -{{{0x031408d36d63727f, 0x6a379aefd7c7b533, 0xa9e18fc5ccaee24b, 0x332f35914f8fbed3}}, - {{0x3f244d2aeed7521e, 0x8e3a9028432e9615, 0xe164ba772e9c16d4, 0x3bc187fa47eb98d8}}, - {{0x6d470115ea86c20c, 0x998ab7cb6c46d125, 0xd77832b53a660188, 0x450d81ce906fba03}}}, -{{{0x6e7bb6a1a6205275, 0xaa4f21d7413c8e83, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1}}, - {{0xd074d8961cae743f, 0xf86d18f5ee1c63ed, 0x97bdc55be7f4ed29, 0x4cbad279663ab108}}, - {{0x80d19024a0d71fcd, 0xc525c20afb288af8, 0xb1a3974b5f3a6419, 0x7d7fbcefe2007233}}}, -{{{0xfaef1e6a266b2801, 0x866c68c4d5739f16, 0xf68a2fbc1b03762c, 0x5975435e87b75a8d}}, - {{0xcd7c5dc5f3c29094, 0xc781a29a2a9105ab, 0x80c61d36421c3058, 0x4f9cd196dcd8d4d7}}, - {{0x199297d86a7b3768, 0xd0d058241ad17a63, 0xba029cad5c1c0c17, 0x7ccdd084387a0307}}}, -{{{0xdca6422c6d260417, 0xae153d50948240bd, 0xa9c0c1b4fb68c677, 0x428bd0ed61d0cf53}}, - {{0x9b0c84186760cc93, 0xcdae007a1ab32a99, 0xa88dec86620bda18, 0x3593ca848190ca44}}, - {{0x9213189a5e849aa7, 0xd4d8c33565d8facd, 0x8c52545b53fdbbd1, 0x27398308da2d63e6}}}, -{{{0x42c38d28435ed413, 0xbd50f3603278ccc9, 0xbb07ab1a79da03ef, 0x269597aebe8c3355}}, - {{0xb9a10e4c0a702453, 0x0fa25866d57d1bde, 0xffb9d9b5cd27daf7, 0x572c2945492c33fd}}, - {{0xc77fc745d6cd30be, 0xe4dfe8d3e3baaefb, 0xa22c8830aa5dda0c, 0x7f985498c05bca80}}}, -{{{0x3849ce889f0be117, 0x8005ad1b7b54a288, 0x3da3c39f23fc921c, 0x76c2ec470a31f304}}, - {{0xd35615520fbf6363, 0x08045a45cf4dfba6, 0xeec24fbc873fa0c2, 0x30f2653cd69b12e7}}, - {{0x8a08c938aac10c85, 0x46179b60db276bcb, 0xa920c01e0e6fac70, 0x2f1273f1596473da}}}, -{{{0x4739fc7c8ae01e11, 0xfd5274904a6aab9f, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2}}, - {{0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, 0xead1a69ebc596162, 0x38ac1997edc5f784}}, - {{0x0666b517a751b13b, 0x747d06867e9b858c, 0xacacc011454dde49, 0x22dfcd9cbfe9e69c}}}, -{{{0x8ddbd2e0c30d0cd9, 0xad8e665facbb4333, 0x8f6b258c322a961f, 0x6b2916c05448c1c7}}, - {{0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472}}, - {{0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17}}}, -{{{0xd30a3bd617b28c85, 0xc5d377b739773bea, 0xc6c6e78c1e6a5cbf, 0x0d61b8f78b2ab7c4}}, - {{0x29fc03580dd94500, 0xecd27aa46fbbec93, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5}}, - {{0x56a8d7efe9c136b0, 0xbd07e5cd58e44b20, 0xafe62fda1b57e0ab, 0x191a2af74277e8d2}}}, -{{{0xce16f74bc53c1431, 0x2b9725ce2072edde, 0xb8b9c36fb5b23ee7, 0x7e2e0e450b5cc908}}, - {{0x9fe62b434f460efb, 0xded303d4a63607d6, 0xf052210eb7a0da24, 0x237e7dbe00545b93}}, - {{0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3}}}, -{{{0x65ce6f9b3953b61d, 0xc65839eaafa141e6, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e}}, - {{0xea423c1c473b50d6, 0x51e87a1f3b38ef10, 0x9b84bf5fb2c9be95, 0x00731fbc78f89a1c}}, - {{0xe430c71848f81880, 0xbf960c225ecec119, 0xb6dae0836bba15e3, 0x4c4d6f3347e15808}}}, -{{{0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, 0xdbde712bf7ee0cdf, 0x193fddaaa7e47a22}}, - {{0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8}}, - {{0x1fd2c93c37e8876f, 0xa2f61e5a18d1462c, 0x5080f58239241276, 0x6a6fb99ebf0d4969}}}, -{{{0x6a46c1bb560855eb, 0x2416bb38f893f09d, 0xd71d11378f71acc1, 0x75f76914a31896ea}}, - {{0xeeb122b5b6e423c6, 0x939d7010f286ff8e, 0x90a92a831dcf5d8c, 0x136fda9f42c5eb10}}, - {{0xf94cdfb1a305bdd1, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba}}}, -{{{0x4af766385ead2d14, 0xa08ed880ca7c5830, 0x0d13a6e610211e3d, 0x6a071ce17b806c03}}, - {{0x9d5a710143307a7f, 0xb063de9ec47da45f, 0x22bbfe52be927ad3, 0x1387c441fd40426c}}, - {{0xb5d3c3d187978af8, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92}}}, -{{{0xa92f319097564ca8, 0xff7bb84c2275e119, 0x4f55fe37a4875150, 0x221fd4873cf0835a}}, - {{0xa60db7d8b28a47d1, 0xa6bf14d61770a4f1, 0xd4a1f89353ddbd58, 0x6c514a63344243e9}}, - {{0x2322204f3a156341, 0xfb73e0e9ba0a032d, 0xfce0dd4c410f030e, 0x48daa596fb924aaa}}}, -{{{0x6eca8e665ca59cc7, 0xa847254b2e38aca0, 0x31afc708d21e17ce, 0x676dd6fccad84af7}}, - {{0x14f61d5dc84c9793, 0x9941f9e3ef418206, 0xcdf5b88f346277ac, 0x58c837fa0e8a79a9}}, - {{0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, 0xdcc2e77d4935d66a, 0x1c4f73f2c6a57f0a}}}, -{{{0x0e7a4fbd305fa0bb, 0x829d4ce054c663ad, 0xf421c3832fe33848, 0x795ac80d1bf64c42}}, - {{0xb36e706efc7c3484, 0x73dfc9b4c3c1cf61, 0xeb1d79c9781cc7e5, 0x70459adb7daf675c}}, - {{0x1b91db4991b42bb3, 0x572696234b02dcca, 0x9fdf9ee51f8c78dc, 0x5fe162848ce21fd3}}}, -{{{0x4e59214fe194961a, 0x49be7dc70d71cd4f, 0x9300cfd23b50f22d, 0x4789d446fc917232}}, - {{0x2879852d5d7cb208, 0xb8dedd70687df2e7, 0xdc0bffab21687891, 0x2b44c043677daa35}}, - {{0x1a1c87ab074eb78e, 0xfac6d18e99daf467, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4}}}, -{{{0x0b5d89bc3bfd8bf1, 0xb06b9237c9f3551a, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab}}, - {{0x702bc5c27cae6d11, 0x44c7699b54a48cab, 0xefbc4056ba492eb2, 0x70d77248d9b6676d}}, - {{0xaa8ae84b3ec2a05b, 0x98699ef4ed1781e0, 0x794513e4708e85d1, 0x63755bd3a976f413}}}, -{{{0xb55fa03e2ad10853, 0x356f75909ee63569, 0x9ff9f1fdbe69b890, 0x0d8cc1c48bc16f84}}, - {{0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56}}, - {{0x029402d36eb419a9, 0xf0b44e7e77b460a5, 0xcfa86230d43c4956, 0x70c2dd8a7ad166e7}}}, -{{{0x656194509f6fec0e, 0xee2e7ea946c6518d, 0x9733c1f367e09b5c, 0x2e0fac6363948495}}, - {{0x91d4967db8ed7e13, 0x74252f0ad776817a, 0xe40982e00d852564, 0x32b8613816a53ce5}}, - {{0x79e7f7bee448cd64, 0x6ac83a67087886d0, 0xf89fd4d9a0e4db2e, 0x4179215c735a4f41}}}, -{{{0x8c7094e7d7dced2a, 0x97fb8ac347d39c70, 0xe13be033a906d902, 0x700344a30cd99d76}}, - {{0xe4ae33b9286bcd34, 0xb7ef7eb6559dd6dc, 0x278b141fb3d38e1f, 0x31fa85662241c286}}, - {{0xaf826c422e3622f4, 0xc12029879833502d, 0x9bc1b7e12b389123, 0x24bb2312a9952489}}}, -{{{0xb1a8ed1732de67c3, 0x3cb49418461b4948, 0x8ebd434376cfbcd2, 0x0fee3e871e188008}}, - {{0x41f80c2af5f85c6b, 0x687284c304fa6794, 0x8945df99a3ba1bad, 0x0d1d2af9ffeb5d16}}, - {{0xa9da8aa132621edf, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76}}}, -{{{0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309}}, - {{0xc959c6c57887b6ad, 0x94e19ead5f90feba, 0x16e24e62a342f504, 0x164ed34b18161700}}, - {{0x487ed94c192fe69a, 0x61ae2cea3a911513, 0x877bf6d3b9a4de27, 0x78da0fc61073f3eb}}}, -{{{0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a}}, - {{0xa29f80f1680c3a94, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd}}, - {{0xdfc8468d19267cb8, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760}}}, -{{{0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650}}, - {{0xcd2a65e777d1f515, 0x548991878faa60f1, 0xb1b73bbcdabc06e5, 0x654878cba97cc9fb}}, - {{0x969ee405055ce6a1, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba}}}, -{{{0xdc4267b1834e2457, 0xb67544b570ce1bc5, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650}}, - {{0xfec7bc0c9b056f85, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9}}, - {{0xc32d36360415171e, 0xcd2bef118998483b, 0x870a6eadd0945110, 0x0bccbb72a2a86561}}}, -{{{0x185e962feab1a9c8, 0x86e7e63565147dcd, 0xb092e031bb5b6df2, 0x4024f0ab59d6b73e}}, - {{0x186d5e4c50fe1296, 0xe0397b82fee89f7e, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2}}, - {{0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701}}}, -{{{0x97f5131594dfd29b, 0x6155985d313f4c6a, 0xeba13f0708455010, 0x676b2608b8d2d322}}, - {{0x21717b0d0f537593, 0x914e690b131e064c, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e}}, - {{0x8138ba651c5b2b47, 0x8671b6ec311b1b80, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0}}}, -{{{0xbf525a1e2bc9c8bd, 0xea5b260826479d81, 0xd511c70edf0155db, 0x1ae23ceb960cf5d0}}, - {{0x6036df5721d34e6a, 0xb1db8827997bb3d0, 0xd3c209c3c8756afa, 0x06e15be54c1dc839}}, - {{0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7}}}, -{{{0xd8173793f266c55c, 0xc8c976c5cc454e49, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9}}, - {{0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8}}, - {{0x77ed3eeec3efc57a, 0x04e05517d4ff4811, 0xea3d7a3ff1a671cb, 0x120633b4947cfe54}}}, -{{{0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185}}, - {{0x82bd31474912100a, 0xde237b6d7e6fbe06, 0xe11e761911ea79c6, 0x07433be3cb393bde}}, - {{0xff7944c05ce997f4, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f}}}, -{{{0x157a316443373409, 0xfab8b7eef4aa81d9, 0xb093fee6f5a64806, 0x2e773654707fa7b6}}, - {{0xaa6202e14e5df981, 0xa20d59175015e1f5, 0x18a275d3bae21d6c, 0x0543618a01600253}}, - {{0x0deabdf4974c23c1, 0xaa6f0a259dce4693, 0x04202cb8a29aba2c, 0x4b1443362d07960d}}}, -{{{0xccc4b7c7b66e1f7a, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7}}, - {{0x967c54e91c529ccb, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c}}, - {{0xc6317bd320324ce4, 0xa81042e8a4488bc4, 0xb21ef18b4e5a1364, 0x0c2a1c4bcda28dc9}}}, -{{{0xd24dc7d06f1f0447, 0xb2269e3edb87c059, 0xd15b0272fbb2d28f, 0x7c558bd1c6f64877}}, - {{0xedc4814869bd6945, 0x0d6d907dbe1c8d22, 0xc63bd212d55cc5ab, 0x5a6a9b30a314dc83}}, - {{0xd0ec1524d396463d, 0x12bb628ac35a24f0, 0xa50c3a791cbc5fa4, 0x0404a5ca0afbafc3}}}, -{{{0x8c1f40070aa743d6, 0xccbad0cb5b265ee8, 0x574b046b668fd2de, 0x46395bfdcadd9633}}, - {{0x62bc9e1b2a416fd1, 0xb5c6f728e350598b, 0x04343fd83d5d6967, 0x39527516e7f8ee98}}, - {{0x117fdb2d1a5d9a9c, 0x9c7745bcd1005c2a, 0xefd4bef154d56fea, 0x76579a29e822d016}}}, -{{{0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1}}, - {{0x333cb51352b434f2, 0xd832284993de80e1, 0xb5512887750d35ce, 0x02c514bb2a2777c1}}, - {{0x684bd5da8bf1b645, 0xfb8bd37ef6b54b53, 0x313916d7a9b0d253, 0x1160920961548059}}}, -{{{0xb44d166929dacfaa, 0xda529f4c8413598f, 0xe9ef63ca453d5559, 0x351e125bc5698e0b}}, - {{0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042}}, - {{0xd4b49b461af67bbe, 0xd603037ac8ab8961, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a}}}, -{{{0x7a7c8e64ab0168ec, 0xcb5a4a5515edc543, 0x095519d347cd0eda, 0x67d4ac8c343e93b0}}, - {{0x09454b728e217522, 0xaa58e8f4d484b8d8, 0xd358254d7f46903c, 0x44acc043241c5217}}, - {{0x1c7d6bbb4f7a5777, 0x8b35fed4918313e1, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd}}}, -{{{0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff}}, - {{0x81f06756b11be821, 0x0faff82310a3f3dd, 0xf8b2d0556a99465d, 0x097abe38cc8c7f05}}, - {{0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd}}}, -{{{0xf0e268ac61a73b0a, 0xf2fafa103791a5f5, 0xc1e13e826b6d00e9, 0x60fa7ee96fd78f42}}, - {{0x94fecebebd4dd72b, 0xf46a4fda060f2211, 0x124a5977c0c8d1ff, 0x705304b8fb009295}}, - {{0xb63d1d354d296ec6, 0xf3c3053e5fad31d8, 0x670b958cb4bd42ec, 0x21398e0ca16353fd}}}, -{{{0x89f5058a382b33f3, 0x5ae2ba0bad48c0b4, 0x8f93b503a53db36e, 0x5aa3ed9d95a232e6}}, - {{0x2798aaf9b4b75601, 0x5eac72135c8dad72, 0xd2ceaa6161b7a023, 0x1bbfb284e98f7d4e}}, - {{0x656777e9c7d96561, 0xcb2b125472c78036, 0x65053299d9506eee, 0x4a07e14e5e8957cc}}}, -{{{0x4ee412cb980df999, 0xa315d76f3c6ec771, 0xbba5edde925c77fd, 0x3f0bac391d313402}}, - {{0x240b58cdc477a49b, 0xfd38dade6447f017, 0x19928d32a7c86aad, 0x50af7aed84afa081}}, - {{0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006}}}, -{{{0x89422f7edfb870fc, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0}}, - {{0xd75aad9ad9f3c18b, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5}}, - {{0xdccbe37a35444483, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64}}}, -{{{0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c}}, - {{0x6bdeeebe6084034b, 0x3199c2b6780fb854, 0x973376abb62d0695, 0x6e3180c98b647d90}}, - {{0xee7ab6e7a128b071, 0xa4c1596d93a88baa, 0xf7b4de82b2216130, 0x363e999ddd97bd18}}}, -{{{0x96a843c135ee1fc4, 0x976eb35508e4c8cf, 0xb42f6801b58cd330, 0x48ee9b78693a052b}}, - {{0x2f1848dce24baec6, 0x769b7255babcaf60, 0x90cb3c6e3cefe931, 0x231f979bc6f9b355}}, - {{0x5c31de4bcc2af3c6, 0xb04bb030fe208d1f, 0xb78d7009c14fb466, 0x079bfa9b08792413}}}, -{{{0xe3903a51da300df4, 0x843964233da95ab0, 0xed3cf12d0b356480, 0x038c77f684817194}}, - {{0xf3c9ed80a2d54245, 0x0aa08b7877f63952, 0xd76dac63d1085475, 0x1ef4fb159470636b}}, - {{0x854e5ee65b167bec, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56}}}, -{{{0xd4c080908a182fcf, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00}}, - {{0x5d46bc450aa4d801, 0xc3af1227a533b9d8, 0x389e3b262b8906c2, 0x200a1e7e382f581b}}, - {{0x518db967eaf93ac5, 0x71bc989b056652c0, 0xfe2b85d9567197f5, 0x050eca52651e4e38}}}, -{{{0xc3431ade453f0c9c, 0xe9f5045eff703b9b, 0xfcd97ac9ed847b3d, 0x4b0ee6c21c58f4c6}}, - {{0x97ac397660e668ea, 0x9b19bbfe153ab497, 0x4cb179b534eca79f, 0x6151c09fa131ae57}}, - {{0x3af55c0dfdf05d96, 0xdd262ee02ab4ee7a, 0x11b2bb8712171709, 0x1fef24fa800f030b}}}, -{{{0x37d653fb1aa73196, 0x0f9495303fd76418, 0xad200b09fb3a17b2, 0x544d49292fc8613e}}, - {{0x22d2aff530976b86, 0x8d90b806c2d24604, 0xdca1896c4de5bae5, 0x28005fe6c8340c17}}, - {{0x6aefba9f34528688, 0x5c1bff9425107da1, 0xf75bbbcd66d94b36, 0x72e472930f316dfa}}}, -{{{0x2695208c9781084f, 0xb1502a0b23450ee1, 0xfd9daea603efde02, 0x5a9d2e8c2733a34c}}, - {{0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438}}, - {{0x765305da03dbf7e5, 0xa4daf2491434cdbd, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543}}}, -{{{0x8d356b23c3d330b2, 0xf21c8b9bb0471b06, 0xb36c316c6e42b83c, 0x07d79c7e8beab10d}}, - {{0xd7ef93bb07af9753, 0x583ed0cf3db766a7, 0xce6998bf6e0b1ec5, 0x47b7ffd25dd40452}}, - {{0x87fbfb9cbc08dd12, 0x8a066b3ae1eec29b, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6}}}, -{{{0x80d253a6bccba34a, 0x3e61c3a13838219b, 0x90c3b6019882e396, 0x1c3d05775d0ee66f}}, - {{0xcda86f40216bc059, 0x1fbb231d12bcd87e, 0xb4956a9e17c70990, 0x38750c3b66d12e55}}, - {{0x692ef1409422e51a, 0xcbc0c73c2b5df671, 0x21014fe7744ce029, 0x0621e2c7d330487c}}}, -{{{0xaf9860cc8259838d, 0x90ea48c1c69f9adc, 0x6526483765581e30, 0x0007d6097bd3a5bc}}, - {{0xb7ae1796b0dbf0f3, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d}}, - {{0xc0bf1d950842a94b, 0xb2d3c363588f2e3e, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86}}}, -{{{0xeceea2ef5da27ae1, 0x597c3a1455670174, 0xc9a62a126609167a, 0x252a5f2e81ed8f70}}, - {{0x90034704cc9d28c7, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a}}, - {{0x0d2894265066e80d, 0xfcc3f785307c8c6b, 0x1b53da780c1112fd, 0x079c170bd843b388}}}, -{{{0x0506ece464fa6fff, 0xbee3431e6205e523, 0x3579422451b8ea42, 0x6dec05e34ac9fb00}}, - {{0xcdd6cd50c0d5d056, 0x9af7686dbb03573b, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc}}, - {{0x94b625e5f155c1b3, 0x417bf3a7997b7b91, 0xc22cbddc6d6b2600, 0x51445e14ddcd52f4}}}, -{{{0x57502b4b3b144951, 0x8e67ff6b444bbcb3, 0xb8bd6927166385db, 0x13186f31e39295c8}}, - {{0x893147ab2bbea455, 0x8c53a24f92079129, 0x4b49f948be30f7a7, 0x12e990086e4fd43d}}, - {{0xf10c96b37fdfbb2e, 0x9f9a935e121ceaf9, 0xdf1136c43a5b983f, 0x77b2e3f05d3e99af}}}, -{{{0x296fa9c59c2ec4de, 0xbc8b61bf4f84f3cb, 0x1c7706d917a8f908, 0x63b795fc7ad3255d}}, - {{0xd598639c12ddb0a4, 0xa5d19f30c024866b, 0xd17c2f0358fce460, 0x07a195152e095e8a}}, - {{0xa8368f02389e5fc8, 0x90433b02cf8de43b, 0xafa1fd5dc5412643, 0x3e8fe83d032f0137}}}, -{{{0x2f8b15b90570a294, 0x94f2427067084549, 0xde1c5ae161bbfd84, 0x75ba3b797fac4007}}, - {{0x08704c8de8efd13c, 0xdfc51a8e33e03731, 0xa59d5da51260cde3, 0x22d60899a6258c86}}, - {{0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, 0xb38847bceb401260, 0x0904d07b87779e5e}}}, -{{{0xb4ce1fd4ddba919c, 0xcf31db3ec74c8daa, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07}}, - {{0xf4322d6648f940b9, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c}}, - {{0xf834749c5ba295a0, 0xd6947c5bca37d25a, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac}}}, -{{{0x362ab9e3f53533eb, 0x338568d56eb93d40, 0x9e0e14521d5a5572, 0x1d24a86d83741318}}, - {{0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754}}, - {{0xf4ec7648ffd4ce1f, 0xe045eaf054ac8c1c, 0x88d225821d09357c, 0x43b261dc9aeb4859}}}, -{{{0xe55b1e1988bb79bb, 0xa09ed07dc17a359d, 0xb02c2ee2603dea33, 0x326055cf5b276bc2}}, - {{0x19513d8b6c951364, 0x94fe7126000bf47b, 0x028d10ddd54f9567, 0x02b4d5e242940964}}, - {{0xb4a155cb28d18df2, 0xeacc4646186ce508, 0xc49cf4936c824389, 0x27a6c809ae5d3410}}}, -{{{0x8ba6ebcd1f0db188, 0x37d3d73a675a5be8, 0xf22edfa315f5585a, 0x2cb67174ff60a17e}}, - {{0xcd2c270ac43d6954, 0xdd4a3e576a66cab2, 0x79fa592469d7036c, 0x221503603d8c2599}}, - {{0x59eecdf9390be1d0, 0xa9422044728ce3f1, 0x82891c667a94f0f4, 0x7b1df4b73890f436}}}, -{{{0xe492f2e0b3b2a224, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992}}, - {{0x5f2e221807f8f58c, 0xe3555c9fd49409d4, 0xb2aaa88d1fb6a630, 0x68698245d352e03d}}, - {{0xdbb15d852a18187a, 0xf3e4aad386ddacd7, 0x44bae2810ff6c482, 0x46cf4c473daf01cf}}}, -{{{0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40}}, - {{0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb}}, - {{0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716}}}, -{{{0x9062b2e0d91a78bc, 0x47c9889cc8509667, 0x9df54a66405070b8, 0x7369e6a92493a1bf}}, - {{0xe1014434dcc5caed, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4}}, - {{0x9d673ffb13986864, 0x3ca5fbd9415dc7b8, 0xe04ecc3bdf273b5e, 0x1420683db54e4cd2}}}, -{{{0xb478bd1e249dd197, 0x620c35005e58c102, 0xfb02d32fccbaac5c, 0x60b63bebf508a72d}}, - {{0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, 0xd3b0da49a66bde53, 0x31e83b4161d081c1}}, - {{0x97e8c7129e062b4f, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317}}}, -{{{0x5879101065c23d58, 0x8b9d086d5094819c, 0xe2402fa912c55fa7, 0x669a6564570891d4}}, - {{0x3076b5e37df58c52, 0xd73ab9dde799cc36, 0xbd831ce34913ee20, 0x1a56fbaa62ba0133}}, - {{0x943e6b505c9dc9ec, 0x302557bba77c371a, 0x9873ae5641347651, 0x13c4836799c58a5c}}}, -{{{0x423a5d465ab3e1b9, 0xfc13c187c7f13f61, 0x19f83664ecb5b9b6, 0x66f80c93a637b607}}, - {{0xc4dcfb6a5d8bd080, 0xdeebc4ec571a4842, 0xd4b2e883b8e55365, 0x50bdc87dc8e5b827}}, - {{0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae}}}, -{{{0x8fa47ff83362127d, 0xbc9f6ac471cd7c15, 0x6e71454349220c8b, 0x0e645912219f732e}}, - {{0xc297e60008bac89a, 0x7d4cea11eae1c3e0, 0xf3e38be19fe7977c, 0x3a3a450f63a305cd}}, - {{0x078f2f31d8394627, 0x389d3183de94a510, 0xd1e36c6d17996f80, 0x318c8d9393a9a87b}}}, -{{{0xf2745d032afffe19, 0x0c9f3c497f24db66, 0xbc98d3e3ba8598ef, 0x224c7c679a1d5314}}, - {{0x5d669e29ab1dd398, 0xfc921658342d9e3b, 0x55851dfdf35973cd, 0x509a41c325950af6}}, - {{0xbdc06edca6f925e9, 0x793ef3f4641b1f33, 0x82ec12809d833e89, 0x05bff02328a11389}}}, -{{{0x3632137023cae00b, 0x544acf0ad1accf59, 0x96741049d21a1c88, 0x780b8cc3fa2a44a7}}, - {{0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea}}, - {{0x1ef38abc234f305f, 0x9a577fbd1405de08, 0x5e82a51434e62a0d, 0x5ff418726271b7a1}}}, -{{{0x398e080c1789db9d, 0xa7602025f3e778f5, 0xfa98894c06bd035d, 0x106a03dc25a966be}}, - {{0xe5db47e813b69540, 0xf35d2a3b432610e1, 0xac1f26e938781276, 0x29d4db8ca0a0cb69}}, - {{0xd9ad0aaf333353d0, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa}}}, -{{{0xda7c2b256768d593, 0x98c1c0574422ca13, 0xf1a80bd5ca0ace1d, 0x29cdd1adc088a690}}, - {{0xd6cfd1ef5fddc09c, 0xe82b3efdf7575dce, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b}}, - {{0x0ff2f2f9d956e148, 0xade797759f356b2e, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b}}}, -{{{0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149}}, - {{0xa95d9a5fd67ff163, 0xe92be69d4cc75681, 0xb7f8024cde20f257, 0x204f2a20fb072df5}}, - {{0xc8143b3d30ebb079, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f}}}, -{{{0x3efa367f2cb61575, 0xf5f96f761cd6026c, 0xe8c7142a65b52562, 0x3dcb65ea53030acd}}, - {{0x192ea9550bb8245a, 0xc8e6fba88f9050d1, 0x7986ea2d88a4c935, 0x241c5f91de018668}}, - {{0x28d8172940de6caa, 0x8fbf2cf022d9733a, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5}}}, -{{{0xcdff20ab8362fa4a, 0x57e118d4e21a3e6e, 0xe3179617fc39e62b, 0x0d9a53efbc1769fd}}, - {{0x0358c34e04f410ce, 0xb6135b5a276e0685, 0x5d9670c7ebb91521, 0x04d654f321db889c}}, - {{0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7}}}, -{{{0xf4a718025fb15f95, 0x3df65f346b5c1b8f, 0xcdfcf08500e01112, 0x11b50c4cddd31848}}, - {{0x24c3b291af372a4b, 0x93da8270718147f2, 0xdd84856486899ef2, 0x4a96314223e0ee33}}, - {{0xa6e8274408a4ffd6, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51}}}, -{{{0xa71fce5ae2242584, 0x26ea725692f58a9e, 0xd21a09d71cea3cf4, 0x73fcdd14b71c01e6}}, - {{0x30e2616ec49d0b6f, 0xe456718fcaec2317, 0x48eb409bf26b4fa6, 0x3042cee561595f37}}, - {{0x427e7079449bac41, 0x855ae36dbce2310a, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6}}}, -{{{0x64fcb3ae34dcb9ce, 0x97500323e348d0ad, 0x45b3f07d62c6381b, 0x61545379465a6788}}, - {{0xc9bd78f6570eac28, 0xe55b0b3227919ce1, 0x65fc3eaba19b91ed, 0x25c425e5d6263690}}, - {{0x3f3e06a6f1d7de6e, 0x3ef976278e062308, 0x8c14f6264e8a6c77, 0x6539a08915484759}}}, -{{{0xe9d21f74c3d2f773, 0xc150544125c46845, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c}}, - {{0xddc4dbd414bb4a19, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90}}, - {{0xd486d1b1cafde0c6, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a}}}, -{{{0x239e9624089c0a2e, 0xc748c4c03afe4738, 0x17dbed2a764fa12a, 0x639b93f0321c8582}}, - {{0xc08f788f3f78d289, 0xfe30a72ca1404d9f, 0xf2778bfccf65cc9d, 0x7ee498165acb2021}}, - {{0x7bd508e39111a1c3, 0x2b2b90d480907489, 0xe7d2aec2ae72fd19, 0x0edf493c85b602a6}}}, -{{{0xaecc8158599b5a68, 0xea574f0febade20e, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4}}, - {{0x6767c4d284764113, 0xa090403ff7f5f835, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369}}, - {{0x4dc22f818b465cf8, 0x71a0f35a1480eff8, 0xaee8bfad04c7d657, 0x355bb12ab26176f4}}}, -{{{0xa71e64cc7493bbf4, 0xe5bd84d9eca3b0c3, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312}}, - {{0xa301dac75a8c7318, 0xed90039db3ceaa11, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e}}, - {{0xa48859c41b7f6c32, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4}}}, -{{{0x5144539771ec4f48, 0xf805b17dc98c5d6e, 0xf762c11a47c3c66b, 0x00b89b85764699dc}}, - {{0xfbe65d50c85066b0, 0x62ecc4b0b3a299b0, 0xe53754ea441ae8e0, 0x08fea02ce8d48d5f}}, - {{0x824ddd7668deead0, 0xc86445204b685d23, 0xb514cfcd5d89d665, 0x473829a74f75d537}}}, -{{{0x82d2da754679c418, 0xe63bd7d8b2618df0, 0x355eef24ac47eb0a, 0x2078684c4833c6b4}}, - {{0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390}}, - {{0x3b48cf217a78820c, 0xf76a0ab281273e97, 0xa96c65a78c8eed7b, 0x7411a6054f8a433f}}}, -{{{0x4d659d32b99dc86d, 0x044cdc75603af115, 0xb34c712cdcc2e488, 0x7c136574fb8134ff}}, - {{0x579ae53d18b175b4, 0x68713159f392a102, 0x8455ecba1eef35f5, 0x1ec9a872458c398f}}, - {{0xb8e6a4d400a2509b, 0x9b81d7020bc882b4, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460}}}, -{{{0xab895770b635dcf2, 0x02dfef6cf66c1fbc, 0x85530268beb6d187, 0x249929fccc879e74}}, - {{0x85c298d459393046, 0x8f7e35985ff659ec, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720}}, - {{0xa3d0a0f116959029, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7}}}, -{{{0x528993434934d643, 0xb9dbf806a51222f5, 0x8f6d878fc3f41c22, 0x37676a2a4d9d9730}}, - {{0x6646b5f477e285d6, 0x40e8ff676c8f6193, 0xa6ec7311abb594dd, 0x7ec846f3658cec4d}}, - {{0x9b5e8f3f1da22ec7, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5}}}, -{{{0x5f3a7562eb3dbe47, 0xf7ea38548ebda0b8, 0x00c3e53145747299, 0x1304e9e71627d551}}, - {{0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa}}, - {{0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, 0xda0fe1fff979c60a, 0x4468de2d7c2dd693}}}, -{{{0x51bb355e9419469e, 0x33e6dc4c23ddc754, 0x93a5b6d6447f9962, 0x6cce7c6ffb44bd63}}, - {{0x4b9ad8c6f86307ce, 0x21113531435d0c28, 0xd4a866c5657a772c, 0x5da6427e63247352}}, - {{0x1a94c688deac22ca, 0xb9066ef7bbae1ff8, 0x88ad8c388d59580f, 0x58f29abfe79f2ca8}}}, -{{{0xe90ecfab8de73e68, 0x54036f9f377e76a5, 0xf0495b0bbe015982, 0x577629c4a7f41e36}}, - {{0x4b5a64bf710ecdf6, 0xb14ce538462c293c, 0x3643d056d50b3ab9, 0x6af93724185b4870}}, - {{0x3220024509c6a888, 0xd2e036134b558973, 0x83e236233c33289f, 0x701f25bb0caec18f}}}, -{{{0xc3a8b0f8e4616ced, 0xf700660e9e25a87d, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9}}, - {{0x9d18f6d97cbec113, 0x844a06e674bfdbe4, 0x20f5b522ac4e60d6, 0x720a5bc050955e51}}, - {{0x0c3f09439b805a35, 0xe84e8b376242abfc, 0x691417f35c229346, 0x0e9b9cbb144ef0ec}}}, -{{{0xfbbad48ffb5720ad, 0xee81916bdbf90d0e, 0xd4813152635543bf, 0x221104eb3f337bd8}}, - {{0x8dee9bd55db1beee, 0xc9c3ab370a723fb9, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde}}, - {{0x9e3c1743f2bc8c14, 0x2eda26fcb5856c3b, 0xccb82f0e68a7fb97, 0x4167a4e6bc593244}}}, -{{{0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a}}, - {{0xc2be2665f8ce8fee, 0xe967ff14e880d62c, 0xf12e6e7e2f364eee, 0x34b33370cb7ed2f6}}, - {{0xcdc591ee8681d6cc, 0xce02109ced85a753, 0xed7485c158808883, 0x1176fc6e2dfe65e4}}}, -{{{0xb4af6cd05b9c619b, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34}}, - {{0xdb90e28949770eb8, 0x98fbcc2aacf440a3, 0x21354ffeded7879b, 0x1f6a3e54f26906b6}}, - {{0x60a4c199d30734ea, 0x40c085b631165cd6, 0xe2333e23f7598295, 0x4f2fad0116b900d1}}}, -{{{0x44beb24194ae4e54, 0x5f541c511857ef6c, 0xa61e6b2d368d0498, 0x445484a4972ef7ab}}, - {{0x962cd91db73bb638, 0xe60577aafc129c08, 0x6f619b39f3b61689, 0x3451995f2944ee81}}, - {{0x9152fcd09fea7d7c, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7}}}, -{{{0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e}}, - {{0x753941be5a45f06e, 0xd07caeed6d9c5f65, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9}}, - {{0x27f2af18073f3e6a, 0xfd3fe519d7521069, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7}}}, -{{{0xb4e37f405307a693, 0xaba714d72f336795, 0xd6fbd0a773761099, 0x5fdf48c58171cbc9}}, - {{0x1d9db7b9f43b29c9, 0xd605824a4f518f75, 0xf2c072bd312f9dc4, 0x1f24ac855a1545b0}}, - {{0x24d608328e9505aa, 0x4748c1d10c1420ee, 0xc7ffe45c06fb25a2, 0x00ba739e2ae395e6}}}, -{{{0x592e98de5c8790d6, 0xe5bfb7d345c2a2df, 0x115a3b60f9b49922, 0x03283a3e67ad78f3}}, - {{0xae4426f5ea88bb26, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226}}, - {{0x48241dc7be0cb939, 0x32f19b4d8b633080, 0xd3dfc90d02289308, 0x05e1296846271945}}}, -{{{0xba82eeb32d9c495a, 0xceefc8fcf12bb97c, 0xb02dabae93b5d1e0, 0x39c00c9c13698d9b}}, - {{0xadbfbbc8242c4550, 0xbcc80cecd03081d9, 0x843566a6f5c8df92, 0x78cf25d38258ce4c}}, - {{0x15ae6b8e31489d68, 0xaa851cab9c2bf087, 0xc9a75a97f04efa05, 0x006b52076b3ff832}}}, -{{{0x29e0cfe19d95781c, 0xb681df18966310e2, 0x57df39d370516b39, 0x4d57e3443bc76122}}, - {{0xf5cb7e16b9ce082d, 0x3407f14c417abc29, 0xd4b36bce2bf4a7ab, 0x7de2e9561a9f75ce}}, - {{0xde70d4f4b6a55ecb, 0x4801527f5d85db99, 0xdbc9c440d3ee9a81, 0x6b2a90af1a6029ed}}}, -{{{0x6923f4fc9ae61e97, 0x5735281de03f5fd1, 0xa764ae43e6edd12d, 0x5fd8f4e9d12d3e4a}}, - {{0x77ebf3245bb2d80a, 0xd8301b472fb9079b, 0xc647e6f24cee7333, 0x465812c8276c2109}}, - {{0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790}}}, -{{{0xc8c05eccd24da8fd, 0xa1cf1aac05dfef83, 0xdbbeeff27df9cd61, 0x3b5556a37b471e99}}, - {{0xf7fca42c7ad58195, 0x3214286e4333f3cc, 0xb6c29d0d340b979d, 0x31771a48567307e1}}, - {{0x32b0c524e14dd482, 0xedb351541a2ba4b6, 0xa3d16048282b5af3, 0x4fc079d27a7336eb}}}, -{{{0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, 0xffffc09c7880e453, 0x124567cecaf98e92}}, - {{0xdc348b440c86c50d, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08}}, - {{0x3ff9ab860ac473b4, 0xf0911dee0113e435, 0x4ae75060ebc6c4af, 0x3f8612966c87000d}}}, -{{{0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d}}, - {{0x9c18fcfa36048d13, 0x29159db373899ddd, 0xdc9f350b9f92d0aa, 0x26f57eee878a19d4}}, - {{0x0cab2cd55687efb1, 0x5180d162247af17b, 0x85c15a344f5a2467, 0x4041943d9dba3069}}}, -{{{0xc3c0eeba43ebcc96, 0x8d749c9c26ea9caf, 0xd9fa95ee1c77ccc6, 0x1420a1d97684340f}}, - {{0x4b217743a26caadd, 0x47a6b424648ab7ce, 0xcb1d4f7a03fbc9e3, 0x12d931429800d019}}, - {{0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012}}}, -{{{0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae}}, - {{0x33cf3030a49866b1, 0x251f73d2215f4859, 0xab82aa4051def4f6, 0x5ff191d56f9a23f6}}, - {{0x819ed433ac2d9068, 0x2883ab795fc98523, 0xef4572805593eb3d, 0x020c526a758f36cb}}}, -{{{0x779834f89ed8dbbc, 0xc8f2aaf9dc7ca46c, 0xa9524cdca3e1b074, 0x02aacc4615313877}}, - {{0xe931ef59f042cc89, 0x2c589c9d8e124bb6, 0xadc8e18aaec75997, 0x452cfe0a5602c50c}}, - {{0x86a0f7a0647877df, 0xbbc464270e607c9f, 0xab17ea25f1fb11c9, 0x4cfb7d7b304b877b}}}, -{{{0x72b43d6cb89b75fe, 0x54c694d99c6adc80, 0xb8c3aa373ee34c9f, 0x14b4622b39075364}}, - {{0xe28699c29789ef12, 0x2b6ecd71df57190d, 0xc343c857ecc970d0, 0x5b1d4cbc434d3ac5}}, - {{0xb6fb2615cc0a9f26, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1}}}, -{{{0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, 0x9a2acc2182300f67, 0x3a6ae249d806aaf9}}, - {{0x2e12ae444f54a701, 0xfcfe3ef0a9cbd7de, 0xcebf890d75835de0, 0x1d8062e9e7614554}}, - {{0x657ada85a9907c5a, 0x1a0ea8b591b90f62, 0x8d0e1dfbdf34b4e9, 0x298b8ce8aef25ff3}}}, -{{{0x2a927953eff70cb2, 0x4b89c92a79157076, 0x9418457a30a7cf6a, 0x34b8a8404d5ce485}}, - {{0x837a72ea0a2165de, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc}}, - {{0xc26eecb583693335, 0xd5a813df63b5fefd, 0xa293aa9aa4b22573, 0x71d62bdd465e1c6a}}}, -{{{0x6533cc28d378df80, 0xf6db43790a0fa4b4, 0xe3645ff9f701da5a, 0x74d5f317f3172ba4}}, - {{0xcd2db5dab1f75ef5, 0xd77f95cf16b065f5, 0x14571fea3f49f085, 0x1c333621262b2b3d}}, - {{0xa86fe55467d9ca81, 0x398b7c752b298c37, 0xda6d0892e3ac623b, 0x4aebcc4547e9d98c}}}, -{{{0x12f0071b276d01c9, 0xe7b8bac586c48c70, 0x5308129b71d6fba9, 0x5d88fbf95a3db792}}, - {{0x0b408d9e7354b610, 0x806b32535ba85b6e, 0xdbe63a034a58a207, 0x173bd9ddc9a1df2c}}, - {{0x2b500f1efe5872df, 0x58d6582ed43918c1, 0xe6ed278ec9673ae0, 0x06e1cd13b19ea319}}}, -{{{0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266}}, - {{0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13}}, - {{0xf7e644395d3d800b, 0x95a8d555c901edf6, 0x68cd7830592c6339, 0x30d0fded2e51307e}}}, -{{{0xe0594d1af21233b3, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868}}, - {{0x9cb4971e68b84750, 0xa09572296664bbcf, 0x5c8de72672fa412b, 0x4615084351c589d9}}, - {{0xbc9019c0aeb9a02e, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe}}}, -{{{0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, 0x98183da2130fb545, 0x5631deddae8f13cd}}, - {{0x9c688eb69ecc01bf, 0xf0bc83ada644896f, 0xca2d955f5f7a9fe2, 0x4ea8b4038df28241}}, - {{0x2aed460af1cad202, 0x46305305a48cee83, 0x9121774549f11a5f, 0x24ce0930542ca463}}}, -{{{0x1fe890f5fd06c106, 0xb5c468355d8810f2, 0x827808fe6e8caf3e, 0x41d4e3c28a06d74b}}, - {{0x3fcfa155fdf30b85, 0xd2f7168e36372ea4, 0xb2e064de6492f844, 0x549928a7324f4280}}, - {{0xf26e32a763ee1a2e, 0xae91e4b7d25ffdea, 0xbc3bd33bd17f4d69, 0x491b66dec0dcff6a}}}, -{{{0x98f5b13dc7ea32a7, 0xe3d5f8cc7e16db98, 0xac0abf52cbf8d947, 0x08f338d0c85ee4ac}}, - {{0x75f04a8ed0da64a1, 0xed222caf67e2284b, 0x8234a3791f7b7ba4, 0x4cf6b8b0b7018b67}}, - {{0xc383a821991a73bd, 0xab27bc01df320c7a, 0xc13d331b84777063, 0x530d4a82eb078a99}}}, -{{{0x004c3630e1f94825, 0x7e2d78268cab535a, 0xc7482323cc84ff8b, 0x65ea753f101770b9}}, - {{0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b}}, - {{0x3d66fc3ee2096363, 0x81d62c7f61b5cb6b, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db}}}, -{{{0x5ce6259a3b24b8a2, 0xb8577acc45afa0b8, 0xcccbe6e88ba07037, 0x3d143c51127809bf}}, - {{0xf5c86162f1cf795f, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf}}, - {{0x126d279179154557, 0xd5e48f5cfc783a0a, 0x36bdb6e8df179bac, 0x2ef517885ba82859}}}, -{{{0x4637974e8c58aedc, 0xb9ef22fbabf041a4, 0xe185d956e980718a, 0x2f1b78fab143a8a6}}, - {{0x96eebffb305b2f51, 0xd3f938ad889596b8, 0xf0f52dc746d5dd25, 0x57968290bb3a0095}}, - {{0xf71ab8430a20e101, 0xf393658d24f0ec47, 0xcf7509a86ee2eed1, 0x7dc43e35dc2aa3e1}}}, -{{{0x85966665887dd9c3, 0xc90f9b314bb05355, 0xc6e08df8ef2079b1, 0x7ef72016758cc12f}}, - {{0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99}}, - {{0xc1df18c5a907e3d9, 0x57b3371dce4c6359, 0xca704534b201bb49, 0x7f79823f9c30dd2e}}}, -{{{0x8334d239a3b513e8, 0xc13670d4b91fa8d8, 0x12b54136f590bd33, 0x0a4e0373d784d9b4}}, - {{0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0}}, - {{0x2eb3d6a15b7d2919, 0xb0b4f6a0d53a8235, 0x7156ce4389a45d47, 0x071a7d0ace18346c}}}, -{{{0xd3072daac887ba0b, 0x01262905bfa562ee, 0xcf543002c0ef768b, 0x2c3bcc7146ea7e9c}}, - {{0xcc0c355220e14431, 0x0d65950709b15141, 0x9af5621b209d5f36, 0x7c69bcf7617755d3}}, - {{0x07f0d7eb04e8295f, 0x10db18252f50f37d, 0xe951a9a3171798d7, 0x6f5a9a7322aca51d}}}, -{{{0x8ba1000c2f41c6c5, 0xc49f79c10cfefb9b, 0x4efa47703cc51c9f, 0x494e21a2e147afca}}, - {{0xe729d4eba3d944be, 0x8d9e09408078af9e, 0x4525567a47869c03, 0x02ab9680ee8d3b24}}, - {{0xefa48a85dde50d9a, 0x219a224e0fb9a249, 0xfa091f1dd91ef6d9, 0x6b5d76cbea46bb34}}}, -{{{0x8857556cec0cd994, 0x6472dc6f5cd01dba, 0xaf0169148f42b477, 0x0ae333f685277354}}, - {{0xe0f941171e782522, 0xf1e6ae74036936d3, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e}}, - {{0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075}}}, -{{{0x7f910fcc7ed9affe, 0x545cb8a12465874b, 0xa8397ed24b0c4704, 0x50510fc104f50993}}, - {{0x0adb7f355f17c824, 0x74b923c3d74299a4, 0xd57c3e8bcbf8eaf7, 0x0ad3e2d34cdedc3d}}, - {{0x6f0c0fc5336e249d, 0x745ede19c331cfd9, 0xf2d6fd0009eefe1c, 0x127c158bf0fa1ebe}}}, -{{{0xf6197c422e9879a2, 0xa44addd452ca3647, 0x9b413fc14b4eaccb, 0x354ef87d07ef4f68}}, - {{0xdea28fc4ae51b974, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95}}, - {{0xfee3b52260c5d975, 0x50352efceb41b0b8, 0x8808ac30a9f6653c, 0x302d92d20539236d}}}, -{{{0x7813c1a2bca4283d, 0xed62f091a1863dd9, 0xaec7bcb8c268fa86, 0x10e5d3b76f1cae4c}}, - {{0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060}}, - {{0x5453bfd653da8e67, 0xe9dc1eec24a9f641, 0xbf87263b03578a23, 0x45b46c51361cba72}}}, -{{{0xa9402abf314f7fa1, 0xe257f1dc8e8cf450, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b}}, - {{0xce9d4ddd8a7fe3e4, 0xab13645676620e30, 0x4b594f7bb30e9958, 0x5c1c0aef321229df}}, - {{0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb}}}, -{{{0x8ddbf6aa5344a32e, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03}}, - {{0x61117e44985bfb83, 0xfce0462a71963136, 0x83ac3448d425904b, 0x75685abe5ba43d64}}, - {{0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, 0xdf7275107af66569, 0x135529b623b0e6aa}}}, -{{{0x18f0dbd7add1d518, 0x979f7888cfc11f11, 0x8732e1f07114759b, 0x79b5b81a65ca3a01}}, - {{0xf5c716bce22e83fe, 0xb42beb19e80985c1, 0xec9da63714254aae, 0x5972ea051590a613}}, - {{0x0fd4ac20dc8f7811, 0x9a9ad294ac4d4fa8, 0xc01b2d64b3360434, 0x4f7e9c95905f3bdb}}}, -{{{0x62674bbc5781302e, 0xd8520f3989addc0f, 0x8c2999ae53fbd9c6, 0x31993ad92e638e4c}}, - {{0x71c8443d355299fe, 0x8bcd3b1cdbebead7, 0x8092499ef1a49466, 0x1942eec4a144adc8}}, - {{0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75}}}, -{{{0x2db7937ff7f927c2, 0xdb741f0617d0a635, 0x5982f3a21155af76, 0x4cf6e218647c2ded}}, - {{0xcf361acd3c1c793a, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13}}, - {{0xb119227cc28d5bb6, 0x07e24ebc774dffab, 0xa83c78cee4a32c89, 0x121a307710aa24b6}}}, -{{{0xe4db5d5e9f034a97, 0xe153fc093034bc2d, 0x460546919551d3b1, 0x333fc76c7a40e52d}}, - {{0xd659713ec77483c9, 0x88bfe077b82b96af, 0x289e28231097bcd3, 0x527bb94a6ced3a9b}}, - {{0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7}}}, -{{{0x812aa0416270220d, 0x995a89faf9245b4e, 0xffadc4ce5072ef05, 0x23bc2103aa73eb73}}, - {{0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf}}, - {{0xcaee792603589e05, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a}}}, -{{{0xeb18b9ab7f5745c6, 0x023a8aee5787c690, 0xb72712da2df7afa9, 0x36597d25ea5c013d}}, - {{0xa2b4dae0b5511c9a, 0x7ac860292bffff06, 0x981f375df5504234, 0x3f6bd725da4ea12d}}, - {{0x734d8d7b106058ac, 0xd940579e6fc6905f, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0}}}, -{{{0x78c2373c695c690d, 0xdd252e660642906e, 0x951d44444ae12bd2, 0x4235ad7601743956}}, - {{0x6dae4a51a77cfa9b, 0x82263654e7a38650, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba}}, - {{0x6258cb0d078975f5, 0x492942549189f298, 0xa0cab423e2e36ee4, 0x0e7ce2b0cdf066a1}}}, -{{{0xc494643ac48c85a3, 0xfd361df43c6139ad, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a}}, - {{0xfea6fedfd94b70f9, 0xf130c051c1fcba2d, 0x4882d47e7f2fab89, 0x615256138aeceeb5}}, - {{0x2abbf64e4870cb0d, 0xcd65bcf0aa458b6b, 0x9abe4eba75e8985d, 0x7f0bc810d514dee4}}}, -{{{0xb9006ba426f4136f, 0x8d67369e57e03035, 0xcbc8dfd94f463c28, 0x0d1f8dbcf8eedbf5}}, - {{0x83ac9dad737213a0, 0x9ff6f8ba2ef72e98, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75}}, - {{0xba1693313ed081dc, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3}}}, -{{{0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1}}, - {{0x16561f696a0aa75c, 0xc1bf725c5852bd6a, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026}}, - {{0x00120753afbd232e, 0xe92bceb8fdd8f683, 0xf81669b384e72b91, 0x33fad52b2368a066}}}, -{{{0x540649c6c5e41e16, 0x0af86430333f7735, 0xb2acfcd2f305e746, 0x16c0f429a256dca7}}, - {{0x8d2cc8d0c422cfe8, 0x072b4f7b05a13acb, 0xa3feb6e6ecf6a56f, 0x3cc355ccb90a71e2}}, - {{0xe9b69443903e9131, 0xb8a494cb7a5637ce, 0xc87cd1a4baba9244, 0x631eaf426bae7568}}}, -{{{0xb3e90410da66fe9f, 0x85dd4b526c16e5a6, 0xbc3d97611ef9bf83, 0x5599648b1ea919b5}}, - {{0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5}}, - {{0xd6026344858f7b19, 0x14ab352fa1ea514a, 0x8900441a2090a9d7, 0x7b04715f91253b26}}}, -{{{0x83edbd28acf6ae43, 0x86357c8b7d5c7ab4, 0xc0404769b7eb2c44, 0x59b37bf5c2f6583f}}, - {{0xb376c280c4e6bac6, 0x970ed3dd6d1d9b0b, 0xb09a9558450bf944, 0x48d0acfa57cde223}}, - {{0xb60f26e47dabe671, 0xf1d1a197622f3a37, 0x4208ce7ee9960394, 0x16234191336d3bdb}}}, -{{{0xb9e499def6267ff6, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006}}, - {{0xdd499cd61ff38640, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231}}, - {{0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc}}}, -{{{0x0b6e5517fd181bae, 0x9022629f2bb963b4, 0x5509bce932064625, 0x578edd74f63c13da}}, - {{0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd}}, - {{0x997276c6492b0c3d, 0x47ccc2c4dfe205fc, 0xdcd29b84dd623a3c, 0x3ec2ab590288c7a2}}}, -{{{0xa1a0d27be4d87bb9, 0xa98b4deb61391aed, 0x99a0ddd073cb9b83, 0x2dd5c25a200fcace}}, - {{0xa7213a09ae32d1cb, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e}}, - {{0xe2abd5e9792c887e, 0x1a020018cb926d5d, 0xbfba69cdbaae5f1e, 0x730548b35ae88f5f}}}, -{{{0xc43551a3cba8b8ee, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca}}, - {{0x805b094ba1d6e334, 0xbf3ef17709353f19, 0x423f06cb0622702b, 0x585a2277d87845dd}}, - {{0xa18a5f8233d48962, 0x6698c4b5ec78257f, 0xa78e6fa5373e41ff, 0x7656278950ef981f}}}, -{{{0x38c3cf59d51fc8c0, 0x9bedd2fd0506b6f2, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6}}, - {{0xe17073a3ea86cf9d, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616}}, - {{0xf2612f5c6f136c7c, 0xafead107f6dd11be, 0x527e9ad213de6f33, 0x1e79cb358188f75d}}}, -{{{0x013436c3eef7e3f1, 0x828b6a7ffe9e10f8, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831}}, - {{0x77e953d8f5e08181, 0x84a50c44299dded9, 0xdc6c2d0c864525e5, 0x478ab52d39d1f2f4}}, - {{0x66a6a4d39252d159, 0xe5dde1bc871ac807, 0xb82c6b40a6c1c96f, 0x16d87a411a212214}}}, -{{{0xb3bd7e5a42066215, 0x879be3cd0c5a24c1, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6}}, - {{0xfba4d5e2d54e0583, 0xe21fafd72ebd99fa, 0x497ac2736ee9778f, 0x1f990b577a5a6dde}}, - {{0xa3344ead1be8f7d6, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e}}}, -{{{0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd}}, - {{0xd8ac9929943c6fe4, 0xb5f9f161a38392a2, 0x2699db13bec89af3, 0x7dcf843ce405f074}}, - {{0x6c90d6484a4732c0, 0xd52143fdca563299, 0xb3be28c3915dc6e1, 0x6739687e7327191b}}}, -{{{0xef782014385675a6, 0xa2649f30aafda9e8, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3}}, - {{0xa66dcc9dc80c1ac0, 0x97a05cf41b38a436, 0xa7ebf3be95dbd7c6, 0x7da0b8f68d7e7dab}}, - {{0xd40f1953c3b5da76, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b}}}, -{{{0x8f6301cf70a13d11, 0xcfceb815350dd0c4, 0xf70297d4a4bca47e, 0x3669b656e44d1434}}, - {{0x9e9628d3a0a643b9, 0xb5c3cb00e6c32064, 0x9b5302897c2dec32, 0x43e37ae2d5d1c70c}}, - {{0x387e3f06eda6e133, 0x67301d5199a13ac0, 0xbd5ad8f836263811, 0x6a21e6cd4fd5e9be}}}, -{{{0xf1c6170a3046e65f, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57}}, - {{0xef4129126699b2e3, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36}}, - {{0xa6db088d5ef8790b, 0x5278f0dc610937e5, 0xac0349d261a16eb8, 0x0eafb03790e52179}}}, -{{{0x960555c13748042f, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661}}, - {{0x5140805e0f75ae1d, 0xec02fbe32662cc30, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3}}, - {{0x9cf289b9bba543ee, 0xf3760e9d5ac97142, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f}}}, -{{{0x524c299c18d0936d, 0xc86bb56c8a0c1a0c, 0xa375052edb4a8631, 0x5c0efde4bc754562}}, - {{0x7585d4263af77a3c, 0xdfae7b11fee9144d, 0xa506708059f7193d, 0x14f29a5383922037}}, - {{0xdf717edc25b2d7f5, 0x21f970db99b53040, 0xda9234b7c3ed4c62, 0x5e72365c7bee093e}}}, -{{{0x575bfc074571217f, 0x3779675d0694d95b, 0x9a0a37bbf4191e33, 0x77f1104c47b4eabc}}, - {{0x7d9339062f08b33e, 0x5b9659e5df9f32be, 0xacff3dad1f9ebdfd, 0x70b20555cb7349b7}}, - {{0xbe5113c555112c4c, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a}}}, -{{{0xb67d22d93ecebde8, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372}}, - {{0x18930b093e4b1928, 0x7de3e10e73f3f640, 0xf43217da73395d6f, 0x6f8aded6ca379c3e}}, - {{0xe340123dfdb7b29a, 0x487b97e1a21ab291, 0xf9967d02fde6949e, 0x780de72ec8d3de97}}}, -{{{0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4}}, - {{0x671feaf300f42772, 0x8f72eb2a2a8c41aa, 0x29a17fd797373292, 0x1defc6ad32b587a6}}, - {{0xaf5bbe1aef5195a7, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867}}}, -{{{0x95fe919a74ef4fad, 0x3a827becf6a308a2, 0x964e01d309a47b01, 0x71c43c4f5ba3c797}}, - {{0xbc1ef4bd567ae7a9, 0x3f624cb2d64498bd, 0xe41064d22c1f4ec8, 0x2ef9c5a5ba384001}}, - {{0xb6fd6df6fa9e74cd, 0xf18278bce4af267a, 0x8255b3d0f1ef990e, 0x5a758ca390c5f293}}}, -{{{0xa2b72710d9462495, 0x3aa8c6d2d57d5003, 0xe3d400bfa0b487ca, 0x2dbae244b3eb72ec}}, - {{0x8ce0918b1d61dc94, 0x8ded36469a813066, 0xd4e6a829afe8aad3, 0x0a738027f639d43f}}, - {{0x980f4a2f57ffe1cc, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c}}}, -{{{0xe765318832b0ba78, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07}}, - {{0x2e3d702f5e3dd90e, 0x9e3f0918e4d25386, 0x5e773ef6024da96a, 0x3c004b0c4afa3332}}, - {{0x9aa946ac06f4b82b, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217}}}, -{{{0xc7a75d4b4697c544, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714}}, - {{0xb5c742583e760ef3, 0x75dc52b9ee0ab990, 0xbf1427c2072b923f, 0x73420b2d6ff0d9f0}}, - {{0xaf2cf6cb9e851e06, 0x8f593913c62238c4, 0xda8ab89699fbf373, 0x3db5632fea34bc9e}}}, -{{{0xf46eee2bf75dd9d8, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13}}, - {{0x2e4990b1829825d5, 0xedeaeb873e9a8991, 0xeef03d394c704af8, 0x59197ea495df2b0e}}, - {{0x04e16019e4e55aae, 0xe77b437a7e2f92e9, 0xc7ce2dc16f159aa4, 0x45eafdc1f4d70cc0}}}, -{{{0x698401858045d72b, 0x4c22faa2cf2f0651, 0x941a36656b222dc6, 0x5a5eebc80362dade}}, - {{0xb60e4624cfccb1ed, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940}}, - {{0xb7a7bfd10a4e8dc6, 0xbe57007e44c9b339, 0x60c1207f1557aefa, 0x26058891266218db}}}, -{{{0x59f704a68360ff04, 0xc3d93fde7661e6f4, 0x831b2a7312873551, 0x54ad0c2e4e615d57}}, - {{0x4c818e3cc676e542, 0x5e422c9303ceccad, 0xec07cccab4129f08, 0x0dedfa10b24443b8}}, - {{0xee3b67d5b82b522a, 0x36f163469fa5c1eb, 0xa5b4d2f26ec19fd3, 0x62ecb2baa77a9408}}}, -{{{0xe5ed795261152b3d, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be}}, - {{0x92072836afb62874, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98}}, - {{0x0dc62d361a3231da, 0xfa47583294200270, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c}}}, -{{{0x9adc0ff9ce5ec54b, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b}}, - {{0xf3aa57a22796bb14, 0x883abab79b07da21, 0xe54be21831a0391c, 0x5ee7fb38d83205f9}}, - {{0x538dfdcb41446a8e, 0xa5acfda9434937f9, 0x46af908d263c8c78, 0x61d0633c9bca0d09}}}, -{{{0x63744935ffdb2566, 0xc5bd6b89780b68bb, 0x6f1b3280553eec03, 0x6e965fd847aed7f5}}, - {{0xada328bcf8fc73df, 0xee84695da6f037fc, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc}}, - {{0x9ad2b953ee80527b, 0xe88f19aafade6d8d, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc}}}, -{{{0xebb355406a3126c2, 0xd26383a868c8c393, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147}}, - {{0xd1997dae8e9f7374, 0xa032a2f8cfbb0816, 0xcd6cba126d445f0a, 0x1ba811460accb834}}, - {{0x708169fb0c429954, 0xe14600acd76ecf67, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2}}}, -{{{0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd}}, - {{0xc845dfa56de66fde, 0xe152a5002c40483a, 0xe9d2e163c7b4f632, 0x30f4452edcbc1b65}}, - {{0x856d2782c5759740, 0xfa134569f99cbecc, 0x8844fc73c0ea4e71, 0x632d9a1a593f2469}}}, -{{{0xf6bb6b15b807cba6, 0x1823c7dfbc54f0d7, 0xbb1d97036e29670b, 0x0b24f48847ed4a57}}, - {{0xbf09fd11ed0c84a7, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2}}, - {{0xdcdad4be511beac7, 0xa4538075ed26ccf2, 0xe19cff9f005f9a65, 0x34fcf74475481f63}}}, -{{{0xc197e04c789767ca, 0xb8714dcb38d9467d, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7}}, - {{0xa5bb1dab78cfaa98, 0x5ceda267190b72f2, 0x9309c9110a92608e, 0x0119a3042fb374b0}}, - {{0x67a2d89ce8c2177d, 0x669da5f66895d0c1, 0xf56598e5b282a2b0, 0x56c088f1ede20a73}}}, -{{{0x336d3d1110a86e17, 0xd7f388320b75b2fa, 0xf915337625072988, 0x09674c6b99108b87}}, - {{0x581b5fac24f38f02, 0xa90be9febae30cbd, 0x9a2169028acf92f0, 0x038b7ea48359038f}}, - {{0x9f4ef82199316ff8, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65}}}, -{{{0xb16c62f587e593fb, 0x4999eddeca5d3e71, 0xb491c1e014cc3e6d, 0x08f5114789a8dba8}}, - {{0x3304fb0e63066222, 0xfb35068987acba3f, 0xbd1924778c1061a3, 0x3058ad43d1838620}}, - {{0x323c0ffde57663d0, 0x05c3df38a22ea610, 0xbdc78abdac994f9a, 0x26549fa4efe3dc99}}}, -{{{0x741d5a461e6bf9d6, 0x2305b3fc7777a581, 0xd45574a26474d3d9, 0x1926e1dc6401e0ff}}, - {{0xdb468549af3f666e, 0xd77fcf04f14a0ea5, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85}}, - {{0xe07f4e8aea17cea0, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15}}}, -{{{0xcc8055947d599832, 0x1e4656da37f15520, 0x99f6f7744e059320, 0x773563bc6a75cf33}}, - {{0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5}}, - {{0x06b1e90863139cb3, 0xa493da67c5a03ecd, 0x8d77cec8ad638932, 0x1f426b701b864f44}}}, -{{{0xefc9264c41911c01, 0xf1a3b7b817a22c25, 0x5875da6bf30f1447, 0x4e1af5271d31b090}}, - {{0xf17e35c891a12552, 0xb76b8153575e9c76, 0xfa83406f0d9b723e, 0x0b76bb1b3fa7e438}}, - {{0x08b8c1f97f92939b, 0xbe6771cbd444ab6e, 0x22e5646399bb8017, 0x7b6dd61eb772a955}}}, -{{{0xb7adc1e850f33d92, 0x7998fa4f608cd5cf, 0xad962dbd8dfc5bdb, 0x703e9bceaf1d2f4f}}, - {{0x5730abf9ab01d2c7, 0x16fb76dc40143b18, 0x866cbe65a0cbb281, 0x53fa9b659bff6afe}}, - {{0x6c14c8e994885455, 0x843a5d6665aed4e5, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50}}}, -{{{0x1c4bd16733e248f3, 0xbd9e128715bf0a5f, 0xd43f8cf0a10b0376, 0x53b09b5ddf191b13}}, - {{0xc3877c60d2e7e3f2, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577}}, - {{0xf306a7235946f1cc, 0x921718b5cce5d97d, 0x28cdd24781b4e975, 0x51caf30c6fcdd907}}}, -{{{0xa60ba7427674e00a, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa}}, - {{0x737af99a18ac54c7, 0x903378dcc51cb30f, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a}}, - {{0xa99ec0cb1f0d01cf, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea}}}, -{{{0xb5dc2ddf2845ab2c, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1}}, - {{0x3c42fe5ebf93cb8e, 0xbedfa85136d4565f, 0xe0f0859e884220e8, 0x7dd73f960725d128}}, - {{0xb10d24fe68059829, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4}}}, -{{{0x83847d429917135f, 0xad1b911f567d03d7, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a}}, - {{0x7041d560b691c301, 0x85201b3fadd7e71e, 0x16c2e16311335585, 0x2aa55e3d010828b1}}, - {{0xed5192e60c07444f, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664}}}, -{{{0x739d8845832fcedb, 0xfa38d6c9ae6bf863, 0x32bc0dcab74ffef7, 0x73937e8814bce45e}}, - {{0xbb2e00c9193b877f, 0xece3a890e0dc506b, 0xecf3b7c036de649f, 0x5f46040898de9e1a}}, - {{0xb9037116297bf48d, 0xa9d13b22d4f06834, 0xe19715574696bdc6, 0x2cf8a4e891d5e835}}}, -{{{0x6d93fd8707110f67, 0xdd4c09d37c38b549, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09}}, - {{0x2cb5487e17d06ba2, 0x24d2381c3950196b, 0xd7659c8185978a30, 0x7a6f7f2891d6a4f6}}, - {{0x7d09fd8d6a9aef49, 0xf0ee60be5b3db90b, 0x4c21b52c519ebfd4, 0x6011aadfc545941d}}}, -{{{0x5f67926dcf95f83c, 0x7c7e856171289071, 0xd6a1e7f3998f7a5b, 0x6fc5cc1b0b62f9e0}}, - {{0x63ded0c802cbf890, 0xfbd098ca0dff6aaa, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e}}, - {{0xd1ef5528b29879cb, 0xdd1aae3cd47e9092, 0x127e0442189f2352, 0x15596b3ae57101f1}}}, -{{{0x462739d23f9179a2, 0xff83123197d6ddcf, 0x1307deb553f2148a, 0x0d2237687b5f4dda}}, - {{0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138}}, - {{0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c}}}, -{{{0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, 0xaac014de22efe4a3, 0x4627e9cefebd6a5c}}, - {{0x3207a4732787ccdf, 0x17e31908f213e3f8, 0xd5b2ecd7f60d964e, 0x746f6336c2600be9}}, - {{0x3f4af345ab6c971c, 0xe288eb729943731f, 0x33596a8a0344186d, 0x7b4917007ed66293}}}, -{{{0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b}}, - {{0x54341b28dd53a2dd, 0xaa17905bdf42fc3f, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d}}, - {{0xc20232cda2b4e554, 0x9ed0fd42115d187f, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c}}}, -{{{0xa287ec4b5d0b2fbb, 0x415c5790074882ca, 0xe044a61ec1d0815c, 0x26334f0a409ef5e0}}, - {{0xace532bf458d72e1, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03}}, - {{0xb6c8f04adf62a3c0, 0x3ef000ef076da45d, 0x9c9cb95849f0d2a9, 0x1cc37f43441b2fae}}}, -{{{0x508f565a5cc7324f, 0xd061c4c0e506a922, 0xfb18abdb5c45ac19, 0x6c6809c10380314a}}, - {{0xd76656f1c9ceaeb9, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838}}, - {{0xd2d55112e2da6ac8, 0xe9bd0331b1e851ed, 0x960746dd8ec67262, 0x05911b9f6ef7c5d0}}}, -{{{0xc1339983f5df0ebb, 0xc0f3758f512c4cac, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62}}, - {{0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17}}, - {{0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d}}}, -{{{0x0e2c52036b1782fc, 0x64816c816cad83b4, 0xd0dcbdd96964073e, 0x13d99df70164c520}}, - {{0xa12ff6d93bdab31d, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43}}, - {{0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80}}}, -{{{0x990f7ad6a33ec4e2, 0x6608f938be2ee08e, 0x9ca143c563284515, 0x4cf38a1fec2db60d}}, - {{0xffd52b40ff6d69aa, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d}}, - {{0xa0aaaa650dfa5ce7, 0xf9c49e2a48b5478c, 0x4f09cc7d7003725b, 0x373cad3a26091abe}}}, -{{{0xb294634d82c9f57c, 0x1fcbfde124934536, 0x9e9c4db3418cdb5a, 0x0040f3d9454419fc}}, - {{0xf1bea8fb89ddbbad, 0x3bcb2cbc61aeaecb, 0x8f58a7bb1f9b8d9d, 0x21547eda5112a686}}, - {{0xdefde939fd5986d3, 0xf4272c89510a380c, 0xb72ba407bb3119b9, 0x63550a334a254df4}}}, -{{{0x6507d6edb569cf37, 0x178429b00ca52ee1, 0xea7c0090eb6bd65d, 0x3eea62c7daf78f51}}, - {{0x9bba584572547b49, 0xf305c6fae2c408e0, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a}}, - {{0x9d24c713e693274e, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd}}}, -{{{0xbc0235e8202f3f27, 0xc75c00e264f975b0, 0x91a4e9d5a38c2416, 0x17b6e7f68ab789f9}}, - {{0x1e56d317e820107c, 0xc5266844840ae965, 0xc1e0a1c6320ffc7a, 0x5373669c91611472}}, - {{0x5d2814ab9a0e5257, 0x908f2084c9cab3fc, 0xafcaf5885b2d1eca, 0x1cb4b5a678f87d11}}}, -{{{0xb664c06b394afc6c, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2}}, - {{0x6b74aa62a2a007e7, 0xf311e0b0f071c7b1, 0x5707e438000be223, 0x2dc0fd2d82ef6eac}}, - {{0x982eff841119744e, 0xf9695e962b074724, 0xc58ac14fbfc953fb, 0x3c31be1b369f1cf5}}}, -{{{0xb0f4864d08948aee, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb}}, - {{0xc168bc93f9cb4272, 0xaeb8711fc7cedb98, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb}}, - {{0xf79619d7a26d808a, 0xbb1fd49e1d9e156d, 0x73d7c36cdba1df27, 0x26b44cd91f28777d}}}, -{{{0x51f048478f387475, 0xb25dbcf49cbecb3c, 0x9aab1244d99f2055, 0x2c709e6c1c10a5d6}}, - {{0xe1b7f29362730383, 0x4b5279ffebca8a2c, 0xdafc778abfd41314, 0x7deb10149c72610f}}, - {{0xcb62af6a8766ee7a, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea}}}, -{{{0x34ad500a4bc130ad, 0x8d38db493d0bd49c, 0xa25c3d98500a89be, 0x2f1f3f87eeba3b09}}, - {{0x2f2d09d50ab8f2f9, 0xacb9218dc55923df, 0x4a8f342673766cb9, 0x4cb13bd738f719f5}}, - {{0xf7848c75e515b64a, 0xa59501badb4a9038, 0xc20d313f3f751b50, 0x19a1e353c0ae2ee8}}}, -{{{0x7d1c7560bafa05c3, 0xb3e1a0a0c6e55e61, 0xe3529718c0d66473, 0x41546b11c20c3486}}, - {{0xb42172cdd596bdbd, 0x93e0454398eefc40, 0x9fb15347b44109b5, 0x736bd3990266ae34}}, - {{0x85532d509334b3b4, 0x46fd114b60816573, 0xcc5f5f30425c8375, 0x412295a2b87fab5c}}}, -{{{0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34}}, - {{0x2e655261e293eac6, 0x845a92032133acdb, 0x460975cb7900996b, 0x0760bb8d195add80}}, - {{0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2}}}, -{{{0xf3df2f643a78c0b2, 0x4c3e971ef22e027c, 0xec7d1c5e49c1b5a3, 0x2012c18f0922dd2d}}, - {{0x11fc69656571f2d3, 0xc6c9e845530e737a, 0xe33ae7a2d4fe5035, 0x01b9c7b62e6dd30b}}, - {{0x880b55e55ac89d29, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8}}}, -{{{0x283499dc881f2533, 0x9d0525da779323b6, 0x897addfb673441f4, 0x32b79d71163a168d}}, - {{0xe27314d289cc2c4b, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e}}, - {{0xcc85f8d9edfcb36a, 0x22bcc28f3746e5f9, 0xe49de338f9e5d3cd, 0x480a5efbc13e2dcc}}}, -{{{0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31}}, - {{0xb6614ce442ce221f, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06}}, - {{0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, 0xf0af66134ea278d6, 0x545b585d14dda094}}}, -{{{0x67bf275ea0d43a0f, 0xade68e34089beebe, 0x4289134cd479e72e, 0x0f62f9c332ba5454}}, - {{0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071}}, - {{0xfcb46589d63b5f39, 0x5cae6a3f57cbcf61, 0xfebac2d2953afa05, 0x1c0fa01a36371436}}}, -{{{0xd2c604b622943dff, 0xbc8cbece44cfb3a0, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf}}, - {{0x69082b0e8c936a50, 0xf9c9a035c1dac5b6, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140}}, - {{0xa003febdb9be82f0, 0x2089c1af3a44ac90, 0xf8499f911954fa8e, 0x1fba218aef40ab42}}}, -{{{0xab549448fac8f53e, 0x81f6e89a7ba63741, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42}}, - {{0x4f3e57043e7b0194, 0xa81d3eee08daaf7f, 0xc839c6ab99dcdef1, 0x6c535d13ff7761d5}}, - {{0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b}}}, -{{{0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351}}, - {{0x915f7ff576f121a7, 0xc34a32272fcd87e3, 0xccba2fde4d1be526, 0x6bba828f8969899b}}, - {{0xe2d1bc6690fe3901, 0x4cb54a18a0997ad5, 0x971d6914af8460d4, 0x559d504f7f6b7be4}}}, -{{{0xa7738378b3eb54d5, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217}}, - {{0x9c4891e7f6d266fd, 0x0744a19b0307781b, 0x88388f1d6061e23b, 0x123ea6a3354bd50e}}, - {{0x118d189041e32d96, 0xb9ede3c2d8315848, 0x1eab4271d83245d9, 0x4a3961e2c918a154}}}, -{{{0x71dc3be0f8e6bba0, 0xd6cef8347effe30a, 0xa992425fe13a476a, 0x2cd6bce3fb1db763}}, - {{0x0327d644f3233f1e, 0x499a260e34fcf016, 0x83b5a716f2dab979, 0x68aceead9bd4111f}}, - {{0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597}}}, -{{{0x6129bfe104aa6397, 0x8f960008a4a7fccb, 0x3f8bc0897d909458, 0x709fa43edcb291a9}}, - {{0x882acbebfd022790, 0x89af3305c4115760, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b}}, - {{0xeb0a5d8c63fd2aca, 0xd22bc1662e694eff, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f}}}, -{{{0x461307b32eed3e33, 0xae042f33a45581e7, 0xc94449d3195f0366, 0x0b7d5d8a6c314858}}, - {{0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1}}, - {{0x25d448327b95d543, 0x70d38300a3340f1d, 0xde1c531c60e1c52b, 0x272224512c7de9e4}}}, -{{{0x1abc92af49c5342e, 0xffeed811b2e6fad0, 0xefa28c8dfcc84e29, 0x11b5df18a44cc543}}, - {{0xbf7bbb8a42a975fc, 0x8c5c397796ada358, 0xe27fc76fcdedaa48, 0x19735fd7f6bc20a6}}, - {{0xe3ab90d042c84266, 0xeb848e0f7f19547e, 0x2503a1d065a497b9, 0x0fef911191df895f}}} \ No newline at end of file diff --git a/ext/ed25519-amd64-asm/ge25519_base_slide_multiples.data b/ext/ed25519-amd64-asm/ge25519_base_slide_multiples.data deleted file mode 100644 index 32a5d4747..000000000 --- a/ext/ed25519-amd64-asm/ge25519_base_slide_multiples.data +++ /dev/null @@ -1,96 +0,0 @@ -{{{0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267}}, - {{0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65}}, - {{0xabc91205877aaa68, 0x26d9e823ccaac49e, 0x5a1b7dcbdd43598c, 0x6f117b689f0c65a8}}}, -{{{0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62}}, - {{0xaf25b0a84cee9730, 0x025a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4}}, - {{0x14ae933f0dd0d889, 0x589423221c35da62, 0xd170e5458cf2db4c, 0x5a2826af12b9b4c6}}}, -{{{0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3}}, - {{0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb}}, - {{0xbcbbdbf1812a8285, 0x270e0807d0bdd1fc, 0xb41b670b1bbda72d, 0x43aabe696b3bb69a}}}, -{{{0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0}}, - {{0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e}}, - {{0xf1836dc801b8b3a2, 0xb3035f47053ea49a, 0x529c41ba5877adf3, 0x7a9fbb1c6a0f90a7}}}, -{{{0xf36e217e039d8064, 0x98a081b6f520419b, 0x96cbc608e75eb044, 0x49c05a51fadc9c8f}}, - {{0x9b2e678aa6a8632f, 0xa6509e6f51bc46c5, 0xceb233c9c686f5b5, 0x34b9ed338add7f59}}, - {{0x06b4e8bf9045af1b, 0xe2ff83e8a719d22f, 0xaaf6fc2993d4cf16, 0x73c172021b008b06}}}, -{{{0x315f5b0249864348, 0x3ed6b36977088381, 0xa3a075556a8deb95, 0x18ab598029d5c77f}}, - {{0x2fbf00848a802ade, 0xe5d9fecf02302e27, 0x113e847117703406, 0x4275aae2546d8faf}}, - {{0xd82b2cc5fd6089e9, 0x031eb4a13282e4a4, 0x44311199b51a8622, 0x3dc65522b53df948}}}, -{{{0x506f013b327fbf93, 0xaefcebc99b776f6b, 0x9d12b232aaad5968, 0x0267882d176024a7}}, - {{0xbf70c222a2007f6d, 0xbf84b39ab5bcdedb, 0x537a0e12fb07ba07, 0x234fd7eec346f241}}, - {{0x5360a119732ea378, 0x2437e6b1df8dd471, 0xa2ef37f891a7e533, 0x497ba6fdaa097863}}}, -{{{0x040bcd86468ccf0b, 0xd3829ba42a9910d6, 0x7508300807b25192, 0x43b5cd4218d05ebf}}, - {{0x24cecc0313cfeaa0, 0x8648c28d189c246d, 0x2dbdbdfac1f2d4d0, 0x61e22917f12de72b}}, - {{0x5d9a762f9bd0b516, 0xeb38af4e373fdeee, 0x032e5a7d93d64270, 0x511d61210ae4d842}}}, -{{{0x081386484420de87, 0x8a1cf016b592edb4, 0x39fa4e2729942d25, 0x71a7fe6fe2482810}}, - {{0x92c676ef950e9d81, 0xa54620cdc0d7044f, 0xaa9b36646f8f1248, 0x6d325924ddb855e3}}, - {{0x6c7182b8a5c8c854, 0x33fd1479fe5f2a03, 0x72cf591883778d0c, 0x4746c4b6559eeaa9}}}, -{{{0x348546c864741147, 0x7d35aedd0efcc849, 0xff939a760672a332, 0x219663497db5e6d6}}, - {{0xd3777b3c6dc69a2b, 0xdefab2276f89f617, 0x45651cf7b53a16b5, 0x5c9a51de34fe9fb7}}, - {{0xf510f1cf79f10e67, 0xffdddaa1e658515b, 0x09c3a71710142277, 0x4804503c608223bb}}}, -{{{0x3b6821d23a36d175, 0xbbb40aa7e99b9e32, 0x5d9e5ce420838a47, 0x771e098858de4c5e}}, - {{0xc4249ed02ca37fc7, 0xa059a0e3a615acab, 0x88a96ed7c96e0e23, 0x553398a51650696d}}, - {{0x9a12f5d278451edf, 0x3ada5d7985899ccb, 0x477f4a2d9fa59508, 0x5a5ed1d68ff5a611}}}, -{{{0xbae5e0c558527359, 0x392e5c19cadb9d7e, 0x28653c1eda1cabe9, 0x019b60135fefdc44}}, - {{0x1195122afe150e83, 0xcf209a257e4b35d8, 0x7387f8291e711e20, 0x44acb897d8bf92f0}}, - {{0x1e6068145e134b83, 0xc4f5e64f24304c16, 0x506e88a8fc1a3ed7, 0x150c49fde6ad2f92}}}, -{{{0xb849863c9cdca868, 0xc83f44dbb8714ad0, 0xfe3ee3560c36168d, 0x78a6d7791e05fbc1}}, - {{0x8e7bf29509471138, 0x5d6fef394f75a651, 0x10af79c425a708ad, 0x6b2b5a075bb99922}}, - {{0x58bf704b47a0b976, 0xa601b355741748d5, 0xaa2b1fb1d542f590, 0x725c7ffc4ad55d00}}}, -{{{0x91802bf71cd098c0, 0xfe416ca4ed5e6366, 0xdf585d714902994c, 0x4cd54625f855fae7}}, - {{0xe4426715d1cf99b2, 0x7352d51102a20d34, 0x23d1157b8b12109f, 0x794cc9277cb1f3a3}}, - {{0x4af6c426c2ac5053, 0xbc9aedad32f67258, 0x2ad032f10a311021, 0x7008357b6fcc8e85}}}, -{{{0xd01b9fbb82584a34, 0x47ab6463d2b4792b, 0xb631639c48536202, 0x13a92a3669d6d428}}, - {{0x0b88672738773f01, 0xb8ccc8fa95fbccfb, 0x8d2dd5a3b9ad29b6, 0x06ef7e9851ad0f6a}}, - {{0xca93771cc0577de5, 0x7540e41e5035dc5c, 0x24680f01d802e071, 0x3c296ddf8a2af86a}}}, -{{{0xfceb4d2ebb1f2541, 0xb89510c740adb91f, 0xfc71a37dd0a1ad05, 0x0a892c700747717b}}, - {{0xaead15f9d914a713, 0xa92f7bf98c8ff912, 0xaff823179f53d730, 0x7a99d393490c77ba}}, - {{0x8f52ed2436bda3e8, 0x77a8c84157e80794, 0xa5a96563262f9ce0, 0x286762d28302f7d2}}}, -{{{0x7c558e2bce2ef5bd, 0xe4986cb46747bc63, 0x154a179f3bbb89b8, 0x7686f2a3d6f1767a}}, - {{0x4e7836093ce35b25, 0x82e1181db26baa97, 0x0cc192d3cbc7b83f, 0x32f1da046a9d9d3a}}, - {{0xaa8d12a66d597c6a, 0x8f11930304d3852b, 0x3f91dc73c209b022, 0x561305f8a9ad28a6}}}, -{{{0x6722cc28e7b0c0d5, 0x709de9bbdb075c53, 0xcaf68da7d7010a61, 0x030a1aef2c57cc6c}}, - {{0x100c978dec92aed1, 0xca43d5434d6d73e5, 0x83131b22d847ba48, 0x00aaec53e35d4d2c}}, - {{0x7bb1f773003ad2aa, 0x0b3f29802b216608, 0x7821dc86520ed23e, 0x20be9c1c24065480}}}, -{{{0x20e0e44ae2025e60, 0xb03b3b2fcbdcb938, 0x105d639cf95a0d1c, 0x69764c545067e311}}, - {{0xe15387d8249673a6, 0x5943bc2df546e493, 0x1c7f9a81c36f63b5, 0x750ab3361f0ac1de}}, - {{0x1e8a3283a2f81037, 0x6f2eda23bd7fcbf1, 0xb72fd15bac2e2563, 0x54f96b3fb7075040}}}, -{{{0x177dafc616b11ecd, 0x89764b9cfa576479, 0xb7a8a110e6ece785, 0x78e6839fbe85dbf0}}, - {{0x0fadf20429669279, 0x3adda2047d7d724a, 0x6f3d94828c5760f1, 0x3d7fe9c52bb7539e}}, - {{0x70332df737b8856b, 0x75d05d43041a178a, 0x320ff74aa0e59e22, 0x70f268f350088242}}}, -{{{0x2324112070dcf355, 0x380cc97ee7fce117, 0xb31ddeed3552b698, 0x404e56c039b8c4b9}}, - {{0x66864583b1805f47, 0xf535c5d160dd7c19, 0xe9874eb71e4cb006, 0x7c0d345cfad889d9}}, - {{0x591f1f4b8c78338a, 0xa0366ab167e0b5e1, 0x5cbc4152b45f3d44, 0x20d754762aaec777}}}, -{{{0x9d74feb135b9f543, 0x84b37df1de8c956c, 0xe9322b0757138ba9, 0x38b8ada8790b4ce1}}, - {{0x5e8fc36fc73bb758, 0xace543a5363cbb9a, 0xa9934a7d903bc922, 0x2b8f1e46f3ceec62}}, - {{0xb5c04a9cdf51f95d, 0x2b3952aecb1fdeac, 0x1d106d8b328b66da, 0x049aeb32ceba1953}}}, -{{{0xd7767d3c63dcfe7e, 0x209c594897856e40, 0xb6676861e14f7c13, 0x51c665e0c8d625fc}}, - {{0xaa507d0b75fc7931, 0x0fef924b7a6725d3, 0x1d82542b396b3930, 0x795ee17530f674fc}}, - {{0x254a5b0a52ecbd81, 0x5d411f6ee034afe7, 0xe6a24d0dcaee4a31, 0x6cd19bf49dc54477}}}, -{{{0x7e87619052179ca3, 0x571d0a060b2c9f85, 0x80a2baa88499711e, 0x7520f3db40b2e638}}, - {{0x1ffe612165afc386, 0x082a2a88b8d51b10, 0x76f6627e20990baa, 0x5e01b3a7429e43e7}}, - {{0x3db50be3d39357a1, 0x967b6cdd599e94a5, 0x1a309a64df311e6e, 0x71092c9ccef3c986}}}, -{{{0x53d8523f0364918c, 0xa2b404f43fab6b1c, 0x080b4a9e6681e5a4, 0x0ea15b03d0257ba7}}, - {{0x856bd8ac74051dcf, 0x03f6a40855b7aa1e, 0x3a4ae7cbc9743ceb, 0x4173a5bb7137abde}}, - {{0x17c56e31f0f9218a, 0x5a696e2b1afc4708, 0xf7931668f4b2f176, 0x5fc565614a4e3a67}}}, -{{{0x136e570dc46d7ae5, 0x0fd0aacc54f8dc8f, 0x59549f03310dad86, 0x62711c414c454aa1}}, - {{0x4892e1e67790988e, 0x01d5950f1c5cd722, 0xe3b0819ae5923eed, 0x3214c7409d46651b}}, - {{0x1329827406651770, 0x3ba4a0668a279436, 0xd9b6b8ec185d223c, 0x5bea94073ecb833c}}}, -{{{0x641dbf0912c89be4, 0xacf38b317d6e579c, 0xabfe9e02f697b065, 0x3aacd5c148f61eec}}, - {{0xb470ce63f343d2f8, 0x0067ba8f0543e8f1, 0x35da51a1a2117b6f, 0x4ad0785944f1bd2f}}, - {{0x858e3b34c3318301, 0xdc99c04707316826, 0x34085b2ed39da88c, 0x3aff0cb1d902853d}}}, -{{{0x87c5c7eb3a20405e, 0x8ee311efedad56c9, 0x29252e48ad29d5f9, 0x110e7e86f4cd251d}}, - {{0x9226430bf4c53505, 0x68e49c13261f2283, 0x09ef33788fd327c6, 0x2ccf9f732bd99e7f}}, - {{0x57c0d89ed603f5e4, 0x12888628f0b0200c, 0x53172709a02e3bb7, 0x05c557e0b9693a37}}}, -{{{0xd8f9ce311fc97e6f, 0x7a3f263011f9fdae, 0xe15b7ea08bed25dd, 0x6e154c178fe9875a}}, - {{0xf776bbb089c20eb0, 0x61f85bf6fa0fd85c, 0xb6b93f4e634421fb, 0x289fef0841861205}}, - {{0xcf616336fed69abf, 0x9b16e4e78335c94f, 0x13789765753a7fe7, 0x6afbf642a95ca319}}}, -{{{0x7da8de0c62f5d2c1, 0x98fc3da4b00e7b9a, 0x7deb6ada0dad70e0, 0x0db4b851b95038c4}}, - {{0x5de55070f913a8cc, 0x7d1d167b2b0cf561, 0xda2956b690ead489, 0x12c093cedb801ed9}}, - {{0xfc147f9308b8190f, 0x06969da0a11ae310, 0xcee75572dac7d7fd, 0x33aa8799c6635ce6}}}, -{{{0xaf0ff51ebd085cf2, 0x78f51a8967d33f1f, 0x6ec2bfe15060033c, 0x233c6f29e8e21a86}}, - {{0x8348f588fc156cb1, 0x6da2ba9b1a0a6d27, 0xe2262d5c87ca5ab6, 0x212cd0c1c8d589a6}}, - {{0xd2f4d5107f18c781, 0x122ecdf2527e9d28, 0xa70a862a3d3d3341, 0x1db7778911914ce3}}}, -{{{0xddf352397c6bc26f, 0x7a97e2cc53d50113, 0x7c74f43abf79a330, 0x31ad97ad26e2adfc}}, - {{0xb3394769dd701ab6, 0xe2b8ded419cf8da5, 0x15df4161fd2ac852, 0x7ae2ca8a017d24be}}, - {{0xb7e817ed0920b962, 0x1e8518cc3f19da9d, 0xe491c14f25560a64, 0x1ed1fc53a6622c83}}} \ No newline at end of file diff --git a/ext/ed25519-amd64-asm/ge25519_dbl_p1p1.s b/ext/ed25519-amd64-asm/ge25519_dbl_p1p1.s deleted file mode 100644 index 265daf091..000000000 --- a/ext/ed25519-amd64-asm/ge25519_dbl_p1p1.s +++ /dev/null @@ -1,2975 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 pp - -# qhasm: input rp - -# qhasm: input pp - -# qhasm: int64 a0 - -# qhasm: int64 a1 - -# qhasm: int64 a2 - -# qhasm: int64 a3 - -# qhasm: stack64 a0_stack - -# qhasm: stack64 a1_stack - -# qhasm: stack64 a2_stack - -# qhasm: stack64 a3_stack - -# qhasm: int64 b0 - -# qhasm: int64 b1 - -# qhasm: int64 b2 - -# qhasm: int64 b3 - -# qhasm: stack64 b0_stack - -# qhasm: stack64 b1_stack - -# qhasm: stack64 b2_stack - -# qhasm: stack64 b3_stack - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: stack64 c0_stack - -# qhasm: stack64 c1_stack - -# qhasm: stack64 c2_stack - -# qhasm: stack64 c3_stack - -# qhasm: int64 d0 - -# qhasm: int64 d1 - -# qhasm: int64 d2 - -# qhasm: int64 d3 - -# qhasm: stack64 d0_stack - -# qhasm: stack64 d1_stack - -# qhasm: stack64 d2_stack - -# qhasm: stack64 d3_stack - -# qhasm: int64 e0 - -# qhasm: int64 e1 - -# qhasm: int64 e2 - -# qhasm: int64 e3 - -# qhasm: stack64 e0_stack - -# qhasm: stack64 e1_stack - -# qhasm: stack64 e2_stack - -# qhasm: stack64 e3_stack - -# qhasm: int64 rx0 - -# qhasm: int64 rx1 - -# qhasm: int64 rx2 - -# qhasm: int64 rx3 - -# qhasm: stack64 rx0_stack - -# qhasm: stack64 rx1_stack - -# qhasm: stack64 rx2_stack - -# qhasm: stack64 rx3_stack - -# qhasm: int64 ry0 - -# qhasm: int64 ry1 - -# qhasm: int64 ry2 - -# qhasm: int64 ry3 - -# qhasm: int64 ry4 - -# qhasm: int64 rz0 - -# qhasm: int64 rz1 - -# qhasm: int64 rz2 - -# qhasm: int64 rz3 - -# qhasm: int64 rt0 - -# qhasm: int64 rt1 - -# qhasm: int64 rt2 - -# qhasm: int64 rt3 - -# qhasm: int64 mulr4 - -# qhasm: int64 mulr5 - -# qhasm: int64 mulr6 - -# qhasm: int64 mulr7 - -# qhasm: int64 mulr8 - -# qhasm: int64 mulrax - -# qhasm: int64 mulrdx - -# qhasm: int64 mulx0 - -# qhasm: int64 mulx1 - -# qhasm: int64 mulx2 - -# qhasm: int64 mulx3 - -# qhasm: int64 mulc - -# qhasm: int64 mulzero - -# qhasm: int64 muli38 - -# qhasm: int64 squarer4 - -# qhasm: int64 squarer5 - -# qhasm: int64 squarer6 - -# qhasm: int64 squarer7 - -# qhasm: int64 squarer8 - -# qhasm: int64 squarerax - -# qhasm: int64 squarerdx - -# qhasm: int64 squaret1 - -# qhasm: int64 squaret2 - -# qhasm: int64 squaret3 - -# qhasm: int64 squarec - -# qhasm: int64 squarezero - -# qhasm: int64 squarei38 - -# qhasm: int64 addt0 - -# qhasm: int64 addt1 - -# qhasm: int64 subt0 - -# qhasm: int64 subt1 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1 -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1 -.globl crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1 -_crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1: -crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1: -mov %rsp,%r11 -and $31,%r11 -add $192,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#4 -# asm 2: mov $0,>squarer7=%rcx -mov $0,%rcx - -# qhasm: squarerax = *(uint64 *)(pp + 8) -# asm 1: movq 8(squarerax=int64#7 -# asm 2: movq 8(squarerax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 0) -# asm 1: mulq 0(a1=int64#5 -# asm 2: mov a1=%r8 -mov %rax,%r8 - -# qhasm: a2 = squarerdx -# asm 1: mov a2=int64#6 -# asm 2: mov a2=%r9 -mov %rdx,%r9 - -# qhasm: squarerax = *(uint64 *)(pp + 16) -# asm 1: movq 16(squarerax=int64#7 -# asm 2: movq 16(squarerax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 8) -# asm 1: mulq 8(a3=int64#8 -# asm 2: mov a3=%r10 -mov %rax,%r10 - -# qhasm: squarer4 = squarerdx -# asm 1: mov squarer4=int64#9 -# asm 2: mov squarer4=%r11 -mov %rdx,%r11 - -# qhasm: squarerax = *(uint64 *)(pp + 24) -# asm 1: movq 24(squarerax=int64#7 -# asm 2: movq 24(squarerax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 16) -# asm 1: mulq 16(squarer5=int64#10 -# asm 2: mov squarer5=%r12 -mov %rax,%r12 - -# qhasm: squarer6 = squarerdx -# asm 1: mov squarer6=int64#11 -# asm 2: mov squarer6=%r13 -mov %rdx,%r13 - -# qhasm: squarerax = *(uint64 *)(pp + 16) -# asm 1: movq 16(squarerax=int64#7 -# asm 2: movq 16(squarerax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 0) -# asm 1: mulq 0(squarerax=int64#7 -# asm 2: movq 24(squarerax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 8) -# asm 1: mulq 8(squarerax=int64#7 -# asm 2: movq 24(squarerax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 0) -# asm 1: mulq 0(squarerax=int64#7 -# asm 2: movq 0(squarerax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 0) -# asm 1: mulq 0(a0=int64#12 -# asm 2: mov a0=%r14 -mov %rax,%r14 - -# qhasm: squaret1 = squarerdx -# asm 1: mov squaret1=int64#13 -# asm 2: mov squaret1=%r15 -mov %rdx,%r15 - -# qhasm: squarerax = *(uint64 *)(pp + 8) -# asm 1: movq 8(squarerax=int64#7 -# asm 2: movq 8(squarerax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 8) -# asm 1: mulq 8(squaret2=int64#14 -# asm 2: mov squaret2=%rbx -mov %rax,%rbx - -# qhasm: squaret3 = squarerdx -# asm 1: mov squaret3=int64#15 -# asm 2: mov squaret3=%rbp -mov %rdx,%rbp - -# qhasm: squarerax = *(uint64 *)(pp + 16) -# asm 1: movq 16(squarerax=int64#7 -# asm 2: movq 16(squarerax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 16) -# asm 1: mulq 16(squarerax=int64#7 -# asm 2: movq 24(squarerax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 24) -# asm 1: mulq 24(squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r11,%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: squarer4 = squarerax -# asm 1: mov squarer4=int64#9 -# asm 2: mov squarer4=%r11 -mov %rax,%r11 - -# qhasm: squarerax = squarer5 -# asm 1: mov squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r12,%rax - -# qhasm: squarer5 = squarerdx -# asm 1: mov squarer5=int64#10 -# asm 2: mov squarer5=%r12 -mov %rdx,%r12 - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? squarer5 += squarerax -# asm 1: add squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r13,%rax - -# qhasm: squarer6 = 0 -# asm 1: mov $0,>squarer6=int64#11 -# asm 2: mov $0,>squarer6=%r13 -mov $0,%r13 - -# qhasm: squarer6 += squarerdx + carry -# asm 1: adc squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %rcx,%rax - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#4 -# asm 2: mov $0,>squarer7=%rcx -mov $0,%rcx - -# qhasm: squarer7 += squarerdx + carry -# asm 1: adc squarer8=int64#7 -# asm 2: mov $0,>squarer8=%rax -mov $0,%rax - -# qhasm: squarer8 += squarerdx + carry -# asm 1: adc squarezero=int64#3 -# asm 2: mov $0,>squarezero=%rdx -mov $0,%rdx - -# qhasm: squarer8 += squarezero + carry -# asm 1: adc squarer8=int64#4 -# asm 2: imulq $38,squarer8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? a0 += squarer8 -# asm 1: add squarezero=int64#3 -# asm 2: imulq $38,squarezero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: a0 += squarezero -# asm 1: add a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %r14,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %r8,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r9,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %r10,80(%rsp) - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#4 -# asm 2: mov $0,>squarer7=%rcx -mov $0,%rcx - -# qhasm: squarerax = *(uint64 *)(pp + 40) -# asm 1: movq 40(squarerax=int64#7 -# asm 2: movq 40(squarerax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 32) -# asm 1: mulq 32(b1=int64#5 -# asm 2: mov b1=%r8 -mov %rax,%r8 - -# qhasm: b2 = squarerdx -# asm 1: mov b2=int64#6 -# asm 2: mov b2=%r9 -mov %rdx,%r9 - -# qhasm: squarerax = *(uint64 *)(pp + 48) -# asm 1: movq 48(squarerax=int64#7 -# asm 2: movq 48(squarerax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 40) -# asm 1: mulq 40(b3=int64#8 -# asm 2: mov b3=%r10 -mov %rax,%r10 - -# qhasm: squarer4 = squarerdx -# asm 1: mov squarer4=int64#9 -# asm 2: mov squarer4=%r11 -mov %rdx,%r11 - -# qhasm: squarerax = *(uint64 *)(pp + 56) -# asm 1: movq 56(squarerax=int64#7 -# asm 2: movq 56(squarerax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 48) -# asm 1: mulq 48(squarer5=int64#10 -# asm 2: mov squarer5=%r12 -mov %rax,%r12 - -# qhasm: squarer6 = squarerdx -# asm 1: mov squarer6=int64#11 -# asm 2: mov squarer6=%r13 -mov %rdx,%r13 - -# qhasm: squarerax = *(uint64 *)(pp + 48) -# asm 1: movq 48(squarerax=int64#7 -# asm 2: movq 48(squarerax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 32) -# asm 1: mulq 32(squarerax=int64#7 -# asm 2: movq 56(squarerax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 40) -# asm 1: mulq 40(squarerax=int64#7 -# asm 2: movq 56(squarerax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 32) -# asm 1: mulq 32(squarerax=int64#7 -# asm 2: movq 32(squarerax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 32) -# asm 1: mulq 32(b0=int64#12 -# asm 2: mov b0=%r14 -mov %rax,%r14 - -# qhasm: squaret1 = squarerdx -# asm 1: mov squaret1=int64#13 -# asm 2: mov squaret1=%r15 -mov %rdx,%r15 - -# qhasm: squarerax = *(uint64 *)(pp + 40) -# asm 1: movq 40(squarerax=int64#7 -# asm 2: movq 40(squarerax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 40) -# asm 1: mulq 40(squaret2=int64#14 -# asm 2: mov squaret2=%rbx -mov %rax,%rbx - -# qhasm: squaret3 = squarerdx -# asm 1: mov squaret3=int64#15 -# asm 2: mov squaret3=%rbp -mov %rdx,%rbp - -# qhasm: squarerax = *(uint64 *)(pp + 48) -# asm 1: movq 48(squarerax=int64#7 -# asm 2: movq 48(squarerax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 48) -# asm 1: mulq 48(squarerax=int64#7 -# asm 2: movq 56(squarerax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 56) -# asm 1: mulq 56(squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r11,%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: squarer4 = squarerax -# asm 1: mov squarer4=int64#9 -# asm 2: mov squarer4=%r11 -mov %rax,%r11 - -# qhasm: squarerax = squarer5 -# asm 1: mov squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r12,%rax - -# qhasm: squarer5 = squarerdx -# asm 1: mov squarer5=int64#10 -# asm 2: mov squarer5=%r12 -mov %rdx,%r12 - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? squarer5 += squarerax -# asm 1: add squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r13,%rax - -# qhasm: squarer6 = 0 -# asm 1: mov $0,>squarer6=int64#11 -# asm 2: mov $0,>squarer6=%r13 -mov $0,%r13 - -# qhasm: squarer6 += squarerdx + carry -# asm 1: adc squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %rcx,%rax - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#4 -# asm 2: mov $0,>squarer7=%rcx -mov $0,%rcx - -# qhasm: squarer7 += squarerdx + carry -# asm 1: adc squarer8=int64#7 -# asm 2: mov $0,>squarer8=%rax -mov $0,%rax - -# qhasm: squarer8 += squarerdx + carry -# asm 1: adc squarezero=int64#3 -# asm 2: mov $0,>squarezero=%rdx -mov $0,%rdx - -# qhasm: squarer8 += squarezero + carry -# asm 1: adc squarer8=int64#4 -# asm 2: imulq $38,squarer8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? b0 += squarer8 -# asm 1: add squarezero=int64#3 -# asm 2: imulq $38,squarezero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: b0 += squarezero -# asm 1: add b0_stack=stack64#12 -# asm 2: movq b0_stack=88(%rsp) -movq %r14,88(%rsp) - -# qhasm: b1_stack = b1 -# asm 1: movq b1_stack=stack64#13 -# asm 2: movq b1_stack=96(%rsp) -movq %r8,96(%rsp) - -# qhasm: b2_stack = b2 -# asm 1: movq b2_stack=stack64#14 -# asm 2: movq b2_stack=104(%rsp) -movq %r9,104(%rsp) - -# qhasm: b3_stack = b3 -# asm 1: movq b3_stack=stack64#15 -# asm 2: movq b3_stack=112(%rsp) -movq %r10,112(%rsp) - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#4 -# asm 2: mov $0,>squarer7=%rcx -mov $0,%rcx - -# qhasm: squarerax = *(uint64 *)(pp + 72) -# asm 1: movq 72(squarerax=int64#7 -# asm 2: movq 72(squarerax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 64) -# asm 1: mulq 64(c1=int64#5 -# asm 2: mov c1=%r8 -mov %rax,%r8 - -# qhasm: c2 = squarerdx -# asm 1: mov c2=int64#6 -# asm 2: mov c2=%r9 -mov %rdx,%r9 - -# qhasm: squarerax = *(uint64 *)(pp + 80) -# asm 1: movq 80(squarerax=int64#7 -# asm 2: movq 80(squarerax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 72) -# asm 1: mulq 72(c3=int64#8 -# asm 2: mov c3=%r10 -mov %rax,%r10 - -# qhasm: squarer4 = squarerdx -# asm 1: mov squarer4=int64#9 -# asm 2: mov squarer4=%r11 -mov %rdx,%r11 - -# qhasm: squarerax = *(uint64 *)(pp + 88) -# asm 1: movq 88(squarerax=int64#7 -# asm 2: movq 88(squarerax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 80) -# asm 1: mulq 80(squarer5=int64#10 -# asm 2: mov squarer5=%r12 -mov %rax,%r12 - -# qhasm: squarer6 = squarerdx -# asm 1: mov squarer6=int64#11 -# asm 2: mov squarer6=%r13 -mov %rdx,%r13 - -# qhasm: squarerax = *(uint64 *)(pp + 80) -# asm 1: movq 80(squarerax=int64#7 -# asm 2: movq 80(squarerax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 64) -# asm 1: mulq 64(squarerax=int64#7 -# asm 2: movq 88(squarerax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 72) -# asm 1: mulq 72(squarerax=int64#7 -# asm 2: movq 88(squarerax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 64) -# asm 1: mulq 64(squarerax=int64#7 -# asm 2: movq 64(squarerax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 64) -# asm 1: mulq 64(c0=int64#12 -# asm 2: mov c0=%r14 -mov %rax,%r14 - -# qhasm: squaret1 = squarerdx -# asm 1: mov squaret1=int64#13 -# asm 2: mov squaret1=%r15 -mov %rdx,%r15 - -# qhasm: squarerax = *(uint64 *)(pp + 72) -# asm 1: movq 72(squarerax=int64#7 -# asm 2: movq 72(squarerax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 72) -# asm 1: mulq 72(squaret2=int64#14 -# asm 2: mov squaret2=%rbx -mov %rax,%rbx - -# qhasm: squaret3 = squarerdx -# asm 1: mov squaret3=int64#15 -# asm 2: mov squaret3=%rbp -mov %rdx,%rbp - -# qhasm: squarerax = *(uint64 *)(pp + 80) -# asm 1: movq 80(squarerax=int64#7 -# asm 2: movq 80(squarerax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 80) -# asm 1: mulq 80(squarerax=int64#7 -# asm 2: movq 88(squarerax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 88) -# asm 1: mulq 88(squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r11,%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: squarer4 = squarerax -# asm 1: mov squarer4=int64#9 -# asm 2: mov squarer4=%r11 -mov %rax,%r11 - -# qhasm: squarerax = squarer5 -# asm 1: mov squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r12,%rax - -# qhasm: squarer5 = squarerdx -# asm 1: mov squarer5=int64#10 -# asm 2: mov squarer5=%r12 -mov %rdx,%r12 - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? squarer5 += squarerax -# asm 1: add squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r13,%rax - -# qhasm: squarer6 = 0 -# asm 1: mov $0,>squarer6=int64#11 -# asm 2: mov $0,>squarer6=%r13 -mov $0,%r13 - -# qhasm: squarer6 += squarerdx + carry -# asm 1: adc squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %rcx,%rax - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#4 -# asm 2: mov $0,>squarer7=%rcx -mov $0,%rcx - -# qhasm: squarer7 += squarerdx + carry -# asm 1: adc squarer8=int64#7 -# asm 2: mov $0,>squarer8=%rax -mov $0,%rax - -# qhasm: squarer8 += squarerdx + carry -# asm 1: adc squarezero=int64#3 -# asm 2: mov $0,>squarezero=%rdx -mov $0,%rdx - -# qhasm: squarer8 += squarezero + carry -# asm 1: adc squarer8=int64#4 -# asm 2: imulq $38,squarer8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? c0 += squarer8 -# asm 1: add squarezero=int64#3 -# asm 2: imulq $38,squarezero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: c0 += squarezero -# asm 1: add addt0=int64#3 -# asm 2: mov $0,>addt0=%rdx -mov $0,%rdx - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#4 -# asm 2: mov $38,>addt1=%rcx -mov $38,%rcx - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae c0_stack=stack64#16 -# asm 2: movq c0_stack=120(%rsp) -movq %r14,120(%rsp) - -# qhasm: c1_stack = c1 -# asm 1: movq c1_stack=stack64#17 -# asm 2: movq c1_stack=128(%rsp) -movq %r8,128(%rsp) - -# qhasm: c2_stack = c2 -# asm 1: movq c2_stack=stack64#18 -# asm 2: movq c2_stack=136(%rsp) -movq %r9,136(%rsp) - -# qhasm: c3_stack = c3 -# asm 1: movq c3_stack=stack64#19 -# asm 2: movq c3_stack=144(%rsp) -movq %r10,144(%rsp) - -# qhasm: d0 = 0 -# asm 1: mov $0,>d0=int64#3 -# asm 2: mov $0,>d0=%rdx -mov $0,%rdx - -# qhasm: d1 = 0 -# asm 1: mov $0,>d1=int64#4 -# asm 2: mov $0,>d1=%rcx -mov $0,%rcx - -# qhasm: d2 = 0 -# asm 1: mov $0,>d2=int64#5 -# asm 2: mov $0,>d2=%r8 -mov $0,%r8 - -# qhasm: d3 = 0 -# asm 1: mov $0,>d3=int64#6 -# asm 2: mov $0,>d3=%r9 -mov $0,%r9 - -# qhasm: carry? d0 -= a0_stack -# asm 1: subq subt0=int64#7 -# asm 2: mov $0,>subt0=%rax -mov $0,%rax - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#8 -# asm 2: mov $38,>subt1=%r10 -mov $38,%r10 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae d0_stack=stack64#8 -# asm 2: movq d0_stack=56(%rsp) -movq %rdx,56(%rsp) - -# qhasm: d1_stack = d1 -# asm 1: movq d1_stack=stack64#9 -# asm 2: movq d1_stack=64(%rsp) -movq %rcx,64(%rsp) - -# qhasm: d2_stack = d2 -# asm 1: movq d2_stack=stack64#10 -# asm 2: movq d2_stack=72(%rsp) -movq %r8,72(%rsp) - -# qhasm: d3_stack = d3 -# asm 1: movq d3_stack=stack64#11 -# asm 2: movq d3_stack=80(%rsp) -movq %r9,80(%rsp) - -# qhasm: e0 = 0 -# asm 1: mov $0,>e0=int64#7 -# asm 2: mov $0,>e0=%rax -mov $0,%rax - -# qhasm: e1 = 0 -# asm 1: mov $0,>e1=int64#8 -# asm 2: mov $0,>e1=%r10 -mov $0,%r10 - -# qhasm: e2 = 0 -# asm 1: mov $0,>e2=int64#9 -# asm 2: mov $0,>e2=%r11 -mov $0,%r11 - -# qhasm: e3 = 0 -# asm 1: mov $0,>e3=int64#10 -# asm 2: mov $0,>e3=%r12 -mov $0,%r12 - -# qhasm: carry? e0 -= b0_stack -# asm 1: subq subt0=int64#11 -# asm 2: mov $0,>subt0=%r13 -mov $0,%r13 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#12 -# asm 2: mov $38,>subt1=%r14 -mov $38,%r14 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae e0_stack=stack64#20 -# asm 2: movq e0_stack=152(%rsp) -movq %rax,152(%rsp) - -# qhasm: e1_stack = e1 -# asm 1: movq e1_stack=stack64#21 -# asm 2: movq e1_stack=160(%rsp) -movq %r10,160(%rsp) - -# qhasm: e2_stack = e2 -# asm 1: movq e2_stack=stack64#22 -# asm 2: movq e2_stack=168(%rsp) -movq %r11,168(%rsp) - -# qhasm: e3_stack = e3 -# asm 1: movq e3_stack=stack64#23 -# asm 2: movq e3_stack=176(%rsp) -movq %r12,176(%rsp) - -# qhasm: rz0 = d0 -# asm 1: mov rz0=int64#7 -# asm 2: mov rz0=%rax -mov %rdx,%rax - -# qhasm: rz1 = d1 -# asm 1: mov rz1=int64#8 -# asm 2: mov rz1=%r10 -mov %rcx,%r10 - -# qhasm: rz2 = d2 -# asm 1: mov rz2=int64#9 -# asm 2: mov rz2=%r11 -mov %r8,%r11 - -# qhasm: rz3 = d3 -# asm 1: mov rz3=int64#10 -# asm 2: mov rz3=%r12 -mov %r9,%r12 - -# qhasm: carry? rz0 += b0_stack -# asm 1: addq addt0=int64#11 -# asm 2: mov $0,>addt0=%r13 -mov $0,%r13 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#12 -# asm 2: mov $38,>addt1=%r14 -mov $38,%r14 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae subt0=int64#11 -# asm 2: mov $0,>subt0=%r13 -mov $0,%r13 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#12 -# asm 2: mov $38,>subt1=%r14 -mov $38,%r14 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae subt0=int64#3 -# asm 2: mov $0,>subt0=%rdx -mov $0,%rdx - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#4 -# asm 2: mov $38,>subt1=%rcx -mov $38,%rcx - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae rx0=int64#3 -# asm 2: movq 0(rx0=%rdx -movq 0(%rsi),%rdx - -# qhasm: rx1 = *(uint64 *)(pp + 8) -# asm 1: movq 8(rx1=int64#4 -# asm 2: movq 8(rx1=%rcx -movq 8(%rsi),%rcx - -# qhasm: rx2 = *(uint64 *)(pp + 16) -# asm 1: movq 16(rx2=int64#5 -# asm 2: movq 16(rx2=%r8 -movq 16(%rsi),%r8 - -# qhasm: rx3 = *(uint64 *)(pp + 24) -# asm 1: movq 24(rx3=int64#6 -# asm 2: movq 24(rx3=%r9 -movq 24(%rsi),%r9 - -# qhasm: carry? rx0 += *(uint64 *)(pp + 32) -# asm 1: addq 32(addt0=int64#2 -# asm 2: mov $0,>addt0=%rsi -mov $0,%rsi - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#7 -# asm 2: mov $38,>addt1=%rax -mov $38,%rax - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae rx0_stack=stack64#12 -# asm 2: movq rx0_stack=88(%rsp) -movq %rdx,88(%rsp) - -# qhasm: rx1_stack = rx1 -# asm 1: movq rx1_stack=stack64#13 -# asm 2: movq rx1_stack=96(%rsp) -movq %rcx,96(%rsp) - -# qhasm: rx2_stack = rx2 -# asm 1: movq rx2_stack=stack64#14 -# asm 2: movq rx2_stack=104(%rsp) -movq %r8,104(%rsp) - -# qhasm: rx3_stack = rx3 -# asm 1: movq rx3_stack=stack64#15 -# asm 2: movq rx3_stack=112(%rsp) -movq %r9,112(%rsp) - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#2 -# asm 2: mov $0,>squarer7=%rsi -mov $0,%rsi - -# qhasm: squarerax = rx1_stack -# asm 1: movq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 96(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx0_stack -# asm 1: mulq rx1=int64#4 -# asm 2: mov rx1=%rcx -mov %rax,%rcx - -# qhasm: rx2 = squarerdx -# asm 1: mov rx2=int64#5 -# asm 2: mov rx2=%r8 -mov %rdx,%r8 - -# qhasm: squarerax = rx2_stack -# asm 1: movq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 104(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx1_stack -# asm 1: mulq rx3=int64#6 -# asm 2: mov rx3=%r9 -mov %rax,%r9 - -# qhasm: squarer4 = squarerdx -# asm 1: mov squarer4=int64#8 -# asm 2: mov squarer4=%r10 -mov %rdx,%r10 - -# qhasm: squarerax = rx3_stack -# asm 1: movq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 112(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx2_stack -# asm 1: mulq squarer5=int64#9 -# asm 2: mov squarer5=%r11 -mov %rax,%r11 - -# qhasm: squarer6 = squarerdx -# asm 1: mov squarer6=int64#10 -# asm 2: mov squarer6=%r12 -mov %rdx,%r12 - -# qhasm: squarerax = rx2_stack -# asm 1: movq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 104(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx0_stack -# asm 1: mulq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 112(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx1_stack -# asm 1: mulq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 112(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx0_stack -# asm 1: mulq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 88(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx0_stack -# asm 1: mulq rx0=int64#11 -# asm 2: mov rx0=%r13 -mov %rax,%r13 - -# qhasm: squaret1 = squarerdx -# asm 1: mov squaret1=int64#12 -# asm 2: mov squaret1=%r14 -mov %rdx,%r14 - -# qhasm: squarerax = rx1_stack -# asm 1: movq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 96(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx1_stack -# asm 1: mulq squaret2=int64#13 -# asm 2: mov squaret2=%r15 -mov %rax,%r15 - -# qhasm: squaret3 = squarerdx -# asm 1: mov squaret3=int64#14 -# asm 2: mov squaret3=%rbx -mov %rdx,%rbx - -# qhasm: squarerax = rx2_stack -# asm 1: movq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 104(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx2_stack -# asm 1: mulq squarerax=int64#7 -# asm 2: movq squarerax=%rax -movq 112(%rsp),%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * rx3_stack -# asm 1: mulq squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r10,%rax - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: squarer4 = squarerax -# asm 1: mov squarer4=int64#8 -# asm 2: mov squarer4=%r10 -mov %rax,%r10 - -# qhasm: squarerax = squarer5 -# asm 1: mov squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r11,%rax - -# qhasm: squarer5 = squarerdx -# asm 1: mov squarer5=int64#9 -# asm 2: mov squarer5=%r11 -mov %rdx,%r11 - -# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? squarer5 += squarerax -# asm 1: add squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %r12,%rax - -# qhasm: squarer6 = 0 -# asm 1: mov $0,>squarer6=int64#10 -# asm 2: mov $0,>squarer6=%r12 -mov $0,%r12 - -# qhasm: squarer6 += squarerdx + carry -# asm 1: adc squarerax=int64#7 -# asm 2: mov squarerax=%rax -mov %rsi,%rax - -# qhasm: squarer7 = 0 -# asm 1: mov $0,>squarer7=int64#2 -# asm 2: mov $0,>squarer7=%rsi -mov $0,%rsi - -# qhasm: squarer7 += squarerdx + carry -# asm 1: adc squarer8=int64#7 -# asm 2: mov $0,>squarer8=%rax -mov $0,%rax - -# qhasm: squarer8 += squarerdx + carry -# asm 1: adc squarezero=int64#2 -# asm 2: mov $0,>squarezero=%rsi -mov $0,%rsi - -# qhasm: squarer8 += squarezero + carry -# asm 1: adc squarer8=int64#3 -# asm 2: imulq $38,squarer8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? rx0 += squarer8 -# asm 1: add squarezero=int64#2 -# asm 2: imulq $38,squarezero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: rx0 += squarezero -# asm 1: add addt0=int64#2 -# asm 2: mov $0,>addt0=%rsi -mov $0,%rsi - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#3 -# asm 2: mov $38,>addt1=%rdx -mov $38,%rdx - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae addt0=int64#2 -# asm 2: mov $0,>addt0=%rsi -mov $0,%rsi - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#3 -# asm 2: mov $38,>addt1=%rdx -mov $38,%rdx - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/ge25519_double.c b/ext/ed25519-amd64-asm/ge25519_double.c deleted file mode 100644 index d55e2b4f8..000000000 --- a/ext/ed25519-amd64-asm/ge25519_double.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "ge25519.h" - -void ge25519_double(ge25519_p3 *r, const ge25519_p3 *p) -{ - ge25519_p1p1 grp1p1; - ge25519_dbl_p1p1(&grp1p1, (ge25519_p2 *)p); - ge25519_p1p1_to_p3(r, &grp1p1); -} diff --git a/ext/ed25519-amd64-asm/ge25519_double_scalarmult.c b/ext/ed25519-amd64-asm/ge25519_double_scalarmult.c deleted file mode 100644 index 30c922af5..000000000 --- a/ext/ed25519-amd64-asm/ge25519_double_scalarmult.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "fe25519.h" -#include "sc25519.h" -#include "ge25519.h" - -#define S1_SWINDOWSIZE 5 -#define PRE1_SIZE (1<<(S1_SWINDOWSIZE-2)) -#define S2_SWINDOWSIZE 7 -#define PRE2_SIZE (1<<(S2_SWINDOWSIZE-2)) - -ge25519_niels pre2[PRE2_SIZE] = { -#include "ge25519_base_slide_multiples.data" -}; - -static const fe25519 ec2d = {{0xEBD69B9426B2F146, 0x00E0149A8283B156, 0x198E80F2EEF3D130, 0xA406D9DC56DFFCE7}}; - -static void setneutral(ge25519 *r) -{ - fe25519_setint(&r->x,0); - fe25519_setint(&r->y,1); - fe25519_setint(&r->z,1); - fe25519_setint(&r->t,0); -} - -/* computes [s1]p1 + [s2]p2 */ -void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const sc25519 *s2) -{ - signed char slide1[256], slide2[256]; - ge25519_pniels pre1[PRE1_SIZE], neg; - ge25519_p3 d1; - ge25519_p1p1 t; - ge25519_niels nneg; - fe25519 d; - int i; - - sc25519_slide(slide1, s1, S1_SWINDOWSIZE); - sc25519_slide(slide2, s2, S2_SWINDOWSIZE); - - /* precomputation */ - pre1[0] = *(ge25519_pniels *)p1; - ge25519_dbl_p1p1(&t,(ge25519_p2 *)pre1); ge25519_p1p1_to_p3(&d1, &t); - /* Convert pre[0] to projective Niels representation */ - d = pre1[0].ysubx; - fe25519_sub(&pre1[0].ysubx, &pre1[0].xaddy, &pre1[0].ysubx); - fe25519_add(&pre1[0].xaddy, &pre1[0].xaddy, &d); - fe25519_mul(&pre1[0].t2d, &pre1[0].t2d, &ec2d); - - for(i=0;i= 0;--i) { - if (slide1[i] || slide2[i]) goto firstbit; - } - - for(;i>=0;i--) - { - firstbit: - - ge25519_dbl_p1p1(&t, (ge25519_p2 *)r); - - if(slide1[i]>0) - { - ge25519_p1p1_to_p3(r, &t); - ge25519_pnielsadd_p1p1(&t, r, &pre1[slide1[i]/2]); - } - else if(slide1[i]<0) - { - ge25519_p1p1_to_p3(r, &t); - neg = pre1[-slide1[i]/2]; - d = neg.ysubx; - neg.ysubx = neg.xaddy; - neg.xaddy = d; - fe25519_neg(&neg.t2d, &neg.t2d); - ge25519_pnielsadd_p1p1(&t, r, &neg); - } - - if(slide2[i]>0) - { - ge25519_p1p1_to_p3(r, &t); - ge25519_nielsadd_p1p1(&t, r, &pre2[slide2[i]/2]); - } - else if(slide2[i]<0) - { - ge25519_p1p1_to_p3(r, &t); - nneg = pre2[-slide2[i]/2]; - d = nneg.ysubx; - nneg.ysubx = nneg.xaddy; - nneg.xaddy = d; - fe25519_neg(&nneg.t2d, &nneg.t2d); - ge25519_nielsadd_p1p1(&t, r, &nneg); - } - - ge25519_p1p1_to_p2((ge25519_p2 *)r, &t); - } -} diff --git a/ext/ed25519-amd64-asm/ge25519_isneutral.c b/ext/ed25519-amd64-asm/ge25519_isneutral.c deleted file mode 100644 index cf566dbae..000000000 --- a/ext/ed25519-amd64-asm/ge25519_isneutral.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "fe25519.h" -#include "ge25519.h" - -int ge25519_isneutral_vartime(const ge25519_p3 *p) -{ - if(!fe25519_iszero_vartime(&p->x)) return 0; - if(!fe25519_iseq_vartime(&p->y, &p->z)) return 0; - return 1; -} diff --git a/ext/ed25519-amd64-asm/ge25519_multi_scalarmult.c b/ext/ed25519-amd64-asm/ge25519_multi_scalarmult.c deleted file mode 100644 index afc6aeae5..000000000 --- a/ext/ed25519-amd64-asm/ge25519_multi_scalarmult.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "fe25519.h" -#include "sc25519.h" -#include "ge25519.h" -#include "index_heap.h" - -static void setneutral(ge25519 *r) -{ - fe25519_setint(&r->x,0); - fe25519_setint(&r->y,1); - fe25519_setint(&r->z,1); - fe25519_setint(&r->t,0); -} - -static void ge25519_scalarmult_vartime_2limbs(ge25519 *r, ge25519 *p, sc25519 *s) -{ - if (s->v[1] == 0 && s->v[0] == 1) /* This will happen most of the time after Bos-Coster */ - *r = *p; - else if (s->v[1] == 0 && s->v[0] == 0) /* This won't ever happen, except for all scalars == 0 in Bos-Coster */ - setneutral(r); - else - { - ge25519 d; - unsigned long long mask = (1ULL << 63); - int i = 1; - while(!(mask & s->v[1]) && mask != 0) - mask >>= 1; - if(mask == 0) - { - mask = (1ULL << 63); - i = 0; - while(!(mask & s->v[0]) && mask != 0) - mask >>= 1; - } - d = *p; - mask >>= 1; - for(;mask != 0;mask >>= 1) - { - ge25519_double(&d,&d); - if(s->v[i] & mask) - ge25519_add(&d,&d,p); - } - if(i==1) - { - mask = (1ULL << 63); - for(;mask != 0;mask >>= 1) - { - ge25519_double(&d,&d); - if(s->v[0] & mask) - ge25519_add(&d,&d,p); - } - } - *r = d; - } -} - -/* caller's responsibility to ensure npoints >= 5 */ -void ge25519_multi_scalarmult_vartime(ge25519_p3 *r, ge25519_p3 *p, sc25519 *s, const unsigned long long npoints) -{ - unsigned long long pos[npoints]; - unsigned long long hlen=((npoints+1)/2)|1; - unsigned long long max1, max2,i; - - heap_init(pos, hlen, s); - - for(i=0;;i++) - { - heap_get2max(pos, &max1, &max2, s); - if((s[max1].v[3] == 0) || (sc25519_iszero_vartime(&s[max2]))) break; - sc25519_sub_nored(&s[max1],&s[max1],&s[max2]); - ge25519_add(&p[max2],&p[max2],&p[max1]); - heap_rootreplaced(pos, hlen, s); - } - for(;;i++) - { - heap_get2max(pos, &max1, &max2, s); - if((s[max1].v[2] == 0) || (sc25519_iszero_vartime(&s[max2]))) break; - sc25519_sub_nored(&s[max1],&s[max1],&s[max2]); - ge25519_add(&p[max2],&p[max2],&p[max1]); - heap_rootreplaced_3limbs(pos, hlen, s); - } - /* We know that (npoints-1)/2 scalars are only 128-bit scalars */ - heap_extend(pos, hlen, npoints, s); - hlen = npoints; - for(;;i++) - { - heap_get2max(pos, &max1, &max2, s); - if((s[max1].v[1] == 0) || (sc25519_iszero_vartime(&s[max2]))) break; - sc25519_sub_nored(&s[max1],&s[max1],&s[max2]); - ge25519_add(&p[max2],&p[max2],&p[max1]); - heap_rootreplaced_2limbs(pos, hlen, s); - } - for(;;i++) - { - heap_get2max(pos, &max1, &max2, s); - if(sc25519_iszero_vartime(&s[max2])) break; - sc25519_sub_nored(&s[max1],&s[max1],&s[max2]); - ge25519_add(&p[max2],&p[max2],&p[max1]); - heap_rootreplaced_1limb(pos, hlen, s); - } - - ge25519_scalarmult_vartime_2limbs(r, &p[max1], &s[max1]); -} diff --git a/ext/ed25519-amd64-asm/ge25519_nielsadd2.s b/ext/ed25519-amd64-asm/ge25519_nielsadd2.s deleted file mode 100644 index 19d71f11a..000000000 --- a/ext/ed25519-amd64-asm/ge25519_nielsadd2.s +++ /dev/null @@ -1,5791 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 qp - -# qhasm: input rp - -# qhasm: input qp - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 a0 - -# qhasm: int64 a1 - -# qhasm: int64 a2 - -# qhasm: int64 a3 - -# qhasm: stack64 a0_stack - -# qhasm: stack64 a1_stack - -# qhasm: stack64 a2_stack - -# qhasm: stack64 a3_stack - -# qhasm: int64 b0 - -# qhasm: int64 b1 - -# qhasm: int64 b2 - -# qhasm: int64 b3 - -# qhasm: stack64 b0_stack - -# qhasm: stack64 b1_stack - -# qhasm: stack64 b2_stack - -# qhasm: stack64 b3_stack - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: stack64 c0_stack - -# qhasm: stack64 c1_stack - -# qhasm: stack64 c2_stack - -# qhasm: stack64 c3_stack - -# qhasm: int64 d0 - -# qhasm: int64 d1 - -# qhasm: int64 d2 - -# qhasm: int64 d3 - -# qhasm: stack64 d0_stack - -# qhasm: stack64 d1_stack - -# qhasm: stack64 d2_stack - -# qhasm: stack64 d3_stack - -# qhasm: int64 e0 - -# qhasm: int64 e1 - -# qhasm: int64 e2 - -# qhasm: int64 e3 - -# qhasm: stack64 e0_stack - -# qhasm: stack64 e1_stack - -# qhasm: stack64 e2_stack - -# qhasm: stack64 e3_stack - -# qhasm: int64 f0 - -# qhasm: int64 f1 - -# qhasm: int64 f2 - -# qhasm: int64 f3 - -# qhasm: stack64 f0_stack - -# qhasm: stack64 f1_stack - -# qhasm: stack64 f2_stack - -# qhasm: stack64 f3_stack - -# qhasm: int64 g0 - -# qhasm: int64 g1 - -# qhasm: int64 g2 - -# qhasm: int64 g3 - -# qhasm: stack64 g0_stack - -# qhasm: stack64 g1_stack - -# qhasm: stack64 g2_stack - -# qhasm: stack64 g3_stack - -# qhasm: int64 h0 - -# qhasm: int64 h1 - -# qhasm: int64 h2 - -# qhasm: int64 h3 - -# qhasm: stack64 h0_stack - -# qhasm: stack64 h1_stack - -# qhasm: stack64 h2_stack - -# qhasm: stack64 h3_stack - -# qhasm: int64 qt0 - -# qhasm: int64 qt1 - -# qhasm: int64 qt2 - -# qhasm: int64 qt3 - -# qhasm: stack64 qt0_stack - -# qhasm: stack64 qt1_stack - -# qhasm: stack64 qt2_stack - -# qhasm: stack64 qt3_stack - -# qhasm: int64 t10 - -# qhasm: int64 t11 - -# qhasm: int64 t12 - -# qhasm: int64 t13 - -# qhasm: stack64 t10_stack - -# qhasm: stack64 t11_stack - -# qhasm: stack64 t12_stack - -# qhasm: stack64 t13_stack - -# qhasm: int64 t20 - -# qhasm: int64 t21 - -# qhasm: int64 t22 - -# qhasm: int64 t23 - -# qhasm: stack64 t20_stack - -# qhasm: stack64 t21_stack - -# qhasm: stack64 t22_stack - -# qhasm: stack64 t23_stack - -# qhasm: int64 rx0 - -# qhasm: int64 rx1 - -# qhasm: int64 rx2 - -# qhasm: int64 rx3 - -# qhasm: int64 ry0 - -# qhasm: int64 ry1 - -# qhasm: int64 ry2 - -# qhasm: int64 ry3 - -# qhasm: int64 rz0 - -# qhasm: int64 rz1 - -# qhasm: int64 rz2 - -# qhasm: int64 rz3 - -# qhasm: int64 rt0 - -# qhasm: int64 rt1 - -# qhasm: int64 rt2 - -# qhasm: int64 rt3 - -# qhasm: int64 mulr4 - -# qhasm: int64 mulr5 - -# qhasm: int64 mulr6 - -# qhasm: int64 mulr7 - -# qhasm: int64 mulr8 - -# qhasm: int64 mulrax - -# qhasm: int64 mulrdx - -# qhasm: int64 mulx0 - -# qhasm: int64 mulx1 - -# qhasm: int64 mulx2 - -# qhasm: int64 mulx3 - -# qhasm: int64 mulc - -# qhasm: int64 mulzero - -# qhasm: int64 muli38 - -# qhasm: int64 addt0 - -# qhasm: int64 addt1 - -# qhasm: int64 subt0 - -# qhasm: int64 subt1 - -# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_nielsadd2 -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_ge25519_nielsadd2 -.globl crypto_sign_ed25519_amd64_64_ge25519_nielsadd2 -_crypto_sign_ed25519_amd64_64_ge25519_nielsadd2: -crypto_sign_ed25519_amd64_64_ge25519_nielsadd2: -mov %rsp,%r11 -and $31,%r11 -add $192,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: a0 = *(uint64 *)(rp + 32) -# asm 1: movq 32(a0=int64#3 -# asm 2: movq 32(a0=%rdx -movq 32(%rdi),%rdx - -# qhasm: a1 = *(uint64 *)(rp + 40) -# asm 1: movq 40(a1=int64#4 -# asm 2: movq 40(a1=%rcx -movq 40(%rdi),%rcx - -# qhasm: a2 = *(uint64 *)(rp + 48) -# asm 1: movq 48(a2=int64#5 -# asm 2: movq 48(a2=%r8 -movq 48(%rdi),%r8 - -# qhasm: a3 = *(uint64 *)(rp + 56) -# asm 1: movq 56(a3=int64#6 -# asm 2: movq 56(a3=%r9 -movq 56(%rdi),%r9 - -# qhasm: b0 = a0 -# asm 1: mov b0=int64#7 -# asm 2: mov b0=%rax -mov %rdx,%rax - -# qhasm: b1 = a1 -# asm 1: mov b1=int64#8 -# asm 2: mov b1=%r10 -mov %rcx,%r10 - -# qhasm: b2 = a2 -# asm 1: mov b2=int64#9 -# asm 2: mov b2=%r11 -mov %r8,%r11 - -# qhasm: b3 = a3 -# asm 1: mov b3=int64#10 -# asm 2: mov b3=%r12 -mov %r9,%r12 - -# qhasm: carry? a0 -= *(uint64 *) (rp + 0) -# asm 1: subq 0(subt0=int64#11 -# asm 2: mov $0,>subt0=%r13 -mov $0,%r13 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#12 -# asm 2: mov $38,>subt1=%r14 -mov $38,%r14 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#11 -# asm 2: mov $0,>addt0=%r13 -mov $0,%r13 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#12 -# asm 2: mov $38,>addt1=%r14 -mov $38,%r14 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %rdx,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %rcx,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r8,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %r9,80(%rsp) - -# qhasm: b0_stack = b0 -# asm 1: movq b0_stack=stack64#12 -# asm 2: movq b0_stack=88(%rsp) -movq %rax,88(%rsp) - -# qhasm: b1_stack = b1 -# asm 1: movq b1_stack=stack64#13 -# asm 2: movq b1_stack=96(%rsp) -movq %r10,96(%rsp) - -# qhasm: b2_stack = b2 -# asm 1: movq b2_stack=stack64#14 -# asm 2: movq b2_stack=104(%rsp) -movq %r11,104(%rsp) - -# qhasm: b3_stack = b3 -# asm 1: movq b3_stack=stack64#15 -# asm 2: movq b3_stack=112(%rsp) -movq %r12,112(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = a0_stack -# asm 1: movq mulx0=int64#9 -# asm 2: movq mulx0=%r11 -movq 56(%rsp),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a0=int64#10 -# asm 2: mov a0=%r12 -mov %rax,%r12 - -# qhasm: a1 = mulrdx -# asm 1: mov a1=int64#11 -# asm 2: mov a1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(qp + 8) -# asm 1: movq 8(mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a2=int64#12 -# asm 2: mov $0,>a2=%r14 -mov $0,%r14 - -# qhasm: a2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a3=int64#13 -# asm 2: mov $0,>a3=%r15 -mov $0,%r15 - -# qhasm: a3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq mulx1=%r11 -movq 64(%rsp),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq mulx2=%r11 -movq 72(%rsp),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq mulx3=%r11 -movq 80(%rsp),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#4 -# asm 2: mov mulr4=%rcx -mov %rax,%rcx - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#5 -# asm 2: mov mulr5=%r8 -mov %rdx,%r8 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#4 -# asm 2: imulq $38,mulr8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? a0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: a0 += mulzero -# asm 1: add a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %r12,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %r13,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r14,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %r15,80(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = b0_stack -# asm 1: movq mulx0=int64#9 -# asm 2: movq mulx0=%r11 -movq 88(%rsp),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul e0=int64#10 -# asm 2: mov e0=%r12 -mov %rax,%r12 - -# qhasm: e1 = mulrdx -# asm 1: mov e1=int64#11 -# asm 2: mov e1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(qp + 40) -# asm 1: movq 40(mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul e2=int64#12 -# asm 2: mov $0,>e2=%r14 -mov $0,%r14 - -# qhasm: e2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul e3=int64#13 -# asm 2: mov $0,>e3=%r15 -mov $0,%r15 - -# qhasm: e3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq mulx1=%r11 -movq 96(%rsp),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq mulx2=%r11 -movq 104(%rsp),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq mulx3=%r11 -movq 112(%rsp),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#4 -# asm 2: mov mulr4=%rcx -mov %rax,%rcx - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#5 -# asm 2: mov mulr5=%r8 -mov %rdx,%r8 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#4 -# asm 2: imulq $38,mulr8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? e0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: e0 += mulzero -# asm 1: add h0=int64#3 -# asm 2: mov h0=%rdx -mov %r12,%rdx - -# qhasm: h1 = e1 -# asm 1: mov h1=int64#4 -# asm 2: mov h1=%rcx -mov %r13,%rcx - -# qhasm: h2 = e2 -# asm 1: mov h2=int64#5 -# asm 2: mov h2=%r8 -mov %r14,%r8 - -# qhasm: h3 = e3 -# asm 1: mov h3=int64#6 -# asm 2: mov h3=%r9 -mov %r15,%r9 - -# qhasm: carry? e0 -= a0_stack -# asm 1: subq subt0=int64#7 -# asm 2: mov $0,>subt0=%rax -mov $0,%rax - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#8 -# asm 2: mov $38,>subt1=%r10 -mov $38,%r10 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#7 -# asm 2: mov $0,>addt0=%rax -mov $0,%rax - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#8 -# asm 2: mov $38,>addt1=%r10 -mov $38,%r10 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae h0_stack=stack64#8 -# asm 2: movq h0_stack=56(%rsp) -movq %rdx,56(%rsp) - -# qhasm: h1_stack = h1 -# asm 1: movq h1_stack=stack64#9 -# asm 2: movq h1_stack=64(%rsp) -movq %rcx,64(%rsp) - -# qhasm: h2_stack = h2 -# asm 1: movq h2_stack=stack64#10 -# asm 2: movq h2_stack=72(%rsp) -movq %r8,72(%rsp) - -# qhasm: h3_stack = h3 -# asm 1: movq h3_stack=stack64#11 -# asm 2: movq h3_stack=80(%rsp) -movq %r9,80(%rsp) - -# qhasm: e0_stack = e0 -# asm 1: movq e0_stack=stack64#12 -# asm 2: movq e0_stack=88(%rsp) -movq %r12,88(%rsp) - -# qhasm: e1_stack = e1 -# asm 1: movq e1_stack=stack64#13 -# asm 2: movq e1_stack=96(%rsp) -movq %r13,96(%rsp) - -# qhasm: e2_stack = e2 -# asm 1: movq e2_stack=stack64#14 -# asm 2: movq e2_stack=104(%rsp) -movq %r14,104(%rsp) - -# qhasm: e3_stack = e3 -# asm 1: movq e3_stack=stack64#15 -# asm 2: movq e3_stack=112(%rsp) -movq %r15,112(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = *(uint64 *)(rp + 96) -# asm 1: movq 96(mulx0=int64#9 -# asm 2: movq 96(mulx0=%r11 -movq 96(%rdi),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c0=int64#10 -# asm 2: mov c0=%r12 -mov %rax,%r12 - -# qhasm: c1 = mulrdx -# asm 1: mov c1=int64#11 -# asm 2: mov c1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(qp + 72) -# asm 1: movq 72(mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c2=int64#12 -# asm 2: mov $0,>c2=%r14 -mov $0,%r14 - -# qhasm: c2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c3=int64#13 -# asm 2: mov $0,>c3=%r15 -mov $0,%r15 - -# qhasm: c3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq 104(mulx1=%r11 -movq 104(%rdi),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq 112(mulx2=%r11 -movq 112(%rdi),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq 120(mulx3=%r11 -movq 120(%rdi),%r11 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? c0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: c0 += mulzero -# asm 1: add f0=int64#2 -# asm 2: movq 64(f0=%rsi -movq 64(%rdi),%rsi - -# qhasm: f1 = *(uint64 *)(rp + 72) -# asm 1: movq 72(f1=int64#3 -# asm 2: movq 72(f1=%rdx -movq 72(%rdi),%rdx - -# qhasm: f2 = *(uint64 *)(rp + 80) -# asm 1: movq 80(f2=int64#4 -# asm 2: movq 80(f2=%rcx -movq 80(%rdi),%rcx - -# qhasm: f3 = *(uint64 *)(rp + 88) -# asm 1: movq 88(f3=int64#5 -# asm 2: movq 88(f3=%r8 -movq 88(%rdi),%r8 - -# qhasm: carry? f0 += f0 -# asm 1: add addt0=int64#6 -# asm 2: mov $0,>addt0=%r9 -mov $0,%r9 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#7 -# asm 2: mov $38,>addt1=%rax -mov $38,%rax - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae g0=int64#6 -# asm 2: mov g0=%r9 -mov %rsi,%r9 - -# qhasm: g1 = f1 -# asm 1: mov g1=int64#7 -# asm 2: mov g1=%rax -mov %rdx,%rax - -# qhasm: g2 = f2 -# asm 1: mov g2=int64#8 -# asm 2: mov g2=%r10 -mov %rcx,%r10 - -# qhasm: g3 = f3 -# asm 1: mov g3=int64#9 -# asm 2: mov g3=%r11 -mov %r8,%r11 - -# qhasm: carry? f0 -= c0 -# asm 1: sub subt0=int64#14 -# asm 2: mov $0,>subt0=%rbx -mov $0,%rbx - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#15 -# asm 2: mov $38,>subt1=%rbp -mov $38,%rbp - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#10 -# asm 2: mov $0,>addt0=%r12 -mov $0,%r12 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#11 -# asm 2: mov $38,>addt1=%r13 -mov $38,%r13 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae g0_stack=stack64#16 -# asm 2: movq g0_stack=120(%rsp) -movq %r9,120(%rsp) - -# qhasm: g1_stack = g1 -# asm 1: movq g1_stack=stack64#17 -# asm 2: movq g1_stack=128(%rsp) -movq %rax,128(%rsp) - -# qhasm: g2_stack = g2 -# asm 1: movq g2_stack=stack64#18 -# asm 2: movq g2_stack=136(%rsp) -movq %r10,136(%rsp) - -# qhasm: g3_stack = g3 -# asm 1: movq g3_stack=stack64#19 -# asm 2: movq g3_stack=144(%rsp) -movq %r11,144(%rsp) - -# qhasm: f0_stack = f0 -# asm 1: movq f0_stack=stack64#20 -# asm 2: movq f0_stack=152(%rsp) -movq %rsi,152(%rsp) - -# qhasm: f1_stack = f1 -# asm 1: movq f1_stack=stack64#21 -# asm 2: movq f1_stack=160(%rsp) -movq %rdx,160(%rsp) - -# qhasm: f2_stack = f2 -# asm 1: movq f2_stack=stack64#22 -# asm 2: movq f2_stack=168(%rsp) -movq %rcx,168(%rsp) - -# qhasm: f3_stack = f3 -# asm 1: movq f3_stack=stack64#23 -# asm 2: movq f3_stack=176(%rsp) -movq %r8,176(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#2 -# asm 2: mov $0,>mulr4=%rsi -mov $0,%rsi - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#4 -# asm 2: mov $0,>mulr5=%rcx -mov $0,%rcx - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulx0 = e0_stack -# asm 1: movq mulx0=int64#8 -# asm 2: movq mulx0=%r10 -movq 88(%rsp),%r10 - -# qhasm: mulrax = f0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx0=int64#9 -# asm 2: mov rx0=%r11 -mov %rax,%r11 - -# qhasm: rx1 = mulrdx -# asm 1: mov rx1=int64#10 -# asm 2: mov rx1=%r12 -mov %rdx,%r12 - -# qhasm: mulrax = f1_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx2=int64#11 -# asm 2: mov $0,>rx2=%r13 -mov $0,%r13 - -# qhasm: rx2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx3=int64#12 -# asm 2: mov $0,>rx3=%r14 -mov $0,%r14 - -# qhasm: rx3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#8 -# asm 2: movq mulx1=%r10 -movq 96(%rsp),%r10 - -# qhasm: mulrax = f0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#8 -# asm 2: movq mulx2=%r10 -movq 104(%rsp),%r10 - -# qhasm: mulrax = f0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#8 -# asm 2: movq mulx3=%r10 -movq 112(%rsp),%r10 - -# qhasm: mulrax = f0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rsi,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? rx0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: rx0 += mulzero -# asm 1: add mulr4=int64#2 -# asm 2: mov $0,>mulr4=%rsi -mov $0,%rsi - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#4 -# asm 2: mov $0,>mulr5=%rcx -mov $0,%rcx - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulx0 = h0_stack -# asm 1: movq mulx0=int64#8 -# asm 2: movq mulx0=%r10 -movq 56(%rsp),%r10 - -# qhasm: mulrax = g0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 120(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry0=int64#9 -# asm 2: mov ry0=%r11 -mov %rax,%r11 - -# qhasm: ry1 = mulrdx -# asm 1: mov ry1=int64#10 -# asm 2: mov ry1=%r12 -mov %rdx,%r12 - -# qhasm: mulrax = g1_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 128(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry2=int64#11 -# asm 2: mov $0,>ry2=%r13 -mov $0,%r13 - -# qhasm: ry2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 136(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry3=int64#12 -# asm 2: mov $0,>ry3=%r14 -mov $0,%r14 - -# qhasm: ry3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 144(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#8 -# asm 2: movq mulx1=%r10 -movq 64(%rsp),%r10 - -# qhasm: mulrax = g0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 120(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 128(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 136(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 144(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#8 -# asm 2: movq mulx2=%r10 -movq 72(%rsp),%r10 - -# qhasm: mulrax = g0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 120(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 128(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 136(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 144(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#8 -# asm 2: movq mulx3=%r10 -movq 80(%rsp),%r10 - -# qhasm: mulrax = g0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 120(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 128(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 136(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 144(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rsi,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? ry0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: ry0 += mulzero -# asm 1: add mulr4=int64#2 -# asm 2: mov $0,>mulr4=%rsi -mov $0,%rsi - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#4 -# asm 2: mov $0,>mulr5=%rcx -mov $0,%rcx - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulx0 = g0_stack -# asm 1: movq mulx0=int64#8 -# asm 2: movq mulx0=%r10 -movq 120(%rsp),%r10 - -# qhasm: mulrax = f0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz0=int64#9 -# asm 2: mov rz0=%r11 -mov %rax,%r11 - -# qhasm: rz1 = mulrdx -# asm 1: mov rz1=int64#10 -# asm 2: mov rz1=%r12 -mov %rdx,%r12 - -# qhasm: mulrax = f1_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz2=int64#11 -# asm 2: mov $0,>rz2=%r13 -mov $0,%r13 - -# qhasm: rz2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz3=int64#12 -# asm 2: mov $0,>rz3=%r14 -mov $0,%r14 - -# qhasm: rz3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#8 -# asm 2: movq mulx1=%r10 -movq 128(%rsp),%r10 - -# qhasm: mulrax = f0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#8 -# asm 2: movq mulx2=%r10 -movq 136(%rsp),%r10 - -# qhasm: mulrax = f0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#8 -# asm 2: movq mulx3=%r10 -movq 144(%rsp),%r10 - -# qhasm: mulrax = f0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 152(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 160(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 168(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 176(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rsi,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? rz0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: rz0 += mulzero -# asm 1: add mulr4=int64#2 -# asm 2: mov $0,>mulr4=%rsi -mov $0,%rsi - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#4 -# asm 2: mov $0,>mulr5=%rcx -mov $0,%rcx - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulx0 = e0_stack -# asm 1: movq mulx0=int64#8 -# asm 2: movq mulx0=%r10 -movq 88(%rsp),%r10 - -# qhasm: mulrax = h0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 56(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt0=int64#9 -# asm 2: mov rt0=%r11 -mov %rax,%r11 - -# qhasm: rt1 = mulrdx -# asm 1: mov rt1=int64#10 -# asm 2: mov rt1=%r12 -mov %rdx,%r12 - -# qhasm: mulrax = h1_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 64(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt2=int64#11 -# asm 2: mov $0,>rt2=%r13 -mov $0,%r13 - -# qhasm: rt2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 72(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt3=int64#12 -# asm 2: mov $0,>rt3=%r14 -mov $0,%r14 - -# qhasm: rt3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 80(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#8 -# asm 2: movq mulx1=%r10 -movq 96(%rsp),%r10 - -# qhasm: mulrax = h0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 56(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 64(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 72(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 80(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#8 -# asm 2: movq mulx2=%r10 -movq 104(%rsp),%r10 - -# qhasm: mulrax = h0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 56(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 64(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 72(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 80(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#8 -# asm 2: movq mulx3=%r10 -movq 112(%rsp),%r10 - -# qhasm: mulrax = h0_stack -# asm 1: movq mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 56(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 64(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 72(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#13 -# asm 2: mov $0,>mulc=%r15 -mov $0,%r15 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq mulrax=%rax -movq 80(%rsp),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rsi,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? rt0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: rt0 += mulzero -# asm 1: add caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/ge25519_nielsadd_p1p1.s b/ext/ed25519-amd64-asm/ge25519_nielsadd_p1p1.s deleted file mode 100644 index b5629462a..000000000 --- a/ext/ed25519-amd64-asm/ge25519_nielsadd_p1p1.s +++ /dev/null @@ -1,3072 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 pp - -# qhasm: int64 qp - -# qhasm: input rp - -# qhasm: input pp - -# qhasm: input qp - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 a0 - -# qhasm: int64 a1 - -# qhasm: int64 a2 - -# qhasm: int64 a3 - -# qhasm: stack64 a0_stack - -# qhasm: stack64 a1_stack - -# qhasm: stack64 a2_stack - -# qhasm: stack64 a3_stack - -# qhasm: int64 b0 - -# qhasm: int64 b1 - -# qhasm: int64 b2 - -# qhasm: int64 b3 - -# qhasm: stack64 b0_stack - -# qhasm: stack64 b1_stack - -# qhasm: stack64 b2_stack - -# qhasm: stack64 b3_stack - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: stack64 c0_stack - -# qhasm: stack64 c1_stack - -# qhasm: stack64 c2_stack - -# qhasm: stack64 c3_stack - -# qhasm: int64 d0 - -# qhasm: int64 d1 - -# qhasm: int64 d2 - -# qhasm: int64 d3 - -# qhasm: stack64 d0_stack - -# qhasm: stack64 d1_stack - -# qhasm: stack64 d2_stack - -# qhasm: stack64 d3_stack - -# qhasm: int64 e0 - -# qhasm: int64 e1 - -# qhasm: int64 e2 - -# qhasm: int64 e3 - -# qhasm: stack64 e0_stack - -# qhasm: stack64 e1_stack - -# qhasm: stack64 e2_stack - -# qhasm: stack64 e3_stack - -# qhasm: int64 f0 - -# qhasm: int64 f1 - -# qhasm: int64 f2 - -# qhasm: int64 f3 - -# qhasm: stack64 f0_stack - -# qhasm: stack64 f1_stack - -# qhasm: stack64 f2_stack - -# qhasm: stack64 f3_stack - -# qhasm: int64 g0 - -# qhasm: int64 g1 - -# qhasm: int64 g2 - -# qhasm: int64 g3 - -# qhasm: stack64 g0_stack - -# qhasm: stack64 g1_stack - -# qhasm: stack64 g2_stack - -# qhasm: stack64 g3_stack - -# qhasm: int64 h0 - -# qhasm: int64 h1 - -# qhasm: int64 h2 - -# qhasm: int64 h3 - -# qhasm: stack64 h0_stack - -# qhasm: stack64 h1_stack - -# qhasm: stack64 h2_stack - -# qhasm: stack64 h3_stack - -# qhasm: int64 qt0 - -# qhasm: int64 qt1 - -# qhasm: int64 qt2 - -# qhasm: int64 qt3 - -# qhasm: stack64 qt0_stack - -# qhasm: stack64 qt1_stack - -# qhasm: stack64 qt2_stack - -# qhasm: stack64 qt3_stack - -# qhasm: int64 t10 - -# qhasm: int64 t11 - -# qhasm: int64 t12 - -# qhasm: int64 t13 - -# qhasm: stack64 t10_stack - -# qhasm: stack64 t11_stack - -# qhasm: stack64 t12_stack - -# qhasm: stack64 t13_stack - -# qhasm: int64 t20 - -# qhasm: int64 t21 - -# qhasm: int64 t22 - -# qhasm: int64 t23 - -# qhasm: stack64 t20_stack - -# qhasm: stack64 t21_stack - -# qhasm: stack64 t22_stack - -# qhasm: stack64 t23_stack - -# qhasm: int64 rx0 - -# qhasm: int64 rx1 - -# qhasm: int64 rx2 - -# qhasm: int64 rx3 - -# qhasm: int64 ry0 - -# qhasm: int64 ry1 - -# qhasm: int64 ry2 - -# qhasm: int64 ry3 - -# qhasm: int64 rz0 - -# qhasm: int64 rz1 - -# qhasm: int64 rz2 - -# qhasm: int64 rz3 - -# qhasm: int64 rt0 - -# qhasm: int64 rt1 - -# qhasm: int64 rt2 - -# qhasm: int64 rt3 - -# qhasm: int64 mulr4 - -# qhasm: int64 mulr5 - -# qhasm: int64 mulr6 - -# qhasm: int64 mulr7 - -# qhasm: int64 mulr8 - -# qhasm: int64 mulrax - -# qhasm: int64 mulrdx - -# qhasm: int64 mulx0 - -# qhasm: int64 mulx1 - -# qhasm: int64 mulx2 - -# qhasm: int64 mulx3 - -# qhasm: int64 mulc - -# qhasm: int64 mulzero - -# qhasm: int64 muli38 - -# qhasm: int64 addt0 - -# qhasm: int64 addt1 - -# qhasm: int64 subt0 - -# qhasm: int64 subt1 - -# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1 -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1 -.globl crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1 -_crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1: -crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1: -mov %rsp,%r11 -and $31,%r11 -add $128,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: qp = qp -# asm 1: mov qp=int64#4 -# asm 2: mov qp=%rcx -mov %rdx,%rcx - -# qhasm: a0 = *(uint64 *)(pp + 32) -# asm 1: movq 32(a0=int64#3 -# asm 2: movq 32(a0=%rdx -movq 32(%rsi),%rdx - -# qhasm: a1 = *(uint64 *)(pp + 40) -# asm 1: movq 40(a1=int64#5 -# asm 2: movq 40(a1=%r8 -movq 40(%rsi),%r8 - -# qhasm: a2 = *(uint64 *)(pp + 48) -# asm 1: movq 48(a2=int64#6 -# asm 2: movq 48(a2=%r9 -movq 48(%rsi),%r9 - -# qhasm: a3 = *(uint64 *)(pp + 56) -# asm 1: movq 56(a3=int64#7 -# asm 2: movq 56(a3=%rax -movq 56(%rsi),%rax - -# qhasm: b0 = a0 -# asm 1: mov b0=int64#8 -# asm 2: mov b0=%r10 -mov %rdx,%r10 - -# qhasm: b1 = a1 -# asm 1: mov b1=int64#9 -# asm 2: mov b1=%r11 -mov %r8,%r11 - -# qhasm: b2 = a2 -# asm 1: mov b2=int64#10 -# asm 2: mov b2=%r12 -mov %r9,%r12 - -# qhasm: b3 = a3 -# asm 1: mov b3=int64#11 -# asm 2: mov b3=%r13 -mov %rax,%r13 - -# qhasm: carry? a0 -= *(uint64 *) (pp + 0) -# asm 1: subq 0(subt0=int64#12 -# asm 2: mov $0,>subt0=%r14 -mov $0,%r14 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#13 -# asm 2: mov $38,>subt1=%r15 -mov $38,%r15 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#12 -# asm 2: mov $0,>addt0=%r14 -mov $0,%r14 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#13 -# asm 2: mov $38,>addt1=%r15 -mov $38,%r15 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %rdx,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %r8,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r9,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %rax,80(%rsp) - -# qhasm: b0_stack = b0 -# asm 1: movq b0_stack=stack64#12 -# asm 2: movq b0_stack=88(%rsp) -movq %r10,88(%rsp) - -# qhasm: b1_stack = b1 -# asm 1: movq b1_stack=stack64#13 -# asm 2: movq b1_stack=96(%rsp) -movq %r11,96(%rsp) - -# qhasm: b2_stack = b2 -# asm 1: movq b2_stack=stack64#14 -# asm 2: movq b2_stack=104(%rsp) -movq %r12,104(%rsp) - -# qhasm: b3_stack = b3 -# asm 1: movq b3_stack=stack64#15 -# asm 2: movq b3_stack=112(%rsp) -movq %r13,112(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = a0_stack -# asm 1: movq mulx0=int64#10 -# asm 2: movq mulx0=%r12 -movq 56(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a0=int64#11 -# asm 2: mov a0=%r13 -mov %rax,%r13 - -# qhasm: a1 = mulrdx -# asm 1: mov a1=int64#12 -# asm 2: mov a1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 8) -# asm 1: movq 8(mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a2=int64#13 -# asm 2: mov $0,>a2=%r15 -mov $0,%r15 - -# qhasm: a2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a3=int64#14 -# asm 2: mov $0,>a3=%rbx -mov $0,%rbx - -# qhasm: a3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq mulx1=%r12 -movq 64(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq mulx2=%r12 -movq 72(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq mulx3=%r12 -movq 80(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? a0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: a0 += mulzero -# asm 1: add a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %r13,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %r14,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r15,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %rbx,80(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = b0_stack -# asm 1: movq mulx0=int64#10 -# asm 2: movq mulx0=%r12 -movq 88(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul e0=int64#11 -# asm 2: mov e0=%r13 -mov %rax,%r13 - -# qhasm: e1 = mulrdx -# asm 1: mov e1=int64#12 -# asm 2: mov e1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 40) -# asm 1: movq 40(mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul e2=int64#13 -# asm 2: mov $0,>e2=%r15 -mov $0,%r15 - -# qhasm: e2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul e3=int64#14 -# asm 2: mov $0,>e3=%rbx -mov $0,%rbx - -# qhasm: e3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq mulx1=%r12 -movq 96(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq mulx2=%r12 -movq 104(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq mulx3=%r12 -movq 112(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? e0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: e0 += mulzero -# asm 1: add h0=int64#3 -# asm 2: mov h0=%rdx -mov %r13,%rdx - -# qhasm: h1 = e1 -# asm 1: mov h1=int64#5 -# asm 2: mov h1=%r8 -mov %r14,%r8 - -# qhasm: h2 = e2 -# asm 1: mov h2=int64#6 -# asm 2: mov h2=%r9 -mov %r15,%r9 - -# qhasm: h3 = e3 -# asm 1: mov h3=int64#7 -# asm 2: mov h3=%rax -mov %rbx,%rax - -# qhasm: carry? e0 -= a0_stack -# asm 1: subq subt0=int64#8 -# asm 2: mov $0,>subt0=%r10 -mov $0,%r10 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#9 -# asm 2: mov $38,>subt1=%r11 -mov $38,%r11 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#8 -# asm 2: mov $0,>addt0=%r10 -mov $0,%r10 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#9 -# asm 2: mov $38,>addt1=%r11 -mov $38,%r11 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulx0=int64#10 -# asm 2: movq 96(mulx0=%r12 -movq 96(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c0=int64#11 -# asm 2: mov c0=%r13 -mov %rax,%r13 - -# qhasm: c1 = mulrdx -# asm 1: mov c1=int64#12 -# asm 2: mov c1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 72) -# asm 1: movq 72(mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c2=int64#13 -# asm 2: mov $0,>c2=%r15 -mov $0,%r15 - -# qhasm: c2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c3=int64#14 -# asm 2: mov $0,>c3=%rbx -mov $0,%rbx - -# qhasm: c3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq 104(mulx1=%r12 -movq 104(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq 112(mulx2=%r12 -movq 112(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq 120(mulx3=%r12 -movq 120(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#4 -# asm 2: mov mulr4=%rcx -mov %rax,%rcx - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#5 -# asm 2: mov mulr5=%r8 -mov %rdx,%r8 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#4 -# asm 2: imulq $38,mulr8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? c0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: c0 += mulzero -# asm 1: add f0=int64#3 -# asm 2: movq 64(f0=%rdx -movq 64(%rsi),%rdx - -# qhasm: f1 = *(uint64 *)(pp + 72) -# asm 1: movq 72(f1=int64#4 -# asm 2: movq 72(f1=%rcx -movq 72(%rsi),%rcx - -# qhasm: f2 = *(uint64 *)(pp + 80) -# asm 1: movq 80(f2=int64#5 -# asm 2: movq 80(f2=%r8 -movq 80(%rsi),%r8 - -# qhasm: f3 = *(uint64 *)(pp + 88) -# asm 1: movq 88(f3=int64#2 -# asm 2: movq 88(f3=%rsi -movq 88(%rsi),%rsi - -# qhasm: carry? f0 += f0 -# asm 1: add addt0=int64#6 -# asm 2: mov $0,>addt0=%r9 -mov $0,%r9 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#7 -# asm 2: mov $38,>addt1=%rax -mov $38,%rax - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae g0=int64#6 -# asm 2: mov g0=%r9 -mov %rdx,%r9 - -# qhasm: g1 = f1 -# asm 1: mov g1=int64#7 -# asm 2: mov g1=%rax -mov %rcx,%rax - -# qhasm: g2 = f2 -# asm 1: mov g2=int64#8 -# asm 2: mov g2=%r10 -mov %r8,%r10 - -# qhasm: g3 = f3 -# asm 1: mov g3=int64#9 -# asm 2: mov g3=%r11 -mov %rsi,%r11 - -# qhasm: carry? f0 -= c0 -# asm 1: sub subt0=int64#10 -# asm 2: mov $0,>subt0=%r12 -mov $0,%r12 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#15 -# asm 2: mov $38,>subt1=%rbp -mov $38,%rbp - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#10 -# asm 2: mov $0,>addt0=%r12 -mov $0,%r12 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#11 -# asm 2: mov $38,>addt1=%r13 -mov $38,%r13 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/ge25519_p1p1_to_p2.s b/ext/ed25519-amd64-asm/ge25519_p1p1_to_p2.s deleted file mode 100644 index beddbc791..000000000 --- a/ext/ed25519-amd64-asm/ge25519_p1p1_to_p2.s +++ /dev/null @@ -1,2236 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 pp - -# qhasm: input rp - -# qhasm: input pp - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 rx0 - -# qhasm: int64 rx1 - -# qhasm: int64 rx2 - -# qhasm: int64 rx3 - -# qhasm: int64 ry0 - -# qhasm: int64 ry1 - -# qhasm: int64 ry2 - -# qhasm: int64 ry3 - -# qhasm: int64 rz0 - -# qhasm: int64 rz1 - -# qhasm: int64 rz2 - -# qhasm: int64 rz3 - -# qhasm: int64 mulr4 - -# qhasm: int64 mulr5 - -# qhasm: int64 mulr6 - -# qhasm: int64 mulr7 - -# qhasm: int64 mulr8 - -# qhasm: int64 mulrax - -# qhasm: int64 mulrdx - -# qhasm: int64 mulx0 - -# qhasm: int64 mulx1 - -# qhasm: int64 mulx2 - -# qhasm: int64 mulx3 - -# qhasm: int64 mulc - -# qhasm: int64 mulzero - -# qhasm: int64 muli38 - -# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2 -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2 -.globl crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2 -_crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2: -crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = *(uint64 *)(pp + 0) -# asm 1: movq 0(mulx0=int64#9 -# asm 2: movq 0(mulx0=%r11 -movq 0(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx0=int64#10 -# asm 2: mov rx0=%r12 -mov %rax,%r12 - -# qhasm: rx1 = mulrdx -# asm 1: mov rx1=int64#11 -# asm 2: mov rx1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(pp + 104) -# asm 1: movq 104(mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx2=int64#12 -# asm 2: mov $0,>rx2=%r14 -mov $0,%r14 - -# qhasm: rx2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx3=int64#13 -# asm 2: mov $0,>rx3=%r15 -mov $0,%r15 - -# qhasm: rx3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq 8(mulx1=%r11 -movq 8(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq 16(mulx2=%r11 -movq 16(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq 24(mulx3=%r11 -movq 24(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#4 -# asm 2: mov mulr4=%rcx -mov %rax,%rcx - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#5 -# asm 2: mov mulr5=%r8 -mov %rdx,%r8 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#4 -# asm 2: imulq $38,mulr8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? rx0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: rx0 += mulzero -# asm 1: add mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = *(uint64 *)(pp + 64) -# asm 1: movq 64(mulx0=int64#9 -# asm 2: movq 64(mulx0=%r11 -movq 64(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry0=int64#10 -# asm 2: mov ry0=%r12 -mov %rax,%r12 - -# qhasm: ry1 = mulrdx -# asm 1: mov ry1=int64#11 -# asm 2: mov ry1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(pp + 40) -# asm 1: movq 40(mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry2=int64#12 -# asm 2: mov $0,>ry2=%r14 -mov $0,%r14 - -# qhasm: ry2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry3=int64#13 -# asm 2: mov $0,>ry3=%r15 -mov $0,%r15 - -# qhasm: ry3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq 72(mulx1=%r11 -movq 72(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq 80(mulx2=%r11 -movq 80(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq 88(mulx3=%r11 -movq 88(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#4 -# asm 2: mov mulr4=%rcx -mov %rax,%rcx - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#5 -# asm 2: mov mulr5=%r8 -mov %rdx,%r8 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#4 -# asm 2: imulq $38,mulr8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? ry0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: ry0 += mulzero -# asm 1: add mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulx0=int64#9 -# asm 2: movq 32(mulx0=%r11 -movq 32(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz0=int64#10 -# asm 2: mov rz0=%r12 -mov %rax,%r12 - -# qhasm: rz1 = mulrdx -# asm 1: mov rz1=int64#11 -# asm 2: mov rz1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(pp + 104) -# asm 1: movq 104(mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz2=int64#12 -# asm 2: mov $0,>rz2=%r14 -mov $0,%r14 - -# qhasm: rz2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz3=int64#13 -# asm 2: mov $0,>rz3=%r15 -mov $0,%r15 - -# qhasm: rz3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq 40(mulx1=%r11 -movq 40(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq 48(mulx2=%r11 -movq 48(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq 56(mulx3=%r11 -movq 56(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? rz0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: rz0 += mulzero -# asm 1: add caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/ge25519_p1p1_to_p3.s b/ext/ed25519-amd64-asm/ge25519_p1p1_to_p3.s deleted file mode 100644 index 82433fba5..000000000 --- a/ext/ed25519-amd64-asm/ge25519_p1p1_to_p3.s +++ /dev/null @@ -1,2926 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 pp - -# qhasm: input rp - -# qhasm: input pp - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 rx0 - -# qhasm: int64 rx1 - -# qhasm: int64 rx2 - -# qhasm: int64 rx3 - -# qhasm: int64 ry0 - -# qhasm: int64 ry1 - -# qhasm: int64 ry2 - -# qhasm: int64 ry3 - -# qhasm: int64 rz0 - -# qhasm: int64 rz1 - -# qhasm: int64 rz2 - -# qhasm: int64 rz3 - -# qhasm: int64 rt0 - -# qhasm: int64 rt1 - -# qhasm: int64 rt2 - -# qhasm: int64 rt3 - -# qhasm: int64 mulr4 - -# qhasm: int64 mulr5 - -# qhasm: int64 mulr6 - -# qhasm: int64 mulr7 - -# qhasm: int64 mulr8 - -# qhasm: int64 mulrax - -# qhasm: int64 mulrdx - -# qhasm: int64 mulx0 - -# qhasm: int64 mulx1 - -# qhasm: int64 mulx2 - -# qhasm: int64 mulx3 - -# qhasm: int64 mulc - -# qhasm: int64 mulzero - -# qhasm: int64 muli38 - -# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3 -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3 -.globl crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3 -_crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3: -crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = *(uint64 *)(pp + 0) -# asm 1: movq 0(mulx0=int64#9 -# asm 2: movq 0(mulx0=%r11 -movq 0(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx0=int64#10 -# asm 2: mov rx0=%r12 -mov %rax,%r12 - -# qhasm: rx1 = mulrdx -# asm 1: mov rx1=int64#11 -# asm 2: mov rx1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(pp + 104) -# asm 1: movq 104(mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx2=int64#12 -# asm 2: mov $0,>rx2=%r14 -mov $0,%r14 - -# qhasm: rx2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx3=int64#13 -# asm 2: mov $0,>rx3=%r15 -mov $0,%r15 - -# qhasm: rx3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq 8(mulx1=%r11 -movq 8(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq 16(mulx2=%r11 -movq 16(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq 24(mulx3=%r11 -movq 24(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#4 -# asm 2: mov mulr4=%rcx -mov %rax,%rcx - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#5 -# asm 2: mov mulr5=%r8 -mov %rdx,%r8 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#4 -# asm 2: imulq $38,mulr8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? rx0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: rx0 += mulzero -# asm 1: add mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = *(uint64 *)(pp + 64) -# asm 1: movq 64(mulx0=int64#9 -# asm 2: movq 64(mulx0=%r11 -movq 64(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry0=int64#10 -# asm 2: mov ry0=%r12 -mov %rax,%r12 - -# qhasm: ry1 = mulrdx -# asm 1: mov ry1=int64#11 -# asm 2: mov ry1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(pp + 40) -# asm 1: movq 40(mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry2=int64#12 -# asm 2: mov $0,>ry2=%r14 -mov $0,%r14 - -# qhasm: ry2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul ry3=int64#13 -# asm 2: mov $0,>ry3=%r15 -mov $0,%r15 - -# qhasm: ry3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq 72(mulx1=%r11 -movq 72(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq 80(mulx2=%r11 -movq 80(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq 88(mulx3=%r11 -movq 88(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#4 -# asm 2: mov mulr4=%rcx -mov %rax,%rcx - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#5 -# asm 2: mov mulr5=%r8 -mov %rdx,%r8 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#4 -# asm 2: imulq $38,mulr8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? ry0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: ry0 += mulzero -# asm 1: add mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = *(uint64 *)(pp + 32) -# asm 1: movq 32(mulx0=int64#9 -# asm 2: movq 32(mulx0=%r11 -movq 32(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz0=int64#10 -# asm 2: mov rz0=%r12 -mov %rax,%r12 - -# qhasm: rz1 = mulrdx -# asm 1: mov rz1=int64#11 -# asm 2: mov rz1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(pp + 104) -# asm 1: movq 104(mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz2=int64#12 -# asm 2: mov $0,>rz2=%r14 -mov $0,%r14 - -# qhasm: rz2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rz3=int64#13 -# asm 2: mov $0,>rz3=%r15 -mov $0,%r15 - -# qhasm: rz3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq 40(mulx1=%r11 -movq 40(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq 48(mulx2=%r11 -movq 48(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq 56(mulx3=%r11 -movq 56(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#4 -# asm 2: mov mulr4=%rcx -mov %rax,%rcx - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#5 -# asm 2: mov mulr5=%r8 -mov %rdx,%r8 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#4 -# asm 2: imulq $38,mulr8=%rcx -imulq $38,%rax,%rcx - -# qhasm: carry? rz0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: rz0 += mulzero -# asm 1: add mulr4=int64#4 -# asm 2: mov $0,>mulr4=%rcx -mov $0,%rcx - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#5 -# asm 2: mov $0,>mulr5=%r8 -mov $0,%r8 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#6 -# asm 2: mov $0,>mulr6=%r9 -mov $0,%r9 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#8 -# asm 2: mov $0,>mulr7=%r10 -mov $0,%r10 - -# qhasm: mulx0 = *(uint64 *)(pp + 0) -# asm 1: movq 0(mulx0=int64#9 -# asm 2: movq 0(mulx0=%r11 -movq 0(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt0=int64#10 -# asm 2: mov rt0=%r12 -mov %rax,%r12 - -# qhasm: rt1 = mulrdx -# asm 1: mov rt1=int64#11 -# asm 2: mov rt1=%r13 -mov %rdx,%r13 - -# qhasm: mulrax = *(uint64 *)(pp + 72) -# asm 1: movq 72(mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt2=int64#12 -# asm 2: mov $0,>rt2=%r14 -mov $0,%r14 - -# qhasm: rt2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt3=int64#13 -# asm 2: mov $0,>rt3=%r15 -mov $0,%r15 - -# qhasm: rt3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#9 -# asm 2: movq 8(mulx1=%r11 -movq 8(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#9 -# asm 2: movq 16(mulx2=%r11 -movq 16(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#9 -# asm 2: movq 24(mulx3=%r11 -movq 24(%rsi),%r11 - -# qhasm: mulrax = *(uint64 *)(pp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#14 -# asm 2: mov $0,>mulc=%rbx -mov $0,%rbx - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rsi),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %rcx,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? rt0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: rt0 += mulzero -# asm 1: add caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/ge25519_pack.c b/ext/ed25519-amd64-asm/ge25519_pack.c deleted file mode 100644 index f289fe570..000000000 --- a/ext/ed25519-amd64-asm/ge25519_pack.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "fe25519.h" -#include "sc25519.h" -#include "ge25519.h" - -void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) -{ - fe25519 tx, ty, zi; - fe25519_invert(&zi, &p->z); - fe25519_mul(&tx, &p->x, &zi); - fe25519_mul(&ty, &p->y, &zi); - fe25519_pack(r, &ty); - r[31] ^= fe25519_getparity(&tx) << 7; -} diff --git a/ext/ed25519-amd64-asm/ge25519_pnielsadd_p1p1.s b/ext/ed25519-amd64-asm/ge25519_pnielsadd_p1p1.s deleted file mode 100644 index aff2e75d2..000000000 --- a/ext/ed25519-amd64-asm/ge25519_pnielsadd_p1p1.s +++ /dev/null @@ -1,3662 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 pp - -# qhasm: int64 qp - -# qhasm: input rp - -# qhasm: input pp - -# qhasm: input qp - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 a0 - -# qhasm: int64 a1 - -# qhasm: int64 a2 - -# qhasm: int64 a3 - -# qhasm: stack64 a0_stack - -# qhasm: stack64 a1_stack - -# qhasm: stack64 a2_stack - -# qhasm: stack64 a3_stack - -# qhasm: int64 b0 - -# qhasm: int64 b1 - -# qhasm: int64 b2 - -# qhasm: int64 b3 - -# qhasm: stack64 b0_stack - -# qhasm: stack64 b1_stack - -# qhasm: stack64 b2_stack - -# qhasm: stack64 b3_stack - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: stack64 c0_stack - -# qhasm: stack64 c1_stack - -# qhasm: stack64 c2_stack - -# qhasm: stack64 c3_stack - -# qhasm: int64 d0 - -# qhasm: int64 d1 - -# qhasm: int64 d2 - -# qhasm: int64 d3 - -# qhasm: stack64 d0_stack - -# qhasm: stack64 d1_stack - -# qhasm: stack64 d2_stack - -# qhasm: stack64 d3_stack - -# qhasm: int64 t10 - -# qhasm: int64 t11 - -# qhasm: int64 t12 - -# qhasm: int64 t13 - -# qhasm: stack64 t10_stack - -# qhasm: stack64 t11_stack - -# qhasm: stack64 t12_stack - -# qhasm: stack64 t13_stack - -# qhasm: int64 t20 - -# qhasm: int64 t21 - -# qhasm: int64 t22 - -# qhasm: int64 t23 - -# qhasm: stack64 t20_stack - -# qhasm: stack64 t21_stack - -# qhasm: stack64 t22_stack - -# qhasm: stack64 t23_stack - -# qhasm: int64 rx0 - -# qhasm: int64 rx1 - -# qhasm: int64 rx2 - -# qhasm: int64 rx3 - -# qhasm: int64 ry0 - -# qhasm: int64 ry1 - -# qhasm: int64 ry2 - -# qhasm: int64 ry3 - -# qhasm: int64 rz0 - -# qhasm: int64 rz1 - -# qhasm: int64 rz2 - -# qhasm: int64 rz3 - -# qhasm: int64 rt0 - -# qhasm: int64 rt1 - -# qhasm: int64 rt2 - -# qhasm: int64 rt3 - -# qhasm: int64 x0 - -# qhasm: int64 x1 - -# qhasm: int64 x2 - -# qhasm: int64 x3 - -# qhasm: int64 mulr4 - -# qhasm: int64 mulr5 - -# qhasm: int64 mulr6 - -# qhasm: int64 mulr7 - -# qhasm: int64 mulr8 - -# qhasm: int64 mulrax - -# qhasm: int64 mulrdx - -# qhasm: int64 mulx0 - -# qhasm: int64 mulx1 - -# qhasm: int64 mulx2 - -# qhasm: int64 mulx3 - -# qhasm: int64 mulc - -# qhasm: int64 mulzero - -# qhasm: int64 muli38 - -# qhasm: int64 addt0 - -# qhasm: int64 addt1 - -# qhasm: int64 subt0 - -# qhasm: int64 subt1 - -# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1 -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1 -.globl crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1 -_crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1: -crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1: -mov %rsp,%r11 -and $31,%r11 -add $128,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: qp = qp -# asm 1: mov qp=int64#4 -# asm 2: mov qp=%rcx -mov %rdx,%rcx - -# qhasm: a0 = *(uint64 *)(pp + 32) -# asm 1: movq 32(a0=int64#3 -# asm 2: movq 32(a0=%rdx -movq 32(%rsi),%rdx - -# qhasm: a1 = *(uint64 *)(pp + 40) -# asm 1: movq 40(a1=int64#5 -# asm 2: movq 40(a1=%r8 -movq 40(%rsi),%r8 - -# qhasm: a2 = *(uint64 *)(pp + 48) -# asm 1: movq 48(a2=int64#6 -# asm 2: movq 48(a2=%r9 -movq 48(%rsi),%r9 - -# qhasm: a3 = *(uint64 *)(pp + 56) -# asm 1: movq 56(a3=int64#7 -# asm 2: movq 56(a3=%rax -movq 56(%rsi),%rax - -# qhasm: b0 = a0 -# asm 1: mov b0=int64#8 -# asm 2: mov b0=%r10 -mov %rdx,%r10 - -# qhasm: b1 = a1 -# asm 1: mov b1=int64#9 -# asm 2: mov b1=%r11 -mov %r8,%r11 - -# qhasm: b2 = a2 -# asm 1: mov b2=int64#10 -# asm 2: mov b2=%r12 -mov %r9,%r12 - -# qhasm: b3 = a3 -# asm 1: mov b3=int64#11 -# asm 2: mov b3=%r13 -mov %rax,%r13 - -# qhasm: carry? a0 -= *(uint64 *)(pp + 0) -# asm 1: subq 0(subt0=int64#12 -# asm 2: mov $0,>subt0=%r14 -mov $0,%r14 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#13 -# asm 2: mov $38,>subt1=%r15 -mov $38,%r15 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae addt0=int64#12 -# asm 2: mov $0,>addt0=%r14 -mov $0,%r14 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#13 -# asm 2: mov $38,>addt1=%r15 -mov $38,%r15 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %rdx,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %r8,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r9,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %rax,80(%rsp) - -# qhasm: b0_stack = b0 -# asm 1: movq b0_stack=stack64#12 -# asm 2: movq b0_stack=88(%rsp) -movq %r10,88(%rsp) - -# qhasm: b1_stack = b1 -# asm 1: movq b1_stack=stack64#13 -# asm 2: movq b1_stack=96(%rsp) -movq %r11,96(%rsp) - -# qhasm: b2_stack = b2 -# asm 1: movq b2_stack=stack64#14 -# asm 2: movq b2_stack=104(%rsp) -movq %r12,104(%rsp) - -# qhasm: b3_stack = b3 -# asm 1: movq b3_stack=stack64#15 -# asm 2: movq b3_stack=112(%rsp) -movq %r13,112(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = a0_stack -# asm 1: movq mulx0=int64#10 -# asm 2: movq mulx0=%r12 -movq 56(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a0=int64#11 -# asm 2: mov a0=%r13 -mov %rax,%r13 - -# qhasm: a1 = mulrdx -# asm 1: mov a1=int64#12 -# asm 2: mov a1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 8) -# asm 1: movq 8(mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a2=int64#13 -# asm 2: mov $0,>a2=%r15 -mov $0,%r15 - -# qhasm: a2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul a3=int64#14 -# asm 2: mov $0,>a3=%rbx -mov $0,%rbx - -# qhasm: a3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq mulx1=%r12 -movq 64(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq mulx2=%r12 -movq 72(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq mulx3=%r12 -movq 80(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 0) -# asm 1: movq 0(mulrax=int64#7 -# asm 2: movq 0(mulrax=%rax -movq 0(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 8(mulrax=%rax -movq 8(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 16(mulrax=%rax -movq 16(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 24(mulrax=%rax -movq 24(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? a0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: a0 += mulzero -# asm 1: add a0_stack=stack64#8 -# asm 2: movq a0_stack=56(%rsp) -movq %r13,56(%rsp) - -# qhasm: a1_stack = a1 -# asm 1: movq a1_stack=stack64#9 -# asm 2: movq a1_stack=64(%rsp) -movq %r14,64(%rsp) - -# qhasm: a2_stack = a2 -# asm 1: movq a2_stack=stack64#10 -# asm 2: movq a2_stack=72(%rsp) -movq %r15,72(%rsp) - -# qhasm: a3_stack = a3 -# asm 1: movq a3_stack=stack64#11 -# asm 2: movq a3_stack=80(%rsp) -movq %rbx,80(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = b0_stack -# asm 1: movq mulx0=int64#10 -# asm 2: movq mulx0=%r12 -movq 88(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx0=int64#11 -# asm 2: mov rx0=%r13 -mov %rax,%r13 - -# qhasm: rx1 = mulrdx -# asm 1: mov rx1=int64#12 -# asm 2: mov rx1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 40) -# asm 1: movq 40(mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx2=int64#13 -# asm 2: mov $0,>rx2=%r15 -mov $0,%r15 - -# qhasm: rx2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rx3=int64#14 -# asm 2: mov $0,>rx3=%rbx -mov $0,%rbx - -# qhasm: rx3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq mulx1=%r12 -movq 96(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq mulx2=%r12 -movq 104(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq mulx3=%r12 -movq 112(%rsp),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 32) -# asm 1: movq 32(mulrax=int64#7 -# asm 2: movq 32(mulrax=%rax -movq 32(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 40(mulrax=%rax -movq 40(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 48(mulrax=%rax -movq 48(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 56(mulrax=%rax -movq 56(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? rx0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: rx0 += mulzero -# asm 1: add ry0=int64#3 -# asm 2: mov ry0=%rdx -mov %r13,%rdx - -# qhasm: ry1 = rx1 -# asm 1: mov ry1=int64#5 -# asm 2: mov ry1=%r8 -mov %r14,%r8 - -# qhasm: ry2 = rx2 -# asm 1: mov ry2=int64#6 -# asm 2: mov ry2=%r9 -mov %r15,%r9 - -# qhasm: ry3 = rx3 -# asm 1: mov ry3=int64#7 -# asm 2: mov ry3=%rax -mov %rbx,%rax - -# qhasm: carry? ry0 += a0_stack -# asm 1: addq addt0=int64#8 -# asm 2: mov $0,>addt0=%r10 -mov $0,%r10 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#9 -# asm 2: mov $38,>addt1=%r11 -mov $38,%r11 - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae subt0=int64#8 -# asm 2: mov $0,>subt0=%r10 -mov $0,%r10 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#9 -# asm 2: mov $38,>subt1=%r11 -mov $38,%r11 - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = *(uint64 *)(pp + 96) -# asm 1: movq 96(mulx0=int64#10 -# asm 2: movq 96(mulx0=%r12 -movq 96(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c0=int64#11 -# asm 2: mov c0=%r13 -mov %rax,%r13 - -# qhasm: c1 = mulrdx -# asm 1: mov c1=int64#12 -# asm 2: mov c1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 104) -# asm 1: movq 104(mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c2=int64#13 -# asm 2: mov $0,>c2=%r15 -mov $0,%r15 - -# qhasm: c2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul c3=int64#14 -# asm 2: mov $0,>c3=%rbx -mov $0,%rbx - -# qhasm: c3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq 104(mulx1=%r12 -movq 104(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq 112(mulx2=%r12 -movq 112(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#10 -# asm 2: movq 120(mulx3=%r12 -movq 120(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 96) -# asm 1: movq 96(mulrax=int64#7 -# asm 2: movq 96(mulrax=%rax -movq 96(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 104(mulrax=%rax -movq 104(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 112(mulrax=%rax -movq 112(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 120(mulrax=%rax -movq 120(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#5 -# asm 2: mov mulr4=%r8 -mov %rax,%r8 - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#6 -# asm 2: mov mulr5=%r9 -mov %rdx,%r9 - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#3 -# asm 2: mov $0,>mulzero=%rdx -mov $0,%rdx - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#5 -# asm 2: imulq $38,mulr8=%r8 -imulq $38,%rax,%r8 - -# qhasm: carry? c0 += mulr8 -# asm 1: add mulzero=int64#3 -# asm 2: imulq $38,mulzero=%rdx -imulq $38,%rdx,%rdx - -# qhasm: c0 += mulzero -# asm 1: add c0_stack=stack64#8 -# asm 2: movq c0_stack=56(%rsp) -movq %r13,56(%rsp) - -# qhasm: c1_stack = c1 -# asm 1: movq c1_stack=stack64#9 -# asm 2: movq c1_stack=64(%rsp) -movq %r14,64(%rsp) - -# qhasm: c2_stack = c2 -# asm 1: movq c2_stack=stack64#10 -# asm 2: movq c2_stack=72(%rsp) -movq %r15,72(%rsp) - -# qhasm: c3_stack = c3 -# asm 1: movq c3_stack=stack64#11 -# asm 2: movq c3_stack=80(%rsp) -movq %rbx,80(%rsp) - -# qhasm: mulr4 = 0 -# asm 1: mov $0,>mulr4=int64#5 -# asm 2: mov $0,>mulr4=%r8 -mov $0,%r8 - -# qhasm: mulr5 = 0 -# asm 1: mov $0,>mulr5=int64#6 -# asm 2: mov $0,>mulr5=%r9 -mov $0,%r9 - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#8 -# asm 2: mov $0,>mulr6=%r10 -mov $0,%r10 - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#9 -# asm 2: mov $0,>mulr7=%r11 -mov $0,%r11 - -# qhasm: mulx0 = *(uint64 *)(pp + 64) -# asm 1: movq 64(mulx0=int64#10 -# asm 2: movq 64(mulx0=%r12 -movq 64(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt0=int64#11 -# asm 2: mov rt0=%r13 -mov %rax,%r13 - -# qhasm: rt1 = mulrdx -# asm 1: mov rt1=int64#12 -# asm 2: mov rt1=%r14 -mov %rdx,%r14 - -# qhasm: mulrax = *(uint64 *)(qp + 72) -# asm 1: movq 72(mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt2=int64#13 -# asm 2: mov $0,>rt2=%r15 -mov $0,%r15 - -# qhasm: rt2 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul rt3=int64#14 -# asm 2: mov $0,>rt3=%rbx -mov $0,%rbx - -# qhasm: rt3 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0 -# asm 1: mul mulx1=int64#10 -# asm 2: movq 72(mulx1=%r12 -movq 72(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1 -# asm 1: mul mulx2=int64#10 -# asm 2: movq 80(mulx2=%r12 -movq 80(%rsi),%r12 - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulc=int64#15 -# asm 2: mov $0,>mulc=%rbp -mov $0,%rbp - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2 -# asm 1: mul mulx3=int64#2 -# asm 2: movq 88(mulx3=%rsi -movq 88(%rsi),%rsi - -# qhasm: mulrax = *(uint64 *)(qp + 64) -# asm 1: movq 64(mulrax=int64#7 -# asm 2: movq 64(mulrax=%rax -movq 64(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 72(mulrax=%rax -movq 72(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 80(mulrax=%rax -movq 80(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulc=int64#10 -# asm 2: mov $0,>mulc=%r12 -mov $0,%r12 - -# qhasm: mulc += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: movq 88(mulrax=%rax -movq 88(%rcx),%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3 -# asm 1: mul mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r8,%rax - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: mulr4 = mulrax -# asm 1: mov mulr4=int64#2 -# asm 2: mov mulr4=%rsi -mov %rax,%rsi - -# qhasm: mulrax = mulr5 -# asm 1: mov mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r9,%rax - -# qhasm: mulr5 = mulrdx -# asm 1: mov mulr5=int64#4 -# asm 2: mov mulr5=%rcx -mov %rdx,%rcx - -# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38 -mulq crypto_sign_ed25519_amd64_64_38(%rip) - -# qhasm: carry? mulr5 += mulrax -# asm 1: add mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r10,%rax - -# qhasm: mulr6 = 0 -# asm 1: mov $0,>mulr6=int64#5 -# asm 2: mov $0,>mulr6=%r8 -mov $0,%r8 - -# qhasm: mulr6 += mulrdx + carry -# asm 1: adc mulrax=int64#7 -# asm 2: mov mulrax=%rax -mov %r11,%rax - -# qhasm: mulr7 = 0 -# asm 1: mov $0,>mulr7=int64#6 -# asm 2: mov $0,>mulr7=%r9 -mov $0,%r9 - -# qhasm: mulr7 += mulrdx + carry -# asm 1: adc mulr8=int64#7 -# asm 2: mov $0,>mulr8=%rax -mov $0,%rax - -# qhasm: mulr8 += mulrdx + carry -# asm 1: adc mulzero=int64#2 -# asm 2: mov $0,>mulzero=%rsi -mov $0,%rsi - -# qhasm: mulr8 += mulzero + carry -# asm 1: adc mulr8=int64#3 -# asm 2: imulq $38,mulr8=%rdx -imulq $38,%rax,%rdx - -# qhasm: carry? rt0 += mulr8 -# asm 1: add mulzero=int64#2 -# asm 2: imulq $38,mulzero=%rsi -imulq $38,%rsi,%rsi - -# qhasm: rt0 += mulzero -# asm 1: add addt0=int64#2 -# asm 2: mov $0,>addt0=%rsi -mov $0,%rsi - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#3 -# asm 2: mov $38,>addt1=%rdx -mov $38,%rdx - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae rz0=int64#2 -# asm 2: mov rz0=%rsi -mov %r13,%rsi - -# qhasm: rz1 = rt1 -# asm 1: mov rz1=int64#3 -# asm 2: mov rz1=%rdx -mov %r14,%rdx - -# qhasm: rz2 = rt2 -# asm 1: mov rz2=int64#4 -# asm 2: mov rz2=%rcx -mov %r15,%rcx - -# qhasm: rz3 = rt3 -# asm 1: mov rz3=int64#5 -# asm 2: mov rz3=%r8 -mov %rbx,%r8 - -# qhasm: carry? rz0 += c0_stack -# asm 1: addq addt0=int64#6 -# asm 2: mov $0,>addt0=%r9 -mov $0,%r9 - -# qhasm: addt1 = 38 -# asm 1: mov $38,>addt1=int64#7 -# asm 2: mov $38,>addt1=%rax -mov $38,%rax - -# qhasm: addt1 = addt0 if !carry -# asm 1: cmovae subt0=int64#6 -# asm 2: mov $0,>subt0=%r9 -mov $0,%r9 - -# qhasm: subt1 = 38 -# asm 1: mov $38,>subt1=int64#7 -# asm 2: mov $38,>subt1=%rax -mov $38,%rax - -# qhasm: subt1 = subt0 if !carry -# asm 1: cmovae caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/ge25519_scalarmult_base.c b/ext/ed25519-amd64-asm/ge25519_scalarmult_base.c deleted file mode 100644 index ffa6e2fa9..000000000 --- a/ext/ed25519-amd64-asm/ge25519_scalarmult_base.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "fe25519.h" -#include "sc25519.h" -#include "ge25519.h" - -/* Multiples of the base point in Niels' representation */ -static const ge25519_niels ge25519_base_multiples_niels[] = { -#ifdef SMALLTABLES -#include "ge25519_base_niels_smalltables.data" -#else -#include "ge25519_base_niels.data" -#endif -}; - -/* d */ -/*static const fe25519 ecd = {{0x75EB4DCA135978A3, 0x00700A4D4141D8AB, 0x8CC740797779E898, 0x52036CEE2B6FFE73}};*/ - -void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) -{ - signed char b[64]; - int i; - ge25519_niels t; - fe25519 d; - - sc25519_window4(b,s); - -#ifdef SMALLTABLES - ge25519_p1p1 tp1p1; - choose_t((ge25519_niels *)r, 0, (signed long long) b[1], ge25519_base_multiples_niels); - fe25519_sub(&d, &r->y, &r->x); - fe25519_add(&r->y, &r->y, &r->x); - r->x = d; - r->t = r->z; - fe25519_setint(&r->z,2); - for(i=3;i<64;i+=2) - { - choose_t(&t, (unsigned long long) i/2, (signed long long) b[i], ge25519_base_multiples_niels); - ge25519_nielsadd2(r, &t); - } - ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)r); - ge25519_p1p1_to_p2((ge25519_p2 *)r, &tp1p1); - ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)r); - ge25519_p1p1_to_p2((ge25519_p2 *)r, &tp1p1); - ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)r); - ge25519_p1p1_to_p2((ge25519_p2 *)r, &tp1p1); - ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)r); - ge25519_p1p1_to_p3(r, &tp1p1); - choose_t(&t, (unsigned long long) 0, (signed long long) b[0], ge25519_base_multiples_niels); - fe25519_mul(&t.t2d, &t.t2d, &ecd); - ge25519_nielsadd2(r, &t); - for(i=2;i<64;i+=2) - { - choose_t(&t, (unsigned long long) i/2, (signed long long) b[i], ge25519_base_multiples_niels); - ge25519_nielsadd2(r, &t); - } -#else - choose_t((ge25519_niels *)r, 0, (signed long long) b[0], ge25519_base_multiples_niels); - fe25519_sub(&d, &r->y, &r->x); - fe25519_add(&r->y, &r->y, &r->x); - r->x = d; - r->t = r->z; - fe25519_setint(&r->z,2); - for(i=1;i<64;i++) - { - choose_t(&t, (unsigned long long) i, (signed long long) b[i], ge25519_base_multiples_niels); - ge25519_nielsadd2(r, &t); - } -#endif -} diff --git a/ext/ed25519-amd64-asm/ge25519_unpackneg.c b/ext/ed25519-amd64-asm/ge25519_unpackneg.c deleted file mode 100644 index ff16fd200..000000000 --- a/ext/ed25519-amd64-asm/ge25519_unpackneg.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "fe25519.h" -#include "ge25519.h" - -/* d */ -static const fe25519 ecd = {{0x75EB4DCA135978A3, 0x00700A4D4141D8AB, 0x8CC740797779E898, 0x52036CEE2B6FFE73}}; -/* sqrt(-1) */ -static const fe25519 sqrtm1 = {{0xC4EE1B274A0EA0B0, 0x2F431806AD2FE478, 0x2B4D00993DFBD7A7, 0x2B8324804FC1DF0B}}; - -/* return 0 on success, -1 otherwise */ -int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) -{ - fe25519 t, chk, num, den, den2, den4, den6; - unsigned char par = p[31] >> 7; - - fe25519_setint(&r->z,1); - fe25519_unpack(&r->y, p); - fe25519_square(&num, &r->y); /* x = y^2 */ - fe25519_mul(&den, &num, &ecd); /* den = dy^2 */ - fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */ - fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */ - - /* Computation of sqrt(num/den) - 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) - */ - fe25519_square(&den2, &den); - fe25519_square(&den4, &den2); - fe25519_mul(&den6, &den4, &den2); - fe25519_mul(&t, &den6, &num); - fe25519_mul(&t, &t, &den); - - fe25519_pow2523(&t, &t); - /* 2. computation of r->x = t * num * den^3 - */ - fe25519_mul(&t, &t, &num); - fe25519_mul(&t, &t, &den); - fe25519_mul(&t, &t, &den); - fe25519_mul(&r->x, &t, &den); - - /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: - */ - fe25519_square(&chk, &r->x); - fe25519_mul(&chk, &chk, &den); - if (!fe25519_iseq_vartime(&chk, &num)) - fe25519_mul(&r->x, &r->x, &sqrtm1); - - /* 4. Now we have one of the two square roots, except if input was not a square - */ - fe25519_square(&chk, &r->x); - fe25519_mul(&chk, &chk, &den); - if (!fe25519_iseq_vartime(&chk, &num)) - return -1; - - /* 5. Choose the desired square root according to parity: - */ - if(fe25519_getparity(&r->x) != (1-par)) - fe25519_neg(&r->x, &r->x); - - fe25519_mul(&r->t, &r->x, &r->y); - return 0; -} diff --git a/ext/ed25519-amd64-asm/heap_rootreplaced.s b/ext/ed25519-amd64-asm/heap_rootreplaced.s deleted file mode 100644 index 8fe385b47..000000000 --- a/ext/ed25519-amd64-asm/heap_rootreplaced.s +++ /dev/null @@ -1,476 +0,0 @@ - -# qhasm: int64 hp - -# qhasm: int64 hlen - -# qhasm: int64 sp - -# qhasm: int64 pp - -# qhasm: input hp - -# qhasm: input hlen - -# qhasm: input sp - -# qhasm: int64 prc - -# qhasm: int64 plc - -# qhasm: int64 pc - -# qhasm: int64 d - -# qhasm: int64 spp - -# qhasm: int64 sprc - -# qhasm: int64 spc - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: int64 t0 - -# qhasm: int64 t1 - -# qhasm: int64 t2 - -# qhasm: int64 t3 - -# qhasm: int64 p0 - -# qhasm: int64 p1 - -# qhasm: int64 p2 - -# qhasm: int64 p3 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_heap_rootreplaced -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_heap_rootreplaced -.globl crypto_sign_ed25519_amd64_64_heap_rootreplaced -_crypto_sign_ed25519_amd64_64_heap_rootreplaced: -crypto_sign_ed25519_amd64_64_heap_rootreplaced: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: pp = 0 -# asm 1: mov $0,>pp=int64#4 -# asm 2: mov $0,>pp=%rcx -mov $0,%rcx - -# qhasm: siftdownloop: -._siftdownloop: - -# qhasm: prc = pp -# asm 1: mov prc=int64#5 -# asm 2: mov prc=%r8 -mov %rcx,%r8 - -# qhasm: prc *= 2 -# asm 1: imulq $2,prc=int64#5 -# asm 2: imulq $2,prc=%r8 -imulq $2,%r8,%r8 - -# qhasm: pc = prc -# asm 1: mov pc=int64#6 -# asm 2: mov pc=%r9 -mov %r8,%r9 - -# qhasm: prc += 2 -# asm 1: add $2,? hlen - prc -# asm 1: cmp -jbe ._siftuploop - -# qhasm: sprc = *(uint64 *)(hp + prc * 8) -# asm 1: movq (sprc=int64#7 -# asm 2: movq (sprc=%rax -movq (%rdi,%r8,8),%rax - -# qhasm: sprc <<= 5 -# asm 1: shl $5,spc=int64#8 -# asm 2: movq (spc=%r10 -movq (%rdi,%r9,8),%r10 - -# qhasm: spc <<= 5 -# asm 1: shl $5,c0=int64#9 -# asm 2: movq 0(c0=%r11 -movq 0(%r10),%r11 - -# qhasm: c1 = *(uint64 *)(spc + 8) -# asm 1: movq 8(c1=int64#10 -# asm 2: movq 8(c1=%r12 -movq 8(%r10),%r12 - -# qhasm: c2 = *(uint64 *)(spc + 16) -# asm 1: movq 16(c2=int64#11 -# asm 2: movq 16(c2=%r13 -movq 16(%r10),%r13 - -# qhasm: c3 = *(uint64 *)(spc + 24) -# asm 1: movq 24(c3=int64#12 -# asm 2: movq 24(c3=%r14 -movq 24(%r10),%r14 - -# qhasm: carry? c0 -= *(uint64 *)(sprc + 0) -# asm 1: subq 0(>= 5 -# asm 1: shr $5,spp=int64#5 -# asm 2: movq (spp=%r8 -movq (%rdi,%rcx,8),%r8 - -# qhasm: *(uint64 *)(hp + pp * 8) = spc -# asm 1: movq pp=int64#4 -# asm 2: mov pp=%rcx -mov %r9,%rcx -# comment:fp stack unchanged by jump - -# qhasm: goto siftdownloop -jmp ._siftdownloop - -# qhasm: siftuploop: -._siftuploop: - -# qhasm: pc = pp -# asm 1: mov pc=int64#2 -# asm 2: mov pc=%rsi -mov %rcx,%rsi - -# qhasm: pp -= 1 -# asm 1: sub $1,>= 1 -# asm 1: shr $1,? pc - 0 -# asm 1: cmp $0, -jbe ._end - -# qhasm: spp = *(uint64 *)(hp + pp * 8) -# asm 1: movq (spp=int64#5 -# asm 2: movq (spp=%r8 -movq (%rdi,%rcx,8),%r8 - -# qhasm: spc = *(uint64 *)(hp + pc * 8) -# asm 1: movq (spc=int64#6 -# asm 2: movq (spc=%r9 -movq (%rdi,%rsi,8),%r9 - -# qhasm: spp <<= 5 -# asm 1: shl $5,c0=int64#7 -# asm 2: movq 0(c0=%rax -movq 0(%r9),%rax - -# qhasm: c1 = *(uint64 *)(spc + 8) -# asm 1: movq 8(c1=int64#8 -# asm 2: movq 8(c1=%r10 -movq 8(%r9),%r10 - -# qhasm: c2 = *(uint64 *)(spc + 16) -# asm 1: movq 16(c2=int64#9 -# asm 2: movq 16(c2=%r11 -movq 16(%r9),%r11 - -# qhasm: c3 = *(uint64 *)(spc + 24) -# asm 1: movq 24(c3=int64#10 -# asm 2: movq 24(c3=%r12 -movq 24(%r9),%r12 - -# qhasm: carry? c0 -= *(uint64 *)(spp + 0) -# asm 1: subq 0(>= 5 -# asm 1: shr $5,>= 5 -# asm 1: shr $5,caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/heap_rootreplaced_1limb.s b/ext/ed25519-amd64-asm/heap_rootreplaced_1limb.s deleted file mode 100644 index 488e9c52d..000000000 --- a/ext/ed25519-amd64-asm/heap_rootreplaced_1limb.s +++ /dev/null @@ -1,416 +0,0 @@ - -# qhasm: int64 hp - -# qhasm: int64 hlen - -# qhasm: int64 sp - -# qhasm: int64 pp - -# qhasm: input hp - -# qhasm: input hlen - -# qhasm: input sp - -# qhasm: int64 prc - -# qhasm: int64 plc - -# qhasm: int64 pc - -# qhasm: int64 d - -# qhasm: int64 spp - -# qhasm: int64 sprc - -# qhasm: int64 spc - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: int64 t0 - -# qhasm: int64 t1 - -# qhasm: int64 t2 - -# qhasm: int64 t3 - -# qhasm: int64 p0 - -# qhasm: int64 p1 - -# qhasm: int64 p2 - -# qhasm: int64 p3 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb -.globl crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb -_crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb: -crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: pp = 0 -# asm 1: mov $0,>pp=int64#4 -# asm 2: mov $0,>pp=%rcx -mov $0,%rcx - -# qhasm: siftdownloop: -._siftdownloop: - -# qhasm: prc = pp -# asm 1: mov prc=int64#5 -# asm 2: mov prc=%r8 -mov %rcx,%r8 - -# qhasm: prc *= 2 -# asm 1: imulq $2,prc=int64#5 -# asm 2: imulq $2,prc=%r8 -imulq $2,%r8,%r8 - -# qhasm: pc = prc -# asm 1: mov pc=int64#6 -# asm 2: mov pc=%r9 -mov %r8,%r9 - -# qhasm: prc += 2 -# asm 1: add $2,? hlen - prc -# asm 1: cmp -jbe ._siftuploop - -# qhasm: sprc = *(uint64 *)(hp + prc * 8) -# asm 1: movq (sprc=int64#7 -# asm 2: movq (sprc=%rax -movq (%rdi,%r8,8),%rax - -# qhasm: sprc <<= 5 -# asm 1: shl $5,spc=int64#8 -# asm 2: movq (spc=%r10 -movq (%rdi,%r9,8),%r10 - -# qhasm: spc <<= 5 -# asm 1: shl $5,c0=int64#9 -# asm 2: movq 0(c0=%r11 -movq 0(%r10),%r11 - -# qhasm: carry? c0 -= *(uint64 *)(sprc + 0) -# asm 1: subq 0(>= 5 -# asm 1: shr $5,spp=int64#5 -# asm 2: movq (spp=%r8 -movq (%rdi,%rcx,8),%r8 - -# qhasm: *(uint64 *)(hp + pp * 8) = spc -# asm 1: movq pp=int64#4 -# asm 2: mov pp=%rcx -mov %r9,%rcx -# comment:fp stack unchanged by jump - -# qhasm: goto siftdownloop -jmp ._siftdownloop - -# qhasm: siftuploop: -._siftuploop: - -# qhasm: pc = pp -# asm 1: mov pc=int64#2 -# asm 2: mov pc=%rsi -mov %rcx,%rsi - -# qhasm: pp -= 1 -# asm 1: sub $1,>= 1 -# asm 1: shr $1,? pc - 0 -# asm 1: cmp $0, -jbe ._end - -# qhasm: spp = *(uint64 *)(hp + pp * 8) -# asm 1: movq (spp=int64#5 -# asm 2: movq (spp=%r8 -movq (%rdi,%rcx,8),%r8 - -# qhasm: spc = *(uint64 *)(hp + pc * 8) -# asm 1: movq (spc=int64#6 -# asm 2: movq (spc=%r9 -movq (%rdi,%rsi,8),%r9 - -# qhasm: spp <<= 5 -# asm 1: shl $5,c0=int64#7 -# asm 2: movq 0(c0=%rax -movq 0(%r9),%rax - -# qhasm: carry? c0 -= *(uint64 *)(spp + 0) -# asm 1: subq 0(>= 5 -# asm 1: shr $5,>= 5 -# asm 1: shr $5,caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/heap_rootreplaced_2limbs.s b/ext/ed25519-amd64-asm/heap_rootreplaced_2limbs.s deleted file mode 100644 index f9259184c..000000000 --- a/ext/ed25519-amd64-asm/heap_rootreplaced_2limbs.s +++ /dev/null @@ -1,436 +0,0 @@ - -# qhasm: int64 hp - -# qhasm: int64 hlen - -# qhasm: int64 sp - -# qhasm: int64 pp - -# qhasm: input hp - -# qhasm: input hlen - -# qhasm: input sp - -# qhasm: int64 prc - -# qhasm: int64 plc - -# qhasm: int64 pc - -# qhasm: int64 d - -# qhasm: int64 spp - -# qhasm: int64 sprc - -# qhasm: int64 spc - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: int64 t0 - -# qhasm: int64 t1 - -# qhasm: int64 t2 - -# qhasm: int64 t3 - -# qhasm: int64 p0 - -# qhasm: int64 p1 - -# qhasm: int64 p2 - -# qhasm: int64 p3 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs -.globl crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs -_crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs: -crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: pp = 0 -# asm 1: mov $0,>pp=int64#4 -# asm 2: mov $0,>pp=%rcx -mov $0,%rcx - -# qhasm: siftdownloop: -._siftdownloop: - -# qhasm: prc = pp -# asm 1: mov prc=int64#5 -# asm 2: mov prc=%r8 -mov %rcx,%r8 - -# qhasm: prc *= 2 -# asm 1: imulq $2,prc=int64#5 -# asm 2: imulq $2,prc=%r8 -imulq $2,%r8,%r8 - -# qhasm: pc = prc -# asm 1: mov pc=int64#6 -# asm 2: mov pc=%r9 -mov %r8,%r9 - -# qhasm: prc += 2 -# asm 1: add $2,? hlen - prc -# asm 1: cmp -jbe ._siftuploop - -# qhasm: sprc = *(uint64 *)(hp + prc * 8) -# asm 1: movq (sprc=int64#7 -# asm 2: movq (sprc=%rax -movq (%rdi,%r8,8),%rax - -# qhasm: sprc <<= 5 -# asm 1: shl $5,spc=int64#8 -# asm 2: movq (spc=%r10 -movq (%rdi,%r9,8),%r10 - -# qhasm: spc <<= 5 -# asm 1: shl $5,c0=int64#9 -# asm 2: movq 0(c0=%r11 -movq 0(%r10),%r11 - -# qhasm: c1 = *(uint64 *)(spc + 8) -# asm 1: movq 8(c1=int64#10 -# asm 2: movq 8(c1=%r12 -movq 8(%r10),%r12 - -# qhasm: carry? c0 -= *(uint64 *)(sprc + 0) -# asm 1: subq 0(>= 5 -# asm 1: shr $5,spp=int64#5 -# asm 2: movq (spp=%r8 -movq (%rdi,%rcx,8),%r8 - -# qhasm: *(uint64 *)(hp + pp * 8) = spc -# asm 1: movq pp=int64#4 -# asm 2: mov pp=%rcx -mov %r9,%rcx -# comment:fp stack unchanged by jump - -# qhasm: goto siftdownloop -jmp ._siftdownloop - -# qhasm: siftuploop: -._siftuploop: - -# qhasm: pc = pp -# asm 1: mov pc=int64#2 -# asm 2: mov pc=%rsi -mov %rcx,%rsi - -# qhasm: pp -= 1 -# asm 1: sub $1,>= 1 -# asm 1: shr $1,? pc - 0 -# asm 1: cmp $0, -jbe ._end - -# qhasm: spp = *(uint64 *)(hp + pp * 8) -# asm 1: movq (spp=int64#5 -# asm 2: movq (spp=%r8 -movq (%rdi,%rcx,8),%r8 - -# qhasm: spc = *(uint64 *)(hp + pc * 8) -# asm 1: movq (spc=int64#6 -# asm 2: movq (spc=%r9 -movq (%rdi,%rsi,8),%r9 - -# qhasm: spp <<= 5 -# asm 1: shl $5,c0=int64#7 -# asm 2: movq 0(c0=%rax -movq 0(%r9),%rax - -# qhasm: c1 = *(uint64 *)(spc + 8) -# asm 1: movq 8(c1=int64#8 -# asm 2: movq 8(c1=%r10 -movq 8(%r9),%r10 - -# qhasm: carry? c0 -= *(uint64 *)(spp + 0) -# asm 1: subq 0(>= 5 -# asm 1: shr $5,>= 5 -# asm 1: shr $5,caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/heap_rootreplaced_3limbs.s b/ext/ed25519-amd64-asm/heap_rootreplaced_3limbs.s deleted file mode 100644 index dcf890ea6..000000000 --- a/ext/ed25519-amd64-asm/heap_rootreplaced_3limbs.s +++ /dev/null @@ -1,456 +0,0 @@ - -# qhasm: int64 hp - -# qhasm: int64 hlen - -# qhasm: int64 sp - -# qhasm: int64 pp - -# qhasm: input hp - -# qhasm: input hlen - -# qhasm: input sp - -# qhasm: int64 prc - -# qhasm: int64 plc - -# qhasm: int64 pc - -# qhasm: int64 d - -# qhasm: int64 spp - -# qhasm: int64 sprc - -# qhasm: int64 spc - -# qhasm: int64 c0 - -# qhasm: int64 c1 - -# qhasm: int64 c2 - -# qhasm: int64 c3 - -# qhasm: int64 t0 - -# qhasm: int64 t1 - -# qhasm: int64 t2 - -# qhasm: int64 t3 - -# qhasm: int64 p0 - -# qhasm: int64 p1 - -# qhasm: int64 p2 - -# qhasm: int64 p3 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs -.globl crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs -_crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs: -crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: pp = 0 -# asm 1: mov $0,>pp=int64#4 -# asm 2: mov $0,>pp=%rcx -mov $0,%rcx - -# qhasm: siftdownloop: -._siftdownloop: - -# qhasm: prc = pp -# asm 1: mov prc=int64#5 -# asm 2: mov prc=%r8 -mov %rcx,%r8 - -# qhasm: prc *= 2 -# asm 1: imulq $2,prc=int64#5 -# asm 2: imulq $2,prc=%r8 -imulq $2,%r8,%r8 - -# qhasm: pc = prc -# asm 1: mov pc=int64#6 -# asm 2: mov pc=%r9 -mov %r8,%r9 - -# qhasm: prc += 2 -# asm 1: add $2,? hlen - prc -# asm 1: cmp -jbe ._siftuploop - -# qhasm: sprc = *(uint64 *)(hp + prc * 8) -# asm 1: movq (sprc=int64#7 -# asm 2: movq (sprc=%rax -movq (%rdi,%r8,8),%rax - -# qhasm: sprc <<= 5 -# asm 1: shl $5,spc=int64#8 -# asm 2: movq (spc=%r10 -movq (%rdi,%r9,8),%r10 - -# qhasm: spc <<= 5 -# asm 1: shl $5,c0=int64#9 -# asm 2: movq 0(c0=%r11 -movq 0(%r10),%r11 - -# qhasm: c1 = *(uint64 *)(spc + 8) -# asm 1: movq 8(c1=int64#10 -# asm 2: movq 8(c1=%r12 -movq 8(%r10),%r12 - -# qhasm: c2 = *(uint64 *)(spc + 16) -# asm 1: movq 16(c2=int64#11 -# asm 2: movq 16(c2=%r13 -movq 16(%r10),%r13 - -# qhasm: carry? c0 -= *(uint64 *)(sprc + 0) -# asm 1: subq 0(>= 5 -# asm 1: shr $5,spp=int64#5 -# asm 2: movq (spp=%r8 -movq (%rdi,%rcx,8),%r8 - -# qhasm: *(uint64 *)(hp + pp * 8) = spc -# asm 1: movq pp=int64#4 -# asm 2: mov pp=%rcx -mov %r9,%rcx -# comment:fp stack unchanged by jump - -# qhasm: goto siftdownloop -jmp ._siftdownloop - -# qhasm: siftuploop: -._siftuploop: - -# qhasm: pc = pp -# asm 1: mov pc=int64#2 -# asm 2: mov pc=%rsi -mov %rcx,%rsi - -# qhasm: pp -= 1 -# asm 1: sub $1,>= 1 -# asm 1: shr $1,? pc - 0 -# asm 1: cmp $0, -jbe ._end - -# qhasm: spp = *(uint64 *)(hp + pp * 8) -# asm 1: movq (spp=int64#5 -# asm 2: movq (spp=%r8 -movq (%rdi,%rcx,8),%r8 - -# qhasm: spc = *(uint64 *)(hp + pc * 8) -# asm 1: movq (spc=int64#6 -# asm 2: movq (spc=%r9 -movq (%rdi,%rsi,8),%r9 - -# qhasm: spp <<= 5 -# asm 1: shl $5,c0=int64#7 -# asm 2: movq 0(c0=%rax -movq 0(%r9),%rax - -# qhasm: c1 = *(uint64 *)(spc + 8) -# asm 1: movq 8(c1=int64#8 -# asm 2: movq 8(c1=%r10 -movq 8(%r9),%r10 - -# qhasm: c2 = *(uint64 *)(spc + 16) -# asm 1: movq 16(c2=int64#9 -# asm 2: movq 16(c2=%r11 -movq 16(%r9),%r11 - -# qhasm: carry? c0 -= *(uint64 *)(spp + 0) -# asm 1: subq 0(>= 5 -# asm 1: shr $5,>= 5 -# asm 1: shr $5,caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/hram.c b/ext/ed25519-amd64-asm/hram.c deleted file mode 100644 index 6f99fc62c..000000000 --- a/ext/ed25519-amd64-asm/hram.c +++ /dev/null @@ -1,16 +0,0 @@ -/*#include "crypto_hash_sha512.h"*/ -#include "hram.h" - -extern void ZT_sha512internal(void *digest,const void *data,unsigned int len); - -void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) -{ - unsigned long long i; - - for (i = 0;i < 32;++i) playground[i] = sm[i]; - for (i = 32;i < 64;++i) playground[i] = pk[i-32]; - for (i = 64;i < smlen;++i) playground[i] = sm[i]; - - /*crypto_hash_sha512(hram,playground,smlen);*/ - ZT_sha512internal(hram,playground,smlen); -} diff --git a/ext/ed25519-amd64-asm/hram.h b/ext/ed25519-amd64-asm/hram.h deleted file mode 100644 index 1740c78a4..000000000 --- a/ext/ed25519-amd64-asm/hram.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef HRAM_H -#define HRAM_H - -#define get_hram crypto_sign_ed25519_amd64_64_get_hram - -extern void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen); - -#endif diff --git a/ext/ed25519-amd64-asm/implementors b/ext/ed25519-amd64-asm/implementors deleted file mode 100644 index 9b5399a38..000000000 --- a/ext/ed25519-amd64-asm/implementors +++ /dev/null @@ -1,5 +0,0 @@ -Daniel J. Bernstein -Niels Duif -Tanja Lange -lead: Peter Schwabe -Bo-Yin Yang diff --git a/ext/ed25519-amd64-asm/index_heap.c b/ext/ed25519-amd64-asm/index_heap.c deleted file mode 100644 index f29f7a289..000000000 --- a/ext/ed25519-amd64-asm/index_heap.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "sc25519.h" -#include "index_heap.h" - -/* caller's responsibility to ensure hlen>=3 */ -void heap_init(unsigned long long *h, unsigned long long hlen, sc25519 *scalars) -{ - h[0] = 0; - unsigned long long i=1; - while(i 0) - { - /* if(sc25519_lt_vartime(&scalars[h[ppos]], &scalars[h[pos]])) */ - if(sc25519_lt(&scalars[h[ppos]], &scalars[h[pos]])) - { - t = h[ppos]; - h[ppos] = h[pos]; - h[pos] = t; - pos = ppos; - ppos = (pos-1)/2; - } - else break; - } - (*hlen)++; -} - -/* Put the largest value in the heap in max1, the second largest in max2 */ -void heap_get2max(unsigned long long *h, unsigned long long *max1, unsigned long long *max2, sc25519 *scalars) -{ - *max1 = h[0]; - *max2 = h[1]; - if(sc25519_lt(&scalars[h[1]],&scalars[h[2]])) - *max2 = h[2]; -} - -/* After the root has been replaced, restore heap property */ -/* extern void heap_rootreplaced(unsigned long long *h, unsigned long long hlen, sc25519 *scalars); -*/ -/* extern void heap_rootreplaced_shortscalars(unsigned long long *h, unsigned long long hlen, sc25519 *scalars); -*/ diff --git a/ext/ed25519-amd64-asm/index_heap.h b/ext/ed25519-amd64-asm/index_heap.h deleted file mode 100644 index 7dee91613..000000000 --- a/ext/ed25519-amd64-asm/index_heap.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef INDEX_HEAP_H -#define INDEX_HEAP_H - -#include "sc25519.h" - -#define heap_init crypto_sign_ed25519_amd64_64_heap_init -#define heap_extend crypto_sign_ed25519_amd64_64_heap_extend -#define heap_pop crypto_sign_ed25519_amd64_64_heap_pop -#define heap_push crypto_sign_ed25519_amd64_64_heap_push -#define heap_get2max crypto_sign_ed25519_amd64_64_heap_get2max -#define heap_rootreplaced crypto_sign_ed25519_amd64_64_heap_rootreplaced -#define heap_rootreplaced_3limbs crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs -#define heap_rootreplaced_2limbs crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs -#define heap_rootreplaced_1limb crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb - -void heap_init(unsigned long long *h, unsigned long long hlen, sc25519 *scalars); - -void heap_extend(unsigned long long *h, unsigned long long oldlen, unsigned long long newlen, sc25519 *scalars); - -unsigned long long heap_pop(unsigned long long *h, unsigned long long *hlen, sc25519 *scalars); - -void heap_push(unsigned long long *h, unsigned long long *hlen, unsigned long long elem, sc25519 *scalars); - -void heap_get2max(unsigned long long *h, unsigned long long *max1, unsigned long long *max2, sc25519 *scalars); - -void heap_rootreplaced(unsigned long long *h, unsigned long long hlen, sc25519 *scalars); -void heap_rootreplaced_3limbs(unsigned long long *h, unsigned long long hlen, sc25519 *scalars); -void heap_rootreplaced_2limbs(unsigned long long *h, unsigned long long hlen, sc25519 *scalars); -void heap_rootreplaced_1limb(unsigned long long *h, unsigned long long hlen, sc25519 *scalars); - -#endif diff --git a/ext/ed25519-amd64-asm/keypair.c b/ext/ed25519-amd64-asm/keypair.c deleted file mode 100644 index 7e0947104..000000000 --- a/ext/ed25519-amd64-asm/keypair.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include "crypto_sign.h" -#include "crypto_hash_sha512.h" -#include "randombytes.h" -#include "ge25519.h" - -int crypto_sign_keypair(unsigned char *pk,unsigned char *sk) -{ - unsigned char az[64]; - sc25519 scsk; - ge25519 gepk; - - randombytes(sk,32); - crypto_hash_sha512(az,sk,32); - az[0] &= 248; - az[31] &= 127; - az[31] |= 64; - - sc25519_from32bytes(&scsk,az); - - ge25519_scalarmult_base(&gepk, &scsk); - ge25519_pack(pk, &gepk); - memmove(sk + 32,pk,32); - return 0; -} diff --git a/ext/ed25519-amd64-asm/open.c b/ext/ed25519-amd64-asm/open.c deleted file mode 100644 index 104d48dc8..000000000 --- a/ext/ed25519-amd64-asm/open.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include "crypto_sign.h" -#include "crypto_verify_32.h" -#include "crypto_hash_sha512.h" -#include "ge25519.h" - -int crypto_sign_open( - unsigned char *m,unsigned long long *mlen, - const unsigned char *sm,unsigned long long smlen, - const unsigned char *pk - ) -{ - unsigned char pkcopy[32]; - unsigned char rcopy[32]; - unsigned char hram[64]; - unsigned char rcheck[32]; - ge25519 get1, get2; - sc25519 schram, scs; - - if (smlen < 64) goto badsig; - if (sm[63] & 224) goto badsig; - if (ge25519_unpackneg_vartime(&get1,pk)) goto badsig; - - memmove(pkcopy,pk,32); - memmove(rcopy,sm,32); - - sc25519_from32bytes(&scs, sm+32); - - memmove(m,sm,smlen); - memmove(m + 32,pkcopy,32); - crypto_hash_sha512(hram,m,smlen); - - sc25519_from64bytes(&schram, hram); - - ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &scs); - ge25519_pack(rcheck, &get2); - - if (crypto_verify_32(rcopy,rcheck) == 0) { - memmove(m,m + 64,smlen - 64); - memset(m + smlen - 64,0,64); - *mlen = smlen - 64; - return 0; - } - -badsig: - *mlen = (unsigned long long) -1; - memset(m,0,smlen); - return -1; -} diff --git a/ext/ed25519-amd64-asm/sc25519.h b/ext/ed25519-amd64-asm/sc25519.h deleted file mode 100644 index 8ff1b1cad..000000000 --- a/ext/ed25519-amd64-asm/sc25519.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef SC25519_H -#define SC25519_H - -#define sc25519 crypto_sign_ed25519_amd64_64_sc25519 -#define shortsc25519 crypto_sign_ed25519_amd64_64_shortsc25519 -#define sc25519_from32bytes crypto_sign_ed25519_amd64_64_sc25519_from32bytes -#define shortsc25519_from16bytes crypto_sign_ed25519_amd64_64_shortsc25519_from16bytes -#define sc25519_from64bytes crypto_sign_ed25519_amd64_64_sc25519_from64bytes -#define sc25519_from_shortsc crypto_sign_ed25519_amd64_64_sc25519_from_shortsc -#define sc25519_to32bytes crypto_sign_ed25519_amd64_64_sc25519_to32bytes -#define sc25519_iszero_vartime crypto_sign_ed25519_amd64_64_sc25519_iszero_vartime -#define sc25519_isshort_vartime crypto_sign_ed25519_amd64_64_sc25519_isshort_vartime -#define sc25519_lt crypto_sign_ed25519_amd64_64_sc25519_lt -#define sc25519_add crypto_sign_ed25519_amd64_64_sc25519_add -#define sc25519_sub_nored crypto_sign_ed25519_amd64_64_sc25519_sub_nored -#define sc25519_mul crypto_sign_ed25519_amd64_64_sc25519_mul -#define sc25519_mul_shortsc crypto_sign_ed25519_amd64_64_sc25519_mul_shortsc -#define sc25519_window4 crypto_sign_ed25519_amd64_64_sc25519_window4 -#define sc25519_slide crypto_sign_ed25519_amd64_64_sc25519_slide -#define sc25519_2interleave2 crypto_sign_ed25519_amd64_64_sc25519_2interleave2 -#define sc25519_barrett crypto_sign_ed25519_amd64_64_sc25519_barrett - -typedef struct -{ - unsigned long long v[4]; -} -sc25519; - -typedef struct -{ - unsigned long long v[2]; -} -shortsc25519; - -void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]); - -void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]); - -void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x); - -void sc25519_to32bytes(unsigned char r[32], const sc25519 *x); - -int sc25519_iszero_vartime(const sc25519 *x); - -int sc25519_lt(const sc25519 *x, const sc25519 *y); - -void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y); - -void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y); - -void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y); - -void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y); - -/* Convert s into a representation of the form \sum_{i=0}^{63}r[i]2^(4*i) - * with r[i] in {-8,...,7} - */ -void sc25519_window4(signed char r[85], const sc25519 *s); - -void sc25519_slide(signed char r[256], const sc25519 *s, int swindowsize); - -void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2); - -void sc25519_barrett(sc25519 *r, unsigned long long x[8]); - -#endif diff --git a/ext/ed25519-amd64-asm/sc25519_add.s b/ext/ed25519-amd64-asm/sc25519_add.s deleted file mode 100644 index d5b941cd6..000000000 --- a/ext/ed25519-amd64-asm/sc25519_add.s +++ /dev/null @@ -1,232 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 xp - -# qhasm: int64 yp - -# qhasm: input rp - -# qhasm: input xp - -# qhasm: input yp - -# qhasm: int64 r0 - -# qhasm: int64 r1 - -# qhasm: int64 r2 - -# qhasm: int64 r3 - -# qhasm: int64 t0 - -# qhasm: int64 t1 - -# qhasm: int64 t2 - -# qhasm: int64 t3 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_sc25519_add -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_sc25519_add -.globl crypto_sign_ed25519_amd64_64_sc25519_add -_crypto_sign_ed25519_amd64_64_sc25519_add: -crypto_sign_ed25519_amd64_64_sc25519_add: -mov %rsp,%r11 -and $31,%r11 -add $32,%r11 -sub %r11,%rsp - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#1 -# asm 2: movq caller4_stack=0(%rsp) -movq %r14,0(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#2 -# asm 2: movq caller5_stack=8(%rsp) -movq %r15,8(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#3 -# asm 2: movq caller6_stack=16(%rsp) -movq %rbx,16(%rsp) - -# qhasm: r0 = *(uint64 *)(xp + 0) -# asm 1: movq 0(r0=int64#4 -# asm 2: movq 0(r0=%rcx -movq 0(%rsi),%rcx - -# qhasm: r1 = *(uint64 *)(xp + 8) -# asm 1: movq 8(r1=int64#5 -# asm 2: movq 8(r1=%r8 -movq 8(%rsi),%r8 - -# qhasm: r2 = *(uint64 *)(xp + 16) -# asm 1: movq 16(r2=int64#6 -# asm 2: movq 16(r2=%r9 -movq 16(%rsi),%r9 - -# qhasm: r3 = *(uint64 *)(xp + 24) -# asm 1: movq 24(r3=int64#2 -# asm 2: movq 24(r3=%rsi -movq 24(%rsi),%rsi - -# qhasm: carry? r0 += *(uint64 *)(yp + 0) -# asm 1: addq 0(t0=int64#3 -# asm 2: mov t0=%rdx -mov %rcx,%rdx - -# qhasm: t1 = r1 -# asm 1: mov t1=int64#7 -# asm 2: mov t1=%rax -mov %r8,%rax - -# qhasm: t2 = r2 -# asm 1: mov t2=int64#8 -# asm 2: mov t2=%r10 -mov %r9,%r10 - -# qhasm: t3 = r3 -# asm 1: mov t3=int64#12 -# asm 2: mov t3=%r14 -mov %rsi,%r14 - -# qhasm: carry? t0 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0 -# asm 1: sub crypto_sign_ed25519_amd64_64_ORDER0,caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 0(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 8(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 16(%rsp),%rbx - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/sc25519_barrett.s b/ext/ed25519-amd64-asm/sc25519_barrett.s deleted file mode 100644 index 7eb56fadc..000000000 --- a/ext/ed25519-amd64-asm/sc25519_barrett.s +++ /dev/null @@ -1,1188 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 xp - -# qhasm: input rp - -# qhasm: input xp - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: int64 q23 - -# qhasm: int64 q24 - -# qhasm: int64 q30 - -# qhasm: int64 q31 - -# qhasm: int64 q32 - -# qhasm: int64 q33 - -# qhasm: int64 r20 - -# qhasm: int64 r21 - -# qhasm: int64 r22 - -# qhasm: int64 r23 - -# qhasm: int64 r24 - -# qhasm: int64 r0 - -# qhasm: int64 r1 - -# qhasm: int64 r2 - -# qhasm: int64 r3 - -# qhasm: int64 t0 - -# qhasm: int64 t1 - -# qhasm: int64 t2 - -# qhasm: int64 t3 - -# qhasm: int64 rax - -# qhasm: int64 rdx - -# qhasm: int64 c - -# qhasm: int64 zero - -# qhasm: int64 mask - -# qhasm: int64 nmask - -# qhasm: stack64 q30_stack - -# qhasm: stack64 q31_stack - -# qhasm: stack64 q32_stack - -# qhasm: stack64 q33_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_sc25519_barrett -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_sc25519_barrett -.globl crypto_sign_ed25519_amd64_64_sc25519_barrett -_crypto_sign_ed25519_amd64_64_sc25519_barrett: -crypto_sign_ed25519_amd64_64_sc25519_barrett: -mov %rsp,%r11 -and $31,%r11 -add $96,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: zero ^= zero -# asm 1: xor rax=int64#7 -# asm 2: movq 24(rax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3 -mulq crypto_sign_ed25519_amd64_64_MU3(%rip) - -# qhasm: q23 = rax -# asm 1: mov q23=int64#10 -# asm 2: mov q23=%r12 -mov %rax,%r12 - -# qhasm: c = rdx -# asm 1: mov c=int64#11 -# asm 2: mov c=%r13 -mov %rdx,%r13 - -# qhasm: rax = *(uint64 *)(xp + 24) -# asm 1: movq 24(rax=int64#7 -# asm 2: movq 24(rax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4 -mulq crypto_sign_ed25519_amd64_64_MU4(%rip) - -# qhasm: q24 = rax -# asm 1: mov q24=int64#12 -# asm 2: mov q24=%r14 -mov %rax,%r14 - -# qhasm: carry? q24 += c -# asm 1: add rax=int64#7 -# asm 2: movq 32(rax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU2 -mulq crypto_sign_ed25519_amd64_64_MU2(%rip) - -# qhasm: carry? q23 += rax -# asm 1: add c=int64#11 -# asm 2: mov $0,>c=%r13 -mov $0,%r13 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 32(rax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3 -mulq crypto_sign_ed25519_amd64_64_MU3(%rip) - -# qhasm: carry? q24 += rax -# asm 1: add c=int64#11 -# asm 2: mov $0,>c=%r13 -mov $0,%r13 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 32(rax=%rax -movq 32(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4 -mulq crypto_sign_ed25519_amd64_64_MU4(%rip) - -# qhasm: carry? q30 += rax -# asm 1: add rax=int64#7 -# asm 2: movq 40(rax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU1 -mulq crypto_sign_ed25519_amd64_64_MU1(%rip) - -# qhasm: carry? q23 += rax -# asm 1: add c=int64#11 -# asm 2: mov $0,>c=%r13 -mov $0,%r13 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 40(rax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU2 -mulq crypto_sign_ed25519_amd64_64_MU2(%rip) - -# qhasm: carry? q24 += rax -# asm 1: add c=int64#11 -# asm 2: mov $0,>c=%r13 -mov $0,%r13 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 40(rax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3 -mulq crypto_sign_ed25519_amd64_64_MU3(%rip) - -# qhasm: carry? q30 += rax -# asm 1: add c=int64#11 -# asm 2: mov $0,>c=%r13 -mov $0,%r13 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 40(rax=%rax -movq 40(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4 -mulq crypto_sign_ed25519_amd64_64_MU4(%rip) - -# qhasm: carry? q31 += rax -# asm 1: add rax=int64#7 -# asm 2: movq 48(rax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU0 -mulq crypto_sign_ed25519_amd64_64_MU0(%rip) - -# qhasm: carry? q23 += rax -# asm 1: add c=int64#10 -# asm 2: mov $0,>c=%r12 -mov $0,%r12 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 48(rax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU1 -mulq crypto_sign_ed25519_amd64_64_MU1(%rip) - -# qhasm: carry? q24 += rax -# asm 1: add c=int64#10 -# asm 2: mov $0,>c=%r12 -mov $0,%r12 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 48(rax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU2 -mulq crypto_sign_ed25519_amd64_64_MU2(%rip) - -# qhasm: carry? q30 += rax -# asm 1: add c=int64#10 -# asm 2: mov $0,>c=%r12 -mov $0,%r12 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 48(rax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3 -mulq crypto_sign_ed25519_amd64_64_MU3(%rip) - -# qhasm: carry? q31 += rax -# asm 1: add c=int64#10 -# asm 2: mov $0,>c=%r12 -mov $0,%r12 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 48(rax=%rax -movq 48(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4 -mulq crypto_sign_ed25519_amd64_64_MU4(%rip) - -# qhasm: carry? q32 += rax -# asm 1: add rax=int64#7 -# asm 2: movq 56(rax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU0 -mulq crypto_sign_ed25519_amd64_64_MU0(%rip) - -# qhasm: carry? q24 += rax -# asm 1: add c=int64#10 -# asm 2: mov $0,>c=%r12 -mov $0,%r12 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 56(rax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU1 -mulq crypto_sign_ed25519_amd64_64_MU1(%rip) - -# qhasm: carry? q30 += rax -# asm 1: add c=int64#10 -# asm 2: mov $0,>c=%r12 -mov $0,%r12 - -# qhasm: c += rdx + carry -# asm 1: adc q30_stack=stack64#8 -# asm 2: movq q30_stack=56(%rsp) -movq %r8,56(%rsp) - -# qhasm: rax = *(uint64 *)(xp + 56) -# asm 1: movq 56(rax=int64#7 -# asm 2: movq 56(rax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU2 -mulq crypto_sign_ed25519_amd64_64_MU2(%rip) - -# qhasm: carry? q31 += rax -# asm 1: add c=int64#5 -# asm 2: mov $0,>c=%r8 -mov $0,%r8 - -# qhasm: c += rdx + carry -# asm 1: adc q31_stack=stack64#9 -# asm 2: movq q31_stack=64(%rsp) -movq %r9,64(%rsp) - -# qhasm: rax = *(uint64 *)(xp + 56) -# asm 1: movq 56(rax=int64#7 -# asm 2: movq 56(rax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3 -mulq crypto_sign_ed25519_amd64_64_MU3(%rip) - -# qhasm: carry? q32 += rax -# asm 1: add c=int64#5 -# asm 2: mov $0,>c=%r8 -mov $0,%r8 - -# qhasm: c += rdx + carry -# asm 1: adc q32_stack=stack64#10 -# asm 2: movq q32_stack=72(%rsp) -movq %r10,72(%rsp) - -# qhasm: rax = *(uint64 *)(xp + 56) -# asm 1: movq 56(rax=int64#7 -# asm 2: movq 56(rax=%rax -movq 56(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4 -mulq crypto_sign_ed25519_amd64_64_MU4(%rip) - -# qhasm: carry? q33 += rax -# asm 1: add q33_stack=stack64#11 -# asm 2: movq q33_stack=80(%rsp) -movq %r11,80(%rsp) - -# qhasm: rax = q30_stack -# asm 1: movq rax=int64#7 -# asm 2: movq rax=%rax -movq 56(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0 -mulq crypto_sign_ed25519_amd64_64_ORDER0(%rip) - -# qhasm: r20 = rax -# asm 1: mov r20=int64#5 -# asm 2: mov r20=%r8 -mov %rax,%r8 - -# qhasm: c = rdx -# asm 1: mov c=int64#6 -# asm 2: mov c=%r9 -mov %rdx,%r9 - -# qhasm: rax = q30_stack -# asm 1: movq rax=int64#7 -# asm 2: movq rax=%rax -movq 56(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1 -mulq crypto_sign_ed25519_amd64_64_ORDER1(%rip) - -# qhasm: r21 = rax -# asm 1: mov r21=int64#8 -# asm 2: mov r21=%r10 -mov %rax,%r10 - -# qhasm: carry? r21 += c -# asm 1: add c=int64#6 -# asm 2: mov $0,>c=%r9 -mov $0,%r9 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq rax=%rax -movq 56(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER2 -mulq crypto_sign_ed25519_amd64_64_ORDER2(%rip) - -# qhasm: r22 = rax -# asm 1: mov r22=int64#9 -# asm 2: mov r22=%r11 -mov %rax,%r11 - -# qhasm: carry? r22 += c -# asm 1: add c=int64#6 -# asm 2: mov $0,>c=%r9 -mov $0,%r9 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq rax=%rax -movq 56(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER3 -mulq crypto_sign_ed25519_amd64_64_ORDER3(%rip) - -# qhasm: free rdx - -# qhasm: r23 = rax -# asm 1: mov r23=int64#10 -# asm 2: mov r23=%r12 -mov %rax,%r12 - -# qhasm: r23 += c -# asm 1: add rax=int64#7 -# asm 2: movq rax=%rax -movq 64(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0 -mulq crypto_sign_ed25519_amd64_64_ORDER0(%rip) - -# qhasm: carry? r21 += rax -# asm 1: add c=int64#6 -# asm 2: mov $0,>c=%r9 -mov $0,%r9 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq rax=%rax -movq 64(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1 -mulq crypto_sign_ed25519_amd64_64_ORDER1(%rip) - -# qhasm: carry? r22 += rax -# asm 1: add c=int64#4 -# asm 2: mov $0,>c=%rcx -mov $0,%rcx - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq rax=%rax -movq 64(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER2 -mulq crypto_sign_ed25519_amd64_64_ORDER2(%rip) - -# qhasm: free rdx - -# qhasm: r23 += rax -# asm 1: add rax=int64#7 -# asm 2: movq rax=%rax -movq 72(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0 -mulq crypto_sign_ed25519_amd64_64_ORDER0(%rip) - -# qhasm: carry? r22 += rax -# asm 1: add c=int64#4 -# asm 2: mov $0,>c=%rcx -mov $0,%rcx - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq rax=%rax -movq 72(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1 -mulq crypto_sign_ed25519_amd64_64_ORDER1(%rip) - -# qhasm: free rdx - -# qhasm: r23 += rax -# asm 1: add rax=int64#7 -# asm 2: movq rax=%rax -movq 80(%rsp),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0 -mulq crypto_sign_ed25519_amd64_64_ORDER0(%rip) - -# qhasm: free rdx - -# qhasm: r23 += rax -# asm 1: add r0=int64#3 -# asm 2: movq 0(r0=%rdx -movq 0(%rsi),%rdx - -# qhasm: carry? r0 -= r20 -# asm 1: sub t0=int64#4 -# asm 2: mov t0=%rcx -mov %rdx,%rcx - -# qhasm: r1 = *(uint64 *)(xp + 8) -# asm 1: movq 8(r1=int64#5 -# asm 2: movq 8(r1=%r8 -movq 8(%rsi),%r8 - -# qhasm: carry? r1 -= r21 - carry -# asm 1: sbb t1=int64#6 -# asm 2: mov t1=%r9 -mov %r8,%r9 - -# qhasm: r2 = *(uint64 *)(xp + 16) -# asm 1: movq 16(r2=int64#7 -# asm 2: movq 16(r2=%rax -movq 16(%rsi),%rax - -# qhasm: carry? r2 -= r22 - carry -# asm 1: sbb t2=int64#8 -# asm 2: mov t2=%r10 -mov %rax,%r10 - -# qhasm: r3 = *(uint64 *)(xp + 24) -# asm 1: movq 24(r3=int64#2 -# asm 2: movq 24(r3=%rsi -movq 24(%rsi),%rsi - -# qhasm: r3 -= r23 - carry -# asm 1: sbb t3=int64#9 -# asm 2: mov t3=%r11 -mov %rsi,%r11 - -# qhasm: carry? t0 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0 -# asm 1: sub crypto_sign_ed25519_amd64_64_ORDER0,t0=int64#4 -# asm 2: mov t0=%rcx -mov %rdx,%rcx - -# qhasm: r1 = t1 if !unsigned< -# asm 1: cmovae t1=int64#6 -# asm 2: mov t1=%r9 -mov %r8,%r9 - -# qhasm: r2 = t2 if !unsigned< -# asm 1: cmovae t2=int64#8 -# asm 2: mov t2=%r10 -mov %rax,%r10 - -# qhasm: r3 = t3 if !unsigned< -# asm 1: cmovae t3=int64#9 -# asm 2: mov t3=%r11 -mov %rsi,%r11 - -# qhasm: carry? t0 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0 -# asm 1: sub crypto_sign_ed25519_amd64_64_ORDER0,caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/ed25519-amd64-asm/sc25519_from32bytes.c b/ext/ed25519-amd64-asm/sc25519_from32bytes.c deleted file mode 100644 index 7f21e6868..000000000 --- a/ext/ed25519-amd64-asm/sc25519_from32bytes.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "sc25519.h" - -/*Arithmetic modulo the group order n = 2^252 + 27742317777372353535851937790883648493 - * = 7237005577332262213973186563042994240857116359379907606001950938285454250989 - */ - -/* Contains order, 2*order, 4*order, 8*order, each represented in 4 consecutive unsigned long long */ -static const unsigned long long order[16] = {0x5812631A5CF5D3EDULL, 0x14DEF9DEA2F79CD6ULL, - 0x0000000000000000ULL, 0x1000000000000000ULL, - 0xB024C634B9EBA7DAULL, 0x29BDF3BD45EF39ACULL, - 0x0000000000000000ULL, 0x2000000000000000ULL, - 0x60498C6973D74FB4ULL, 0x537BE77A8BDE7359ULL, - 0x0000000000000000ULL, 0x4000000000000000ULL, - 0xC09318D2E7AE9F68ULL, 0xA6F7CEF517BCE6B2ULL, - 0x0000000000000000ULL, 0x8000000000000000ULL}; - -static unsigned long long smaller(unsigned long long a,unsigned long long b) -{ - unsigned long long atop = a >> 32; - unsigned long long abot = a & 4294967295; - unsigned long long btop = b >> 32; - unsigned long long bbot = b & 4294967295; - unsigned long long atopbelowbtop = (atop - btop) >> 63; - unsigned long long atopeqbtop = ((atop ^ btop) - 1) >> 63; - unsigned long long abotbelowbbot = (abot - bbot) >> 63; - return atopbelowbtop | (atopeqbtop & abotbelowbbot); -} - -void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) -{ - unsigned long long t[4]; - unsigned long long b; - unsigned long long mask; - int i, j; - - /* assuming little-endian */ - r->v[0] = *(unsigned long long *)x; - r->v[1] = *(((unsigned long long *)x)+1); - r->v[2] = *(((unsigned long long *)x)+2); - r->v[3] = *(((unsigned long long *)x)+3); - - for(j=3;j>=0;j--) - { - b=0; - for(i=0;i<4;i++) - { - b += order[4*j+i]; /* no overflow for this particular order */ - t[i] = r->v[i] - b; - b = smaller(r->v[i],b); - } - mask = b - 1; - for(i=0;i<4;i++) - r->v[i] ^= mask & (r->v[i] ^ t[i]); - } -} diff --git a/ext/ed25519-amd64-asm/sc25519_from64bytes.c b/ext/ed25519-amd64-asm/sc25519_from64bytes.c deleted file mode 100644 index 8e76a1b36..000000000 --- a/ext/ed25519-amd64-asm/sc25519_from64bytes.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "sc25519.h" - -void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) -{ - /* assuming little-endian representation of unsigned long long */ - sc25519_barrett(r, (unsigned long long *)x); -} diff --git a/ext/ed25519-amd64-asm/sc25519_from_shortsc.c b/ext/ed25519-amd64-asm/sc25519_from_shortsc.c deleted file mode 100644 index 3b8ff2fbd..000000000 --- a/ext/ed25519-amd64-asm/sc25519_from_shortsc.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "sc25519.h" - -void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x) -{ - r->v[0] = x->v[0]; - r->v[1] = x->v[1]; - r->v[2] = 0; - r->v[3] = 0; -} diff --git a/ext/ed25519-amd64-asm/sc25519_iszero.c b/ext/ed25519-amd64-asm/sc25519_iszero.c deleted file mode 100644 index 21f593d77..000000000 --- a/ext/ed25519-amd64-asm/sc25519_iszero.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "sc25519.h" - -int sc25519_iszero_vartime(const sc25519 *x) -{ - if(x->v[0] != 0) return 0; - if(x->v[1] != 0) return 0; - if(x->v[2] != 0) return 0; - if(x->v[3] != 0) return 0; - return 1; -} diff --git a/ext/ed25519-amd64-asm/sc25519_lt.s b/ext/ed25519-amd64-asm/sc25519_lt.s deleted file mode 100644 index 3ba431782..000000000 --- a/ext/ed25519-amd64-asm/sc25519_lt.s +++ /dev/null @@ -1,131 +0,0 @@ - -# qhasm: int64 xp - -# qhasm: int64 yp - -# qhasm: int64 ret - -# qhasm: input xp - -# qhasm: input yp - -# qhasm: output ret - -# qhasm: int64 t0 - -# qhasm: int64 t1 - -# qhasm: int64 t2 - -# qhasm: int64 t3 - -# qhasm: int64 doof - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_sc25519_lt -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_sc25519_lt -.globl crypto_sign_ed25519_amd64_64_sc25519_lt -_crypto_sign_ed25519_amd64_64_sc25519_lt: -crypto_sign_ed25519_amd64_64_sc25519_lt: -mov %rsp,%r11 -and $31,%r11 -add $0,%r11 -sub %r11,%rsp - -# qhasm: t0 = *(uint64 *)(xp + 0) -# asm 1: movq 0(t0=int64#3 -# asm 2: movq 0(t0=%rdx -movq 0(%rdi),%rdx - -# qhasm: t1 = *(uint64 *)(xp + 8) -# asm 1: movq 8(t1=int64#4 -# asm 2: movq 8(t1=%rcx -movq 8(%rdi),%rcx - -# qhasm: t2 = *(uint64 *)(xp + 16) -# asm 1: movq 16(t2=int64#5 -# asm 2: movq 16(t2=%r8 -movq 16(%rdi),%r8 - -# qhasm: t3 = *(uint64 *)(xp + 24) -# asm 1: movq 24(t3=int64#1 -# asm 2: movq 24(t3=%rdi -movq 24(%rdi),%rdi - -# qhasm: carry? t0 -= *(uint64 *)(yp + 0) -# asm 1: subq 0(ret=int64#1 -# asm 2: mov $0,>ret=%rdi -mov $0,%rdi - -# qhasm: doof = 1 -# asm 1: mov $1,>doof=int64#2 -# asm 2: mov $1,>doof=%rsi -mov $1,%rsi - -# qhasm: ret = doof if carry -# asm 1: cmovc v, y->v); - sc25519_barrett(r, t); -} diff --git a/ext/ed25519-amd64-asm/sc25519_mul_shortsc.c b/ext/ed25519-amd64-asm/sc25519_mul_shortsc.c deleted file mode 100644 index 0c67250d7..000000000 --- a/ext/ed25519-amd64-asm/sc25519_mul_shortsc.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "sc25519.h" - -void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y) -{ - /* XXX: This wants to be faster */ - sc25519 t; - sc25519_from_shortsc(&t, y); - sc25519_mul(r, x, &t); -} diff --git a/ext/ed25519-amd64-asm/sc25519_slide.c b/ext/ed25519-amd64-asm/sc25519_slide.c deleted file mode 100644 index 4e52010d5..000000000 --- a/ext/ed25519-amd64-asm/sc25519_slide.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "sc25519.h" - -void sc25519_slide(signed char r[256], const sc25519 *s, int swindowsize) -{ - int i,j,k,b,m=(1<<(swindowsize-1))-1, soplen=256; - unsigned long long sv0 = s->v[0]; - unsigned long long sv1 = s->v[1]; - unsigned long long sv2 = s->v[2]; - unsigned long long sv3 = s->v[3]; - - /* first put the binary expansion into r */ - for(i=0;i<64;i++) { - r[i] = sv0 & 1; - r[i+64] = sv1 & 1; - r[i+128] = sv2 & 1; - r[i+192] = sv3 & 1; - sv0 >>= 1; - sv1 >>= 1; - sv2 >>= 1; - sv3 >>= 1; - } - - /* Making it sliding window */ - for (j = 0;j < soplen;++j) - { - if (r[j]) { - for (b = 1;b < soplen - j && b <= 6;++b) { - if (r[j] + (r[j + b] << b) <= m) - { - r[j] += r[j + b] << b; r[j + b] = 0; - } - else if (r[j] - (r[j + b] << b) >= -m) - { - r[j] -= r[j + b] << b; - for (k = j + b;k < soplen;++k) - { - if (!r[k]) { - r[k] = 1; - break; - } - r[k] = 0; - } - } - else if (r[j + b]) - break; - } - } - } -} diff --git a/ext/ed25519-amd64-asm/sc25519_sub_nored.s b/ext/ed25519-amd64-asm/sc25519_sub_nored.s deleted file mode 100644 index a347e7d44..000000000 --- a/ext/ed25519-amd64-asm/sc25519_sub_nored.s +++ /dev/null @@ -1,142 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 xp - -# qhasm: int64 yp - -# qhasm: input rp - -# qhasm: input xp - -# qhasm: input yp - -# qhasm: int64 r0 - -# qhasm: int64 r1 - -# qhasm: int64 r2 - -# qhasm: int64 r3 - -# qhasm: int64 t0 - -# qhasm: int64 t1 - -# qhasm: int64 t2 - -# qhasm: int64 t3 - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_sc25519_sub_nored -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_sc25519_sub_nored -.globl crypto_sign_ed25519_amd64_64_sc25519_sub_nored -_crypto_sign_ed25519_amd64_64_sc25519_sub_nored: -crypto_sign_ed25519_amd64_64_sc25519_sub_nored: -mov %rsp,%r11 -and $31,%r11 -add $0,%r11 -sub %r11,%rsp - -# qhasm: r0 = *(uint64 *)(xp + 0) -# asm 1: movq 0(r0=int64#4 -# asm 2: movq 0(r0=%rcx -movq 0(%rsi),%rcx - -# qhasm: r1 = *(uint64 *)(xp + 8) -# asm 1: movq 8(r1=int64#5 -# asm 2: movq 8(r1=%r8 -movq 8(%rsi),%r8 - -# qhasm: r2 = *(uint64 *)(xp + 16) -# asm 1: movq 16(r2=int64#6 -# asm 2: movq 16(r2=%r9 -movq 16(%rsi),%r9 - -# qhasm: r3 = *(uint64 *)(xp + 24) -# asm 1: movq 24(r3=int64#2 -# asm 2: movq 24(r3=%rsi -movq 24(%rsi),%rsi - -# qhasm: carry? r0 -= *(uint64 *)(yp + 0) -# asm 1: subq 0(v]; -} diff --git a/ext/ed25519-amd64-asm/sc25519_window4.c b/ext/ed25519-amd64-asm/sc25519_window4.c deleted file mode 100644 index 683a1d4b8..000000000 --- a/ext/ed25519-amd64-asm/sc25519_window4.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "sc25519.h" - -void sc25519_window4(signed char r[64], const sc25519 *s) -{ - char carry; - int i; - for(i=0;i<16;i++) - r[i] = (s->v[0] >> (4*i)) & 15; - for(i=0;i<16;i++) - r[i+16] = (s->v[1] >> (4*i)) & 15; - for(i=0;i<16;i++) - r[i+32] = (s->v[2] >> (4*i)) & 15; - for(i=0;i<16;i++) - r[i+48] = (s->v[3] >> (4*i)) & 15; - - /* Making it signed */ - carry = 0; - for(i=0;i<63;i++) - { - r[i] += carry; - r[i+1] += r[i] >> 4; - r[i] &= 15; - carry = r[i] >> 3; - r[i] -= carry << 4; - } - r[63] += carry; -} diff --git a/ext/ed25519-amd64-asm/sign.c b/ext/ed25519-amd64-asm/sign.c deleted file mode 100644 index 715feb5b7..000000000 --- a/ext/ed25519-amd64-asm/sign.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -/*#include "crypto_sign.h" -#include "crypto_hash_sha512.h"*/ -#include "ge25519.h" - -/* Original */ -#if 0 -int crypto_sign( - unsigned char *sm,unsigned long long *smlen, - const unsigned char *m,unsigned long long mlen, - const unsigned char *sk - ) -{ - unsigned char pk[32]; - unsigned char az[64]; - unsigned char nonce[64]; - unsigned char hram[64]; - sc25519 sck, scs, scsk; - ge25519 ger; - - memmove(pk,sk + 32,32); - /* pk: 32-byte public key A */ - - crypto_hash_sha512(az,sk,32); - az[0] &= 248; - az[31] &= 127; - az[31] |= 64; - /* az: 32-byte scalar a, 32-byte randomizer z */ - - *smlen = mlen + 64; - memmove(sm + 64,m,mlen); - memmove(sm + 32,az + 32,32); - /* sm: 32-byte uninit, 32-byte z, mlen-byte m */ - - crypto_hash_sha512(nonce, sm+32, mlen+32); - /* nonce: 64-byte H(z,m) */ - - sc25519_from64bytes(&sck, nonce); - ge25519_scalarmult_base(&ger, &sck); - ge25519_pack(sm, &ger); - /* sm: 32-byte R, 32-byte z, mlen-byte m */ - - memmove(sm + 32,pk,32); - /* sm: 32-byte R, 32-byte A, mlen-byte m */ - - crypto_hash_sha512(hram,sm,mlen + 64); - /* hram: 64-byte H(R,A,m) */ - - sc25519_from64bytes(&scs, hram); - sc25519_from32bytes(&scsk, az); - sc25519_mul(&scs, &scs, &scsk); - sc25519_add(&scs, &scs, &sck); - /* scs: S = nonce + H(R,A,m)a */ - - sc25519_to32bytes(sm + 32,&scs); - /* sm: 32-byte R, 32-byte S, mlen-byte m */ - - return 0; -} -#endif - -#if 0 -void ECC::sign(const ECC::Private &myPrivate,const ECC::Public &myPublic,const void *msg,unsigned int len,void *signature) -{ - sc25519 sck, scs, scsk; - ge25519 ger; - unsigned char r[32]; - unsigned char s[32]; - unsigned char extsk[64]; - unsigned char hmg[crypto_hash_sha512_BYTES]; - unsigned char hram[crypto_hash_sha512_BYTES]; - unsigned char *sig = (unsigned char *)signature; - unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg) - - SHA512::hash(digest,msg,len); - - SHA512::hash(extsk,myPrivate.data + 32,32); - extsk[0] &= 248; - extsk[31] &= 127; - extsk[31] |= 64; - - for(unsigned int i=0;i<32;i++) - sig[32 + i] = extsk[32 + i]; - for(unsigned int i=0;i<32;i++) - sig[64 + i] = digest[i]; - - SHA512::hash(hmg,sig + 32,64); - - /* Computation of R */ - sc25519_from64bytes(&sck, hmg); - ge25519_scalarmult_base(&ger, &sck); - ge25519_pack(r, &ger); - - /* Computation of s */ - for(unsigned int i=0;i<32;i++) - sig[i] = r[i]; - - get_hram(hram,sig,myPublic.data + 32,sig,96); - - sc25519_from64bytes(&scs, hram); - sc25519_from32bytes(&scsk, extsk); - sc25519_mul(&scs, &scs, &scsk); - - sc25519_add(&scs, &scs, &sck); - - sc25519_to32bytes(s,&scs); /* cat s */ - for(unsigned int i=0;i<32;i++) - sig[32 + i] = s[i]; -} - -void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) -{ - unsigned long long i; - - for (i = 0;i < 32;++i) playground[i] = sm[i]; - for (i = 32;i < 64;++i) playground[i] = pk[i-32]; - for (i = 64;i < smlen;++i) playground[i] = sm[i]; - - //crypto_hash_sha512(hram,playground,smlen); - ZeroTier::SHA512::hash(hram,playground,(unsigned int)smlen); -} -#endif - -extern void ZT_sha512internal(void *digest,const void *data,unsigned int len); - -extern void ed25519_amd64_asm_sign(const unsigned char *sk,const unsigned char *pk,const unsigned char *digest,unsigned char *sig) -{ - unsigned char az[64]; - unsigned char nonce[64]; - unsigned char hram[64]; - sc25519 sck, scs, scsk; - ge25519 ger; - unsigned int i; - - ZT_sha512internal(az,sk,32); - az[0] &= 248; - az[31] &= 127; - az[31] |= 64; - - for(i=0;i<32;i++) - sig[32 + i] = az[32 + i]; - for(i=0;i<32;i++) - sig[64 + i] = digest[i]; - - ZT_sha512internal(nonce,sig + 32,64); - - sc25519_from64bytes(&sck, nonce); - ge25519_scalarmult_base(&ger, &sck); - ge25519_pack(sig, &ger); - - memmove(sig + 32,pk,32); - - ZT_sha512internal(hram,sig,96); - - sc25519_from64bytes(&scs, hram); - sc25519_from32bytes(&scsk, az); - sc25519_mul(&scs, &scs, &scsk); - sc25519_add(&scs, &scs, &sck); - - sc25519_to32bytes(sig + 32,&scs); -} diff --git a/ext/ed25519-amd64-asm/ull4_mul.s b/ext/ed25519-amd64-asm/ull4_mul.s deleted file mode 100644 index 9f7b4fa26..000000000 --- a/ext/ed25519-amd64-asm/ull4_mul.s +++ /dev/null @@ -1,716 +0,0 @@ - -# qhasm: int64 rp - -# qhasm: int64 xp - -# qhasm: int64 yp - -# qhasm: input rp - -# qhasm: input xp - -# qhasm: input yp - -# qhasm: int64 r0 - -# qhasm: int64 r1 - -# qhasm: int64 r2 - -# qhasm: int64 r3 - -# qhasm: int64 r4 - -# qhasm: int64 r5 - -# qhasm: int64 r6 - -# qhasm: int64 r7 - -# qhasm: int64 c - -# qhasm: int64 zero - -# qhasm: int64 rax - -# qhasm: int64 rdx - -# qhasm: int64 caller1 - -# qhasm: int64 caller2 - -# qhasm: int64 caller3 - -# qhasm: int64 caller4 - -# qhasm: int64 caller5 - -# qhasm: int64 caller6 - -# qhasm: int64 caller7 - -# qhasm: caller caller1 - -# qhasm: caller caller2 - -# qhasm: caller caller3 - -# qhasm: caller caller4 - -# qhasm: caller caller5 - -# qhasm: caller caller6 - -# qhasm: caller caller7 - -# qhasm: stack64 caller1_stack - -# qhasm: stack64 caller2_stack - -# qhasm: stack64 caller3_stack - -# qhasm: stack64 caller4_stack - -# qhasm: stack64 caller5_stack - -# qhasm: stack64 caller6_stack - -# qhasm: stack64 caller7_stack - -# qhasm: enter crypto_sign_ed25519_amd64_64_ull4_mul -.text -.p2align 5 -.globl _crypto_sign_ed25519_amd64_64_ull4_mul -.globl crypto_sign_ed25519_amd64_64_ull4_mul -_crypto_sign_ed25519_amd64_64_ull4_mul: -crypto_sign_ed25519_amd64_64_ull4_mul: -mov %rsp,%r11 -and $31,%r11 -add $64,%r11 -sub %r11,%rsp - -# qhasm: caller1_stack = caller1 -# asm 1: movq caller1_stack=stack64#1 -# asm 2: movq caller1_stack=0(%rsp) -movq %r11,0(%rsp) - -# qhasm: caller2_stack = caller2 -# asm 1: movq caller2_stack=stack64#2 -# asm 2: movq caller2_stack=8(%rsp) -movq %r12,8(%rsp) - -# qhasm: caller3_stack = caller3 -# asm 1: movq caller3_stack=stack64#3 -# asm 2: movq caller3_stack=16(%rsp) -movq %r13,16(%rsp) - -# qhasm: caller4_stack = caller4 -# asm 1: movq caller4_stack=stack64#4 -# asm 2: movq caller4_stack=24(%rsp) -movq %r14,24(%rsp) - -# qhasm: caller5_stack = caller5 -# asm 1: movq caller5_stack=stack64#5 -# asm 2: movq caller5_stack=32(%rsp) -movq %r15,32(%rsp) - -# qhasm: caller6_stack = caller6 -# asm 1: movq caller6_stack=stack64#6 -# asm 2: movq caller6_stack=40(%rsp) -movq %rbx,40(%rsp) - -# qhasm: caller7_stack = caller7 -# asm 1: movq caller7_stack=stack64#7 -# asm 2: movq caller7_stack=48(%rsp) -movq %rbp,48(%rsp) - -# qhasm: yp = yp -# asm 1: mov yp=int64#4 -# asm 2: mov yp=%rcx -mov %rdx,%rcx - -# qhasm: r4 = 0 -# asm 1: mov $0,>r4=int64#5 -# asm 2: mov $0,>r4=%r8 -mov $0,%r8 - -# qhasm: r5 = 0 -# asm 1: mov $0,>r5=int64#6 -# asm 2: mov $0,>r5=%r9 -mov $0,%r9 - -# qhasm: r6 = 0 -# asm 1: mov $0,>r6=int64#8 -# asm 2: mov $0,>r6=%r10 -mov $0,%r10 - -# qhasm: r7 = 0 -# asm 1: mov $0,>r7=int64#9 -# asm 2: mov $0,>r7=%r11 -mov $0,%r11 - -# qhasm: zero = 0 -# asm 1: mov $0,>zero=int64#10 -# asm 2: mov $0,>zero=%r12 -mov $0,%r12 - -# qhasm: rax = *(uint64 *)(xp + 0) -# asm 1: movq 0(rax=int64#7 -# asm 2: movq 0(rax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 0) -# asm 1: mulq 0(r0=int64#11 -# asm 2: mov r0=%r13 -mov %rax,%r13 - -# qhasm: c = rdx -# asm 1: mov c=int64#12 -# asm 2: mov c=%r14 -mov %rdx,%r14 - -# qhasm: rax = *(uint64 *)(xp + 0) -# asm 1: movq 0(rax=int64#7 -# asm 2: movq 0(rax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 8) -# asm 1: mulq 8(r1=int64#13 -# asm 2: mov r1=%r15 -mov %rax,%r15 - -# qhasm: carry? r1 += c -# asm 1: add c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 0(rax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 16) -# asm 1: mulq 16(r2=int64#14 -# asm 2: mov r2=%rbx -mov %rax,%rbx - -# qhasm: carry? r2 += c -# asm 1: add c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 0(rax=%rax -movq 0(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 24) -# asm 1: mulq 24(r3=int64#15 -# asm 2: mov r3=%rbp -mov %rax,%rbp - -# qhasm: carry? r3 += c -# asm 1: add rax=int64#7 -# asm 2: movq 8(rax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 0) -# asm 1: mulq 0(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 8(rax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 8) -# asm 1: mulq 8(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 8(rax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 16) -# asm 1: mulq 16(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 8(rax=%rax -movq 8(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 24) -# asm 1: mulq 24(rax=int64#7 -# asm 2: movq 16(rax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 0) -# asm 1: mulq 0(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 16(rax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 8) -# asm 1: mulq 8(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 16(rax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 16) -# asm 1: mulq 16(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 16(rax=%rax -movq 16(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 24) -# asm 1: mulq 24(rax=int64#7 -# asm 2: movq 24(rax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 0) -# asm 1: mulq 0(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 24(rax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 8) -# asm 1: mulq 8(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 24(rax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 16) -# asm 1: mulq 16(c=int64#12 -# asm 2: mov $0,>c=%r14 -mov $0,%r14 - -# qhasm: c += rdx + carry -# asm 1: adc rax=int64#7 -# asm 2: movq 24(rax=%rax -movq 24(%rsi),%rax - -# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 24) -# asm 1: mulq 24(caller1=int64#9 -# asm 2: movq caller1=%r11 -movq 0(%rsp),%r11 - -# qhasm: caller2 = caller2_stack -# asm 1: movq caller2=int64#10 -# asm 2: movq caller2=%r12 -movq 8(%rsp),%r12 - -# qhasm: caller3 = caller3_stack -# asm 1: movq caller3=int64#11 -# asm 2: movq caller3=%r13 -movq 16(%rsp),%r13 - -# qhasm: caller4 = caller4_stack -# asm 1: movq caller4=int64#12 -# asm 2: movq caller4=%r14 -movq 24(%rsp),%r14 - -# qhasm: caller5 = caller5_stack -# asm 1: movq caller5=int64#13 -# asm 2: movq caller5=%r15 -movq 32(%rsp),%r15 - -# qhasm: caller6 = caller6_stack -# asm 1: movq caller6=int64#14 -# asm 2: movq caller6=%rbx -movq 40(%rsp),%rbx - -# qhasm: caller7 = caller7_stack -# asm 1: movq caller7=int64#15 -# asm 2: movq caller7=%rbp -movq 48(%rsp),%rbp - -# qhasm: leave -add %r11,%rsp -mov %rdi,%rax -mov %rsi,%rdx -ret diff --git a/ext/hiredis-0.14.1/.gitignore b/ext/hiredis-0.14.1/.gitignore deleted file mode 100644 index db2ad032a..000000000 --- a/ext/hiredis-0.14.1/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -/hiredis-test -/examples/hiredis-example* -/*.o -/*.so -/*.dylib -/*.pc diff --git a/ext/hiredis-0.14.1/.travis.yml b/ext/hiredis-0.14.1/.travis.yml deleted file mode 100644 index faf2ce684..000000000 --- a/ext/hiredis-0.14.1/.travis.yml +++ /dev/null @@ -1,45 +0,0 @@ -language: c -sudo: false -compiler: - - gcc - - clang - -os: - - linux - - osx - -branches: - only: - - staging - - trying - - master - -before_script: - - if [ "$TRAVIS_OS_NAME" == "osx" ] ; then brew update; brew install redis; fi - -addons: - apt: - packages: - - libc6-dbg - - libc6-dev - - libc6:i386 - - libc6-dev-i386 - - libc6-dbg:i386 - - gcc-multilib - - valgrind - -env: - - CFLAGS="-Werror" - - PRE="valgrind --track-origins=yes --leak-check=full" - - TARGET="32bit" TARGET_VARS="32bit-vars" CFLAGS="-Werror" - - TARGET="32bit" TARGET_VARS="32bit-vars" PRE="valgrind --track-origins=yes --leak-check=full" - -matrix: - exclude: - - os: osx - env: PRE="valgrind --track-origins=yes --leak-check=full" - - - os: osx - env: TARGET="32bit" TARGET_VARS="32bit-vars" PRE="valgrind --track-origins=yes --leak-check=full" - -script: make $TARGET CFLAGS="$CFLAGS" && make check PRE="$PRE" && make $TARGET_VARS hiredis-example diff --git a/ext/hiredis-0.14.1/CHANGELOG.md b/ext/hiredis-0.14.1/CHANGELOG.md deleted file mode 100644 index f8e577369..000000000 --- a/ext/hiredis-0.14.1/CHANGELOG.md +++ /dev/null @@ -1,190 +0,0 @@ -**NOTE: BREAKING CHANGES upgrading from 0.13.x to 0.14.x **: - -* Bulk and multi-bulk lengths less than -1 or greater than `LLONG_MAX` are now - protocol errors. This is consistent with the RESP specification. On 32-bit - platforms, the upper bound is lowered to `SIZE_MAX`. - -* Change `redisReply.len` to `size_t`, as it denotes the the size of a string - - User code should compare this to `size_t` values as well. If it was used to - compare to other values, casting might be necessary or can be removed, if - casting was applied before. - -### 0.14.1 (2020-03-13) - -* Adds safe allocation wrappers (CVE-2020-7105, #747, #752) (Michael Grunder) - -### 0.14.0 (2018-09-25) - -* Make string2ll static to fix conflict with Redis (Tom Lee [c3188b]) -* Use -dynamiclib instead of -shared for OSX (Ryan Schmidt [a65537]) -* Use string2ll from Redis w/added tests (Michael Grunder [7bef04, 60f622]) -* Makefile - OSX compilation fixes (Ryan Schmidt [881fcb, 0e9af8]) -* Remove redundant NULL checks (Justin Brewer [54acc8, 58e6b8]) -* Fix bulk and multi-bulk length truncation (Justin Brewer [109197]) -* Fix SIGSEGV in OpenBSD by checking for NULL before calling freeaddrinfo (Justin Brewer [546d94]) -* Several POSIX compatibility fixes (Justin Brewer [bbeab8, 49bbaa, d1c1b6]) -* Makefile - Compatibility fixes (Dimitri Vorobiev [3238cf, 12a9d1]) -* Makefile - Fix make install on FreeBSD (Zach Shipko [a2ef2b]) -* Makefile - don't assume $(INSTALL) is cp (Igor Gnatenko [725a96]) -* Separate side-effect causing function from assert and small cleanup (amallia [b46413, 3c3234]) -* Don't send negative values to `__redisAsyncCommand` (Frederik Deweerdt [706129]) -* Fix leak if setsockopt fails (Frederik Deweerdt [e21c9c]) -* Fix libevent leak (zfz [515228]) -* Clean up GCC warning (Ichito Nagata [2ec774]) -* Keep track of errno in `__redisSetErrorFromErrno()` as snprintf may use it (Jin Qing [25cd88]) -* Solaris compilation fix (Donald Whyte [41b07d]) -* Reorder linker arguments when building examples (Tustfarm-heart [06eedd]) -* Keep track of subscriptions in case of rapid subscribe/unsubscribe (Hyungjin Kim [073dc8, be76c5, d46999]) -* libuv use after free fix (Paul Scott [cbb956]) -* Properly close socket fd on reconnect attempt (WSL [64d1ec]) -* Skip valgrind in OSX tests (Jan-Erik Rediger [9deb78]) -* Various updates for Travis testing OSX (Ted Nyman [fa3774, 16a459, bc0ea5]) -* Update libevent (Chris Xin [386802]) -* Change sds.h for building in C++ projects (Ali Volkan ATLI [f5b32e]) -* Use proper format specifier in redisFormatSdsCommandArgv (Paulino Huerta, Jan-Erik Rediger [360a06, 8655a6]) -* Better handling of NULL reply in example code (Jan-Erik Rediger [1b8ed3]) -* Prevent overflow when formatting an error (Jan-Erik Rediger [0335cb]) -* Compatibility fix for strerror_r (Tom Lee [bb1747]) -* Properly detect integer parse/overflow errors (Justin Brewer [93421f]) -* Adds CI for Windows and cygwin fixes (owent, [6c53d6, 6c3e40]) -* Catch a buffer overflow when formatting the error message -* Import latest upstream sds. This breaks applications that are linked against the old hiredis v0.13 -* Fix warnings, when compiled with -Wshadow -* Make hiredis compile in Cygwin on Windows, now CI-tested - -**BREAKING CHANGES**: - -* Remove backwards compatibility macro's - -This removes the following old function aliases, use the new name now: - -| Old | New | -| --------------------------- | ---------------------- | -| redisReplyReaderCreate | redisReaderCreate | -| redisReplyReaderCreate | redisReaderCreate | -| redisReplyReaderFree | redisReaderFree | -| redisReplyReaderFeed | redisReaderFeed | -| redisReplyReaderGetReply | redisReaderGetReply | -| redisReplyReaderSetPrivdata | redisReaderSetPrivdata | -| redisReplyReaderGetObject | redisReaderGetObject | -| redisReplyReaderGetError | redisReaderGetError | - -* The `DEBUG` variable in the Makefile was renamed to `DEBUG_FLAGS` - -Previously it broke some builds for people that had `DEBUG` set to some arbitrary value, -due to debugging other software. -By renaming we avoid unintentional name clashes. - -Simply rename `DEBUG` to `DEBUG_FLAGS` in your environment to make it working again. - -### 0.13.3 (2015-09-16) - -* Revert "Clear `REDIS_CONNECTED` flag when connection is closed". -* Make tests pass on FreeBSD (Thanks, Giacomo Olgeni) - - -If the `REDIS_CONNECTED` flag is cleared, -the async onDisconnect callback function will never be called. -This causes problems as the disconnect is never reported back to the user. - -### 0.13.2 (2015-08-25) - -* Prevent crash on pending replies in async code (Thanks, @switch-st) -* Clear `REDIS_CONNECTED` flag when connection is closed (Thanks, Jerry Jacobs) -* Add MacOS X addapter (Thanks, @dizzus) -* Add Qt adapter (Thanks, Pietro Cerutti) -* Add Ivykis adapter (Thanks, Gergely Nagy) - -All adapters are provided as is and are only tested where possible. - -### 0.13.1 (2015-05-03) - -This is a bug fix release. -The new `reconnect` method introduced new struct members, which clashed with pre-defined names in pre-C99 code. -Another commit forced C99 compilation just to make it work, but of course this is not desirable for outside projects. -Other non-C99 code can now use hiredis as usual again. -Sorry for the inconvenience. - -* Fix memory leak in async reply handling (Salvatore Sanfilippo) -* Rename struct member to avoid name clash with pre-c99 code (Alex Balashov, ncopa) - -### 0.13.0 (2015-04-16) - -This release adds a minimal Windows compatibility layer. -The parser, standalone since v0.12.0, can now be compiled on Windows -(and thus used in other client libraries as well) - -* Windows compatibility layer for parser code (tzickel) -* Properly escape data printed to PKGCONF file (Dan Skorupski) -* Fix tests when assert() undefined (Keith Bennett, Matt Stancliff) -* Implement a reconnect method for the client context, this changes the structure of `redisContext` (Aaron Bedra) - -### 0.12.1 (2015-01-26) - -* Fix `make install`: DESTDIR support, install all required files, install PKGCONF in proper location -* Fix `make test` as 32 bit build on 64 bit platform - -### 0.12.0 (2015-01-22) - -* Add optional KeepAlive support - -* Try again on EINTR errors - -* Add libuv adapter - -* Add IPv6 support - -* Remove possibility of multiple close on same fd - -* Add ability to bind source address on connect - -* Add redisConnectFd() and redisFreeKeepFd() - -* Fix getaddrinfo() memory leak - -* Free string if it is unused (fixes memory leak) - -* Improve redisAppendCommandArgv performance 2.5x - -* Add support for SO_REUSEADDR - -* Fix redisvFormatCommand format parsing - -* Add GLib 2.0 adapter - -* Refactor reading code into read.c - -* Fix errno error buffers to not clobber errors - -* Generate pkgconf during build - -* Silence _BSD_SOURCE warnings - -* Improve digit counting for multibulk creation - - -### 0.11.0 - -* Increase the maximum multi-bulk reply depth to 7. - -* Increase the read buffer size from 2k to 16k. - -* Use poll(2) instead of select(2) to support large fds (>= 1024). - -### 0.10.1 - -* Makefile overhaul. Important to check out if you override one or more - variables using environment variables or via arguments to the "make" tool. - -* Issue #45: Fix potential memory leak for a multi bulk reply with 0 elements - being created by the default reply object functions. - -* Issue #43: Don't crash in an asynchronous context when Redis returns an error - reply after the connection has been made (this happens when the maximum - number of connections is reached). - -### 0.10.0 - -* See commit log. - diff --git a/ext/hiredis-0.14.1/COPYING b/ext/hiredis-0.14.1/COPYING deleted file mode 100644 index a5fc97395..000000000 --- a/ext/hiredis-0.14.1/COPYING +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2009-2011, Salvatore Sanfilippo -Copyright (c) 2010-2011, Pieter Noordhuis - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of Redis nor the names of its contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/ext/hiredis-0.14.1/Makefile b/ext/hiredis-0.14.1/Makefile deleted file mode 100644 index d1f005af4..000000000 --- a/ext/hiredis-0.14.1/Makefile +++ /dev/null @@ -1,214 +0,0 @@ -# Hiredis Makefile -# Copyright (C) 2010-2011 Salvatore Sanfilippo -# Copyright (C) 2010-2011 Pieter Noordhuis -# This file is released under the BSD license, see the COPYING file - -OBJ=net.o hiredis.o sds.o async.o read.o alloc.o -EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib -TESTS=hiredis-test -LIBNAME=libhiredis -PKGCONFNAME=hiredis.pc - -HIREDIS_MAJOR=$(shell grep HIREDIS_MAJOR hiredis.h | awk '{print $$3}') -HIREDIS_MINOR=$(shell grep HIREDIS_MINOR hiredis.h | awk '{print $$3}') -HIREDIS_PATCH=$(shell grep HIREDIS_PATCH hiredis.h | awk '{print $$3}') -HIREDIS_SONAME=$(shell grep HIREDIS_SONAME hiredis.h | awk '{print $$3}') - -# Installation related variables and target -PREFIX?=/usr/local -INCLUDE_PATH?=include/hiredis -LIBRARY_PATH?=lib -PKGCONF_PATH?=pkgconfig -INSTALL_INCLUDE_PATH= $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH) -INSTALL_LIBRARY_PATH= $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH) -INSTALL_PKGCONF_PATH= $(INSTALL_LIBRARY_PATH)/$(PKGCONF_PATH) - -# redis-server configuration used for testing -REDIS_PORT=56379 -REDIS_SERVER=redis-server -define REDIS_TEST_CONFIG - daemonize yes - pidfile /tmp/hiredis-test-redis.pid - port $(REDIS_PORT) - bind 127.0.0.1 - unixsocket /tmp/hiredis-test-redis.sock -endef -export REDIS_TEST_CONFIG - -# Fallback to gcc when $CC is not in $PATH. -CC:=$(shell sh -c 'type $${CC%% *} >/dev/null 2>/dev/null && echo $(CC) || echo gcc') -CXX:=$(shell sh -c 'type $${CXX%% *} >/dev/null 2>/dev/null && echo $(CXX) || echo g++') -OPTIMIZATION?=-O3 -WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings -DEBUG_FLAGS?= -g -ggdb -REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS) -REAL_LDFLAGS=$(LDFLAGS) - -DYLIBSUFFIX=so -STLIBSUFFIX=a -DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_SONAME) -DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR) -DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX) -DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) -STLIBNAME=$(LIBNAME).$(STLIBSUFFIX) -STLIB_MAKE_CMD=ar rcs $(STLIBNAME) - -# Platform-specific overrides -uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') -ifeq ($(uname_S),SunOS) - REAL_LDFLAGS+= -ldl -lnsl -lsocket - DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS) -endif -ifeq ($(uname_S),Darwin) - DYLIBSUFFIX=dylib - DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX) - DYLIB_MAKE_CMD=$(CC) -dynamiclib -Wl,-install_name,$(PREFIX)/$(LIBRARY_PATH)/$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) -endif - -all: $(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME) - -# Deps (use make dep to generate this) -alloc.o: alloc.c fmacros.h alloc.h -async.o: async.c fmacros.h alloc.h async.h hiredis.h read.h sds.h net.h dict.c dict.h -dict.o: dict.c fmacros.h alloc.h dict.h -hiredis.o: hiredis.c fmacros.h hiredis.h read.h sds.h alloc.h net.h -net.o: net.c fmacros.h net.h hiredis.h read.h sds.h alloc.h -read.o: read.c fmacros.h read.h sds.h -sds.o: sds.c sds.h sdsalloc.h -test.o: test.c fmacros.h hiredis.h read.h sds.h alloc.h net.h - -$(DYLIBNAME): $(OBJ) - $(DYLIB_MAKE_CMD) $(OBJ) - -$(STLIBNAME): $(OBJ) - $(STLIB_MAKE_CMD) $(OBJ) - -dynamic: $(DYLIBNAME) -static: $(STLIBNAME) - -# Binaries: -hiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -levent $(STLIBNAME) - -hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME) - -hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(shell pkg-config --cflags --libs glib-2.0) $(STLIBNAME) - -hiredis-example-ivykis: examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -livykis $(STLIBNAME) - -hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -framework CoreFoundation $(STLIBNAME) - -ifndef AE_DIR -hiredis-example-ae: - @echo "Please specify AE_DIR (e.g. /src)" - @false -else -hiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(AE_DIR) $< $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o $(AE_DIR)/../deps/jemalloc/lib/libjemalloc.a -pthread $(STLIBNAME) -endif - -ifndef LIBUV_DIR -hiredis-example-libuv: - @echo "Please specify LIBUV_DIR (e.g. ../libuv/)" - @false -else -hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME) -endif - -ifeq ($(and $(QT_MOC),$(QT_INCLUDE_DIR),$(QT_LIBRARY_DIR)),) -hiredis-example-qt: - @echo "Please specify QT_MOC, QT_INCLUDE_DIR AND QT_LIBRARY_DIR" - @false -else -hiredis-example-qt: examples/example-qt.cpp adapters/qt.h $(STLIBNAME) - $(QT_MOC) adapters/qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \ - $(CXX) -x c++ -o qt-adapter-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore - $(QT_MOC) examples/example-qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \ - $(CXX) -x c++ -o qt-example-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore - $(CXX) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore -L$(QT_LIBRARY_DIR) qt-adapter-moc.o qt-example-moc.o $< -pthread $(STLIBNAME) -lQtCore -endif - -hiredis-example: examples/example.c $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME) - -examples: $(EXAMPLES) - -hiredis-test: test.o $(STLIBNAME) - -hiredis-%: %.o $(STLIBNAME) - $(CC) $(REAL_CFLAGS) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME) - -test: hiredis-test - ./hiredis-test - -check: hiredis-test - @echo "$$REDIS_TEST_CONFIG" | $(REDIS_SERVER) - - $(PRE) ./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \ - ( kill `cat /tmp/hiredis-test-redis.pid` && false ) - kill `cat /tmp/hiredis-test-redis.pid` - -.c.o: - $(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $< - -clean: - rm -rf $(DYLIBNAME) $(STLIBNAME) $(TESTS) $(PKGCONFNAME) examples/hiredis-example* *.o *.gcda *.gcno *.gcov - -dep: - $(CC) -MM *.c - -INSTALL?= cp -pPR - -$(PKGCONFNAME): hiredis.h - @echo "Generating $@ for pkgconfig..." - @echo prefix=$(PREFIX) > $@ - @echo exec_prefix=\$${prefix} >> $@ - @echo libdir=$(PREFIX)/$(LIBRARY_PATH) >> $@ - @echo includedir=$(PREFIX)/$(INCLUDE_PATH) >> $@ - @echo >> $@ - @echo Name: hiredis >> $@ - @echo Description: Minimalistic C client library for Redis. >> $@ - @echo Version: $(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(HIREDIS_PATCH) >> $@ - @echo Libs: -L\$${libdir} -lhiredis >> $@ - @echo Cflags: -I\$${includedir} -D_FILE_OFFSET_BITS=64 >> $@ - -install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME) - mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL_LIBRARY_PATH) - $(INSTALL) hiredis.h async.h read.h sds.h alloc.h $(INSTALL_INCLUDE_PATH) - $(INSTALL) adapters/*.h $(INSTALL_INCLUDE_PATH)/adapters - $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) - cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME) - $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH) - mkdir -p $(INSTALL_PKGCONF_PATH) - $(INSTALL) $(PKGCONFNAME) $(INSTALL_PKGCONF_PATH) - -32bit: - @echo "" - @echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386" - @echo "" - $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" - -32bit-vars: - $(eval CFLAGS=-m32) - $(eval LDFLAGS=-m32) - -gprof: - $(MAKE) CFLAGS="-pg" LDFLAGS="-pg" - -gcov: - $(MAKE) CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs" - -coverage: gcov - make check - mkdir -p tmp/lcov - lcov -d . -c -o tmp/lcov/hiredis.info - genhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info - -noopt: - $(MAKE) OPTIMIZATION="" - -.PHONY: all test check clean dep install 32bit 32bit-vars gprof gcov noopt diff --git a/ext/hiredis-0.14.1/README.md b/ext/hiredis-0.14.1/README.md deleted file mode 100644 index 50e2e6be6..000000000 --- a/ext/hiredis-0.14.1/README.md +++ /dev/null @@ -1,410 +0,0 @@ -[![Build Status](https://travis-ci.org/redis/hiredis.png)](https://travis-ci.org/redis/hiredis) - -**This Readme reflects the latest changed in the master branch. See [v0.14.1](https://github.com/redis/hiredis/tree/v0.14.1) for the Readme and documentation for the latest release.** - -# HIREDIS - -Hiredis is a minimalistic C client library for the [Redis](http://redis.io/) database. - -It is minimalistic because it just adds minimal support for the protocol, but -at the same time it uses a high level printf-alike API in order to make it -much higher level than otherwise suggested by its minimal code base and the -lack of explicit bindings for every Redis command. - -Apart from supporting sending commands and receiving replies, it comes with -a reply parser that is decoupled from the I/O layer. It -is a stream parser designed for easy reusability, which can for instance be used -in higher level language bindings for efficient reply parsing. - -Hiredis only supports the binary-safe Redis protocol, so you can use it with any -Redis version >= 1.2.0. - -The library comes with multiple APIs. There is the -*synchronous API*, the *asynchronous API* and the *reply parsing API*. - -## IMPORTANT: Breaking changes when upgrading from 0.13.x -> 0.14.x - -Bulk and multi-bulk lengths less than -1 or greater than `LLONG_MAX` are now -protocol errors. This is consistent with the RESP specification. On 32-bit -platforms, the upper bound is lowered to `SIZE_MAX`. - -Change `redisReply.len` to `size_t`, as it denotes the the size of a string - -User code should compare this to `size_t` values as well. If it was used to -compare to other values, casting might be necessary or can be removed, if -casting was applied before. - -For a detailed list of changes please view our [Changelog](CHANGELOG.md). - -## Synchronous API - -To consume the synchronous API, there are only a few function calls that need to be introduced: - -```c -redisContext *redisConnect(const char *ip, int port); -void *redisCommand(redisContext *c, const char *format, ...); -void freeReplyObject(void *reply); -``` - -### Connecting - -The function `redisConnect` is used to create a so-called `redisContext`. The -context is where Hiredis holds state for a connection. The `redisContext` -struct has an integer `err` field that is non-zero when the connection is in -an error state. The field `errstr` will contain a string with a description of -the error. More information on errors can be found in the **Errors** section. -After trying to connect to Redis using `redisConnect` you should -check the `err` field to see if establishing the connection was successful: -```c -redisContext *c = redisConnect("127.0.0.1", 6379); -if (c == NULL || c->err) { - if (c) { - printf("Error: %s\n", c->errstr); - // handle error - } else { - printf("Can't allocate redis context\n"); - } -} -``` - -*Note: A `redisContext` is not thread-safe.* - -### Sending commands - -There are several ways to issue commands to Redis. The first that will be introduced is -`redisCommand`. This function takes a format similar to printf. In the simplest form, -it is used like this: -```c -reply = redisCommand(context, "SET foo bar"); -``` - -The specifier `%s` interpolates a string in the command, and uses `strlen` to -determine the length of the string: -```c -reply = redisCommand(context, "SET foo %s", value); -``` -When you need to pass binary safe strings in a command, the `%b` specifier can be -used. Together with a pointer to the string, it requires a `size_t` length argument -of the string: -```c -reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen); -``` -Internally, Hiredis splits the command in different arguments and will -convert it to the protocol used to communicate with Redis. -One or more spaces separates arguments, so you can use the specifiers -anywhere in an argument: -```c -reply = redisCommand(context, "SET key:%s %s", myid, value); -``` - -### Using replies - -The return value of `redisCommand` holds a reply when the command was -successfully executed. When an error occurs, the return value is `NULL` and -the `err` field in the context will be set (see section on **Errors**). -Once an error is returned the context cannot be reused and you should set up -a new connection. - -The standard replies that `redisCommand` are of the type `redisReply`. The -`type` field in the `redisReply` should be used to test what kind of reply -was received: - -* **`REDIS_REPLY_STATUS`**: - * The command replied with a status reply. The status string can be accessed using `reply->str`. - The length of this string can be accessed using `reply->len`. - -* **`REDIS_REPLY_ERROR`**: - * The command replied with an error. The error string can be accessed identical to `REDIS_REPLY_STATUS`. - -* **`REDIS_REPLY_INTEGER`**: - * The command replied with an integer. The integer value can be accessed using the - `reply->integer` field of type `long long`. - -* **`REDIS_REPLY_NIL`**: - * The command replied with a **nil** object. There is no data to access. - -* **`REDIS_REPLY_STRING`**: - * A bulk (string) reply. The value of the reply can be accessed using `reply->str`. - The length of this string can be accessed using `reply->len`. - -* **`REDIS_REPLY_ARRAY`**: - * A multi bulk reply. The number of elements in the multi bulk reply is stored in - `reply->elements`. Every element in the multi bulk reply is a `redisReply` object as well - and can be accessed via `reply->element[..index..]`. - Redis may reply with nested arrays but this is fully supported. - -Replies should be freed using the `freeReplyObject()` function. -Note that this function will take care of freeing sub-reply objects -contained in arrays and nested arrays, so there is no need for the user to -free the sub replies (it is actually harmful and will corrupt the memory). - -**Important:** the current version of hiredis (0.10.0) frees replies when the -asynchronous API is used. This means you should not call `freeReplyObject` when -you use this API. The reply is cleaned up by hiredis _after_ the callback -returns. This behavior will probably change in future releases, so make sure to -keep an eye on the changelog when upgrading (see issue #39). - -### Cleaning up - -To disconnect and free the context the following function can be used: -```c -void redisFree(redisContext *c); -``` -This function immediately closes the socket and then frees the allocations done in -creating the context. - -### Sending commands (cont'd) - -Together with `redisCommand`, the function `redisCommandArgv` can be used to issue commands. -It has the following prototype: -```c -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); -``` -It takes the number of arguments `argc`, an array of strings `argv` and the lengths of the -arguments `argvlen`. For convenience, `argvlen` may be set to `NULL` and the function will -use `strlen(3)` on every argument to determine its length. Obviously, when any of the arguments -need to be binary safe, the entire array of lengths `argvlen` should be provided. - -The return value has the same semantic as `redisCommand`. - -### Pipelining - -To explain how Hiredis supports pipelining in a blocking connection, there needs to be -understanding of the internal execution flow. - -When any of the functions in the `redisCommand` family is called, Hiredis first formats the -command according to the Redis protocol. The formatted command is then put in the output buffer -of the context. This output buffer is dynamic, so it can hold any number of commands. -After the command is put in the output buffer, `redisGetReply` is called. This function has the -following two execution paths: - -1. The input buffer is non-empty: - * Try to parse a single reply from the input buffer and return it - * If no reply could be parsed, continue at *2* -2. The input buffer is empty: - * Write the **entire** output buffer to the socket - * Read from the socket until a single reply could be parsed - -The function `redisGetReply` is exported as part of the Hiredis API and can be used when a reply -is expected on the socket. To pipeline commands, the only things that needs to be done is -filling up the output buffer. For this cause, two commands can be used that are identical -to the `redisCommand` family, apart from not returning a reply: -```c -void redisAppendCommand(redisContext *c, const char *format, ...); -void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); -``` -After calling either function one or more times, `redisGetReply` can be used to receive the -subsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where -the latter means an error occurred while reading a reply. Just as with the other commands, -the `err` field in the context can be used to find out what the cause of this error is. - -The following examples shows a simple pipeline (resulting in only a single call to `write(2)` and -a single call to `read(2)`): -```c -redisReply *reply; -redisAppendCommand(context,"SET foo bar"); -redisAppendCommand(context,"GET foo"); -redisGetReply(context,&reply); // reply for SET -freeReplyObject(reply); -redisGetReply(context,&reply); // reply for GET -freeReplyObject(reply); -``` -This API can also be used to implement a blocking subscriber: -```c -reply = redisCommand(context,"SUBSCRIBE foo"); -freeReplyObject(reply); -while(redisGetReply(context,&reply) == REDIS_OK) { - // consume message - freeReplyObject(reply); -} -``` -### Errors - -When a function call is not successful, depending on the function either `NULL` or `REDIS_ERR` is -returned. The `err` field inside the context will be non-zero and set to one of the -following constants: - -* **`REDIS_ERR_IO`**: - There was an I/O error while creating the connection, trying to write - to the socket or read from the socket. If you included `errno.h` in your - application, you can use the global `errno` variable to find out what is - wrong. - -* **`REDIS_ERR_EOF`**: - The server closed the connection which resulted in an empty read. - -* **`REDIS_ERR_PROTOCOL`**: - There was an error while parsing the protocol. - -* **`REDIS_ERR_OTHER`**: - Any other error. Currently, it is only used when a specified hostname to connect - to cannot be resolved. - -In every case, the `errstr` field in the context will be set to hold a string representation -of the error. - -## Asynchronous API - -Hiredis comes with an asynchronous API that works easily with any event library. -Examples are bundled that show using Hiredis with [libev](http://software.schmorp.de/pkg/libev.html) -and [libevent](http://monkey.org/~provos/libevent/). - -### Connecting - -The function `redisAsyncConnect` can be used to establish a non-blocking connection to -Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The `err` field -should be checked after creation to see if there were errors creating the connection. -Because the connection that will be created is non-blocking, the kernel is not able to -instantly return if the specified host and port is able to accept a connection. - -*Note: A `redisAsyncContext` is not thread-safe.* - -```c -redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); -if (c->err) { - printf("Error: %s\n", c->errstr); - // handle error -} -``` - -The asynchronous context can hold a disconnect callback function that is called when the -connection is disconnected (either because of an error or per user request). This function should -have the following prototype: -```c -void(const redisAsyncContext *c, int status); -``` -On a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the -user, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `err` -field in the context can be accessed to find out the cause of the error. - -The context object is always freed after the disconnect callback fired. When a reconnect is needed, -the disconnect callback is a good point to do so. - -Setting the disconnect callback can only be done once per context. For subsequent calls it will -return `REDIS_ERR`. The function to set the disconnect callback has the following prototype: -```c -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); -``` -### Sending commands and their callbacks - -In an asynchronous context, commands are automatically pipelined due to the nature of an event loop. -Therefore, unlike the synchronous API, there is only a single way to send commands. -Because commands are sent to Redis asynchronously, issuing a command requires a callback function -that is called when the reply is received. Reply callbacks should have the following prototype: -```c -void(redisAsyncContext *c, void *reply, void *privdata); -``` -The `privdata` argument can be used to curry arbitrary data to the callback from the point where -the command is initially queued for execution. - -The functions that can be used to issue commands in an asynchronous context are: -```c -int redisAsyncCommand( - redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, - const char *format, ...); -int redisAsyncCommandArgv( - redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, - int argc, const char **argv, const size_t *argvlen); -``` -Both functions work like their blocking counterparts. The return value is `REDIS_OK` when the command -was successfully added to the output buffer and `REDIS_ERR` otherwise. Example: when the connection -is being disconnected per user-request, no new commands may be added to the output buffer and `REDIS_ERR` is -returned on calls to the `redisAsyncCommand` family. - -If the reply for a command with a `NULL` callback is read, it is immediately freed. When the callback -for a command is non-`NULL`, the memory is freed immediately following the callback: the reply is only -valid for the duration of the callback. - -All pending callbacks are called with a `NULL` reply when the context encountered an error. - -### Disconnecting - -An asynchronous connection can be terminated using: -```c -void redisAsyncDisconnect(redisAsyncContext *ac); -``` -When this function is called, the connection is **not** immediately terminated. Instead, new -commands are no longer accepted and the connection is only terminated when all pending commands -have been written to the socket, their respective replies have been read and their respective -callbacks have been executed. After this, the disconnection callback is executed with the -`REDIS_OK` status and the context object is freed. - -### Hooking it up to event library *X* - -There are a few hooks that need to be set on the context object after it is created. -See the `adapters/` directory for bindings to *libev* and *libevent*. - -## Reply parsing API - -Hiredis comes with a reply parsing API that makes it easy for writing higher -level language bindings. - -The reply parsing API consists of the following functions: -```c -redisReader *redisReaderCreate(void); -void redisReaderFree(redisReader *reader); -int redisReaderFeed(redisReader *reader, const char *buf, size_t len); -int redisReaderGetReply(redisReader *reader, void **reply); -``` -The same set of functions are used internally by hiredis when creating a -normal Redis context, the above API just exposes it to the user for a direct -usage. - -### Usage - -The function `redisReaderCreate` creates a `redisReader` structure that holds a -buffer with unparsed data and state for the protocol parser. - -Incoming data -- most likely from a socket -- can be placed in the internal -buffer of the `redisReader` using `redisReaderFeed`. This function will make a -copy of the buffer pointed to by `buf` for `len` bytes. This data is parsed -when `redisReaderGetReply` is called. This function returns an integer status -and a reply object (as described above) via `void **reply`. The returned status -can be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went -wrong (either a protocol error, or an out of memory error). - -The parser limits the level of nesting for multi bulk payloads to 7. If the -multi bulk nesting level is higher than this, the parser returns an error. - -### Customizing replies - -The function `redisReaderGetReply` creates `redisReply` and makes the function -argument `reply` point to the created `redisReply` variable. For instance, if -the response of type `REDIS_REPLY_STATUS` then the `str` field of `redisReply` -will hold the status as a vanilla C string. However, the functions that are -responsible for creating instances of the `redisReply` can be customized by -setting the `fn` field on the `redisReader` struct. This should be done -immediately after creating the `redisReader`. - -For example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c) -uses customized reply object functions to create Ruby objects. - -### Reader max buffer - -Both when using the Reader API directly or when using it indirectly via a -normal Redis context, the redisReader structure uses a buffer in order to -accumulate data from the server. -Usually this buffer is destroyed when it is empty and is larger than 16 -KiB in order to avoid wasting memory in unused buffers - -However when working with very big payloads destroying the buffer may slow -down performances considerably, so it is possible to modify the max size of -an idle buffer changing the value of the `maxbuf` field of the reader structure -to the desired value. The special value of 0 means that there is no maximum -value for an idle buffer, so the buffer will never get freed. - -For instance if you have a normal Redis context you can set the maximum idle -buffer to zero (unlimited) just with: -```c -context->reader->maxbuf = 0; -``` -This should be done only in order to maximize performances when working with -large payloads. The context should be set back to `REDIS_READER_MAX_BUF` again -as soon as possible in order to prevent allocation of useless memory. - -## AUTHORS - -Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and -Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license. -Hiredis is currently maintained by Matt Stancliff (matt at genges dot com) and -Jan-Erik Rediger (janerik at fnordig dot com) diff --git a/ext/hiredis-0.14.1/adapters/ae.h b/ext/hiredis-0.14.1/adapters/ae.h deleted file mode 100644 index 03939928d..000000000 --- a/ext/hiredis-0.14.1/adapters/ae.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_AE_H__ -#define __HIREDIS_AE_H__ -#include -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisAeEvents { - redisAsyncContext *context; - aeEventLoop *loop; - int fd; - int reading, writing; -} redisAeEvents; - -static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) { - ((void)el); ((void)fd); ((void)mask); - - redisAeEvents *e = (redisAeEvents*)privdata; - redisAsyncHandleRead(e->context); -} - -static void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) { - ((void)el); ((void)fd); ((void)mask); - - redisAeEvents *e = (redisAeEvents*)privdata; - redisAsyncHandleWrite(e->context); -} - -static void redisAeAddRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (!e->reading) { - e->reading = 1; - aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e); - } -} - -static void redisAeDelRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (e->reading) { - e->reading = 0; - aeDeleteFileEvent(loop,e->fd,AE_READABLE); - } -} - -static void redisAeAddWrite(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (!e->writing) { - e->writing = 1; - aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e); - } -} - -static void redisAeDelWrite(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (e->writing) { - e->writing = 0; - aeDeleteFileEvent(loop,e->fd,AE_WRITABLE); - } -} - -static void redisAeCleanup(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - redisAeDelRead(privdata); - redisAeDelWrite(privdata); - free(e); -} - -static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisAeEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisAeEvents*)hi_malloc(sizeof(*e)); - e->context = ac; - e->loop = loop; - e->fd = c->fd; - e->reading = e->writing = 0; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisAeAddRead; - ac->ev.delRead = redisAeDelRead; - ac->ev.addWrite = redisAeAddWrite; - ac->ev.delWrite = redisAeDelWrite; - ac->ev.cleanup = redisAeCleanup; - ac->ev.data = e; - - return REDIS_OK; -} -#endif diff --git a/ext/hiredis-0.14.1/adapters/glib.h b/ext/hiredis-0.14.1/adapters/glib.h deleted file mode 100644 index e0a6411d3..000000000 --- a/ext/hiredis-0.14.1/adapters/glib.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef __HIREDIS_GLIB_H__ -#define __HIREDIS_GLIB_H__ - -#include - -#include "../hiredis.h" -#include "../async.h" - -typedef struct -{ - GSource source; - redisAsyncContext *ac; - GPollFD poll_fd; -} RedisSource; - -static void -redis_source_add_read (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - g_return_if_fail(source); - source->poll_fd.events |= G_IO_IN; - g_main_context_wakeup(g_source_get_context((GSource *)data)); -} - -static void -redis_source_del_read (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - g_return_if_fail(source); - source->poll_fd.events &= ~G_IO_IN; - g_main_context_wakeup(g_source_get_context((GSource *)data)); -} - -static void -redis_source_add_write (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - g_return_if_fail(source); - source->poll_fd.events |= G_IO_OUT; - g_main_context_wakeup(g_source_get_context((GSource *)data)); -} - -static void -redis_source_del_write (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - g_return_if_fail(source); - source->poll_fd.events &= ~G_IO_OUT; - g_main_context_wakeup(g_source_get_context((GSource *)data)); -} - -static void -redis_source_cleanup (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - - g_return_if_fail(source); - - redis_source_del_read(source); - redis_source_del_write(source); - /* - * It is not our responsibility to remove ourself from the - * current main loop. However, we will remove the GPollFD. - */ - if (source->poll_fd.fd >= 0) { - g_source_remove_poll((GSource *)data, &source->poll_fd); - source->poll_fd.fd = -1; - } -} - -static gboolean -redis_source_prepare (GSource *source, - gint *timeout_) -{ - RedisSource *redis = (RedisSource *)source; - *timeout_ = -1; - return !!(redis->poll_fd.events & redis->poll_fd.revents); -} - -static gboolean -redis_source_check (GSource *source) -{ - RedisSource *redis = (RedisSource *)source; - return !!(redis->poll_fd.events & redis->poll_fd.revents); -} - -static gboolean -redis_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - RedisSource *redis = (RedisSource *)source; - - if ((redis->poll_fd.revents & G_IO_OUT)) { - redisAsyncHandleWrite(redis->ac); - redis->poll_fd.revents &= ~G_IO_OUT; - } - - if ((redis->poll_fd.revents & G_IO_IN)) { - redisAsyncHandleRead(redis->ac); - redis->poll_fd.revents &= ~G_IO_IN; - } - - if (callback) { - return callback(user_data); - } - - return TRUE; -} - -static void -redis_source_finalize (GSource *source) -{ - RedisSource *redis = (RedisSource *)source; - - if (redis->poll_fd.fd >= 0) { - g_source_remove_poll(source, &redis->poll_fd); - redis->poll_fd.fd = -1; - } -} - -static GSource * -redis_source_new (redisAsyncContext *ac) -{ - static GSourceFuncs source_funcs = { - .prepare = redis_source_prepare, - .check = redis_source_check, - .dispatch = redis_source_dispatch, - .finalize = redis_source_finalize, - }; - redisContext *c = &ac->c; - RedisSource *source; - - g_return_val_if_fail(ac != NULL, NULL); - - source = (RedisSource *)g_source_new(&source_funcs, sizeof *source); - source->ac = ac; - source->poll_fd.fd = c->fd; - source->poll_fd.events = 0; - source->poll_fd.revents = 0; - g_source_add_poll((GSource *)source, &source->poll_fd); - - ac->ev.addRead = redis_source_add_read; - ac->ev.delRead = redis_source_del_read; - ac->ev.addWrite = redis_source_add_write; - ac->ev.delWrite = redis_source_del_write; - ac->ev.cleanup = redis_source_cleanup; - ac->ev.data = source; - - return (GSource *)source; -} - -#endif /* __HIREDIS_GLIB_H__ */ diff --git a/ext/hiredis-0.14.1/adapters/ivykis.h b/ext/hiredis-0.14.1/adapters/ivykis.h deleted file mode 100644 index 75616ee24..000000000 --- a/ext/hiredis-0.14.1/adapters/ivykis.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef __HIREDIS_IVYKIS_H__ -#define __HIREDIS_IVYKIS_H__ -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisIvykisEvents { - redisAsyncContext *context; - struct iv_fd fd; -} redisIvykisEvents; - -static void redisIvykisReadEvent(void *arg) { - redisAsyncContext *context = (redisAsyncContext *)arg; - redisAsyncHandleRead(context); -} - -static void redisIvykisWriteEvent(void *arg) { - redisAsyncContext *context = (redisAsyncContext *)arg; - redisAsyncHandleWrite(context); -} - -static void redisIvykisAddRead(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - iv_fd_set_handler_in(&e->fd, redisIvykisReadEvent); -} - -static void redisIvykisDelRead(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - iv_fd_set_handler_in(&e->fd, NULL); -} - -static void redisIvykisAddWrite(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - iv_fd_set_handler_out(&e->fd, redisIvykisWriteEvent); -} - -static void redisIvykisDelWrite(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - iv_fd_set_handler_out(&e->fd, NULL); -} - -static void redisIvykisCleanup(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - - iv_fd_unregister(&e->fd); - free(e); -} - -static int redisIvykisAttach(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisIvykisEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisIvykisEvents*)hi_malloc(sizeof(*e)); - e->context = ac; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisIvykisAddRead; - ac->ev.delRead = redisIvykisDelRead; - ac->ev.addWrite = redisIvykisAddWrite; - ac->ev.delWrite = redisIvykisDelWrite; - ac->ev.cleanup = redisIvykisCleanup; - ac->ev.data = e; - - /* Initialize and install read/write events */ - IV_FD_INIT(&e->fd); - e->fd.fd = c->fd; - e->fd.handler_in = redisIvykisReadEvent; - e->fd.handler_out = redisIvykisWriteEvent; - e->fd.handler_err = NULL; - e->fd.cookie = e->context; - - iv_fd_register(&e->fd); - - return REDIS_OK; -} -#endif diff --git a/ext/hiredis-0.14.1/adapters/libev.h b/ext/hiredis-0.14.1/adapters/libev.h deleted file mode 100644 index abad43634..000000000 --- a/ext/hiredis-0.14.1/adapters/libev.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_LIBEV_H__ -#define __HIREDIS_LIBEV_H__ -#include -#include -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisLibevEvents { - redisAsyncContext *context; - struct ev_loop *loop; - int reading, writing; - ev_io rev, wev; -} redisLibevEvents; - -static void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) { -#if EV_MULTIPLICITY - ((void)loop); -#endif - ((void)revents); - - redisLibevEvents *e = (redisLibevEvents*)watcher->data; - redisAsyncHandleRead(e->context); -} - -static void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) { -#if EV_MULTIPLICITY - ((void)loop); -#endif - ((void)revents); - - redisLibevEvents *e = (redisLibevEvents*)watcher->data; - redisAsyncHandleWrite(e->context); -} - -static void redisLibevAddRead(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (!e->reading) { - e->reading = 1; - ev_io_start(EV_A_ &e->rev); - } -} - -static void redisLibevDelRead(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (e->reading) { - e->reading = 0; - ev_io_stop(EV_A_ &e->rev); - } -} - -static void redisLibevAddWrite(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (!e->writing) { - e->writing = 1; - ev_io_start(EV_A_ &e->wev); - } -} - -static void redisLibevDelWrite(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (e->writing) { - e->writing = 0; - ev_io_stop(EV_A_ &e->wev); - } -} - -static void redisLibevCleanup(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - redisLibevDelRead(privdata); - redisLibevDelWrite(privdata); - free(e); -} - -static int redisLibevAttach(EV_P_ redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisLibevEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisLibevEvents*)hi_malloc(sizeof(*e)); - e->context = ac; -#if EV_MULTIPLICITY - e->loop = loop; -#else - e->loop = NULL; -#endif - e->reading = e->writing = 0; - e->rev.data = e; - e->wev.data = e; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisLibevAddRead; - ac->ev.delRead = redisLibevDelRead; - ac->ev.addWrite = redisLibevAddWrite; - ac->ev.delWrite = redisLibevDelWrite; - ac->ev.cleanup = redisLibevCleanup; - ac->ev.data = e; - - /* Initialize read/write events */ - ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ); - ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE); - return REDIS_OK; -} - -#endif diff --git a/ext/hiredis-0.14.1/adapters/libevent.h b/ext/hiredis-0.14.1/adapters/libevent.h deleted file mode 100644 index f2330d6f0..000000000 --- a/ext/hiredis-0.14.1/adapters/libevent.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_LIBEVENT_H__ -#define __HIREDIS_LIBEVENT_H__ -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisLibeventEvents { - redisAsyncContext *context; - struct event *rev, *wev; -} redisLibeventEvents; - -static void redisLibeventReadEvent(int fd, short event, void *arg) { - ((void)fd); ((void)event); - redisLibeventEvents *e = (redisLibeventEvents*)arg; - redisAsyncHandleRead(e->context); -} - -static void redisLibeventWriteEvent(int fd, short event, void *arg) { - ((void)fd); ((void)event); - redisLibeventEvents *e = (redisLibeventEvents*)arg; - redisAsyncHandleWrite(e->context); -} - -static void redisLibeventAddRead(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_add(e->rev,NULL); -} - -static void redisLibeventDelRead(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_del(e->rev); -} - -static void redisLibeventAddWrite(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_add(e->wev,NULL); -} - -static void redisLibeventDelWrite(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_del(e->wev); -} - -static void redisLibeventCleanup(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - event_free(e->rev); - event_free(e->wev); - free(e); -} - -static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) { - redisContext *c = &(ac->c); - redisLibeventEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisLibeventEvents*)hi_calloc(1, sizeof(*e)); - e->context = ac; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisLibeventAddRead; - ac->ev.delRead = redisLibeventDelRead; - ac->ev.addWrite = redisLibeventAddWrite; - ac->ev.delWrite = redisLibeventDelWrite; - ac->ev.cleanup = redisLibeventCleanup; - ac->ev.data = e; - - /* Initialize and install read/write events */ - e->rev = event_new(base, c->fd, EV_READ, redisLibeventReadEvent, e); - e->wev = event_new(base, c->fd, EV_WRITE, redisLibeventWriteEvent, e); - event_add(e->rev, NULL); - event_add(e->wev, NULL); - return REDIS_OK; -} -#endif diff --git a/ext/hiredis-0.14.1/adapters/libuv.h b/ext/hiredis-0.14.1/adapters/libuv.h deleted file mode 100644 index ff08c25e1..000000000 --- a/ext/hiredis-0.14.1/adapters/libuv.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef __HIREDIS_LIBUV_H__ -#define __HIREDIS_LIBUV_H__ -#include -#include -#include "../hiredis.h" -#include "../async.h" -#include - -typedef struct redisLibuvEvents { - redisAsyncContext* context; - uv_poll_t handle; - int events; -} redisLibuvEvents; - - -static void redisLibuvPoll(uv_poll_t* handle, int status, int events) { - redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - - if (status != 0) { - return; - } - - if (p->context != NULL && (events & UV_READABLE)) { - redisAsyncHandleRead(p->context); - } - if (p->context != NULL && (events & UV_WRITABLE)) { - redisAsyncHandleWrite(p->context); - } -} - - -static void redisLibuvAddRead(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->events |= UV_READABLE; - - uv_poll_start(&p->handle, p->events, redisLibuvPoll); -} - - -static void redisLibuvDelRead(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->events &= ~UV_READABLE; - - if (p->events) { - uv_poll_start(&p->handle, p->events, redisLibuvPoll); - } else { - uv_poll_stop(&p->handle); - } -} - - -static void redisLibuvAddWrite(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->events |= UV_WRITABLE; - - uv_poll_start(&p->handle, p->events, redisLibuvPoll); -} - - -static void redisLibuvDelWrite(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->events &= ~UV_WRITABLE; - - if (p->events) { - uv_poll_start(&p->handle, p->events, redisLibuvPoll); - } else { - uv_poll_stop(&p->handle); - } -} - - -static void on_close(uv_handle_t* handle) { - redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - - free(p); -} - - -static void redisLibuvCleanup(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->context = NULL; // indicate that context might no longer exist - uv_close((uv_handle_t*)&p->handle, on_close); -} - - -static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) { - redisContext *c = &(ac->c); - - if (ac->ev.data != NULL) { - return REDIS_ERR; - } - - ac->ev.addRead = redisLibuvAddRead; - ac->ev.delRead = redisLibuvDelRead; - ac->ev.addWrite = redisLibuvAddWrite; - ac->ev.delWrite = redisLibuvDelWrite; - ac->ev.cleanup = redisLibuvCleanup; - - redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p)); - - if (!p) { - return REDIS_ERR; - } - - memset(p, 0, sizeof(*p)); - - if (uv_poll_init(loop, &p->handle, c->fd) != 0) { - return REDIS_ERR; - } - - ac->ev.data = p; - p->handle.data = p; - p->context = ac; - - return REDIS_OK; -} -#endif diff --git a/ext/hiredis-0.14.1/adapters/macosx.h b/ext/hiredis-0.14.1/adapters/macosx.h deleted file mode 100644 index 72121f606..000000000 --- a/ext/hiredis-0.14.1/adapters/macosx.h +++ /dev/null @@ -1,114 +0,0 @@ -// -// Created by Дмитрий Бахвалов on 13.07.15. -// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. -// - -#ifndef __HIREDIS_MACOSX_H__ -#define __HIREDIS_MACOSX_H__ - -#include - -#include "../hiredis.h" -#include "../async.h" - -typedef struct { - redisAsyncContext *context; - CFSocketRef socketRef; - CFRunLoopSourceRef sourceRef; -} RedisRunLoop; - -static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) { - if( redisRunLoop != NULL ) { - if( redisRunLoop->sourceRef != NULL ) { - CFRunLoopSourceInvalidate(redisRunLoop->sourceRef); - CFRelease(redisRunLoop->sourceRef); - } - if( redisRunLoop->socketRef != NULL ) { - CFSocketInvalidate(redisRunLoop->socketRef); - CFRelease(redisRunLoop->socketRef); - } - free(redisRunLoop); - } - return REDIS_ERR; -} - -static void redisMacOSAddRead(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack); -} - -static void redisMacOSDelRead(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack); -} - -static void redisMacOSAddWrite(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack); -} - -static void redisMacOSDelWrite(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack); -} - -static void redisMacOSCleanup(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - freeRedisRunLoop(redisRunLoop); -} - -static void redisMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) { - redisAsyncContext* context = (redisAsyncContext*) info; - - switch (callbackType) { - case kCFSocketReadCallBack: - redisAsyncHandleRead(context); - break; - - case kCFSocketWriteCallBack: - redisAsyncHandleWrite(context); - break; - - default: - break; - } -} - -static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLoop) { - redisContext *redisCtx = &(redisAsyncCtx->c); - - /* Nothing should be attached when something is already attached */ - if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR; - - RedisRunLoop* redisRunLoop = (RedisRunLoop*) calloc(1, sizeof(RedisRunLoop)); - if( !redisRunLoop ) return REDIS_ERR; - - /* Setup redis stuff */ - redisRunLoop->context = redisAsyncCtx; - - redisAsyncCtx->ev.addRead = redisMacOSAddRead; - redisAsyncCtx->ev.delRead = redisMacOSDelRead; - redisAsyncCtx->ev.addWrite = redisMacOSAddWrite; - redisAsyncCtx->ev.delWrite = redisMacOSDelWrite; - redisAsyncCtx->ev.cleanup = redisMacOSCleanup; - redisAsyncCtx->ev.data = redisRunLoop; - - /* Initialize and install read/write events */ - CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL }; - - redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd, - kCFSocketReadCallBack | kCFSocketWriteCallBack, - redisMacOSAsyncCallback, - &socketCtx); - if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop); - - redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redisRunLoop->socketRef, 0); - if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop); - - CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, kCFRunLoopDefaultMode); - - return REDIS_OK; -} - -#endif - diff --git a/ext/hiredis-0.14.1/adapters/qt.h b/ext/hiredis-0.14.1/adapters/qt.h deleted file mode 100644 index 5cc02e6ce..000000000 --- a/ext/hiredis-0.14.1/adapters/qt.h +++ /dev/null @@ -1,135 +0,0 @@ -/*- - * Copyright (C) 2014 Pietro Cerutti - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef __HIREDIS_QT_H__ -#define __HIREDIS_QT_H__ -#include -#include "../async.h" - -static void RedisQtAddRead(void *); -static void RedisQtDelRead(void *); -static void RedisQtAddWrite(void *); -static void RedisQtDelWrite(void *); -static void RedisQtCleanup(void *); - -class RedisQtAdapter : public QObject { - - Q_OBJECT - - friend - void RedisQtAddRead(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->addRead(); - } - - friend - void RedisQtDelRead(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->delRead(); - } - - friend - void RedisQtAddWrite(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->addWrite(); - } - - friend - void RedisQtDelWrite(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->delWrite(); - } - - friend - void RedisQtCleanup(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->cleanup(); - } - - public: - RedisQtAdapter(QObject * parent = 0) - : QObject(parent), m_ctx(0), m_read(0), m_write(0) { } - - ~RedisQtAdapter() { - if (m_ctx != 0) { - m_ctx->ev.data = NULL; - } - } - - int setContext(redisAsyncContext * ac) { - if (ac->ev.data != NULL) { - return REDIS_ERR; - } - m_ctx = ac; - m_ctx->ev.data = this; - m_ctx->ev.addRead = RedisQtAddRead; - m_ctx->ev.delRead = RedisQtDelRead; - m_ctx->ev.addWrite = RedisQtAddWrite; - m_ctx->ev.delWrite = RedisQtDelWrite; - m_ctx->ev.cleanup = RedisQtCleanup; - return REDIS_OK; - } - - private: - void addRead() { - if (m_read) return; - m_read = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Read, 0); - connect(m_read, SIGNAL(activated(int)), this, SLOT(read())); - } - - void delRead() { - if (!m_read) return; - delete m_read; - m_read = 0; - } - - void addWrite() { - if (m_write) return; - m_write = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Write, 0); - connect(m_write, SIGNAL(activated(int)), this, SLOT(write())); - } - - void delWrite() { - if (!m_write) return; - delete m_write; - m_write = 0; - } - - void cleanup() { - delRead(); - delWrite(); - } - - private slots: - void read() { redisAsyncHandleRead(m_ctx); } - void write() { redisAsyncHandleWrite(m_ctx); } - - private: - redisAsyncContext * m_ctx; - QSocketNotifier * m_read; - QSocketNotifier * m_write; -}; - -#endif /* !__HIREDIS_QT_H__ */ diff --git a/ext/hiredis-0.14.1/alloc.c b/ext/hiredis-0.14.1/alloc.c deleted file mode 100644 index 55c3020e7..000000000 --- a/ext/hiredis-0.14.1/alloc.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2020, Michael Grunder - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include "alloc.h" -#include - -void *hi_malloc(size_t size) { - void *ptr = malloc(size); - if (ptr == NULL) - HIREDIS_OOM_HANDLER; - - return ptr; -} - -void *hi_calloc(size_t nmemb, size_t size) { - void *ptr = calloc(nmemb, size); - if (ptr == NULL) - HIREDIS_OOM_HANDLER; - - return ptr; -} - -void *hi_realloc(void *ptr, size_t size) { - void *newptr = realloc(ptr, size); - if (newptr == NULL) - HIREDIS_OOM_HANDLER; - - return newptr; -} - -char *hi_strdup(const char *str) { - char *newstr = strdup(str); - if (newstr == NULL) - HIREDIS_OOM_HANDLER; - - return newstr; -} diff --git a/ext/hiredis-0.14.1/alloc.h b/ext/hiredis-0.14.1/alloc.h deleted file mode 100644 index 2c9b04e35..000000000 --- a/ext/hiredis-0.14.1/alloc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2020, Michael Grunder - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HIREDIS_ALLOC_H -#define HIREDIS_ALLOC_H - -#include /* for size_t */ - -#ifndef HIREDIS_OOM_HANDLER -#define HIREDIS_OOM_HANDLER abort() -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -void *hi_malloc(size_t size); -void *hi_calloc(size_t nmemb, size_t size); -void *hi_realloc(void *ptr, size_t size); -char *hi_strdup(const char *str); - -#ifdef __cplusplus -} -#endif - -#endif /* HIREDIS_ALLOC_H */ diff --git a/ext/hiredis-0.14.1/appveyor.yml b/ext/hiredis-0.14.1/appveyor.yml deleted file mode 100644 index 819efbd58..000000000 --- a/ext/hiredis-0.14.1/appveyor.yml +++ /dev/null @@ -1,23 +0,0 @@ -# Appveyor configuration file for CI build of hiredis on Windows (under Cygwin) -environment: - matrix: - - CYG_BASH: C:\cygwin64\bin\bash - CC: gcc - - CYG_BASH: C:\cygwin\bin\bash - CC: gcc - TARGET: 32bit - TARGET_VARS: 32bit-vars - -clone_depth: 1 - -# Attempt to ensure we don't try to convert line endings to Win32 CRLF as this will cause build to fail -init: - - git config --global core.autocrlf input - -# Install needed build dependencies -install: - - '%CYG_BASH% -lc "cygcheck -dc cygwin"' - -build_script: - - 'echo building...' - - '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include "alloc.h" -#include -#include -#include -#include -#include -#include -#include "async.h" -#include "net.h" -#include "dict.c" -#include "sds.h" - -#define _EL_ADD_READ(ctx) do { \ - if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \ - } while(0) -#define _EL_DEL_READ(ctx) do { \ - if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \ - } while(0) -#define _EL_ADD_WRITE(ctx) do { \ - if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \ - } while(0) -#define _EL_DEL_WRITE(ctx) do { \ - if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \ - } while(0) -#define _EL_CLEANUP(ctx) do { \ - if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \ - } while(0); - -/* Forward declaration of function in hiredis.c */ -int __redisAppendCommand(redisContext *c, const char *cmd, size_t len); - -/* Functions managing dictionary of callbacks for pub/sub. */ -static unsigned int callbackHash(const void *key) { - return dictGenHashFunction((const unsigned char *)key, - sdslen((const sds)key)); -} - -static void *callbackValDup(void *privdata, const void *src) { - ((void) privdata); - redisCallback *dup = hi_malloc(sizeof(*dup)); - memcpy(dup,src,sizeof(*dup)); - return dup; -} - -static int callbackKeyCompare(void *privdata, const void *key1, const void *key2) { - int l1, l2; - ((void) privdata); - - l1 = sdslen((const sds)key1); - l2 = sdslen((const sds)key2); - if (l1 != l2) return 0; - return memcmp(key1,key2,l1) == 0; -} - -static void callbackKeyDestructor(void *privdata, void *key) { - ((void) privdata); - sdsfree((sds)key); -} - -static void callbackValDestructor(void *privdata, void *val) { - ((void) privdata); - free(val); -} - -static dictType callbackDict = { - callbackHash, - NULL, - callbackValDup, - callbackKeyCompare, - callbackKeyDestructor, - callbackValDestructor -}; - -static redisAsyncContext *redisAsyncInitialize(redisContext *c) { - redisAsyncContext *ac; - - ac = realloc(c,sizeof(redisAsyncContext)); - if (ac == NULL) - return NULL; - - c = &(ac->c); - - /* The regular connect functions will always set the flag REDIS_CONNECTED. - * For the async API, we want to wait until the first write event is - * received up before setting this flag, so reset it here. */ - c->flags &= ~REDIS_CONNECTED; - - ac->err = 0; - ac->errstr = NULL; - ac->data = NULL; - - ac->ev.data = NULL; - ac->ev.addRead = NULL; - ac->ev.delRead = NULL; - ac->ev.addWrite = NULL; - ac->ev.delWrite = NULL; - ac->ev.cleanup = NULL; - - ac->onConnect = NULL; - ac->onDisconnect = NULL; - - ac->replies.head = NULL; - ac->replies.tail = NULL; - ac->sub.invalid.head = NULL; - ac->sub.invalid.tail = NULL; - ac->sub.channels = dictCreate(&callbackDict,NULL); - ac->sub.patterns = dictCreate(&callbackDict,NULL); - return ac; -} - -/* We want the error field to be accessible directly instead of requiring - * an indirection to the redisContext struct. */ -static void __redisAsyncCopyError(redisAsyncContext *ac) { - if (!ac) - return; - - redisContext *c = &(ac->c); - ac->err = c->err; - ac->errstr = c->errstr; -} - -redisAsyncContext *redisAsyncConnect(const char *ip, int port) { - redisContext *c; - redisAsyncContext *ac; - - c = redisConnectNonBlock(ip,port); - if (c == NULL) - return NULL; - - ac = redisAsyncInitialize(c); - if (ac == NULL) { - redisFree(c); - return NULL; - } - - __redisAsyncCopyError(ac); - return ac; -} - -redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, - const char *source_addr) { - redisContext *c = redisConnectBindNonBlock(ip,port,source_addr); - redisAsyncContext *ac = redisAsyncInitialize(c); - __redisAsyncCopyError(ac); - return ac; -} - -redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port, - const char *source_addr) { - redisContext *c = redisConnectBindNonBlockWithReuse(ip,port,source_addr); - redisAsyncContext *ac = redisAsyncInitialize(c); - __redisAsyncCopyError(ac); - return ac; -} - -redisAsyncContext *redisAsyncConnectUnix(const char *path) { - redisContext *c; - redisAsyncContext *ac; - - c = redisConnectUnixNonBlock(path); - if (c == NULL) - return NULL; - - ac = redisAsyncInitialize(c); - if (ac == NULL) { - redisFree(c); - return NULL; - } - - __redisAsyncCopyError(ac); - return ac; -} - -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) { - if (ac->onConnect == NULL) { - ac->onConnect = fn; - - /* The common way to detect an established connection is to wait for - * the first write event to be fired. This assumes the related event - * library functions are already set. */ - _EL_ADD_WRITE(ac); - return REDIS_OK; - } - return REDIS_ERR; -} - -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn) { - if (ac->onDisconnect == NULL) { - ac->onDisconnect = fn; - return REDIS_OK; - } - return REDIS_ERR; -} - -/* Helper functions to push/shift callbacks */ -static int __redisPushCallback(redisCallbackList *list, redisCallback *source) { - redisCallback *cb; - - /* Copy callback from stack to heap */ - cb = malloc(sizeof(*cb)); - if (cb == NULL) - return REDIS_ERR_OOM; - - if (source != NULL) { - memcpy(cb,source,sizeof(*cb)); - cb->next = NULL; - } - - /* Store callback in list */ - if (list->head == NULL) - list->head = cb; - if (list->tail != NULL) - list->tail->next = cb; - list->tail = cb; - return REDIS_OK; -} - -static int __redisShiftCallback(redisCallbackList *list, redisCallback *target) { - redisCallback *cb = list->head; - if (cb != NULL) { - list->head = cb->next; - if (cb == list->tail) - list->tail = NULL; - - /* Copy callback from heap to stack */ - if (target != NULL) - memcpy(target,cb,sizeof(*cb)); - free(cb); - return REDIS_OK; - } - return REDIS_ERR; -} - -static void __redisRunCallback(redisAsyncContext *ac, redisCallback *cb, redisReply *reply) { - redisContext *c = &(ac->c); - if (cb->fn != NULL) { - c->flags |= REDIS_IN_CALLBACK; - cb->fn(ac,reply,cb->privdata); - c->flags &= ~REDIS_IN_CALLBACK; - } -} - -/* Helper function to free the context. */ -static void __redisAsyncFree(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisCallback cb; - dictIterator *it; - dictEntry *de; - - /* Execute pending callbacks with NULL reply. */ - while (__redisShiftCallback(&ac->replies,&cb) == REDIS_OK) - __redisRunCallback(ac,&cb,NULL); - - /* Execute callbacks for invalid commands */ - while (__redisShiftCallback(&ac->sub.invalid,&cb) == REDIS_OK) - __redisRunCallback(ac,&cb,NULL); - - /* Run subscription callbacks callbacks with NULL reply */ - it = dictGetIterator(ac->sub.channels); - while ((de = dictNext(it)) != NULL) - __redisRunCallback(ac,dictGetEntryVal(de),NULL); - dictReleaseIterator(it); - dictRelease(ac->sub.channels); - - it = dictGetIterator(ac->sub.patterns); - while ((de = dictNext(it)) != NULL) - __redisRunCallback(ac,dictGetEntryVal(de),NULL); - dictReleaseIterator(it); - dictRelease(ac->sub.patterns); - - /* Signal event lib to clean up */ - _EL_CLEANUP(ac); - - /* Execute disconnect callback. When redisAsyncFree() initiated destroying - * this context, the status will always be REDIS_OK. */ - if (ac->onDisconnect && (c->flags & REDIS_CONNECTED)) { - if (c->flags & REDIS_FREEING) { - ac->onDisconnect(ac,REDIS_OK); - } else { - ac->onDisconnect(ac,(ac->err == 0) ? REDIS_OK : REDIS_ERR); - } - } - - /* Cleanup self */ - redisFree(c); -} - -/* Free the async context. When this function is called from a callback, - * control needs to be returned to redisProcessCallbacks() before actual - * free'ing. To do so, a flag is set on the context which is picked up by - * redisProcessCallbacks(). Otherwise, the context is immediately free'd. */ -void redisAsyncFree(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - c->flags |= REDIS_FREEING; - if (!(c->flags & REDIS_IN_CALLBACK)) - __redisAsyncFree(ac); -} - -/* Helper function to make the disconnect happen and clean up. */ -static void __redisAsyncDisconnect(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - /* Make sure error is accessible if there is any */ - __redisAsyncCopyError(ac); - - if (ac->err == 0) { - /* For clean disconnects, there should be no pending callbacks. */ - int ret = __redisShiftCallback(&ac->replies,NULL); - assert(ret == REDIS_ERR); - } else { - /* Disconnection is caused by an error, make sure that pending - * callbacks cannot call new commands. */ - c->flags |= REDIS_DISCONNECTING; - } - - /* For non-clean disconnects, __redisAsyncFree() will execute pending - * callbacks with a NULL-reply. */ - __redisAsyncFree(ac); -} - -/* Tries to do a clean disconnect from Redis, meaning it stops new commands - * from being issued, but tries to flush the output buffer and execute - * callbacks for all remaining replies. When this function is called from a - * callback, there might be more replies and we can safely defer disconnecting - * to redisProcessCallbacks(). Otherwise, we can only disconnect immediately - * when there are no pending callbacks. */ -void redisAsyncDisconnect(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - c->flags |= REDIS_DISCONNECTING; - if (!(c->flags & REDIS_IN_CALLBACK) && ac->replies.head == NULL) - __redisAsyncDisconnect(ac); -} - -static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, redisCallback *dstcb) { - redisContext *c = &(ac->c); - dict *callbacks; - redisCallback *cb; - dictEntry *de; - int pvariant; - char *stype; - sds sname; - - /* Custom reply functions are not supported for pub/sub. This will fail - * very hard when they are used... */ - if (reply->type == REDIS_REPLY_ARRAY) { - assert(reply->elements >= 2); - assert(reply->element[0]->type == REDIS_REPLY_STRING); - stype = reply->element[0]->str; - pvariant = (tolower(stype[0]) == 'p') ? 1 : 0; - - if (pvariant) - callbacks = ac->sub.patterns; - else - callbacks = ac->sub.channels; - - /* Locate the right callback */ - assert(reply->element[1]->type == REDIS_REPLY_STRING); - sname = sdsnewlen(reply->element[1]->str,reply->element[1]->len); - de = dictFind(callbacks,sname); - if (de != NULL) { - cb = dictGetEntryVal(de); - - /* If this is an subscribe reply decrease pending counter. */ - if (strcasecmp(stype+pvariant,"subscribe") == 0) { - cb->pending_subs -= 1; - } - - memcpy(dstcb,cb,sizeof(*dstcb)); - - /* If this is an unsubscribe message, remove it. */ - if (strcasecmp(stype+pvariant,"unsubscribe") == 0) { - if (cb->pending_subs == 0) - dictDelete(callbacks,sname); - - /* If this was the last unsubscribe message, revert to - * non-subscribe mode. */ - assert(reply->element[2]->type == REDIS_REPLY_INTEGER); - - /* Unset subscribed flag only when no pipelined pending subscribe. */ - if (reply->element[2]->integer == 0 - && dictSize(ac->sub.channels) == 0 - && dictSize(ac->sub.patterns) == 0) - c->flags &= ~REDIS_SUBSCRIBED; - } - } - sdsfree(sname); - } else { - /* Shift callback for invalid commands. */ - __redisShiftCallback(&ac->sub.invalid,dstcb); - } - return REDIS_OK; -} - -void redisProcessCallbacks(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisCallback cb = {NULL, NULL, 0, NULL}; - void *reply = NULL; - int status; - - while((status = redisGetReply(c,&reply)) == REDIS_OK) { - if (reply == NULL) { - /* When the connection is being disconnected and there are - * no more replies, this is the cue to really disconnect. */ - if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0 - && ac->replies.head == NULL) { - __redisAsyncDisconnect(ac); - return; - } - - /* If monitor mode, repush callback */ - if(c->flags & REDIS_MONITORING) { - __redisPushCallback(&ac->replies,&cb); - } - - /* When the connection is not being disconnected, simply stop - * trying to get replies and wait for the next loop tick. */ - break; - } - - /* Even if the context is subscribed, pending regular callbacks will - * get a reply before pub/sub messages arrive. */ - if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) { - /* - * A spontaneous reply in a not-subscribed context can be the error - * reply that is sent when a new connection exceeds the maximum - * number of allowed connections on the server side. - * - * This is seen as an error instead of a regular reply because the - * server closes the connection after sending it. - * - * To prevent the error from being overwritten by an EOF error the - * connection is closed here. See issue #43. - * - * Another possibility is that the server is loading its dataset. - * In this case we also want to close the connection, and have the - * user wait until the server is ready to take our request. - */ - if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) { - c->err = REDIS_ERR_OTHER; - snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str); - c->reader->fn->freeObject(reply); - __redisAsyncDisconnect(ac); - return; - } - /* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */ - assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING)); - if(c->flags & REDIS_SUBSCRIBED) - __redisGetSubscribeCallback(ac,reply,&cb); - } - - if (cb.fn != NULL) { - __redisRunCallback(ac,&cb,reply); - c->reader->fn->freeObject(reply); - - /* Proceed with free'ing when redisAsyncFree() was called. */ - if (c->flags & REDIS_FREEING) { - __redisAsyncFree(ac); - return; - } - } else { - /* No callback for this reply. This can either be a NULL callback, - * or there were no callbacks to begin with. Either way, don't - * abort with an error, but simply ignore it because the client - * doesn't know what the server will spit out over the wire. */ - c->reader->fn->freeObject(reply); - } - } - - /* Disconnect when there was an error reading the reply */ - if (status != REDIS_OK) - __redisAsyncDisconnect(ac); -} - -/* Internal helper function to detect socket status the first time a read or - * write event fires. When connecting was not successful, the connect callback - * is called with a REDIS_ERR status and the context is free'd. */ -static int __redisAsyncHandleConnect(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - if (redisCheckSocketError(c) == REDIS_ERR) { - /* Try again later when connect(2) is still in progress. */ - if (errno == EINPROGRESS) - return REDIS_OK; - - if (ac->onConnect) ac->onConnect(ac,REDIS_ERR); - __redisAsyncDisconnect(ac); - return REDIS_ERR; - } - - /* Mark context as connected. */ - c->flags |= REDIS_CONNECTED; - if (ac->onConnect) ac->onConnect(ac,REDIS_OK); - return REDIS_OK; -} - -/* This function should be called when the socket is readable. - * It processes all replies that can be read and executes their callbacks. - */ -void redisAsyncHandleRead(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - if (!(c->flags & REDIS_CONNECTED)) { - /* Abort connect was not successful. */ - if (__redisAsyncHandleConnect(ac) != REDIS_OK) - return; - /* Try again later when the context is still not connected. */ - if (!(c->flags & REDIS_CONNECTED)) - return; - } - - if (redisBufferRead(c) == REDIS_ERR) { - __redisAsyncDisconnect(ac); - } else { - /* Always re-schedule reads */ - _EL_ADD_READ(ac); - redisProcessCallbacks(ac); - } -} - -void redisAsyncHandleWrite(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - int done = 0; - - if (!(c->flags & REDIS_CONNECTED)) { - /* Abort connect was not successful. */ - if (__redisAsyncHandleConnect(ac) != REDIS_OK) - return; - /* Try again later when the context is still not connected. */ - if (!(c->flags & REDIS_CONNECTED)) - return; - } - - if (redisBufferWrite(c,&done) == REDIS_ERR) { - __redisAsyncDisconnect(ac); - } else { - /* Continue writing when not done, stop writing otherwise */ - if (!done) - _EL_ADD_WRITE(ac); - else - _EL_DEL_WRITE(ac); - - /* Always schedule reads after writes */ - _EL_ADD_READ(ac); - } -} - -/* Sets a pointer to the first argument and its length starting at p. Returns - * the number of bytes to skip to get to the following argument. */ -static const char *nextArgument(const char *start, const char **str, size_t *len) { - const char *p = start; - if (p[0] != '$') { - p = strchr(p,'$'); - if (p == NULL) return NULL; - } - - *len = (int)strtol(p+1,NULL,10); - p = strchr(p,'\r'); - assert(p); - *str = p+2; - return p+2+(*len)+2; -} - -/* Helper function for the redisAsyncCommand* family of functions. Writes a - * formatted command to the output buffer and registers the provided callback - * function with the context. */ -static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len) { - redisContext *c = &(ac->c); - redisCallback cb; - struct dict *cbdict; - dictEntry *de; - redisCallback *existcb; - int pvariant, hasnext; - const char *cstr, *astr; - size_t clen, alen; - const char *p; - sds sname; - int ret; - - /* Don't accept new commands when the connection is about to be closed. */ - if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR; - - /* Setup callback */ - cb.fn = fn; - cb.privdata = privdata; - cb.pending_subs = 1; - - /* Find out which command will be appended. */ - p = nextArgument(cmd,&cstr,&clen); - assert(p != NULL); - hasnext = (p[0] == '$'); - pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0; - cstr += pvariant; - clen -= pvariant; - - if (hasnext && strncasecmp(cstr,"subscribe\r\n",11) == 0) { - c->flags |= REDIS_SUBSCRIBED; - - /* Add every channel/pattern to the list of subscription callbacks. */ - while ((p = nextArgument(p,&astr,&alen)) != NULL) { - sname = sdsnewlen(astr,alen); - if (pvariant) - cbdict = ac->sub.patterns; - else - cbdict = ac->sub.channels; - - de = dictFind(cbdict,sname); - - if (de != NULL) { - existcb = dictGetEntryVal(de); - cb.pending_subs = existcb->pending_subs + 1; - } - - ret = dictReplace(cbdict,sname,&cb); - - if (ret == 0) sdsfree(sname); - } - } else if (strncasecmp(cstr,"unsubscribe\r\n",13) == 0) { - /* It is only useful to call (P)UNSUBSCRIBE when the context is - * subscribed to one or more channels or patterns. */ - if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR; - - /* (P)UNSUBSCRIBE does not have its own response: every channel or - * pattern that is unsubscribed will receive a message. This means we - * should not append a callback function for this command. */ - } else if(strncasecmp(cstr,"monitor\r\n",9) == 0) { - /* Set monitor flag and push callback */ - c->flags |= REDIS_MONITORING; - __redisPushCallback(&ac->replies,&cb); - } else { - if (c->flags & REDIS_SUBSCRIBED) - /* This will likely result in an error reply, but it needs to be - * received and passed to the callback. */ - __redisPushCallback(&ac->sub.invalid,&cb); - else - __redisPushCallback(&ac->replies,&cb); - } - - __redisAppendCommand(c,cmd,len); - - /* Always schedule a write when the write buffer is non-empty */ - _EL_ADD_WRITE(ac); - - return REDIS_OK; -} - -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap) { - char *cmd; - int len; - int status; - len = redisvFormatCommand(&cmd,format,ap); - - /* We don't want to pass -1 or -2 to future functions as a length. */ - if (len < 0) - return REDIS_ERR; - - status = __redisAsyncCommand(ac,fn,privdata,cmd,len); - free(cmd); - return status; -} - -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...) { - va_list ap; - int status; - va_start(ap,format); - status = redisvAsyncCommand(ac,fn,privdata,format,ap); - va_end(ap); - return status; -} - -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen) { - sds cmd; - int len; - int status; - len = redisFormatSdsCommandArgv(&cmd,argc,argv,argvlen); - if (len < 0) - return REDIS_ERR; - status = __redisAsyncCommand(ac,fn,privdata,cmd,len); - sdsfree(cmd); - return status; -} - -int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len) { - int status = __redisAsyncCommand(ac,fn,privdata,cmd,len); - return status; -} diff --git a/ext/hiredis-0.14.1/async.h b/ext/hiredis-0.14.1/async.h deleted file mode 100644 index e69d84090..000000000 --- a/ext/hiredis-0.14.1/async.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_ASYNC_H -#define __HIREDIS_ASYNC_H -#include "hiredis.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ -struct dict; /* dictionary header is included in async.c */ - -/* Reply callback prototype and container */ -typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); -typedef struct redisCallback { - struct redisCallback *next; /* simple singly linked list */ - redisCallbackFn *fn; - int pending_subs; - void *privdata; -} redisCallback; - -/* List of callbacks for either regular replies or pub/sub */ -typedef struct redisCallbackList { - redisCallback *head, *tail; -} redisCallbackList; - -/* Connection callback prototypes */ -typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); -typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); - -/* Context for an async connection to Redis */ -typedef struct redisAsyncContext { - /* Hold the regular context, so it can be realloc'ed. */ - redisContext c; - - /* Setup error flags so they can be used directly. */ - int err; - char *errstr; - - /* Not used by hiredis */ - void *data; - - /* Event library data and hooks */ - struct { - void *data; - - /* Hooks that are called when the library expects to start - * reading/writing. These functions should be idempotent. */ - void (*addRead)(void *privdata); - void (*delRead)(void *privdata); - void (*addWrite)(void *privdata); - void (*delWrite)(void *privdata); - void (*cleanup)(void *privdata); - } ev; - - /* Called when either the connection is terminated due to an error or per - * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */ - redisDisconnectCallback *onDisconnect; - - /* Called when the first write event was received. */ - redisConnectCallback *onConnect; - - /* Regular command callbacks */ - redisCallbackList replies; - - /* Subscription callbacks */ - struct { - redisCallbackList invalid; - struct dict *channels; - struct dict *patterns; - } sub; -} redisAsyncContext; - -/* Functions that proxy to hiredis */ -redisAsyncContext *redisAsyncConnect(const char *ip, int port); -redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr); -redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port, - const char *source_addr); -redisAsyncContext *redisAsyncConnectUnix(const char *path); -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); -void redisAsyncDisconnect(redisAsyncContext *ac); -void redisAsyncFree(redisAsyncContext *ac); - -/* Handle read/write events */ -void redisAsyncHandleRead(redisAsyncContext *ac); -void redisAsyncHandleWrite(redisAsyncContext *ac); - -/* Command functions for an async context. Write the command to the - * output buffer and register the provided callback. */ -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); -int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-0.14.1/dict.c b/ext/hiredis-0.14.1/dict.c deleted file mode 100644 index 29cdc190f..000000000 --- a/ext/hiredis-0.14.1/dict.c +++ /dev/null @@ -1,339 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include "alloc.h" -#include -#include -#include -#include "dict.h" - -/* -------------------------- private prototypes ---------------------------- */ - -static int _dictExpandIfNeeded(dict *ht); -static unsigned long _dictNextPower(unsigned long size); -static int _dictKeyIndex(dict *ht, const void *key); -static int _dictInit(dict *ht, dictType *type, void *privDataPtr); - -/* -------------------------- hash functions -------------------------------- */ - -/* Generic hash function (a popular one from Bernstein). - * I tested a few and this was the best. */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len) { - unsigned int hash = 5381; - - while (len--) - hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */ - return hash; -} - -/* ----------------------------- API implementation ------------------------- */ - -/* Reset an hashtable already initialized with ht_init(). - * NOTE: This function should only called by ht_destroy(). */ -static void _dictReset(dict *ht) { - ht->table = NULL; - ht->size = 0; - ht->sizemask = 0; - ht->used = 0; -} - -/* Create a new hash table */ -static dict *dictCreate(dictType *type, void *privDataPtr) { - dict *ht = hi_malloc(sizeof(*ht)); - _dictInit(ht,type,privDataPtr); - return ht; -} - -/* Initialize the hash table */ -static int _dictInit(dict *ht, dictType *type, void *privDataPtr) { - _dictReset(ht); - ht->type = type; - ht->privdata = privDataPtr; - return DICT_OK; -} - -/* Expand or create the hashtable */ -static int dictExpand(dict *ht, unsigned long size) { - dict n; /* the new hashtable */ - unsigned long realsize = _dictNextPower(size), i; - - /* the size is invalid if it is smaller than the number of - * elements already inside the hashtable */ - if (ht->used > size) - return DICT_ERR; - - _dictInit(&n, ht->type, ht->privdata); - n.size = realsize; - n.sizemask = realsize-1; - n.table = calloc(realsize,sizeof(dictEntry*)); - - /* Copy all the elements from the old to the new table: - * note that if the old hash table is empty ht->size is zero, - * so dictExpand just creates an hash table. */ - n.used = ht->used; - for (i = 0; i < ht->size && ht->used > 0; i++) { - dictEntry *he, *nextHe; - - if (ht->table[i] == NULL) continue; - - /* For each hash entry on this slot... */ - he = ht->table[i]; - while(he) { - unsigned int h; - - nextHe = he->next; - /* Get the new element index */ - h = dictHashKey(ht, he->key) & n.sizemask; - he->next = n.table[h]; - n.table[h] = he; - ht->used--; - /* Pass to the next element */ - he = nextHe; - } - } - assert(ht->used == 0); - free(ht->table); - - /* Remap the new hashtable in the old */ - *ht = n; - return DICT_OK; -} - -/* Add an element to the target hash table */ -static int dictAdd(dict *ht, void *key, void *val) { - int index; - dictEntry *entry; - - /* Get the index of the new element, or -1 if - * the element already exists. */ - if ((index = _dictKeyIndex(ht, key)) == -1) - return DICT_ERR; - - /* Allocates the memory and stores key */ - entry = hi_malloc(sizeof(*entry)); - entry->next = ht->table[index]; - ht->table[index] = entry; - - /* Set the hash entry fields. */ - dictSetHashKey(ht, entry, key); - dictSetHashVal(ht, entry, val); - ht->used++; - return DICT_OK; -} - -/* Add an element, discarding the old if the key already exists. - * Return 1 if the key was added from scratch, 0 if there was already an - * element with such key and dictReplace() just performed a value update - * operation. */ -static int dictReplace(dict *ht, void *key, void *val) { - dictEntry *entry, auxentry; - - /* Try to add the element. If the key - * does not exists dictAdd will succeed. */ - if (dictAdd(ht, key, val) == DICT_OK) - return 1; - /* It already exists, get the entry */ - entry = dictFind(ht, key); - /* Free the old value and set the new one */ - /* Set the new value and free the old one. Note that it is important - * to do that in this order, as the value may just be exactly the same - * as the previous one. In this context, think to reference counting, - * you want to increment (set), and then decrement (free), and not the - * reverse. */ - auxentry = *entry; - dictSetHashVal(ht, entry, val); - dictFreeEntryVal(ht, &auxentry); - return 0; -} - -/* Search and remove an element */ -static int dictDelete(dict *ht, const void *key) { - unsigned int h; - dictEntry *de, *prevde; - - if (ht->size == 0) - return DICT_ERR; - h = dictHashKey(ht, key) & ht->sizemask; - de = ht->table[h]; - - prevde = NULL; - while(de) { - if (dictCompareHashKeys(ht,key,de->key)) { - /* Unlink the element from the list */ - if (prevde) - prevde->next = de->next; - else - ht->table[h] = de->next; - - dictFreeEntryKey(ht,de); - dictFreeEntryVal(ht,de); - free(de); - ht->used--; - return DICT_OK; - } - prevde = de; - de = de->next; - } - return DICT_ERR; /* not found */ -} - -/* Destroy an entire hash table */ -static int _dictClear(dict *ht) { - unsigned long i; - - /* Free all the elements */ - for (i = 0; i < ht->size && ht->used > 0; i++) { - dictEntry *he, *nextHe; - - if ((he = ht->table[i]) == NULL) continue; - while(he) { - nextHe = he->next; - dictFreeEntryKey(ht, he); - dictFreeEntryVal(ht, he); - free(he); - ht->used--; - he = nextHe; - } - } - /* Free the table and the allocated cache structure */ - free(ht->table); - /* Re-initialize the table */ - _dictReset(ht); - return DICT_OK; /* never fails */ -} - -/* Clear & Release the hash table */ -static void dictRelease(dict *ht) { - _dictClear(ht); - free(ht); -} - -static dictEntry *dictFind(dict *ht, const void *key) { - dictEntry *he; - unsigned int h; - - if (ht->size == 0) return NULL; - h = dictHashKey(ht, key) & ht->sizemask; - he = ht->table[h]; - while(he) { - if (dictCompareHashKeys(ht, key, he->key)) - return he; - he = he->next; - } - return NULL; -} - -static dictIterator *dictGetIterator(dict *ht) { - dictIterator *iter = hi_malloc(sizeof(*iter)); - - iter->ht = ht; - iter->index = -1; - iter->entry = NULL; - iter->nextEntry = NULL; - return iter; -} - -static dictEntry *dictNext(dictIterator *iter) { - while (1) { - if (iter->entry == NULL) { - iter->index++; - if (iter->index >= - (signed)iter->ht->size) break; - iter->entry = iter->ht->table[iter->index]; - } else { - iter->entry = iter->nextEntry; - } - if (iter->entry) { - /* We need to save the 'next' here, the iterator user - * may delete the entry we are returning. */ - iter->nextEntry = iter->entry->next; - return iter->entry; - } - } - return NULL; -} - -static void dictReleaseIterator(dictIterator *iter) { - free(iter); -} - -/* ------------------------- private functions ------------------------------ */ - -/* Expand the hash table if needed */ -static int _dictExpandIfNeeded(dict *ht) { - /* If the hash table is empty expand it to the initial size, - * if the table is "full" dobule its size. */ - if (ht->size == 0) - return dictExpand(ht, DICT_HT_INITIAL_SIZE); - if (ht->used == ht->size) - return dictExpand(ht, ht->size*2); - return DICT_OK; -} - -/* Our hash table capability is a power of two */ -static unsigned long _dictNextPower(unsigned long size) { - unsigned long i = DICT_HT_INITIAL_SIZE; - - if (size >= LONG_MAX) return LONG_MAX; - while(1) { - if (i >= size) - return i; - i *= 2; - } -} - -/* Returns the index of a free slot that can be populated with - * an hash entry for the given 'key'. - * If the key already exists, -1 is returned. */ -static int _dictKeyIndex(dict *ht, const void *key) { - unsigned int h; - dictEntry *he; - - /* Expand the hashtable if needed */ - if (_dictExpandIfNeeded(ht) == DICT_ERR) - return -1; - /* Compute the key hash value */ - h = dictHashKey(ht, key) & ht->sizemask; - /* Search if this slot does not already contain the given key */ - he = ht->table[h]; - while(he) { - if (dictCompareHashKeys(ht, key, he->key)) - return -1; - he = he->next; - } - return h; -} - diff --git a/ext/hiredis-0.14.1/dict.h b/ext/hiredis-0.14.1/dict.h deleted file mode 100644 index 95fcd280e..000000000 --- a/ext/hiredis-0.14.1/dict.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DICT_H -#define __DICT_H - -#define DICT_OK 0 -#define DICT_ERR 1 - -/* Unused arguments generate annoying warnings... */ -#define DICT_NOTUSED(V) ((void) V) - -typedef struct dictEntry { - void *key; - void *val; - struct dictEntry *next; -} dictEntry; - -typedef struct dictType { - unsigned int (*hashFunction)(const void *key); - void *(*keyDup)(void *privdata, const void *key); - void *(*valDup)(void *privdata, const void *obj); - int (*keyCompare)(void *privdata, const void *key1, const void *key2); - void (*keyDestructor)(void *privdata, void *key); - void (*valDestructor)(void *privdata, void *obj); -} dictType; - -typedef struct dict { - dictEntry **table; - dictType *type; - unsigned long size; - unsigned long sizemask; - unsigned long used; - void *privdata; -} dict; - -typedef struct dictIterator { - dict *ht; - int index; - dictEntry *entry, *nextEntry; -} dictIterator; - -/* This is the initial size of every hash table */ -#define DICT_HT_INITIAL_SIZE 4 - -/* ------------------------------- Macros ------------------------------------*/ -#define dictFreeEntryVal(ht, entry) \ - if ((ht)->type->valDestructor) \ - (ht)->type->valDestructor((ht)->privdata, (entry)->val) - -#define dictSetHashVal(ht, entry, _val_) do { \ - if ((ht)->type->valDup) \ - entry->val = (ht)->type->valDup((ht)->privdata, _val_); \ - else \ - entry->val = (_val_); \ -} while(0) - -#define dictFreeEntryKey(ht, entry) \ - if ((ht)->type->keyDestructor) \ - (ht)->type->keyDestructor((ht)->privdata, (entry)->key) - -#define dictSetHashKey(ht, entry, _key_) do { \ - if ((ht)->type->keyDup) \ - entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ - else \ - entry->key = (_key_); \ -} while(0) - -#define dictCompareHashKeys(ht, key1, key2) \ - (((ht)->type->keyCompare) ? \ - (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ - (key1) == (key2)) - -#define dictHashKey(ht, key) (ht)->type->hashFunction(key) - -#define dictGetEntryKey(he) ((he)->key) -#define dictGetEntryVal(he) ((he)->val) -#define dictSlots(ht) ((ht)->size) -#define dictSize(ht) ((ht)->used) - -/* API */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len); -static dict *dictCreate(dictType *type, void *privDataPtr); -static int dictExpand(dict *ht, unsigned long size); -static int dictAdd(dict *ht, void *key, void *val); -static int dictReplace(dict *ht, void *key, void *val); -static int dictDelete(dict *ht, const void *key); -static void dictRelease(dict *ht); -static dictEntry * dictFind(dict *ht, const void *key); -static dictIterator *dictGetIterator(dict *ht); -static dictEntry *dictNext(dictIterator *iter); -static void dictReleaseIterator(dictIterator *iter); - -#endif /* __DICT_H */ diff --git a/ext/hiredis-0.14.1/examples/example-ae.c b/ext/hiredis-0.14.1/examples/example-ae.c deleted file mode 100644 index 8efa7306a..000000000 --- a/ext/hiredis-0.14.1/examples/example-ae.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -/* Put event loop in the global scope, so it can be explicitly stopped */ -static aeEventLoop *loop; - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - aeStop(loop); - return; - } - - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - aeStop(loop); - return; - } - - printf("Disconnected...\n"); - aeStop(loop); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - loop = aeCreateEventLoop(64); - redisAeAttach(loop, c); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - aeMain(loop); - return 0; -} - diff --git a/ext/hiredis-0.14.1/examples/example-glib.c b/ext/hiredis-0.14.1/examples/example-glib.c deleted file mode 100644 index d6e10f8e8..000000000 --- a/ext/hiredis-0.14.1/examples/example-glib.c +++ /dev/null @@ -1,73 +0,0 @@ -#include - -#include -#include -#include - -static GMainLoop *mainloop; - -static void -connect_cb (const redisAsyncContext *ac G_GNUC_UNUSED, - int status) -{ - if (status != REDIS_OK) { - g_printerr("Failed to connect: %s\n", ac->errstr); - g_main_loop_quit(mainloop); - } else { - g_printerr("Connected...\n"); - } -} - -static void -disconnect_cb (const redisAsyncContext *ac G_GNUC_UNUSED, - int status) -{ - if (status != REDIS_OK) { - g_error("Failed to disconnect: %s", ac->errstr); - } else { - g_printerr("Disconnected...\n"); - g_main_loop_quit(mainloop); - } -} - -static void -command_cb(redisAsyncContext *ac, - gpointer r, - gpointer user_data G_GNUC_UNUSED) -{ - redisReply *reply = r; - - if (reply) { - g_print("REPLY: %s\n", reply->str); - } - - redisAsyncDisconnect(ac); -} - -gint -main (gint argc G_GNUC_UNUSED, - gchar *argv[] G_GNUC_UNUSED) -{ - redisAsyncContext *ac; - GMainContext *context = NULL; - GSource *source; - - ac = redisAsyncConnect("127.0.0.1", 6379); - if (ac->err) { - g_printerr("%s\n", ac->errstr); - exit(EXIT_FAILURE); - } - - source = redis_source_new(ac); - mainloop = g_main_loop_new(context, FALSE); - g_source_attach(source, context); - - redisAsyncSetConnectCallback(ac, connect_cb); - redisAsyncSetDisconnectCallback(ac, disconnect_cb); - redisAsyncCommand(ac, command_cb, NULL, "SET key 1234"); - redisAsyncCommand(ac, command_cb, NULL, "GET key"); - - g_main_loop_run(mainloop); - - return EXIT_SUCCESS; -} diff --git a/ext/hiredis-0.14.1/examples/example-ivykis.c b/ext/hiredis-0.14.1/examples/example-ivykis.c deleted file mode 100644 index 67affcef3..000000000 --- a/ext/hiredis-0.14.1/examples/example-ivykis.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - - iv_init(); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisIvykisAttach(c); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - - iv_main(); - - iv_deinit(); - - return 0; -} diff --git a/ext/hiredis-0.14.1/examples/example-libev.c b/ext/hiredis-0.14.1/examples/example-libev.c deleted file mode 100644 index cc8b166ec..000000000 --- a/ext/hiredis-0.14.1/examples/example-libev.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisLibevAttach(EV_DEFAULT_ c); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - ev_loop(EV_DEFAULT_ 0); - return 0; -} diff --git a/ext/hiredis-0.14.1/examples/example-libevent.c b/ext/hiredis-0.14.1/examples/example-libevent.c deleted file mode 100644 index d333c22b7..000000000 --- a/ext/hiredis-0.14.1/examples/example-libevent.c +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - struct event_base *base = event_base_new(); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisLibeventAttach(c,base); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - event_base_dispatch(base); - return 0; -} diff --git a/ext/hiredis-0.14.1/examples/example-libuv.c b/ext/hiredis-0.14.1/examples/example-libuv.c deleted file mode 100644 index a5462d410..000000000 --- a/ext/hiredis-0.14.1/examples/example-libuv.c +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - uv_loop_t* loop = uv_default_loop(); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisLibuvAttach(c,loop); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - uv_run(loop, UV_RUN_DEFAULT); - return 0; -} diff --git a/ext/hiredis-0.14.1/examples/example-macosx.c b/ext/hiredis-0.14.1/examples/example-macosx.c deleted file mode 100644 index bc84ed5ba..000000000 --- a/ext/hiredis-0.14.1/examples/example-macosx.c +++ /dev/null @@ -1,66 +0,0 @@ -// -// Created by Дмитрий Бахвалов on 13.07.15. -// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. -// - -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - CFRunLoopStop(CFRunLoopGetCurrent()); - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - - CFRunLoopRef loop = CFRunLoopGetCurrent(); - if( !loop ) { - printf("Error: Cannot get current run loop\n"); - return 1; - } - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisMacOSAttach(c, loop); - - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - - CFRunLoopRun(); - - return 0; -} - diff --git a/ext/hiredis-0.14.1/examples/example-qt.cpp b/ext/hiredis-0.14.1/examples/example-qt.cpp deleted file mode 100644 index f524c3f3d..000000000 --- a/ext/hiredis-0.14.1/examples/example-qt.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -using namespace std; - -#include -#include - -#include "example-qt.h" - -void getCallback(redisAsyncContext *, void * r, void * privdata) { - - redisReply * reply = static_cast(r); - ExampleQt * ex = static_cast(privdata); - if (reply == nullptr || ex == nullptr) return; - - cout << "key: " << reply->str << endl; - - ex->finish(); -} - -void ExampleQt::run() { - - m_ctx = redisAsyncConnect("localhost", 6379); - - if (m_ctx->err) { - cerr << "Error: " << m_ctx->errstr << endl; - redisAsyncFree(m_ctx); - emit finished(); - } - - m_adapter.setContext(m_ctx); - - redisAsyncCommand(m_ctx, NULL, NULL, "SET key %s", m_value); - redisAsyncCommand(m_ctx, getCallback, this, "GET key"); -} - -int main (int argc, char **argv) { - - QCoreApplication app(argc, argv); - - ExampleQt example(argv[argc-1]); - - QObject::connect(&example, SIGNAL(finished()), &app, SLOT(quit())); - QTimer::singleShot(0, &example, SLOT(run())); - - return app.exec(); -} diff --git a/ext/hiredis-0.14.1/examples/example-qt.h b/ext/hiredis-0.14.1/examples/example-qt.h deleted file mode 100644 index 374f47666..000000000 --- a/ext/hiredis-0.14.1/examples/example-qt.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __HIREDIS_EXAMPLE_QT_H -#define __HIREDIS_EXAMPLE_QT_H - -#include - -class ExampleQt : public QObject { - - Q_OBJECT - - public: - ExampleQt(const char * value, QObject * parent = 0) - : QObject(parent), m_value(value) {} - - signals: - void finished(); - - public slots: - void run(); - - private: - void finish() { emit finished(); } - - private: - const char * m_value; - redisAsyncContext * m_ctx; - RedisQtAdapter m_adapter; - - friend - void getCallback(redisAsyncContext *, void *, void *); -}; - -#endif /* !__HIREDIS_EXAMPLE_QT_H */ diff --git a/ext/hiredis-0.14.1/examples/example.c b/ext/hiredis-0.14.1/examples/example.c deleted file mode 100644 index 4d494c55a..000000000 --- a/ext/hiredis-0.14.1/examples/example.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include - -#include - -int main(int argc, char **argv) { - unsigned int j; - redisContext *c; - redisReply *reply; - const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; - int port = (argc > 2) ? atoi(argv[2]) : 6379; - - struct timeval timeout = { 1, 500000 }; // 1.5 seconds - c = redisConnectWithTimeout(hostname, port, timeout); - if (c == NULL || c->err) { - if (c) { - printf("Connection error: %s\n", c->errstr); - redisFree(c); - } else { - printf("Connection error: can't allocate redis context\n"); - } - exit(1); - } - - /* PING server */ - reply = redisCommand(c,"PING"); - printf("PING: %s\n", reply->str); - freeReplyObject(reply); - - /* Set a key */ - reply = redisCommand(c,"SET %s %s", "foo", "hello world"); - printf("SET: %s\n", reply->str); - freeReplyObject(reply); - - /* Set a key using binary safe API */ - reply = redisCommand(c,"SET %b %b", "bar", (size_t) 3, "hello", (size_t) 5); - printf("SET (binary API): %s\n", reply->str); - freeReplyObject(reply); - - /* Try a GET and two INCR */ - reply = redisCommand(c,"GET foo"); - printf("GET foo: %s\n", reply->str); - freeReplyObject(reply); - - reply = redisCommand(c,"INCR counter"); - printf("INCR counter: %lld\n", reply->integer); - freeReplyObject(reply); - /* again ... */ - reply = redisCommand(c,"INCR counter"); - printf("INCR counter: %lld\n", reply->integer); - freeReplyObject(reply); - - /* Create a list of numbers, from 0 to 9 */ - reply = redisCommand(c,"DEL mylist"); - freeReplyObject(reply); - for (j = 0; j < 10; j++) { - char buf[64]; - - snprintf(buf,64,"%u",j); - reply = redisCommand(c,"LPUSH mylist element-%s", buf); - freeReplyObject(reply); - } - - /* Let's check what we have inside the list */ - reply = redisCommand(c,"LRANGE mylist 0 -1"); - if (reply->type == REDIS_REPLY_ARRAY) { - for (j = 0; j < reply->elements; j++) { - printf("%u) %s\n", j, reply->element[j]->str); - } - } - freeReplyObject(reply); - - /* Disconnects and frees the context */ - redisFree(c); - - return 0; -} diff --git a/ext/hiredis-0.14.1/fmacros.h b/ext/hiredis-0.14.1/fmacros.h deleted file mode 100644 index 3227faafd..000000000 --- a/ext/hiredis-0.14.1/fmacros.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __HIREDIS_FMACRO_H -#define __HIREDIS_FMACRO_H - -#define _XOPEN_SOURCE 600 -#define _POSIX_C_SOURCE 200112L - -#if defined(__APPLE__) && defined(__MACH__) -/* Enable TCP_KEEPALIVE */ -#define _DARWIN_C_SOURCE -#endif - -#endif diff --git a/ext/hiredis-0.14.1/hiredis.c b/ext/hiredis-0.14.1/hiredis.c deleted file mode 100644 index 98f43c993..000000000 --- a/ext/hiredis-0.14.1/hiredis.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include -#include - -#include "hiredis.h" -#include "net.h" -#include "sds.h" - -static redisReply *createReplyObject(int type); -static void *createStringObject(const redisReadTask *task, char *str, size_t len); -static void *createArrayObject(const redisReadTask *task, int elements); -static void *createIntegerObject(const redisReadTask *task, long long value); -static void *createNilObject(const redisReadTask *task); - -/* Default set of functions to build the reply. Keep in mind that such a - * function returning NULL is interpreted as OOM. */ -static redisReplyObjectFunctions defaultFunctions = { - createStringObject, - createArrayObject, - createIntegerObject, - createNilObject, - freeReplyObject -}; - -/* Create a reply object */ -static redisReply *createReplyObject(int type) { - redisReply *r = calloc(1,sizeof(*r)); - - if (r == NULL) - return NULL; - - r->type = type; - return r; -} - -/* Free a reply object */ -void freeReplyObject(void *reply) { - redisReply *r = reply; - size_t j; - - if (r == NULL) - return; - - switch(r->type) { - case REDIS_REPLY_INTEGER: - break; /* Nothing to free */ - case REDIS_REPLY_ARRAY: - if (r->element != NULL) { - for (j = 0; j < r->elements; j++) - freeReplyObject(r->element[j]); - free(r->element); - } - break; - case REDIS_REPLY_ERROR: - case REDIS_REPLY_STATUS: - case REDIS_REPLY_STRING: - free(r->str); - break; - } - free(r); -} - -static void *createStringObject(const redisReadTask *task, char *str, size_t len) { - redisReply *r, *parent; - char *buf; - - r = createReplyObject(task->type); - if (r == NULL) - return NULL; - - buf = malloc(len+1); - if (buf == NULL) { - freeReplyObject(r); - return NULL; - } - - assert(task->type == REDIS_REPLY_ERROR || - task->type == REDIS_REPLY_STATUS || - task->type == REDIS_REPLY_STRING); - - /* Copy string value */ - memcpy(buf,str,len); - buf[len] = '\0'; - r->str = buf; - r->len = len; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); - parent->element[task->idx] = r; - } - return r; -} - -static void *createArrayObject(const redisReadTask *task, int elements) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_ARRAY); - if (r == NULL) - return NULL; - - if (elements > 0) { - r->element = calloc(elements,sizeof(redisReply*)); - if (r->element == NULL) { - freeReplyObject(r); - return NULL; - } - } - - r->elements = elements; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); - parent->element[task->idx] = r; - } - return r; -} - -static void *createIntegerObject(const redisReadTask *task, long long value) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_INTEGER); - if (r == NULL) - return NULL; - - r->integer = value; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); - parent->element[task->idx] = r; - } - return r; -} - -static void *createNilObject(const redisReadTask *task) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_NIL); - if (r == NULL) - return NULL; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); - parent->element[task->idx] = r; - } - return r; -} - -/* Return the number of digits of 'v' when converted to string in radix 10. - * Implementation borrowed from link in redis/src/util.c:string2ll(). */ -static uint32_t countDigits(uint64_t v) { - uint32_t result = 1; - for (;;) { - if (v < 10) return result; - if (v < 100) return result + 1; - if (v < 1000) return result + 2; - if (v < 10000) return result + 3; - v /= 10000U; - result += 4; - } -} - -/* Helper that calculates the bulk length given a certain string length. */ -static size_t bulklen(size_t len) { - return 1+countDigits(len)+2+len+2; -} - -int redisvFormatCommand(char **target, const char *format, va_list ap) { - const char *c = format; - char *cmd = NULL; /* final command */ - int pos; /* position in final command */ - sds curarg, newarg; /* current argument */ - int touched = 0; /* was the current argument touched? */ - char **curargv = NULL, **newargv = NULL; - int argc = 0; - int totlen = 0; - int error_type = 0; /* 0 = no error; -1 = memory error; -2 = format error */ - int j; - - /* Abort if there is not target to set */ - if (target == NULL) - return -1; - - /* Build the command string accordingly to protocol */ - curarg = sdsempty(); - if (curarg == NULL) - return -1; - - while(*c != '\0') { - if (*c != '%' || c[1] == '\0') { - if (*c == ' ') { - if (touched) { - newargv = realloc(curargv,sizeof(char*)*(argc+1)); - if (newargv == NULL) goto memory_err; - curargv = newargv; - curargv[argc++] = curarg; - totlen += bulklen(sdslen(curarg)); - - /* curarg is put in argv so it can be overwritten. */ - curarg = sdsempty(); - if (curarg == NULL) goto memory_err; - touched = 0; - } - } else { - newarg = sdscatlen(curarg,c,1); - if (newarg == NULL) goto memory_err; - curarg = newarg; - touched = 1; - } - } else { - char *arg; - size_t size; - - /* Set newarg so it can be checked even if it is not touched. */ - newarg = curarg; - - switch(c[1]) { - case 's': - arg = va_arg(ap,char*); - size = strlen(arg); - if (size > 0) - newarg = sdscatlen(curarg,arg,size); - break; - case 'b': - arg = va_arg(ap,char*); - size = va_arg(ap,size_t); - if (size > 0) - newarg = sdscatlen(curarg,arg,size); - break; - case '%': - newarg = sdscat(curarg,"%"); - break; - default: - /* Try to detect printf format */ - { - static const char intfmts[] = "diouxX"; - static const char flags[] = "#0-+ "; - char _format[16]; - const char *_p = c+1; - size_t _l = 0; - va_list _cpy; - - /* Flags */ - while (*_p != '\0' && strchr(flags,*_p) != NULL) _p++; - - /* Field width */ - while (*_p != '\0' && isdigit(*_p)) _p++; - - /* Precision */ - if (*_p == '.') { - _p++; - while (*_p != '\0' && isdigit(*_p)) _p++; - } - - /* Copy va_list before consuming with va_arg */ - va_copy(_cpy,ap); - - /* Integer conversion (without modifiers) */ - if (strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); - goto fmt_valid; - } - - /* Double conversion (without modifiers) */ - if (strchr("eEfFgGaA",*_p) != NULL) { - va_arg(ap,double); - goto fmt_valid; - } - - /* Size: char */ - if (_p[0] == 'h' && _p[1] == 'h') { - _p += 2; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); /* char gets promoted to int */ - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: short */ - if (_p[0] == 'h') { - _p += 1; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); /* short gets promoted to int */ - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: long long */ - if (_p[0] == 'l' && _p[1] == 'l') { - _p += 2; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,long long); - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: long */ - if (_p[0] == 'l') { - _p += 1; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,long); - goto fmt_valid; - } - goto fmt_invalid; - } - - fmt_invalid: - va_end(_cpy); - goto format_err; - - fmt_valid: - _l = (_p+1)-c; - if (_l < sizeof(_format)-2) { - memcpy(_format,c,_l); - _format[_l] = '\0'; - newarg = sdscatvprintf(curarg,_format,_cpy); - - /* Update current position (note: outer blocks - * increment c twice so compensate here) */ - c = _p-1; - } - - va_end(_cpy); - break; - } - } - - if (newarg == NULL) goto memory_err; - curarg = newarg; - - touched = 1; - c++; - } - c++; - } - - /* Add the last argument if needed */ - if (touched) { - newargv = realloc(curargv,sizeof(char*)*(argc+1)); - if (newargv == NULL) goto memory_err; - curargv = newargv; - curargv[argc++] = curarg; - totlen += bulklen(sdslen(curarg)); - } else { - sdsfree(curarg); - } - - /* Clear curarg because it was put in curargv or was free'd. */ - curarg = NULL; - - /* Add bytes needed to hold multi bulk count */ - totlen += 1+countDigits(argc)+2; - - /* Build the command at protocol level */ - cmd = malloc(totlen+1); - if (cmd == NULL) goto memory_err; - - pos = sprintf(cmd,"*%d\r\n",argc); - for (j = 0; j < argc; j++) { - pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(curargv[j])); - memcpy(cmd+pos,curargv[j],sdslen(curargv[j])); - pos += sdslen(curargv[j]); - sdsfree(curargv[j]); - cmd[pos++] = '\r'; - cmd[pos++] = '\n'; - } - assert(pos == totlen); - cmd[pos] = '\0'; - - free(curargv); - *target = cmd; - return totlen; - -format_err: - error_type = -2; - goto cleanup; - -memory_err: - error_type = -1; - goto cleanup; - -cleanup: - if (curargv) { - while(argc--) - sdsfree(curargv[argc]); - free(curargv); - } - - sdsfree(curarg); - free(cmd); - - return error_type; -} - -/* Format a command according to the Redis protocol. This function - * takes a format similar to printf: - * - * %s represents a C null terminated string you want to interpolate - * %b represents a binary safe string - * - * When using %b you need to provide both the pointer to the string - * and the length in bytes as a size_t. Examples: - * - * len = redisFormatCommand(target, "GET %s", mykey); - * len = redisFormatCommand(target, "SET %s %b", mykey, myval, myvallen); - */ -int redisFormatCommand(char **target, const char *format, ...) { - va_list ap; - int len; - va_start(ap,format); - len = redisvFormatCommand(target,format,ap); - va_end(ap); - - /* The API says "-1" means bad result, but we now also return "-2" in some - * cases. Force the return value to always be -1. */ - if (len < 0) - len = -1; - - return len; -} - -/* Format a command according to the Redis protocol using an sds string and - * sdscatfmt for the processing of arguments. This function takes the - * number of arguments, an array with arguments and an array with their - * lengths. If the latter is set to NULL, strlen will be used to compute the - * argument lengths. - */ -int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv, - const size_t *argvlen) -{ - sds cmd; - unsigned long long totlen; - int j; - size_t len; - - /* Abort on a NULL target */ - if (target == NULL) - return -1; - - /* Calculate our total size */ - totlen = 1+countDigits(argc)+2; - for (j = 0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - totlen += bulklen(len); - } - - /* Use an SDS string for command construction */ - cmd = sdsempty(); - if (cmd == NULL) - return -1; - - /* We already know how much storage we need */ - cmd = sdsMakeRoomFor(cmd, totlen); - if (cmd == NULL) - return -1; - - /* Construct command */ - cmd = sdscatfmt(cmd, "*%i\r\n", argc); - for (j=0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - cmd = sdscatfmt(cmd, "$%u\r\n", len); - cmd = sdscatlen(cmd, argv[j], len); - cmd = sdscatlen(cmd, "\r\n", sizeof("\r\n")-1); - } - - assert(sdslen(cmd)==totlen); - - *target = cmd; - return totlen; -} - -void redisFreeSdsCommand(sds cmd) { - sdsfree(cmd); -} - -/* Format a command according to the Redis protocol. This function takes the - * number of arguments, an array with arguments and an array with their - * lengths. If the latter is set to NULL, strlen will be used to compute the - * argument lengths. - */ -int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen) { - char *cmd = NULL; /* final command */ - int pos; /* position in final command */ - size_t len; - int totlen, j; - - /* Abort on a NULL target */ - if (target == NULL) - return -1; - - /* Calculate number of bytes needed for the command */ - totlen = 1+countDigits(argc)+2; - for (j = 0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - totlen += bulklen(len); - } - - /* Build the command at protocol level */ - cmd = malloc(totlen+1); - if (cmd == NULL) - return -1; - - pos = sprintf(cmd,"*%d\r\n",argc); - for (j = 0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - pos += sprintf(cmd+pos,"$%zu\r\n",len); - memcpy(cmd+pos,argv[j],len); - pos += len; - cmd[pos++] = '\r'; - cmd[pos++] = '\n'; - } - assert(pos == totlen); - cmd[pos] = '\0'; - - *target = cmd; - return totlen; -} - -void redisFreeCommand(char *cmd) { - free(cmd); -} - -void __redisSetError(redisContext *c, int type, const char *str) { - size_t len; - - c->err = type; - if (str != NULL) { - len = strlen(str); - len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1); - memcpy(c->errstr,str,len); - c->errstr[len] = '\0'; - } else { - /* Only REDIS_ERR_IO may lack a description! */ - assert(type == REDIS_ERR_IO); - strerror_r(errno, c->errstr, sizeof(c->errstr)); - } -} - -redisReader *redisReaderCreate(void) { - return redisReaderCreateWithFunctions(&defaultFunctions); -} - -static redisContext *redisContextInit(void) { - redisContext *c; - - c = calloc(1,sizeof(redisContext)); - if (c == NULL) - return NULL; - - c->obuf = sdsempty(); - c->reader = redisReaderCreate(); - - if (c->obuf == NULL || c->reader == NULL) { - redisFree(c); - return NULL; - } - - return c; -} - -void redisFree(redisContext *c) { - if (c == NULL) - return; - if (c->fd > 0) - close(c->fd); - sdsfree(c->obuf); - redisReaderFree(c->reader); - free(c->tcp.host); - free(c->tcp.source_addr); - free(c->unix_sock.path); - free(c->timeout); - free(c); -} - -int redisFreeKeepFd(redisContext *c) { - int fd = c->fd; - c->fd = -1; - redisFree(c); - return fd; -} - -int redisReconnect(redisContext *c) { - c->err = 0; - memset(c->errstr, '\0', strlen(c->errstr)); - - if (c->fd > 0) { - close(c->fd); - } - - sdsfree(c->obuf); - redisReaderFree(c->reader); - - c->obuf = sdsempty(); - c->reader = redisReaderCreate(); - - if (c->connection_type == REDIS_CONN_TCP) { - return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port, - c->timeout, c->tcp.source_addr); - } else if (c->connection_type == REDIS_CONN_UNIX) { - return redisContextConnectUnix(c, c->unix_sock.path, c->timeout); - } else { - /* Something bad happened here and shouldn't have. There isn't - enough information in the context to reconnect. */ - __redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect"); - } - - return REDIS_ERR; -} - -/* Connect to a Redis instance. On error the field error in the returned - * context will be set to the return value of the error function. - * When no set of reply functions is given, the default set will be used. */ -redisContext *redisConnect(const char *ip, int port) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags |= REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,NULL); - return c; -} - -redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags |= REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,&tv); - return c; -} - -redisContext *redisConnectNonBlock(const char *ip, int port) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags &= ~REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,NULL); - return c; -} - -redisContext *redisConnectBindNonBlock(const char *ip, int port, - const char *source_addr) { - redisContext *c = redisContextInit(); - if (c == NULL) - return NULL; - c->flags &= ~REDIS_BLOCK; - redisContextConnectBindTcp(c,ip,port,NULL,source_addr); - return c; -} - -redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, - const char *source_addr) { - redisContext *c = redisContextInit(); - if (c == NULL) - return NULL; - c->flags &= ~REDIS_BLOCK; - c->flags |= REDIS_REUSEADDR; - redisContextConnectBindTcp(c,ip,port,NULL,source_addr); - return c; -} - -redisContext *redisConnectUnix(const char *path) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags |= REDIS_BLOCK; - redisContextConnectUnix(c,path,NULL); - return c; -} - -redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags |= REDIS_BLOCK; - redisContextConnectUnix(c,path,&tv); - return c; -} - -redisContext *redisConnectUnixNonBlock(const char *path) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags &= ~REDIS_BLOCK; - redisContextConnectUnix(c,path,NULL); - return c; -} - -redisContext *redisConnectFd(int fd) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->fd = fd; - c->flags |= REDIS_BLOCK | REDIS_CONNECTED; - return c; -} - -/* Set read/write timeout on a blocking socket. */ -int redisSetTimeout(redisContext *c, const struct timeval tv) { - if (c->flags & REDIS_BLOCK) - return redisContextSetTimeout(c,tv); - return REDIS_ERR; -} - -/* Enable connection KeepAlive. */ -int redisEnableKeepAlive(redisContext *c) { - if (redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL) != REDIS_OK) - return REDIS_ERR; - return REDIS_OK; -} - -/* Use this function to handle a read event on the descriptor. It will try - * and read some bytes from the socket and feed them to the reply parser. - * - * After this function is called, you may use redisContextReadReply to - * see if there is a reply available. */ -int redisBufferRead(redisContext *c) { - char buf[1024*16]; - int nread; - - /* Return early when the context has seen an error. */ - if (c->err) - return REDIS_ERR; - - nread = read(c->fd,buf,sizeof(buf)); - if (nread == -1) { - if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { - /* Try again later */ - } else { - __redisSetError(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - } else if (nread == 0) { - __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); - return REDIS_ERR; - } else { - if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { - __redisSetError(c,c->reader->err,c->reader->errstr); - return REDIS_ERR; - } - } - return REDIS_OK; -} - -/* Write the output buffer to the socket. - * - * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was - * successfully written to the socket. When the buffer is empty after the - * write operation, "done" is set to 1 (if given). - * - * Returns REDIS_ERR if an error occurred trying to write and sets - * c->errstr to hold the appropriate error string. - */ -int redisBufferWrite(redisContext *c, int *done) { - int nwritten; - - /* Return early when the context has seen an error. */ - if (c->err) - return REDIS_ERR; - - if (sdslen(c->obuf) > 0) { - nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); - if (nwritten == -1) { - if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { - /* Try again later */ - } else { - __redisSetError(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - } else if (nwritten > 0) { - if (nwritten == (signed)sdslen(c->obuf)) { - sdsfree(c->obuf); - c->obuf = sdsempty(); - } else { - sdsrange(c->obuf,nwritten,-1); - } - } - } - if (done != NULL) *done = (sdslen(c->obuf) == 0); - return REDIS_OK; -} - -/* Internal helper function to try and get a reply from the reader, - * or set an error in the context otherwise. */ -int redisGetReplyFromReader(redisContext *c, void **reply) { - if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { - __redisSetError(c,c->reader->err,c->reader->errstr); - return REDIS_ERR; - } - return REDIS_OK; -} - -int redisGetReply(redisContext *c, void **reply) { - int wdone = 0; - void *aux = NULL; - - /* Try to read pending replies */ - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) - return REDIS_ERR; - - /* For the blocking context, flush output buffer and read reply */ - if (aux == NULL && c->flags & REDIS_BLOCK) { - /* Write until done */ - do { - if (redisBufferWrite(c,&wdone) == REDIS_ERR) - return REDIS_ERR; - } while (!wdone); - - /* Read until there is a reply */ - do { - if (redisBufferRead(c) == REDIS_ERR) - return REDIS_ERR; - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) - return REDIS_ERR; - } while (aux == NULL); - } - - /* Set reply object */ - if (reply != NULL) *reply = aux; - return REDIS_OK; -} - - -/* Helper function for the redisAppendCommand* family of functions. - * - * Write a formatted command to the output buffer. When this family - * is used, you need to call redisGetReply yourself to retrieve - * the reply (or replies in pub/sub). - */ -int __redisAppendCommand(redisContext *c, const char *cmd, size_t len) { - sds newbuf; - - newbuf = sdscatlen(c->obuf,cmd,len); - if (newbuf == NULL) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } - - c->obuf = newbuf; - return REDIS_OK; -} - -int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len) { - - if (__redisAppendCommand(c, cmd, len) != REDIS_OK) { - return REDIS_ERR; - } - - return REDIS_OK; -} - -int redisvAppendCommand(redisContext *c, const char *format, va_list ap) { - char *cmd; - int len; - - len = redisvFormatCommand(&cmd,format,ap); - if (len == -1) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } else if (len == -2) { - __redisSetError(c,REDIS_ERR_OTHER,"Invalid format string"); - return REDIS_ERR; - } - - if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { - free(cmd); - return REDIS_ERR; - } - - free(cmd); - return REDIS_OK; -} - -int redisAppendCommand(redisContext *c, const char *format, ...) { - va_list ap; - int ret; - - va_start(ap,format); - ret = redisvAppendCommand(c,format,ap); - va_end(ap); - return ret; -} - -int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { - sds cmd; - int len; - - len = redisFormatSdsCommandArgv(&cmd,argc,argv,argvlen); - if (len == -1) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } - - if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { - sdsfree(cmd); - return REDIS_ERR; - } - - sdsfree(cmd); - return REDIS_OK; -} - -/* Helper function for the redisCommand* family of functions. - * - * Write a formatted command to the output buffer. If the given context is - * blocking, immediately read the reply into the "reply" pointer. When the - * context is non-blocking, the "reply" pointer will not be used and the - * command is simply appended to the write buffer. - * - * Returns the reply when a reply was successfully retrieved. Returns NULL - * otherwise. When NULL is returned in a blocking context, the error field - * in the context will be set. - */ -static void *__redisBlockForReply(redisContext *c) { - void *reply; - - if (c->flags & REDIS_BLOCK) { - if (redisGetReply(c,&reply) != REDIS_OK) - return NULL; - return reply; - } - return NULL; -} - -void *redisvCommand(redisContext *c, const char *format, va_list ap) { - if (redisvAppendCommand(c,format,ap) != REDIS_OK) - return NULL; - return __redisBlockForReply(c); -} - -void *redisCommand(redisContext *c, const char *format, ...) { - va_list ap; - va_start(ap,format); - void *reply = redisvCommand(c,format,ap); - va_end(ap); - return reply; -} - -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { - if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK) - return NULL; - return __redisBlockForReply(c); -} diff --git a/ext/hiredis-0.14.1/hiredis.h b/ext/hiredis-0.14.1/hiredis.h deleted file mode 100644 index d945bf204..000000000 --- a/ext/hiredis-0.14.1/hiredis.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_H -#define __HIREDIS_H -#include "read.h" -#include /* for va_list */ -#include /* for struct timeval */ -#include /* uintXX_t, etc */ -#include "sds.h" /* for sds */ -#include "alloc.h" /* for allocation wrappers */ - -#define HIREDIS_MAJOR 0 -#define HIREDIS_MINOR 14 -#define HIREDIS_PATCH 1 -#define HIREDIS_SONAME 0.14 - -/* Connection type can be blocking or non-blocking and is set in the - * least significant bit of the flags field in redisContext. */ -#define REDIS_BLOCK 0x1 - -/* Connection may be disconnected before being free'd. The second bit - * in the flags field is set when the context is connected. */ -#define REDIS_CONNECTED 0x2 - -/* The async API might try to disconnect cleanly and flush the output - * buffer and read all subsequent replies before disconnecting. - * This flag means no new commands can come in and the connection - * should be terminated once all replies have been read. */ -#define REDIS_DISCONNECTING 0x4 - -/* Flag specific to the async API which means that the context should be clean - * up as soon as possible. */ -#define REDIS_FREEING 0x8 - -/* Flag that is set when an async callback is executed. */ -#define REDIS_IN_CALLBACK 0x10 - -/* Flag that is set when the async context has one or more subscriptions. */ -#define REDIS_SUBSCRIBED 0x20 - -/* Flag that is set when monitor mode is active */ -#define REDIS_MONITORING 0x40 - -/* Flag that is set when we should set SO_REUSEADDR before calling bind() */ -#define REDIS_REUSEADDR 0x80 - -#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ - -/* number of times we retry to connect in the case of EADDRNOTAVAIL and - * SO_REUSEADDR is being used. */ -#define REDIS_CONNECT_RETRIES 10 - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the reply object returned by redisCommand() */ -typedef struct redisReply { - int type; /* REDIS_REPLY_* */ - long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ - size_t len; /* Length of string */ - char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ - size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ - struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ -} redisReply; - -redisReader *redisReaderCreate(void); - -/* Function to free the reply objects hiredis returns by default. */ -void freeReplyObject(void *reply); - -/* Functions to format a command according to the protocol. */ -int redisvFormatCommand(char **target, const char *format, va_list ap); -int redisFormatCommand(char **target, const char *format, ...); -int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); -int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen); -void redisFreeCommand(char *cmd); -void redisFreeSdsCommand(sds cmd); - -enum redisConnectionType { - REDIS_CONN_TCP, - REDIS_CONN_UNIX -}; - -/* Context for a connection to Redis */ -typedef struct redisContext { - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - int fd; - int flags; - char *obuf; /* Write buffer */ - redisReader *reader; /* Protocol reader */ - - enum redisConnectionType connection_type; - struct timeval *timeout; - - struct { - char *host; - char *source_addr; - int port; - } tcp; - - struct { - char *path; - } unix_sock; - -} redisContext; - -redisContext *redisConnect(const char *ip, int port); -redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); -redisContext *redisConnectNonBlock(const char *ip, int port); -redisContext *redisConnectBindNonBlock(const char *ip, int port, - const char *source_addr); -redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, - const char *source_addr); -redisContext *redisConnectUnix(const char *path); -redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); -redisContext *redisConnectUnixNonBlock(const char *path); -redisContext *redisConnectFd(int fd); - -/** - * Reconnect the given context using the saved information. - * - * This re-uses the exact same connect options as in the initial connection. - * host, ip (or path), timeout and bind address are reused, - * flags are used unmodified from the existing context. - * - * Returns REDIS_OK on successful connect or REDIS_ERR otherwise. - */ -int redisReconnect(redisContext *c); - -int redisSetTimeout(redisContext *c, const struct timeval tv); -int redisEnableKeepAlive(redisContext *c); -void redisFree(redisContext *c); -int redisFreeKeepFd(redisContext *c); -int redisBufferRead(redisContext *c); -int redisBufferWrite(redisContext *c, int *done); - -/* In a blocking context, this function first checks if there are unconsumed - * replies to return and returns one if so. Otherwise, it flushes the output - * buffer to the socket and reads until it has a reply. In a non-blocking - * context, it will return unconsumed replies until there are no more. */ -int redisGetReply(redisContext *c, void **reply); -int redisGetReplyFromReader(redisContext *c, void **reply); - -/* Write a formatted command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); - -/* Write a command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisvAppendCommand(redisContext *c, const char *format, va_list ap); -int redisAppendCommand(redisContext *c, const char *format, ...); -int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -/* Issue a command to Redis. In a blocking context, it is identical to calling - * redisAppendCommand, followed by redisGetReply. The function will return - * NULL if there was an error in performing the request, otherwise it will - * return the reply. In a non-blocking context, it is identical to calling - * only redisAppendCommand and will always return NULL. */ -void *redisvCommand(redisContext *c, const char *format, va_list ap); -void *redisCommand(redisContext *c, const char *format, ...); -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-0.14.1/include/hiredis/alloc.h b/ext/hiredis-0.14.1/include/hiredis/alloc.h deleted file mode 100644 index 2c9b04e35..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/alloc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2020, Michael Grunder - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HIREDIS_ALLOC_H -#define HIREDIS_ALLOC_H - -#include /* for size_t */ - -#ifndef HIREDIS_OOM_HANDLER -#define HIREDIS_OOM_HANDLER abort() -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -void *hi_malloc(size_t size); -void *hi_calloc(size_t nmemb, size_t size); -void *hi_realloc(void *ptr, size_t size); -char *hi_strdup(const char *str); - -#ifdef __cplusplus -} -#endif - -#endif /* HIREDIS_ALLOC_H */ diff --git a/ext/hiredis-0.14.1/include/hiredis/async.h b/ext/hiredis-0.14.1/include/hiredis/async.h deleted file mode 100644 index e69d84090..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/async.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_ASYNC_H -#define __HIREDIS_ASYNC_H -#include "hiredis.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ -struct dict; /* dictionary header is included in async.c */ - -/* Reply callback prototype and container */ -typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); -typedef struct redisCallback { - struct redisCallback *next; /* simple singly linked list */ - redisCallbackFn *fn; - int pending_subs; - void *privdata; -} redisCallback; - -/* List of callbacks for either regular replies or pub/sub */ -typedef struct redisCallbackList { - redisCallback *head, *tail; -} redisCallbackList; - -/* Connection callback prototypes */ -typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); -typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); - -/* Context for an async connection to Redis */ -typedef struct redisAsyncContext { - /* Hold the regular context, so it can be realloc'ed. */ - redisContext c; - - /* Setup error flags so they can be used directly. */ - int err; - char *errstr; - - /* Not used by hiredis */ - void *data; - - /* Event library data and hooks */ - struct { - void *data; - - /* Hooks that are called when the library expects to start - * reading/writing. These functions should be idempotent. */ - void (*addRead)(void *privdata); - void (*delRead)(void *privdata); - void (*addWrite)(void *privdata); - void (*delWrite)(void *privdata); - void (*cleanup)(void *privdata); - } ev; - - /* Called when either the connection is terminated due to an error or per - * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */ - redisDisconnectCallback *onDisconnect; - - /* Called when the first write event was received. */ - redisConnectCallback *onConnect; - - /* Regular command callbacks */ - redisCallbackList replies; - - /* Subscription callbacks */ - struct { - redisCallbackList invalid; - struct dict *channels; - struct dict *patterns; - } sub; -} redisAsyncContext; - -/* Functions that proxy to hiredis */ -redisAsyncContext *redisAsyncConnect(const char *ip, int port); -redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr); -redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port, - const char *source_addr); -redisAsyncContext *redisAsyncConnectUnix(const char *path); -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); -void redisAsyncDisconnect(redisAsyncContext *ac); -void redisAsyncFree(redisAsyncContext *ac); - -/* Handle read/write events */ -void redisAsyncHandleRead(redisAsyncContext *ac); -void redisAsyncHandleWrite(redisAsyncContext *ac); - -/* Command functions for an async context. Write the command to the - * output buffer and register the provided callback. */ -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); -int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-0.14.1/include/hiredis/dict.h b/ext/hiredis-0.14.1/include/hiredis/dict.h deleted file mode 100644 index 95fcd280e..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/dict.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DICT_H -#define __DICT_H - -#define DICT_OK 0 -#define DICT_ERR 1 - -/* Unused arguments generate annoying warnings... */ -#define DICT_NOTUSED(V) ((void) V) - -typedef struct dictEntry { - void *key; - void *val; - struct dictEntry *next; -} dictEntry; - -typedef struct dictType { - unsigned int (*hashFunction)(const void *key); - void *(*keyDup)(void *privdata, const void *key); - void *(*valDup)(void *privdata, const void *obj); - int (*keyCompare)(void *privdata, const void *key1, const void *key2); - void (*keyDestructor)(void *privdata, void *key); - void (*valDestructor)(void *privdata, void *obj); -} dictType; - -typedef struct dict { - dictEntry **table; - dictType *type; - unsigned long size; - unsigned long sizemask; - unsigned long used; - void *privdata; -} dict; - -typedef struct dictIterator { - dict *ht; - int index; - dictEntry *entry, *nextEntry; -} dictIterator; - -/* This is the initial size of every hash table */ -#define DICT_HT_INITIAL_SIZE 4 - -/* ------------------------------- Macros ------------------------------------*/ -#define dictFreeEntryVal(ht, entry) \ - if ((ht)->type->valDestructor) \ - (ht)->type->valDestructor((ht)->privdata, (entry)->val) - -#define dictSetHashVal(ht, entry, _val_) do { \ - if ((ht)->type->valDup) \ - entry->val = (ht)->type->valDup((ht)->privdata, _val_); \ - else \ - entry->val = (_val_); \ -} while(0) - -#define dictFreeEntryKey(ht, entry) \ - if ((ht)->type->keyDestructor) \ - (ht)->type->keyDestructor((ht)->privdata, (entry)->key) - -#define dictSetHashKey(ht, entry, _key_) do { \ - if ((ht)->type->keyDup) \ - entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ - else \ - entry->key = (_key_); \ -} while(0) - -#define dictCompareHashKeys(ht, key1, key2) \ - (((ht)->type->keyCompare) ? \ - (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ - (key1) == (key2)) - -#define dictHashKey(ht, key) (ht)->type->hashFunction(key) - -#define dictGetEntryKey(he) ((he)->key) -#define dictGetEntryVal(he) ((he)->val) -#define dictSlots(ht) ((ht)->size) -#define dictSize(ht) ((ht)->used) - -/* API */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len); -static dict *dictCreate(dictType *type, void *privDataPtr); -static int dictExpand(dict *ht, unsigned long size); -static int dictAdd(dict *ht, void *key, void *val); -static int dictReplace(dict *ht, void *key, void *val); -static int dictDelete(dict *ht, const void *key); -static void dictRelease(dict *ht); -static dictEntry * dictFind(dict *ht, const void *key); -static dictIterator *dictGetIterator(dict *ht); -static dictEntry *dictNext(dictIterator *iter); -static void dictReleaseIterator(dictIterator *iter); - -#endif /* __DICT_H */ diff --git a/ext/hiredis-0.14.1/include/hiredis/fmacros.h b/ext/hiredis-0.14.1/include/hiredis/fmacros.h deleted file mode 100644 index 3227faafd..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/fmacros.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __HIREDIS_FMACRO_H -#define __HIREDIS_FMACRO_H - -#define _XOPEN_SOURCE 600 -#define _POSIX_C_SOURCE 200112L - -#if defined(__APPLE__) && defined(__MACH__) -/* Enable TCP_KEEPALIVE */ -#define _DARWIN_C_SOURCE -#endif - -#endif diff --git a/ext/hiredis-0.14.1/include/hiredis/hiredis.h b/ext/hiredis-0.14.1/include/hiredis/hiredis.h deleted file mode 100644 index d945bf204..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/hiredis.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_H -#define __HIREDIS_H -#include "read.h" -#include /* for va_list */ -#include /* for struct timeval */ -#include /* uintXX_t, etc */ -#include "sds.h" /* for sds */ -#include "alloc.h" /* for allocation wrappers */ - -#define HIREDIS_MAJOR 0 -#define HIREDIS_MINOR 14 -#define HIREDIS_PATCH 1 -#define HIREDIS_SONAME 0.14 - -/* Connection type can be blocking or non-blocking and is set in the - * least significant bit of the flags field in redisContext. */ -#define REDIS_BLOCK 0x1 - -/* Connection may be disconnected before being free'd. The second bit - * in the flags field is set when the context is connected. */ -#define REDIS_CONNECTED 0x2 - -/* The async API might try to disconnect cleanly and flush the output - * buffer and read all subsequent replies before disconnecting. - * This flag means no new commands can come in and the connection - * should be terminated once all replies have been read. */ -#define REDIS_DISCONNECTING 0x4 - -/* Flag specific to the async API which means that the context should be clean - * up as soon as possible. */ -#define REDIS_FREEING 0x8 - -/* Flag that is set when an async callback is executed. */ -#define REDIS_IN_CALLBACK 0x10 - -/* Flag that is set when the async context has one or more subscriptions. */ -#define REDIS_SUBSCRIBED 0x20 - -/* Flag that is set when monitor mode is active */ -#define REDIS_MONITORING 0x40 - -/* Flag that is set when we should set SO_REUSEADDR before calling bind() */ -#define REDIS_REUSEADDR 0x80 - -#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ - -/* number of times we retry to connect in the case of EADDRNOTAVAIL and - * SO_REUSEADDR is being used. */ -#define REDIS_CONNECT_RETRIES 10 - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the reply object returned by redisCommand() */ -typedef struct redisReply { - int type; /* REDIS_REPLY_* */ - long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ - size_t len; /* Length of string */ - char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ - size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ - struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ -} redisReply; - -redisReader *redisReaderCreate(void); - -/* Function to free the reply objects hiredis returns by default. */ -void freeReplyObject(void *reply); - -/* Functions to format a command according to the protocol. */ -int redisvFormatCommand(char **target, const char *format, va_list ap); -int redisFormatCommand(char **target, const char *format, ...); -int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); -int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen); -void redisFreeCommand(char *cmd); -void redisFreeSdsCommand(sds cmd); - -enum redisConnectionType { - REDIS_CONN_TCP, - REDIS_CONN_UNIX -}; - -/* Context for a connection to Redis */ -typedef struct redisContext { - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - int fd; - int flags; - char *obuf; /* Write buffer */ - redisReader *reader; /* Protocol reader */ - - enum redisConnectionType connection_type; - struct timeval *timeout; - - struct { - char *host; - char *source_addr; - int port; - } tcp; - - struct { - char *path; - } unix_sock; - -} redisContext; - -redisContext *redisConnect(const char *ip, int port); -redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); -redisContext *redisConnectNonBlock(const char *ip, int port); -redisContext *redisConnectBindNonBlock(const char *ip, int port, - const char *source_addr); -redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, - const char *source_addr); -redisContext *redisConnectUnix(const char *path); -redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); -redisContext *redisConnectUnixNonBlock(const char *path); -redisContext *redisConnectFd(int fd); - -/** - * Reconnect the given context using the saved information. - * - * This re-uses the exact same connect options as in the initial connection. - * host, ip (or path), timeout and bind address are reused, - * flags are used unmodified from the existing context. - * - * Returns REDIS_OK on successful connect or REDIS_ERR otherwise. - */ -int redisReconnect(redisContext *c); - -int redisSetTimeout(redisContext *c, const struct timeval tv); -int redisEnableKeepAlive(redisContext *c); -void redisFree(redisContext *c); -int redisFreeKeepFd(redisContext *c); -int redisBufferRead(redisContext *c); -int redisBufferWrite(redisContext *c, int *done); - -/* In a blocking context, this function first checks if there are unconsumed - * replies to return and returns one if so. Otherwise, it flushes the output - * buffer to the socket and reads until it has a reply. In a non-blocking - * context, it will return unconsumed replies until there are no more. */ -int redisGetReply(redisContext *c, void **reply); -int redisGetReplyFromReader(redisContext *c, void **reply); - -/* Write a formatted command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); - -/* Write a command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisvAppendCommand(redisContext *c, const char *format, va_list ap); -int redisAppendCommand(redisContext *c, const char *format, ...); -int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -/* Issue a command to Redis. In a blocking context, it is identical to calling - * redisAppendCommand, followed by redisGetReply. The function will return - * NULL if there was an error in performing the request, otherwise it will - * return the reply. In a non-blocking context, it is identical to calling - * only redisAppendCommand and will always return NULL. */ -void *redisvCommand(redisContext *c, const char *format, va_list ap); -void *redisCommand(redisContext *c, const char *format, ...); -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-0.14.1/include/hiredis/net.h b/ext/hiredis-0.14.1/include/hiredis/net.h deleted file mode 100644 index d9dc36257..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/net.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __NET_H -#define __NET_H - -#include "hiredis.h" - -int redisCheckSocketError(redisContext *c); -int redisContextSetTimeout(redisContext *c, const struct timeval tv); -int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); -int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr); -int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); -int redisKeepAlive(redisContext *c, int interval); - -#endif diff --git a/ext/hiredis-0.14.1/include/hiredis/read.h b/ext/hiredis-0.14.1/include/hiredis/read.h deleted file mode 100644 index 2988aa453..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/read.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef __HIREDIS_READ_H -#define __HIREDIS_READ_H -#include /* for size_t */ - -#define REDIS_ERR -1 -#define REDIS_OK 0 - -/* When an error occurs, the err flag in a context is set to hold the type of - * error that occurred. REDIS_ERR_IO means there was an I/O error and you - * should use the "errno" variable to find out what is wrong. - * For other values, the "errstr" field will hold a description. */ -#define REDIS_ERR_IO 1 /* Error in read or write */ -#define REDIS_ERR_EOF 3 /* End of file */ -#define REDIS_ERR_PROTOCOL 4 /* Protocol error */ -#define REDIS_ERR_OOM 5 /* Out of memory */ -#define REDIS_ERR_OTHER 2 /* Everything else... */ - -#define REDIS_REPLY_STRING 1 -#define REDIS_REPLY_ARRAY 2 -#define REDIS_REPLY_INTEGER 3 -#define REDIS_REPLY_NIL 4 -#define REDIS_REPLY_STATUS 5 -#define REDIS_REPLY_ERROR 6 - -#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct redisReadTask { - int type; - int elements; /* number of elements in multibulk container */ - int idx; /* index in parent (array) object */ - void *obj; /* holds user-generated value for a read task */ - struct redisReadTask *parent; /* parent task */ - void *privdata; /* user-settable arbitrary field */ -} redisReadTask; - -typedef struct redisReplyObjectFunctions { - void *(*createString)(const redisReadTask*, char*, size_t); - void *(*createArray)(const redisReadTask*, int); - void *(*createInteger)(const redisReadTask*, long long); - void *(*createNil)(const redisReadTask*); - void (*freeObject)(void*); -} redisReplyObjectFunctions; - -typedef struct redisReader { - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - - char *buf; /* Read buffer */ - size_t pos; /* Buffer cursor */ - size_t len; /* Buffer length */ - size_t maxbuf; /* Max length of unused buffer */ - - redisReadTask rstack[9]; - int ridx; /* Index of current read task */ - void *reply; /* Temporary reply pointer */ - - redisReplyObjectFunctions *fn; - void *privdata; -} redisReader; - -/* Public API for the protocol parser. */ -redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn); -void redisReaderFree(redisReader *r); -int redisReaderFeed(redisReader *r, const char *buf, size_t len); -int redisReaderGetReply(redisReader *r, void **reply); - -#define redisReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) -#define redisReaderGetObject(_r) (((redisReader*)(_r))->reply) -#define redisReaderGetError(_r) (((redisReader*)(_r))->errstr) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-0.14.1/include/hiredis/sds.h b/ext/hiredis-0.14.1/include/hiredis/sds.h deleted file mode 100644 index 13be75a9f..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/sds.h +++ /dev/null @@ -1,273 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SDS_H -#define __SDS_H - -#define SDS_MAX_PREALLOC (1024*1024) - -#include -#include -#include - -typedef char *sds; - -/* Note: sdshdr5 is never used, we just access the flags byte directly. - * However is here to document the layout of type 5 SDS strings. */ -struct __attribute__ ((__packed__)) sdshdr5 { - unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr8 { - uint8_t len; /* used */ - uint8_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr16 { - uint16_t len; /* used */ - uint16_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr32 { - uint32_t len; /* used */ - uint32_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr64 { - uint64_t len; /* used */ - uint64_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; - -#define SDS_TYPE_5 0 -#define SDS_TYPE_8 1 -#define SDS_TYPE_16 2 -#define SDS_TYPE_32 3 -#define SDS_TYPE_64 4 -#define SDS_TYPE_MASK 7 -#define SDS_TYPE_BITS 3 -#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))); -#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) -#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) - -static inline size_t sdslen(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->len; - case SDS_TYPE_16: - return SDS_HDR(16,s)->len; - case SDS_TYPE_32: - return SDS_HDR(32,s)->len; - case SDS_TYPE_64: - return SDS_HDR(64,s)->len; - } - return 0; -} - -static inline size_t sdsavail(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: { - return 0; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - return sh->alloc - sh->len; - } - } - return 0; -} - -static inline void sdssetlen(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len = newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len = newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len = newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len = newlen; - break; - } -} - -static inline void sdsinclen(sds s, size_t inc) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len += inc; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len += inc; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len += inc; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len += inc; - break; - } -} - -/* sdsalloc() = sdsavail() + sdslen() */ -static inline size_t sdsalloc(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->alloc; - case SDS_TYPE_16: - return SDS_HDR(16,s)->alloc; - case SDS_TYPE_32: - return SDS_HDR(32,s)->alloc; - case SDS_TYPE_64: - return SDS_HDR(64,s)->alloc; - } - return 0; -} - -static inline void sdssetalloc(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - /* Nothing to do, this type has no total allocation info. */ - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->alloc = newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->alloc = newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->alloc = newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->alloc = newlen; - break; - } -} - -sds sdsnewlen(const void *init, size_t initlen); -sds sdsnew(const char *init); -sds sdsempty(void); -sds sdsdup(const sds s); -void sdsfree(sds s); -sds sdsgrowzero(sds s, size_t len); -sds sdscatlen(sds s, const void *t, size_t len); -sds sdscat(sds s, const char *t); -sds sdscatsds(sds s, const sds t); -sds sdscpylen(sds s, const char *t, size_t len); -sds sdscpy(sds s, const char *t); - -sds sdscatvprintf(sds s, const char *fmt, va_list ap); -#ifdef __GNUC__ -sds sdscatprintf(sds s, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else -sds sdscatprintf(sds s, const char *fmt, ...); -#endif - -sds sdscatfmt(sds s, char const *fmt, ...); -sds sdstrim(sds s, const char *cset); -void sdsrange(sds s, int start, int end); -void sdsupdatelen(sds s); -void sdsclear(sds s); -int sdscmp(const sds s1, const sds s2); -sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); -void sdsfreesplitres(sds *tokens, int count); -void sdstolower(sds s); -void sdstoupper(sds s); -sds sdsfromlonglong(long long value); -sds sdscatrepr(sds s, const char *p, size_t len); -sds *sdssplitargs(const char *line, int *argc); -sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); -sds sdsjoin(char **argv, int argc, char *sep); -sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); - -/* Low level functions exposed to the user API */ -sds sdsMakeRoomFor(sds s, size_t addlen); -void sdsIncrLen(sds s, int incr); -sds sdsRemoveFreeSpace(sds s); -size_t sdsAllocSize(sds s); -void *sdsAllocPtr(sds s); - -/* Export the allocator used by SDS to the program using SDS. - * Sometimes the program SDS is linked to, may use a different set of - * allocators, but may want to allocate or free things that SDS will - * respectively free or allocate. */ -void *sds_malloc(size_t size); -void *sds_realloc(void *ptr, size_t size); -void sds_free(void *ptr); - -#ifdef REDIS_TEST -int sdsTest(int argc, char *argv[]); -#endif - -#endif diff --git a/ext/hiredis-0.14.1/include/hiredis/sdsalloc.h b/ext/hiredis-0.14.1/include/hiredis/sdsalloc.h deleted file mode 100644 index f43023c48..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/sdsalloc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* SDS allocator selection. - * - * This file is used in order to change the SDS allocator at compile time. - * Just define the following defines to what you want to use. Also add - * the include of your alternate allocator if needed (not needed in order - * to use the default libc allocator). */ - -#define s_malloc malloc -#define s_realloc realloc -#define s_free free diff --git a/ext/hiredis-0.14.1/include/hiredis/win32.h b/ext/hiredis-0.14.1/include/hiredis/win32.h deleted file mode 100644 index 1a27c18f2..000000000 --- a/ext/hiredis-0.14.1/include/hiredis/win32.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _WIN32_HELPER_INCLUDE -#define _WIN32_HELPER_INCLUDE -#ifdef _MSC_VER - -#ifndef inline -#define inline __inline -#endif - -#ifndef va_copy -#define va_copy(d,s) ((d) = (s)) -#endif - -#ifndef snprintf -#define snprintf c99_snprintf - -__inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) -{ - int count = -1; - - if (size != 0) - count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - -__inline int c99_snprintf(char* str, size_t size, const char* format, ...) -{ - int count; - va_list ap; - - va_start(ap, format); - count = c99_vsnprintf(str, size, format, ap); - va_end(ap); - - return count; -} -#endif - -#endif -#endif \ No newline at end of file diff --git a/ext/hiredis-0.14.1/lib/centos8/libhiredis.a b/ext/hiredis-0.14.1/lib/centos8/libhiredis.a deleted file mode 100644 index 0b9638798..000000000 Binary files a/ext/hiredis-0.14.1/lib/centos8/libhiredis.a and /dev/null differ diff --git a/ext/hiredis-0.14.1/lib/macos/libhiredis.a b/ext/hiredis-0.14.1/lib/macos/libhiredis.a deleted file mode 100644 index 02bdb8808..000000000 Binary files a/ext/hiredis-0.14.1/lib/macos/libhiredis.a and /dev/null differ diff --git a/ext/hiredis-0.14.1/net.c b/ext/hiredis-0.14.1/net.c deleted file mode 100644 index d71bbcd57..000000000 --- a/ext/hiredis-0.14.1/net.c +++ /dev/null @@ -1,477 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "net.h" -#include "sds.h" - -/* Defined in hiredis.c */ -void __redisSetError(redisContext *c, int type, const char *str); - -static void redisContextCloseFd(redisContext *c) { - if (c && c->fd >= 0) { - close(c->fd); - c->fd = -1; - } -} - -static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { - int errorno = errno; /* snprintf() may change errno */ - char buf[128] = { 0 }; - size_t len = 0; - - if (prefix != NULL) - len = snprintf(buf,sizeof(buf),"%s: ",prefix); - strerror_r(errorno, (char *)(buf + len), sizeof(buf) - len); - __redisSetError(c,type,buf); -} - -static int redisSetReuseAddr(redisContext *c) { - int on = 1; - if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); - return REDIS_ERR; - } - return REDIS_OK; -} - -static int redisCreateSocket(redisContext *c, int type) { - int s; - if ((s = socket(type, SOCK_STREAM, 0)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - c->fd = s; - if (type == AF_INET) { - if (redisSetReuseAddr(c) == REDIS_ERR) { - return REDIS_ERR; - } - } - return REDIS_OK; -} - -static int redisSetBlocking(redisContext *c, int blocking) { - int flags; - - /* Set the socket nonblocking. - * Note that fcntl(2) for F_GETFL and F_SETFL can't be - * interrupted by a signal. */ - if ((flags = fcntl(c->fd, F_GETFL)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)"); - redisContextCloseFd(c); - return REDIS_ERR; - } - - if (blocking) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - - if (fcntl(c->fd, F_SETFL, flags) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)"); - redisContextCloseFd(c); - return REDIS_ERR; - } - return REDIS_OK; -} - -int redisKeepAlive(redisContext *c, int interval) { - int val = 1; - int fd = c->fd; - - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){ - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } - - val = interval; - -#if defined(__APPLE__) && defined(__MACH__) - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) { - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } -#else -#if defined(__GLIBC__) && !defined(__FreeBSD_kernel__) - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } - - val = interval/3; - if (val == 0) val = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } - - val = 3; - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } -#endif -#endif - - return REDIS_OK; -} - -static int redisSetTcpNoDelay(redisContext *c) { - int yes = 1; - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)"); - redisContextCloseFd(c); - return REDIS_ERR; - } - return REDIS_OK; -} - -#define __MAX_MSEC (((LONG_MAX) - 999) / 1000) - -static int redisContextTimeoutMsec(redisContext *c, long *result) -{ - const struct timeval *timeout = c->timeout; - long msec = -1; - - /* Only use timeout when not NULL. */ - if (timeout != NULL) { - if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { - *result = msec; - return REDIS_ERR; - } - - msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000); - - if (msec < 0 || msec > INT_MAX) { - msec = INT_MAX; - } - } - - *result = msec; - return REDIS_OK; -} - -static int redisContextWaitReady(redisContext *c, long msec) { - struct pollfd wfd[1]; - - wfd[0].fd = c->fd; - wfd[0].events = POLLOUT; - - if (errno == EINPROGRESS) { - int res; - - if ((res = poll(wfd, 1, msec)) == -1) { - __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); - redisContextCloseFd(c); - return REDIS_ERR; - } else if (res == 0) { - errno = ETIMEDOUT; - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); - return REDIS_ERR; - } - - if (redisCheckSocketError(c) != REDIS_OK) - return REDIS_ERR; - - return REDIS_OK; - } - - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); - return REDIS_ERR; -} - -int redisCheckSocketError(redisContext *c) { - int err = 0; - socklen_t errlen = sizeof(err); - - if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)"); - return REDIS_ERR; - } - - if (err) { - errno = err; - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - - return REDIS_OK; -} - -int redisContextSetTimeout(redisContext *c, const struct timeval tv) { - if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)"); - return REDIS_ERR; - } - if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)"); - return REDIS_ERR; - } - return REDIS_OK; -} - -static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr) { - int s, rv, n; - char _port[6]; /* strlen("65535"); */ - struct addrinfo hints, *servinfo, *bservinfo, *p, *b; - int blocking = (c->flags & REDIS_BLOCK); - int reuseaddr = (c->flags & REDIS_REUSEADDR); - int reuses = 0; - long timeout_msec = -1; - - servinfo = NULL; - c->connection_type = REDIS_CONN_TCP; - c->tcp.port = port; - - /* We need to take possession of the passed parameters - * to make them reusable for a reconnect. - * We also carefully check we don't free data we already own, - * as in the case of the reconnect method. - * - * This is a bit ugly, but atleast it works and doesn't leak memory. - **/ - if (c->tcp.host != addr) { - free(c->tcp.host); - - c->tcp.host = hi_strdup(addr); - } - - if (timeout) { - if (c->timeout != timeout) { - if (c->timeout == NULL) - c->timeout = hi_malloc(sizeof(struct timeval)); - - memcpy(c->timeout, timeout, sizeof(struct timeval)); - } - } else { - free(c->timeout); - c->timeout = NULL; - } - - if (redisContextTimeoutMsec(c, &timeout_msec) != REDIS_OK) { - __redisSetError(c, REDIS_ERR_IO, "Invalid timeout specified"); - goto error; - } - - if (source_addr == NULL) { - free(c->tcp.source_addr); - c->tcp.source_addr = NULL; - } else if (c->tcp.source_addr != source_addr) { - free(c->tcp.source_addr); - c->tcp.source_addr = hi_strdup(source_addr); - } - - snprintf(_port, 6, "%d", port); - memset(&hints,0,sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - /* Try with IPv6 if no IPv4 address was found. We do it in this order since - * in a Redis client you can't afford to test if you have IPv6 connectivity - * as this would add latency to every connect. Otherwise a more sensible - * route could be: Use IPv6 if both addresses are available and there is IPv6 - * connectivity. */ - if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) { - hints.ai_family = AF_INET6; - if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { - __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); - return REDIS_ERR; - } - } - for (p = servinfo; p != NULL; p = p->ai_next) { -addrretry: - if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) - continue; - - c->fd = s; - if (redisSetBlocking(c,0) != REDIS_OK) - goto error; - if (c->tcp.source_addr) { - int bound = 0; - /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */ - if ((rv = getaddrinfo(c->tcp.source_addr, NULL, &hints, &bservinfo)) != 0) { - char buf[128]; - snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv)); - __redisSetError(c,REDIS_ERR_OTHER,buf); - goto error; - } - - if (reuseaddr) { - n = 1; - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*) &n, - sizeof(n)) < 0) { - freeaddrinfo(bservinfo); - goto error; - } - } - - for (b = bservinfo; b != NULL; b = b->ai_next) { - if (bind(s,b->ai_addr,b->ai_addrlen) != -1) { - bound = 1; - break; - } - } - freeaddrinfo(bservinfo); - if (!bound) { - char buf[128]; - snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno)); - __redisSetError(c,REDIS_ERR_OTHER,buf); - goto error; - } - } - if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { - if (errno == EHOSTUNREACH) { - redisContextCloseFd(c); - continue; - } else if (errno == EINPROGRESS && !blocking) { - /* This is ok. */ - } else if (errno == EADDRNOTAVAIL && reuseaddr) { - if (++reuses >= REDIS_CONNECT_RETRIES) { - goto error; - } else { - redisContextCloseFd(c); - goto addrretry; - } - } else { - if (redisContextWaitReady(c,timeout_msec) != REDIS_OK) - goto error; - } - } - if (blocking && redisSetBlocking(c,1) != REDIS_OK) - goto error; - if (redisSetTcpNoDelay(c) != REDIS_OK) - goto error; - - c->flags |= REDIS_CONNECTED; - rv = REDIS_OK; - goto end; - } - if (p == NULL) { - char buf[128]; - snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno)); - __redisSetError(c,REDIS_ERR_OTHER,buf); - goto error; - } - -error: - rv = REDIS_ERR; -end: - if(servinfo) { - freeaddrinfo(servinfo); - } - - return rv; // Need to return REDIS_OK if alright -} - -int redisContextConnectTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout) { - return _redisContextConnectTcp(c, addr, port, timeout, NULL); -} - -int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr) { - return _redisContextConnectTcp(c, addr, port, timeout, source_addr); -} - -int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) { - int blocking = (c->flags & REDIS_BLOCK); - struct sockaddr_un sa; - long timeout_msec = -1; - - if (redisCreateSocket(c,AF_UNIX) < 0) - return REDIS_ERR; - if (redisSetBlocking(c,0) != REDIS_OK) - return REDIS_ERR; - - c->connection_type = REDIS_CONN_UNIX; - if (c->unix_sock.path != path) - c->unix_sock.path = hi_strdup(path); - - if (timeout) { - if (c->timeout != timeout) { - if (c->timeout == NULL) - c->timeout = hi_malloc(sizeof(struct timeval)); - - memcpy(c->timeout, timeout, sizeof(struct timeval)); - } - } else { - free(c->timeout); - c->timeout = NULL; - } - - if (redisContextTimeoutMsec(c,&timeout_msec) != REDIS_OK) - return REDIS_ERR; - - sa.sun_family = AF_UNIX; - strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); - if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { - if (errno == EINPROGRESS && !blocking) { - /* This is ok. */ - } else { - if (redisContextWaitReady(c,timeout_msec) != REDIS_OK) - return REDIS_ERR; - } - } - - /* Reset socket to be blocking after connect(2). */ - if (blocking && redisSetBlocking(c,1) != REDIS_OK) - return REDIS_ERR; - - c->flags |= REDIS_CONNECTED; - return REDIS_OK; -} diff --git a/ext/hiredis-0.14.1/net.h b/ext/hiredis-0.14.1/net.h deleted file mode 100644 index d9dc36257..000000000 --- a/ext/hiredis-0.14.1/net.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __NET_H -#define __NET_H - -#include "hiredis.h" - -int redisCheckSocketError(redisContext *c); -int redisContextSetTimeout(redisContext *c, const struct timeval tv); -int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); -int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr); -int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); -int redisKeepAlive(redisContext *c, int interval); - -#endif diff --git a/ext/hiredis-0.14.1/read.c b/ext/hiredis-0.14.1/read.c deleted file mode 100644 index cc2126778..000000000 --- a/ext/hiredis-0.14.1/read.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#include "fmacros.h" -#include -#include -#ifndef _MSC_VER -#include -#endif -#include -#include -#include -#include - -#include "read.h" -#include "sds.h" - -static void __redisReaderSetError(redisReader *r, int type, const char *str) { - size_t len; - - if (r->reply != NULL && r->fn && r->fn->freeObject) { - r->fn->freeObject(r->reply); - r->reply = NULL; - } - - /* Clear input buffer on errors. */ - sdsfree(r->buf); - r->buf = NULL; - r->pos = r->len = 0; - - /* Reset task stack. */ - r->ridx = -1; - - /* Set error. */ - r->err = type; - len = strlen(str); - len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1); - memcpy(r->errstr,str,len); - r->errstr[len] = '\0'; -} - -static size_t chrtos(char *buf, size_t size, char byte) { - size_t len = 0; - - switch(byte) { - case '\\': - case '"': - len = snprintf(buf,size,"\"\\%c\"",byte); - break; - case '\n': len = snprintf(buf,size,"\"\\n\""); break; - case '\r': len = snprintf(buf,size,"\"\\r\""); break; - case '\t': len = snprintf(buf,size,"\"\\t\""); break; - case '\a': len = snprintf(buf,size,"\"\\a\""); break; - case '\b': len = snprintf(buf,size,"\"\\b\""); break; - default: - if (isprint(byte)) - len = snprintf(buf,size,"\"%c\"",byte); - else - len = snprintf(buf,size,"\"\\x%02x\"",(unsigned char)byte); - break; - } - - return len; -} - -static void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) { - char cbuf[8], sbuf[128]; - - chrtos(cbuf,sizeof(cbuf),byte); - snprintf(sbuf,sizeof(sbuf), - "Protocol error, got %s as reply type byte", cbuf); - __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf); -} - -static void __redisReaderSetErrorOOM(redisReader *r) { - __redisReaderSetError(r,REDIS_ERR_OOM,"Out of memory"); -} - -static char *readBytes(redisReader *r, unsigned int bytes) { - char *p; - if (r->len-r->pos >= bytes) { - p = r->buf+r->pos; - r->pos += bytes; - return p; - } - return NULL; -} - -/* Find pointer to \r\n. */ -static char *seekNewline(char *s, size_t len) { - int pos = 0; - int _len = len-1; - - /* Position should be < len-1 because the character at "pos" should be - * followed by a \n. Note that strchr cannot be used because it doesn't - * allow to search a limited length and the buffer that is being searched - * might not have a trailing NULL character. */ - while (pos < _len) { - while(pos < _len && s[pos] != '\r') pos++; - if (pos==_len) { - /* Not found. */ - return NULL; - } else { - if (s[pos+1] == '\n') { - /* Found. */ - return s+pos; - } else { - /* Continue searching. */ - pos++; - } - } - } - return NULL; -} - -/* Convert a string into a long long. Returns REDIS_OK if the string could be - * parsed into a (non-overflowing) long long, REDIS_ERR otherwise. The value - * will be set to the parsed value when appropriate. - * - * Note that this function demands that the string strictly represents - * a long long: no spaces or other characters before or after the string - * representing the number are accepted, nor zeroes at the start if not - * for the string "0" representing the zero number. - * - * Because of its strictness, it is safe to use this function to check if - * you can convert a string into a long long, and obtain back the string - * from the number without any loss in the string representation. */ -static int string2ll(const char *s, size_t slen, long long *value) { - const char *p = s; - size_t plen = 0; - int negative = 0; - unsigned long long v; - - if (plen == slen) - return REDIS_ERR; - - /* Special case: first and only digit is 0. */ - if (slen == 1 && p[0] == '0') { - if (value != NULL) *value = 0; - return REDIS_OK; - } - - if (p[0] == '-') { - negative = 1; - p++; plen++; - - /* Abort on only a negative sign. */ - if (plen == slen) - return REDIS_ERR; - } - - /* First digit should be 1-9, otherwise the string should just be 0. */ - if (p[0] >= '1' && p[0] <= '9') { - v = p[0]-'0'; - p++; plen++; - } else if (p[0] == '0' && slen == 1) { - *value = 0; - return REDIS_OK; - } else { - return REDIS_ERR; - } - - while (plen < slen && p[0] >= '0' && p[0] <= '9') { - if (v > (ULLONG_MAX / 10)) /* Overflow. */ - return REDIS_ERR; - v *= 10; - - if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */ - return REDIS_ERR; - v += p[0]-'0'; - - p++; plen++; - } - - /* Return if not all bytes were used. */ - if (plen < slen) - return REDIS_ERR; - - if (negative) { - if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */ - return REDIS_ERR; - if (value != NULL) *value = -v; - } else { - if (v > LLONG_MAX) /* Overflow. */ - return REDIS_ERR; - if (value != NULL) *value = v; - } - return REDIS_OK; -} - -static char *readLine(redisReader *r, int *_len) { - char *p, *s; - int len; - - p = r->buf+r->pos; - s = seekNewline(p,(r->len-r->pos)); - if (s != NULL) { - len = s-(r->buf+r->pos); - r->pos += len+2; /* skip \r\n */ - if (_len) *_len = len; - return p; - } - return NULL; -} - -static void moveToNextTask(redisReader *r) { - redisReadTask *cur, *prv; - while (r->ridx >= 0) { - /* Return a.s.a.p. when the stack is now empty. */ - if (r->ridx == 0) { - r->ridx--; - return; - } - - cur = &(r->rstack[r->ridx]); - prv = &(r->rstack[r->ridx-1]); - assert(prv->type == REDIS_REPLY_ARRAY); - if (cur->idx == prv->elements-1) { - r->ridx--; - } else { - /* Reset the type because the next item can be anything */ - assert(cur->idx < prv->elements); - cur->type = -1; - cur->elements = -1; - cur->idx++; - return; - } - } -} - -static int processLineItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); - void *obj; - char *p; - int len; - - if ((p = readLine(r,&len)) != NULL) { - if (cur->type == REDIS_REPLY_INTEGER) { - if (r->fn && r->fn->createInteger) { - long long v; - if (string2ll(p, len, &v) == REDIS_ERR) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bad integer value"); - return REDIS_ERR; - } - obj = r->fn->createInteger(cur,v); - } else { - obj = (void*)REDIS_REPLY_INTEGER; - } - } else { - /* Type will be error or status. */ - if (r->fn && r->fn->createString) - obj = r->fn->createString(cur,p,len); - else - obj = (void*)(size_t)(cur->type); - } - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - /* Set reply if this is the root object. */ - if (r->ridx == 0) r->reply = obj; - moveToNextTask(r); - return REDIS_OK; - } - - return REDIS_ERR; -} - -static int processBulkItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); - void *obj = NULL; - char *p, *s; - long long len; - unsigned long bytelen; - int success = 0; - - p = r->buf+r->pos; - s = seekNewline(p,r->len-r->pos); - if (s != NULL) { - p = r->buf+r->pos; - bytelen = s-(r->buf+r->pos)+2; /* include \r\n */ - - if (string2ll(p, bytelen - 2, &len) == REDIS_ERR) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bad bulk string length"); - return REDIS_ERR; - } - - if (len < -1 || (LLONG_MAX > SIZE_MAX && len > (long long)SIZE_MAX)) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bulk string length out of range"); - return REDIS_ERR; - } - - if (len == -1) { - /* The nil object can always be created. */ - if (r->fn && r->fn->createNil) - obj = r->fn->createNil(cur); - else - obj = (void*)REDIS_REPLY_NIL; - success = 1; - } else { - /* Only continue when the buffer contains the entire bulk item. */ - bytelen += len+2; /* include \r\n */ - if (r->pos+bytelen <= r->len) { - if (r->fn && r->fn->createString) - obj = r->fn->createString(cur,s+2,len); - else - obj = (void*)REDIS_REPLY_STRING; - success = 1; - } - } - - /* Proceed when obj was created. */ - if (success) { - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - r->pos += bytelen; - - /* Set reply if this is the root object. */ - if (r->ridx == 0) r->reply = obj; - moveToNextTask(r); - return REDIS_OK; - } - } - - return REDIS_ERR; -} - -static int processMultiBulkItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); - void *obj; - char *p; - long long elements; - int root = 0, len; - - /* Set error for nested multi bulks with depth > 7 */ - if (r->ridx == 8) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "No support for nested multi bulk replies with depth > 7"); - return REDIS_ERR; - } - - if ((p = readLine(r,&len)) != NULL) { - if (string2ll(p, len, &elements) == REDIS_ERR) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bad multi-bulk length"); - return REDIS_ERR; - } - - root = (r->ridx == 0); - - if (elements < -1 || elements > INT_MAX) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Multi-bulk length out of range"); - return REDIS_ERR; - } - - if (elements == -1) { - if (r->fn && r->fn->createNil) - obj = r->fn->createNil(cur); - else - obj = (void*)REDIS_REPLY_NIL; - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - moveToNextTask(r); - } else { - if (r->fn && r->fn->createArray) - obj = r->fn->createArray(cur,elements); - else - obj = (void*)REDIS_REPLY_ARRAY; - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - /* Modify task stack when there are more than 0 elements. */ - if (elements > 0) { - cur->elements = elements; - cur->obj = obj; - r->ridx++; - r->rstack[r->ridx].type = -1; - r->rstack[r->ridx].elements = -1; - r->rstack[r->ridx].idx = 0; - r->rstack[r->ridx].obj = NULL; - r->rstack[r->ridx].parent = cur; - r->rstack[r->ridx].privdata = r->privdata; - } else { - moveToNextTask(r); - } - } - - /* Set reply if this is the root object. */ - if (root) r->reply = obj; - return REDIS_OK; - } - - return REDIS_ERR; -} - -static int processItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); - char *p; - - /* check if we need to read type */ - if (cur->type < 0) { - if ((p = readBytes(r,1)) != NULL) { - switch (p[0]) { - case '-': - cur->type = REDIS_REPLY_ERROR; - break; - case '+': - cur->type = REDIS_REPLY_STATUS; - break; - case ':': - cur->type = REDIS_REPLY_INTEGER; - break; - case '$': - cur->type = REDIS_REPLY_STRING; - break; - case '*': - cur->type = REDIS_REPLY_ARRAY; - break; - default: - __redisReaderSetErrorProtocolByte(r,*p); - return REDIS_ERR; - } - } else { - /* could not consume 1 byte */ - return REDIS_ERR; - } - } - - /* process typed item */ - switch(cur->type) { - case REDIS_REPLY_ERROR: - case REDIS_REPLY_STATUS: - case REDIS_REPLY_INTEGER: - return processLineItem(r); - case REDIS_REPLY_STRING: - return processBulkItem(r); - case REDIS_REPLY_ARRAY: - return processMultiBulkItem(r); - default: - assert(NULL); - return REDIS_ERR; /* Avoid warning. */ - } -} - -redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn) { - redisReader *r; - - r = calloc(1,sizeof(redisReader)); - if (r == NULL) - return NULL; - - r->fn = fn; - r->buf = sdsempty(); - r->maxbuf = REDIS_READER_MAX_BUF; - if (r->buf == NULL) { - free(r); - return NULL; - } - - r->ridx = -1; - return r; -} - -void redisReaderFree(redisReader *r) { - if (r == NULL) - return; - if (r->reply != NULL && r->fn && r->fn->freeObject) - r->fn->freeObject(r->reply); - sdsfree(r->buf); - free(r); -} - -int redisReaderFeed(redisReader *r, const char *buf, size_t len) { - sds newbuf; - - /* Return early when this reader is in an erroneous state. */ - if (r->err) - return REDIS_ERR; - - /* Copy the provided buffer. */ - if (buf != NULL && len >= 1) { - /* Destroy internal buffer when it is empty and is quite large. */ - if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) { - sdsfree(r->buf); - r->buf = sdsempty(); - r->pos = 0; - - /* r->buf should not be NULL since we just free'd a larger one. */ - assert(r->buf != NULL); - } - - newbuf = sdscatlen(r->buf,buf,len); - if (newbuf == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - r->buf = newbuf; - r->len = sdslen(r->buf); - } - - return REDIS_OK; -} - -int redisReaderGetReply(redisReader *r, void **reply) { - /* Default target pointer to NULL. */ - if (reply != NULL) - *reply = NULL; - - /* Return early when this reader is in an erroneous state. */ - if (r->err) - return REDIS_ERR; - - /* When the buffer is empty, there will never be a reply. */ - if (r->len == 0) - return REDIS_OK; - - /* Set first item to process when the stack is empty. */ - if (r->ridx == -1) { - r->rstack[0].type = -1; - r->rstack[0].elements = -1; - r->rstack[0].idx = -1; - r->rstack[0].obj = NULL; - r->rstack[0].parent = NULL; - r->rstack[0].privdata = r->privdata; - r->ridx = 0; - } - - /* Process items in reply. */ - while (r->ridx >= 0) - if (processItem(r) != REDIS_OK) - break; - - /* Return ASAP when an error occurred. */ - if (r->err) - return REDIS_ERR; - - /* Discard part of the buffer when we've consumed at least 1k, to avoid - * doing unnecessary calls to memmove() in sds.c. */ - if (r->pos >= 1024) { - sdsrange(r->buf,r->pos,-1); - r->pos = 0; - r->len = sdslen(r->buf); - } - - /* Emit a reply when there is one. */ - if (r->ridx == -1) { - if (reply != NULL) - *reply = r->reply; - r->reply = NULL; - } - return REDIS_OK; -} diff --git a/ext/hiredis-0.14.1/read.h b/ext/hiredis-0.14.1/read.h deleted file mode 100644 index 2988aa453..000000000 --- a/ext/hiredis-0.14.1/read.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef __HIREDIS_READ_H -#define __HIREDIS_READ_H -#include /* for size_t */ - -#define REDIS_ERR -1 -#define REDIS_OK 0 - -/* When an error occurs, the err flag in a context is set to hold the type of - * error that occurred. REDIS_ERR_IO means there was an I/O error and you - * should use the "errno" variable to find out what is wrong. - * For other values, the "errstr" field will hold a description. */ -#define REDIS_ERR_IO 1 /* Error in read or write */ -#define REDIS_ERR_EOF 3 /* End of file */ -#define REDIS_ERR_PROTOCOL 4 /* Protocol error */ -#define REDIS_ERR_OOM 5 /* Out of memory */ -#define REDIS_ERR_OTHER 2 /* Everything else... */ - -#define REDIS_REPLY_STRING 1 -#define REDIS_REPLY_ARRAY 2 -#define REDIS_REPLY_INTEGER 3 -#define REDIS_REPLY_NIL 4 -#define REDIS_REPLY_STATUS 5 -#define REDIS_REPLY_ERROR 6 - -#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct redisReadTask { - int type; - int elements; /* number of elements in multibulk container */ - int idx; /* index in parent (array) object */ - void *obj; /* holds user-generated value for a read task */ - struct redisReadTask *parent; /* parent task */ - void *privdata; /* user-settable arbitrary field */ -} redisReadTask; - -typedef struct redisReplyObjectFunctions { - void *(*createString)(const redisReadTask*, char*, size_t); - void *(*createArray)(const redisReadTask*, int); - void *(*createInteger)(const redisReadTask*, long long); - void *(*createNil)(const redisReadTask*); - void (*freeObject)(void*); -} redisReplyObjectFunctions; - -typedef struct redisReader { - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - - char *buf; /* Read buffer */ - size_t pos; /* Buffer cursor */ - size_t len; /* Buffer length */ - size_t maxbuf; /* Max length of unused buffer */ - - redisReadTask rstack[9]; - int ridx; /* Index of current read task */ - void *reply; /* Temporary reply pointer */ - - redisReplyObjectFunctions *fn; - void *privdata; -} redisReader; - -/* Public API for the protocol parser. */ -redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn); -void redisReaderFree(redisReader *r); -int redisReaderFeed(redisReader *r, const char *buf, size_t len); -int redisReaderGetReply(redisReader *r, void **reply); - -#define redisReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) -#define redisReaderGetObject(_r) (((redisReader*)(_r))->reply) -#define redisReaderGetError(_r) (((redisReader*)(_r))->errstr) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-0.14.1/sds.c b/ext/hiredis-0.14.1/sds.c deleted file mode 100644 index 923ffd82f..000000000 --- a/ext/hiredis-0.14.1/sds.c +++ /dev/null @@ -1,1272 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include "sds.h" -#include "sdsalloc.h" - -static inline int sdsHdrSize(char type) { - switch(type&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return sizeof(struct sdshdr5); - case SDS_TYPE_8: - return sizeof(struct sdshdr8); - case SDS_TYPE_16: - return sizeof(struct sdshdr16); - case SDS_TYPE_32: - return sizeof(struct sdshdr32); - case SDS_TYPE_64: - return sizeof(struct sdshdr64); - } - return 0; -} - -static inline char sdsReqType(size_t string_size) { - if (string_size < 32) - return SDS_TYPE_5; - if (string_size < 0xff) - return SDS_TYPE_8; - if (string_size < 0xffff) - return SDS_TYPE_16; - if (string_size < 0xffffffff) - return SDS_TYPE_32; - return SDS_TYPE_64; -} - -/* Create a new sds string with the content specified by the 'init' pointer - * and 'initlen'. - * If NULL is used for 'init' the string is initialized with zero bytes. - * - * The string is always null-termined (all the sds strings are, always) so - * even if you create an sds string with: - * - * mystring = sdsnewlen("abc",3); - * - * You can print the string with printf() as there is an implicit \0 at the - * end of the string. However the string is binary safe and can contain - * \0 characters in the middle, as the length is stored in the sds header. */ -sds sdsnewlen(const void *init, size_t initlen) { - void *sh; - sds s; - char type = sdsReqType(initlen); - /* Empty strings are usually created in order to append. Use type 8 - * since type 5 is not good at this. */ - if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8; - int hdrlen = sdsHdrSize(type); - unsigned char *fp; /* flags pointer. */ - - sh = s_malloc(hdrlen+initlen+1); - if (sh == NULL) return NULL; - if (!init) - memset(sh, 0, hdrlen+initlen+1); - s = (char*)sh+hdrlen; - fp = ((unsigned char*)s)-1; - switch(type) { - case SDS_TYPE_5: { - *fp = type | (initlen << SDS_TYPE_BITS); - break; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - sh->len = initlen; - sh->alloc = initlen; - *fp = type; - break; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - sh->len = initlen; - sh->alloc = initlen; - *fp = type; - break; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - sh->len = initlen; - sh->alloc = initlen; - *fp = type; - break; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - sh->len = initlen; - sh->alloc = initlen; - *fp = type; - break; - } - } - if (initlen && init) - memcpy(s, init, initlen); - s[initlen] = '\0'; - return s; -} - -/* Create an empty (zero length) sds string. Even in this case the string - * always has an implicit null term. */ -sds sdsempty(void) { - return sdsnewlen("",0); -} - -/* Create a new sds string starting from a null terminated C string. */ -sds sdsnew(const char *init) { - size_t initlen = (init == NULL) ? 0 : strlen(init); - return sdsnewlen(init, initlen); -} - -/* Duplicate an sds string. */ -sds sdsdup(const sds s) { - return sdsnewlen(s, sdslen(s)); -} - -/* Free an sds string. No operation is performed if 's' is NULL. */ -void sdsfree(sds s) { - if (s == NULL) return; - s_free((char*)s-sdsHdrSize(s[-1])); -} - -/* Set the sds string length to the length as obtained with strlen(), so - * considering as content only up to the first null term character. - * - * This function is useful when the sds string is hacked manually in some - * way, like in the following example: - * - * s = sdsnew("foobar"); - * s[2] = '\0'; - * sdsupdatelen(s); - * printf("%d\n", sdslen(s)); - * - * The output will be "2", but if we comment out the call to sdsupdatelen() - * the output will be "6" as the string was modified but the logical length - * remains 6 bytes. */ -void sdsupdatelen(sds s) { - int reallen = strlen(s); - sdssetlen(s, reallen); -} - -/* Modify an sds string in-place to make it empty (zero length). - * However all the existing buffer is not discarded but set as free space - * so that next append operations will not require allocations up to the - * number of bytes previously available. */ -void sdsclear(sds s) { - sdssetlen(s, 0); - s[0] = '\0'; -} - -/* Enlarge the free space at the end of the sds string so that the caller - * is sure that after calling this function can overwrite up to addlen - * bytes after the end of the string, plus one more byte for nul term. - * - * Note: this does not change the *length* of the sds string as returned - * by sdslen(), but only the free buffer space we have. */ -sds sdsMakeRoomFor(sds s, size_t addlen) { - void *sh, *newsh; - size_t avail = sdsavail(s); - size_t len, newlen; - char type, oldtype = s[-1] & SDS_TYPE_MASK; - int hdrlen; - - /* Return ASAP if there is enough space left. */ - if (avail >= addlen) return s; - - len = sdslen(s); - sh = (char*)s-sdsHdrSize(oldtype); - newlen = (len+addlen); - if (newlen < SDS_MAX_PREALLOC) - newlen *= 2; - else - newlen += SDS_MAX_PREALLOC; - - type = sdsReqType(newlen); - - /* Don't use type 5: the user is appending to the string and type 5 is - * not able to remember empty space, so sdsMakeRoomFor() must be called - * at every appending operation. */ - if (type == SDS_TYPE_5) type = SDS_TYPE_8; - - hdrlen = sdsHdrSize(type); - if (oldtype==type) { - newsh = s_realloc(sh, hdrlen+newlen+1); - if (newsh == NULL) return NULL; - s = (char*)newsh+hdrlen; - } else { - /* Since the header size changes, need to move the string forward, - * and can't use realloc */ - newsh = s_malloc(hdrlen+newlen+1); - if (newsh == NULL) return NULL; - memcpy((char*)newsh+hdrlen, s, len+1); - s_free(sh); - s = (char*)newsh+hdrlen; - s[-1] = type; - sdssetlen(s, len); - } - sdssetalloc(s, newlen); - return s; -} - -/* Reallocate the sds string so that it has no free space at the end. The - * contained string remains not altered, but next concatenation operations - * will require a reallocation. - * - * After the call, the passed sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdsRemoveFreeSpace(sds s) { - void *sh, *newsh; - char type, oldtype = s[-1] & SDS_TYPE_MASK; - int hdrlen; - size_t len = sdslen(s); - sh = (char*)s-sdsHdrSize(oldtype); - - type = sdsReqType(len); - hdrlen = sdsHdrSize(type); - if (oldtype==type) { - newsh = s_realloc(sh, hdrlen+len+1); - if (newsh == NULL) return NULL; - s = (char*)newsh+hdrlen; - } else { - newsh = s_malloc(hdrlen+len+1); - if (newsh == NULL) return NULL; - memcpy((char*)newsh+hdrlen, s, len+1); - s_free(sh); - s = (char*)newsh+hdrlen; - s[-1] = type; - sdssetlen(s, len); - } - sdssetalloc(s, len); - return s; -} - -/* Return the total size of the allocation of the specifed sds string, - * including: - * 1) The sds header before the pointer. - * 2) The string. - * 3) The free buffer at the end if any. - * 4) The implicit null term. - */ -size_t sdsAllocSize(sds s) { - size_t alloc = sdsalloc(s); - return sdsHdrSize(s[-1])+alloc+1; -} - -/* Return the pointer of the actual SDS allocation (normally SDS strings - * are referenced by the start of the string buffer). */ -void *sdsAllocPtr(sds s) { - return (void*) (s-sdsHdrSize(s[-1])); -} - -/* Increment the sds length and decrements the left free space at the - * end of the string according to 'incr'. Also set the null term - * in the new end of the string. - * - * This function is used in order to fix the string length after the - * user calls sdsMakeRoomFor(), writes something after the end of - * the current string, and finally needs to set the new length. - * - * Note: it is possible to use a negative increment in order to - * right-trim the string. - * - * Usage example: - * - * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the - * following schema, to cat bytes coming from the kernel to the end of an - * sds string without copying into an intermediate buffer: - * - * oldlen = sdslen(s); - * s = sdsMakeRoomFor(s, BUFFER_SIZE); - * nread = read(fd, s+oldlen, BUFFER_SIZE); - * ... check for nread <= 0 and handle it ... - * sdsIncrLen(s, nread); - */ -void sdsIncrLen(sds s, int incr) { - unsigned char flags = s[-1]; - size_t len; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: { - unsigned char *fp = ((unsigned char*)s)-1; - unsigned char oldlen = SDS_TYPE_5_LEN(flags); - assert((incr > 0 && oldlen+incr < 32) || (incr < 0 && oldlen >= (unsigned int)(-incr))); - *fp = SDS_TYPE_5 | ((oldlen+incr) << SDS_TYPE_BITS); - len = oldlen+incr; - break; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr))); - len = (sh->len += incr); - break; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr))); - len = (sh->len += incr); - break; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - assert((incr >= 0 && sh->alloc-sh->len >= (unsigned int)incr) || (incr < 0 && sh->len >= (unsigned int)(-incr))); - len = (sh->len += incr); - break; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - assert((incr >= 0 && sh->alloc-sh->len >= (uint64_t)incr) || (incr < 0 && sh->len >= (uint64_t)(-incr))); - len = (sh->len += incr); - break; - } - default: len = 0; /* Just to avoid compilation warnings. */ - } - s[len] = '\0'; -} - -/* Grow the sds to have the specified length. Bytes that were not part of - * the original length of the sds will be set to zero. - * - * if the specified length is smaller than the current length, no operation - * is performed. */ -sds sdsgrowzero(sds s, size_t len) { - size_t curlen = sdslen(s); - - if (len <= curlen) return s; - s = sdsMakeRoomFor(s,len-curlen); - if (s == NULL) return NULL; - - /* Make sure added region doesn't contain garbage */ - memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */ - sdssetlen(s, len); - return s; -} - -/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the - * end of the specified sds string 's'. - * - * After the call, the passed sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdscatlen(sds s, const void *t, size_t len) { - size_t curlen = sdslen(s); - - s = sdsMakeRoomFor(s,len); - if (s == NULL) return NULL; - memcpy(s+curlen, t, len); - sdssetlen(s, curlen+len); - s[curlen+len] = '\0'; - return s; -} - -/* Append the specified null termianted C string to the sds string 's'. - * - * After the call, the passed sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdscat(sds s, const char *t) { - return sdscatlen(s, t, strlen(t)); -} - -/* Append the specified sds 't' to the existing sds 's'. - * - * After the call, the modified sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdscatsds(sds s, const sds t) { - return sdscatlen(s, t, sdslen(t)); -} - -/* Destructively modify the sds string 's' to hold the specified binary - * safe string pointed by 't' of length 'len' bytes. */ -sds sdscpylen(sds s, const char *t, size_t len) { - if (sdsalloc(s) < len) { - s = sdsMakeRoomFor(s,len-sdslen(s)); - if (s == NULL) return NULL; - } - memcpy(s, t, len); - s[len] = '\0'; - sdssetlen(s, len); - return s; -} - -/* Like sdscpylen() but 't' must be a null-termined string so that the length - * of the string is obtained with strlen(). */ -sds sdscpy(sds s, const char *t) { - return sdscpylen(s, t, strlen(t)); -} - -/* Helper for sdscatlonglong() doing the actual number -> string - * conversion. 's' must point to a string with room for at least - * SDS_LLSTR_SIZE bytes. - * - * The function returns the length of the null-terminated string - * representation stored at 's'. */ -#define SDS_LLSTR_SIZE 21 -int sdsll2str(char *s, long long value) { - char *p, aux; - unsigned long long v; - size_t l; - - /* Generate the string representation, this method produces - * an reversed string. */ - v = (value < 0) ? -value : value; - p = s; - do { - *p++ = '0'+(v%10); - v /= 10; - } while(v); - if (value < 0) *p++ = '-'; - - /* Compute length and add null term. */ - l = p-s; - *p = '\0'; - - /* Reverse the string. */ - p--; - while(s < p) { - aux = *s; - *s = *p; - *p = aux; - s++; - p--; - } - return l; -} - -/* Identical sdsll2str(), but for unsigned long long type. */ -int sdsull2str(char *s, unsigned long long v) { - char *p, aux; - size_t l; - - /* Generate the string representation, this method produces - * an reversed string. */ - p = s; - do { - *p++ = '0'+(v%10); - v /= 10; - } while(v); - - /* Compute length and add null term. */ - l = p-s; - *p = '\0'; - - /* Reverse the string. */ - p--; - while(s < p) { - aux = *s; - *s = *p; - *p = aux; - s++; - p--; - } - return l; -} - -/* Create an sds string from a long long value. It is much faster than: - * - * sdscatprintf(sdsempty(),"%lld\n", value); - */ -sds sdsfromlonglong(long long value) { - char buf[SDS_LLSTR_SIZE]; - int len = sdsll2str(buf,value); - - return sdsnewlen(buf,len); -} - -/* Like sdscatprintf() but gets va_list instead of being variadic. */ -sds sdscatvprintf(sds s, const char *fmt, va_list ap) { - va_list cpy; - char staticbuf[1024], *buf = staticbuf, *t; - size_t buflen = strlen(fmt)*2; - - /* We try to start using a static buffer for speed. - * If not possible we revert to heap allocation. */ - if (buflen > sizeof(staticbuf)) { - buf = s_malloc(buflen); - if (buf == NULL) return NULL; - } else { - buflen = sizeof(staticbuf); - } - - /* Try with buffers two times bigger every time we fail to - * fit the string in the current buffer size. */ - while(1) { - buf[buflen-2] = '\0'; - va_copy(cpy,ap); - vsnprintf(buf, buflen, fmt, cpy); - va_end(cpy); - if (buf[buflen-2] != '\0') { - if (buf != staticbuf) s_free(buf); - buflen *= 2; - buf = s_malloc(buflen); - if (buf == NULL) return NULL; - continue; - } - break; - } - - /* Finally concat the obtained string to the SDS string and return it. */ - t = sdscat(s, buf); - if (buf != staticbuf) s_free(buf); - return t; -} - -/* Append to the sds string 's' a string obtained using printf-alike format - * specifier. - * - * After the call, the modified sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. - * - * Example: - * - * s = sdsnew("Sum is: "); - * s = sdscatprintf(s,"%d+%d = %d",a,b,a+b). - * - * Often you need to create a string from scratch with the printf-alike - * format. When this is the need, just use sdsempty() as the target string: - * - * s = sdscatprintf(sdsempty(), "... your format ...", args); - */ -sds sdscatprintf(sds s, const char *fmt, ...) { - va_list ap; - char *t; - va_start(ap, fmt); - t = sdscatvprintf(s,fmt,ap); - va_end(ap); - return t; -} - -/* This function is similar to sdscatprintf, but much faster as it does - * not rely on sprintf() family functions implemented by the libc that - * are often very slow. Moreover directly handling the sds string as - * new data is concatenated provides a performance improvement. - * - * However this function only handles an incompatible subset of printf-alike - * format specifiers: - * - * %s - C String - * %S - SDS string - * %i - signed int - * %I - 64 bit signed integer (long long, int64_t) - * %u - unsigned int - * %U - 64 bit unsigned integer (unsigned long long, uint64_t) - * %% - Verbatim "%" character. - */ -sds sdscatfmt(sds s, char const *fmt, ...) { - const char *f = fmt; - int i; - va_list ap; - - va_start(ap,fmt); - i = sdslen(s); /* Position of the next byte to write to dest str. */ - while(*f) { - char next, *str; - size_t l; - long long num; - unsigned long long unum; - - /* Make sure there is always space for at least 1 char. */ - if (sdsavail(s)==0) { - s = sdsMakeRoomFor(s,1); - } - - switch(*f) { - case '%': - next = *(f+1); - f++; - switch(next) { - case 's': - case 'S': - str = va_arg(ap,char*); - l = (next == 's') ? strlen(str) : sdslen(str); - if (sdsavail(s) < l) { - s = sdsMakeRoomFor(s,l); - } - memcpy(s+i,str,l); - sdsinclen(s,l); - i += l; - break; - case 'i': - case 'I': - if (next == 'i') - num = va_arg(ap,int); - else - num = va_arg(ap,long long); - { - char buf[SDS_LLSTR_SIZE]; - l = sdsll2str(buf,num); - if (sdsavail(s) < l) { - s = sdsMakeRoomFor(s,l); - } - memcpy(s+i,buf,l); - sdsinclen(s,l); - i += l; - } - break; - case 'u': - case 'U': - if (next == 'u') - unum = va_arg(ap,unsigned int); - else - unum = va_arg(ap,unsigned long long); - { - char buf[SDS_LLSTR_SIZE]; - l = sdsull2str(buf,unum); - if (sdsavail(s) < l) { - s = sdsMakeRoomFor(s,l); - } - memcpy(s+i,buf,l); - sdsinclen(s,l); - i += l; - } - break; - default: /* Handle %% and generally %. */ - s[i++] = next; - sdsinclen(s,1); - break; - } - break; - default: - s[i++] = *f; - sdsinclen(s,1); - break; - } - f++; - } - va_end(ap); - - /* Add null-term */ - s[i] = '\0'; - return s; -} - -/* Remove the part of the string from left and from right composed just of - * contiguous characters found in 'cset', that is a null terminted C string. - * - * After the call, the modified sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. - * - * Example: - * - * s = sdsnew("AA...AA.a.aa.aHelloWorld :::"); - * s = sdstrim(s,"Aa. :"); - * printf("%s\n", s); - * - * Output will be just "Hello World". - */ -sds sdstrim(sds s, const char *cset) { - char *start, *end, *sp, *ep; - size_t len; - - sp = start = s; - ep = end = s+sdslen(s)-1; - while(sp <= end && strchr(cset, *sp)) sp++; - while(ep > sp && strchr(cset, *ep)) ep--; - len = (sp > ep) ? 0 : ((ep-sp)+1); - if (s != sp) memmove(s, sp, len); - s[len] = '\0'; - sdssetlen(s,len); - return s; -} - -/* Turn the string into a smaller (or equal) string containing only the - * substring specified by the 'start' and 'end' indexes. - * - * start and end can be negative, where -1 means the last character of the - * string, -2 the penultimate character, and so forth. - * - * The interval is inclusive, so the start and end characters will be part - * of the resulting string. - * - * The string is modified in-place. - * - * Example: - * - * s = sdsnew("Hello World"); - * sdsrange(s,1,-1); => "ello World" - */ -void sdsrange(sds s, int start, int end) { - size_t newlen, len = sdslen(s); - - if (len == 0) return; - if (start < 0) { - start = len+start; - if (start < 0) start = 0; - } - if (end < 0) { - end = len+end; - if (end < 0) end = 0; - } - newlen = (start > end) ? 0 : (end-start)+1; - if (newlen != 0) { - if (start >= (signed)len) { - newlen = 0; - } else if (end >= (signed)len) { - end = len-1; - newlen = (start > end) ? 0 : (end-start)+1; - } - } else { - start = 0; - } - if (start && newlen) memmove(s, s+start, newlen); - s[newlen] = 0; - sdssetlen(s,newlen); -} - -/* Apply tolower() to every character of the sds string 's'. */ -void sdstolower(sds s) { - int len = sdslen(s), j; - - for (j = 0; j < len; j++) s[j] = tolower(s[j]); -} - -/* Apply toupper() to every character of the sds string 's'. */ -void sdstoupper(sds s) { - int len = sdslen(s), j; - - for (j = 0; j < len; j++) s[j] = toupper(s[j]); -} - -/* Compare two sds strings s1 and s2 with memcmp(). - * - * Return value: - * - * positive if s1 > s2. - * negative if s1 < s2. - * 0 if s1 and s2 are exactly the same binary string. - * - * If two strings share exactly the same prefix, but one of the two has - * additional characters, the longer string is considered to be greater than - * the smaller one. */ -int sdscmp(const sds s1, const sds s2) { - size_t l1, l2, minlen; - int cmp; - - l1 = sdslen(s1); - l2 = sdslen(s2); - minlen = (l1 < l2) ? l1 : l2; - cmp = memcmp(s1,s2,minlen); - if (cmp == 0) return l1-l2; - return cmp; -} - -/* Split 's' with separator in 'sep'. An array - * of sds strings is returned. *count will be set - * by reference to the number of tokens returned. - * - * On out of memory, zero length string, zero length - * separator, NULL is returned. - * - * Note that 'sep' is able to split a string using - * a multi-character separator. For example - * sdssplit("foo_-_bar","_-_"); will return two - * elements "foo" and "bar". - * - * This version of the function is binary-safe but - * requires length arguments. sdssplit() is just the - * same function but for zero-terminated strings. - */ -sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) { - int elements = 0, slots = 5, start = 0, j; - sds *tokens; - - if (seplen < 1 || len < 0) return NULL; - - tokens = s_malloc(sizeof(sds)*slots); - if (tokens == NULL) return NULL; - - if (len == 0) { - *count = 0; - return tokens; - } - for (j = 0; j < (len-(seplen-1)); j++) { - /* make sure there is room for the next element and the final one */ - if (slots < elements+2) { - sds *newtokens; - - slots *= 2; - newtokens = s_realloc(tokens,sizeof(sds)*slots); - if (newtokens == NULL) goto cleanup; - tokens = newtokens; - } - /* search the separator */ - if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) { - tokens[elements] = sdsnewlen(s+start,j-start); - if (tokens[elements] == NULL) goto cleanup; - elements++; - start = j+seplen; - j = j+seplen-1; /* skip the separator */ - } - } - /* Add the final element. We are sure there is room in the tokens array. */ - tokens[elements] = sdsnewlen(s+start,len-start); - if (tokens[elements] == NULL) goto cleanup; - elements++; - *count = elements; - return tokens; - -cleanup: - { - int i; - for (i = 0; i < elements; i++) sdsfree(tokens[i]); - s_free(tokens); - *count = 0; - return NULL; - } -} - -/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */ -void sdsfreesplitres(sds *tokens, int count) { - if (!tokens) return; - while(count--) - sdsfree(tokens[count]); - s_free(tokens); -} - -/* Append to the sds string "s" an escaped string representation where - * all the non-printable characters (tested with isprint()) are turned into - * escapes in the form "\n\r\a...." or "\x". - * - * After the call, the modified sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdscatrepr(sds s, const char *p, size_t len) { - s = sdscatlen(s,"\"",1); - while(len--) { - switch(*p) { - case '\\': - case '"': - s = sdscatprintf(s,"\\%c",*p); - break; - case '\n': s = sdscatlen(s,"\\n",2); break; - case '\r': s = sdscatlen(s,"\\r",2); break; - case '\t': s = sdscatlen(s,"\\t",2); break; - case '\a': s = sdscatlen(s,"\\a",2); break; - case '\b': s = sdscatlen(s,"\\b",2); break; - default: - if (isprint(*p)) - s = sdscatprintf(s,"%c",*p); - else - s = sdscatprintf(s,"\\x%02x",(unsigned char)*p); - break; - } - p++; - } - return sdscatlen(s,"\"",1); -} - -/* Helper function for sdssplitargs() that returns non zero if 'c' - * is a valid hex digit. */ -int is_hex_digit(char c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || - (c >= 'A' && c <= 'F'); -} - -/* Helper function for sdssplitargs() that converts a hex digit into an - * integer from 0 to 15 */ -int hex_digit_to_int(char c) { - switch(c) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; - default: return 0; - } -} - -/* Split a line into arguments, where every argument can be in the - * following programming-language REPL-alike form: - * - * foo bar "newline are supported\n" and "\xff\x00otherstuff" - * - * The number of arguments is stored into *argc, and an array - * of sds is returned. - * - * The caller should free the resulting array of sds strings with - * sdsfreesplitres(). - * - * Note that sdscatrepr() is able to convert back a string into - * a quoted string in the same format sdssplitargs() is able to parse. - * - * The function returns the allocated tokens on success, even when the - * input string is empty, or NULL if the input contains unbalanced - * quotes or closed quotes followed by non space characters - * as in: "foo"bar or "foo' - */ -sds *sdssplitargs(const char *line, int *argc) { - const char *p = line; - char *current = NULL; - char **vector = NULL; - - *argc = 0; - while(1) { - /* skip blanks */ - while(*p && isspace(*p)) p++; - if (*p) { - /* get a token */ - int inq=0; /* set to 1 if we are in "quotes" */ - int insq=0; /* set to 1 if we are in 'single quotes' */ - int done=0; - - if (current == NULL) current = sdsempty(); - while(!done) { - if (inq) { - if (*p == '\\' && *(p+1) == 'x' && - is_hex_digit(*(p+2)) && - is_hex_digit(*(p+3))) - { - unsigned char byte; - - byte = (hex_digit_to_int(*(p+2))*16)+ - hex_digit_to_int(*(p+3)); - current = sdscatlen(current,(char*)&byte,1); - p += 3; - } else if (*p == '\\' && *(p+1)) { - char c; - - p++; - switch(*p) { - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'b': c = '\b'; break; - case 'a': c = '\a'; break; - default: c = *p; break; - } - current = sdscatlen(current,&c,1); - } else if (*p == '"') { - /* closing quote must be followed by a space or - * nothing at all. */ - if (*(p+1) && !isspace(*(p+1))) goto err; - done=1; - } else if (!*p) { - /* unterminated quotes */ - goto err; - } else { - current = sdscatlen(current,p,1); - } - } else if (insq) { - if (*p == '\\' && *(p+1) == '\'') { - p++; - current = sdscatlen(current,"'",1); - } else if (*p == '\'') { - /* closing quote must be followed by a space or - * nothing at all. */ - if (*(p+1) && !isspace(*(p+1))) goto err; - done=1; - } else if (!*p) { - /* unterminated quotes */ - goto err; - } else { - current = sdscatlen(current,p,1); - } - } else { - switch(*p) { - case ' ': - case '\n': - case '\r': - case '\t': - case '\0': - done=1; - break; - case '"': - inq=1; - break; - case '\'': - insq=1; - break; - default: - current = sdscatlen(current,p,1); - break; - } - } - if (*p) p++; - } - /* add the token to the vector */ - vector = s_realloc(vector,((*argc)+1)*sizeof(char*)); - vector[*argc] = current; - (*argc)++; - current = NULL; - } else { - /* Even on empty input string return something not NULL. */ - if (vector == NULL) vector = s_malloc(sizeof(void*)); - return vector; - } - } - -err: - while((*argc)--) - sdsfree(vector[*argc]); - s_free(vector); - if (current) sdsfree(current); - *argc = 0; - return NULL; -} - -/* Modify the string substituting all the occurrences of the set of - * characters specified in the 'from' string to the corresponding character - * in the 'to' array. - * - * For instance: sdsmapchars(mystring, "ho", "01", 2) - * will have the effect of turning the string "hello" into "0ell1". - * - * The function returns the sds string pointer, that is always the same - * as the input pointer since no resize is needed. */ -sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) { - size_t j, i, l = sdslen(s); - - for (j = 0; j < l; j++) { - for (i = 0; i < setlen; i++) { - if (s[j] == from[i]) { - s[j] = to[i]; - break; - } - } - } - return s; -} - -/* Join an array of C strings using the specified separator (also a C string). - * Returns the result as an sds string. */ -sds sdsjoin(char **argv, int argc, char *sep) { - sds join = sdsempty(); - int j; - - for (j = 0; j < argc; j++) { - join = sdscat(join, argv[j]); - if (j != argc-1) join = sdscat(join,sep); - } - return join; -} - -/* Like sdsjoin, but joins an array of SDS strings. */ -sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) { - sds join = sdsempty(); - int j; - - for (j = 0; j < argc; j++) { - join = sdscatsds(join, argv[j]); - if (j != argc-1) join = sdscatlen(join,sep,seplen); - } - return join; -} - -/* Wrappers to the allocators used by SDS. Note that SDS will actually - * just use the macros defined into sdsalloc.h in order to avoid to pay - * the overhead of function calls. Here we define these wrappers only for - * the programs SDS is linked to, if they want to touch the SDS internals - * even if they use a different allocator. */ -void *sds_malloc(size_t size) { return s_malloc(size); } -void *sds_realloc(void *ptr, size_t size) { return s_realloc(ptr,size); } -void sds_free(void *ptr) { s_free(ptr); } - -#if defined(SDS_TEST_MAIN) -#include -#include "testhelp.h" -#include "limits.h" - -#define UNUSED(x) (void)(x) -int sdsTest(void) { - { - sds x = sdsnew("foo"), y; - - test_cond("Create a string and obtain the length", - sdslen(x) == 3 && memcmp(x,"foo\0",4) == 0) - - sdsfree(x); - x = sdsnewlen("foo",2); - test_cond("Create a string with specified length", - sdslen(x) == 2 && memcmp(x,"fo\0",3) == 0) - - x = sdscat(x,"bar"); - test_cond("Strings concatenation", - sdslen(x) == 5 && memcmp(x,"fobar\0",6) == 0); - - x = sdscpy(x,"a"); - test_cond("sdscpy() against an originally longer string", - sdslen(x) == 1 && memcmp(x,"a\0",2) == 0) - - x = sdscpy(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk"); - test_cond("sdscpy() against an originally shorter string", - sdslen(x) == 33 && - memcmp(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\0",33) == 0) - - sdsfree(x); - x = sdscatprintf(sdsempty(),"%d",123); - test_cond("sdscatprintf() seems working in the base case", - sdslen(x) == 3 && memcmp(x,"123\0",4) == 0) - - sdsfree(x); - x = sdsnew("--"); - x = sdscatfmt(x, "Hello %s World %I,%I--", "Hi!", LLONG_MIN,LLONG_MAX); - test_cond("sdscatfmt() seems working in the base case", - sdslen(x) == 60 && - memcmp(x,"--Hello Hi! World -9223372036854775808," - "9223372036854775807--",60) == 0) - printf("[%s]\n",x); - - sdsfree(x); - x = sdsnew("--"); - x = sdscatfmt(x, "%u,%U--", UINT_MAX, ULLONG_MAX); - test_cond("sdscatfmt() seems working with unsigned numbers", - sdslen(x) == 35 && - memcmp(x,"--4294967295,18446744073709551615--",35) == 0) - - sdsfree(x); - x = sdsnew(" x "); - sdstrim(x," x"); - test_cond("sdstrim() works when all chars match", - sdslen(x) == 0) - - sdsfree(x); - x = sdsnew(" x "); - sdstrim(x," "); - test_cond("sdstrim() works when a single char remains", - sdslen(x) == 1 && x[0] == 'x') - - sdsfree(x); - x = sdsnew("xxciaoyyy"); - sdstrim(x,"xy"); - test_cond("sdstrim() correctly trims characters", - sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0) - - y = sdsdup(x); - sdsrange(y,1,1); - test_cond("sdsrange(...,1,1)", - sdslen(y) == 1 && memcmp(y,"i\0",2) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,1,-1); - test_cond("sdsrange(...,1,-1)", - sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,-2,-1); - test_cond("sdsrange(...,-2,-1)", - sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,2,1); - test_cond("sdsrange(...,2,1)", - sdslen(y) == 0 && memcmp(y,"\0",1) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,1,100); - test_cond("sdsrange(...,1,100)", - sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,100,100); - test_cond("sdsrange(...,100,100)", - sdslen(y) == 0 && memcmp(y,"\0",1) == 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("foo"); - y = sdsnew("foa"); - test_cond("sdscmp(foo,foa)", sdscmp(x,y) > 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("bar"); - y = sdsnew("bar"); - test_cond("sdscmp(bar,bar)", sdscmp(x,y) == 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("aar"); - y = sdsnew("bar"); - test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0) - - sdsfree(y); - sdsfree(x); - x = sdsnewlen("\a\n\0foo\r",7); - y = sdscatrepr(sdsempty(),x,sdslen(x)); - test_cond("sdscatrepr(...data...)", - memcmp(y,"\"\\a\\n\\x00foo\\r\"",15) == 0) - - { - unsigned int oldfree; - char *p; - int step = 10, j, i; - - sdsfree(x); - sdsfree(y); - x = sdsnew("0"); - test_cond("sdsnew() free/len buffers", sdslen(x) == 1 && sdsavail(x) == 0); - - /* Run the test a few times in order to hit the first two - * SDS header types. */ - for (i = 0; i < 10; i++) { - int oldlen = sdslen(x); - x = sdsMakeRoomFor(x,step); - int type = x[-1]&SDS_TYPE_MASK; - - test_cond("sdsMakeRoomFor() len", sdslen(x) == oldlen); - if (type != SDS_TYPE_5) { - test_cond("sdsMakeRoomFor() free", sdsavail(x) >= step); - oldfree = sdsavail(x); - } - p = x+oldlen; - for (j = 0; j < step; j++) { - p[j] = 'A'+j; - } - sdsIncrLen(x,step); - } - test_cond("sdsMakeRoomFor() content", - memcmp("0ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ",x,101) == 0); - test_cond("sdsMakeRoomFor() final length",sdslen(x)==101); - - sdsfree(x); - } - } - test_report() - return 0; -} -#endif - -#ifdef SDS_TEST_MAIN -int main(void) { - return sdsTest(); -} -#endif diff --git a/ext/hiredis-0.14.1/sds.h b/ext/hiredis-0.14.1/sds.h deleted file mode 100644 index 13be75a9f..000000000 --- a/ext/hiredis-0.14.1/sds.h +++ /dev/null @@ -1,273 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SDS_H -#define __SDS_H - -#define SDS_MAX_PREALLOC (1024*1024) - -#include -#include -#include - -typedef char *sds; - -/* Note: sdshdr5 is never used, we just access the flags byte directly. - * However is here to document the layout of type 5 SDS strings. */ -struct __attribute__ ((__packed__)) sdshdr5 { - unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr8 { - uint8_t len; /* used */ - uint8_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr16 { - uint16_t len; /* used */ - uint16_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr32 { - uint32_t len; /* used */ - uint32_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr64 { - uint64_t len; /* used */ - uint64_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; - -#define SDS_TYPE_5 0 -#define SDS_TYPE_8 1 -#define SDS_TYPE_16 2 -#define SDS_TYPE_32 3 -#define SDS_TYPE_64 4 -#define SDS_TYPE_MASK 7 -#define SDS_TYPE_BITS 3 -#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))); -#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) -#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) - -static inline size_t sdslen(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->len; - case SDS_TYPE_16: - return SDS_HDR(16,s)->len; - case SDS_TYPE_32: - return SDS_HDR(32,s)->len; - case SDS_TYPE_64: - return SDS_HDR(64,s)->len; - } - return 0; -} - -static inline size_t sdsavail(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: { - return 0; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - return sh->alloc - sh->len; - } - } - return 0; -} - -static inline void sdssetlen(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len = newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len = newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len = newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len = newlen; - break; - } -} - -static inline void sdsinclen(sds s, size_t inc) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len += inc; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len += inc; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len += inc; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len += inc; - break; - } -} - -/* sdsalloc() = sdsavail() + sdslen() */ -static inline size_t sdsalloc(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->alloc; - case SDS_TYPE_16: - return SDS_HDR(16,s)->alloc; - case SDS_TYPE_32: - return SDS_HDR(32,s)->alloc; - case SDS_TYPE_64: - return SDS_HDR(64,s)->alloc; - } - return 0; -} - -static inline void sdssetalloc(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - /* Nothing to do, this type has no total allocation info. */ - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->alloc = newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->alloc = newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->alloc = newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->alloc = newlen; - break; - } -} - -sds sdsnewlen(const void *init, size_t initlen); -sds sdsnew(const char *init); -sds sdsempty(void); -sds sdsdup(const sds s); -void sdsfree(sds s); -sds sdsgrowzero(sds s, size_t len); -sds sdscatlen(sds s, const void *t, size_t len); -sds sdscat(sds s, const char *t); -sds sdscatsds(sds s, const sds t); -sds sdscpylen(sds s, const char *t, size_t len); -sds sdscpy(sds s, const char *t); - -sds sdscatvprintf(sds s, const char *fmt, va_list ap); -#ifdef __GNUC__ -sds sdscatprintf(sds s, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else -sds sdscatprintf(sds s, const char *fmt, ...); -#endif - -sds sdscatfmt(sds s, char const *fmt, ...); -sds sdstrim(sds s, const char *cset); -void sdsrange(sds s, int start, int end); -void sdsupdatelen(sds s); -void sdsclear(sds s); -int sdscmp(const sds s1, const sds s2); -sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); -void sdsfreesplitres(sds *tokens, int count); -void sdstolower(sds s); -void sdstoupper(sds s); -sds sdsfromlonglong(long long value); -sds sdscatrepr(sds s, const char *p, size_t len); -sds *sdssplitargs(const char *line, int *argc); -sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); -sds sdsjoin(char **argv, int argc, char *sep); -sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); - -/* Low level functions exposed to the user API */ -sds sdsMakeRoomFor(sds s, size_t addlen); -void sdsIncrLen(sds s, int incr); -sds sdsRemoveFreeSpace(sds s); -size_t sdsAllocSize(sds s); -void *sdsAllocPtr(sds s); - -/* Export the allocator used by SDS to the program using SDS. - * Sometimes the program SDS is linked to, may use a different set of - * allocators, but may want to allocate or free things that SDS will - * respectively free or allocate. */ -void *sds_malloc(size_t size); -void *sds_realloc(void *ptr, size_t size); -void sds_free(void *ptr); - -#ifdef REDIS_TEST -int sdsTest(int argc, char *argv[]); -#endif - -#endif diff --git a/ext/hiredis-0.14.1/sdsalloc.h b/ext/hiredis-0.14.1/sdsalloc.h deleted file mode 100644 index f43023c48..000000000 --- a/ext/hiredis-0.14.1/sdsalloc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* SDS allocator selection. - * - * This file is used in order to change the SDS allocator at compile time. - * Just define the following defines to what you want to use. Also add - * the include of your alternate allocator if needed (not needed in order - * to use the default libc allocator). */ - -#define s_malloc malloc -#define s_realloc realloc -#define s_free free diff --git a/ext/hiredis-0.14.1/test.c b/ext/hiredis-0.14.1/test.c deleted file mode 100644 index 0f5bfe572..000000000 --- a/ext/hiredis-0.14.1/test.c +++ /dev/null @@ -1,923 +0,0 @@ -#include "fmacros.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hiredis.h" -#include "net.h" - -enum connection_type { - CONN_TCP, - CONN_UNIX, - CONN_FD -}; - -struct config { - enum connection_type type; - - struct { - const char *host; - int port; - struct timeval timeout; - } tcp; - - struct { - const char *path; - } unix_sock; -}; - -/* The following lines make up our testing "framework" :) */ -static int tests = 0, fails = 0; -#define test(_s) { printf("#%02d ", ++tests); printf(_s); } -#define test_cond(_c) if(_c) printf("\033[0;32mPASSED\033[0;0m\n"); else {printf("\033[0;31mFAILED\033[0;0m\n"); fails++;} - -static long long usec(void) { - struct timeval tv; - gettimeofday(&tv,NULL); - return (((long long)tv.tv_sec)*1000000)+tv.tv_usec; -} - -/* The assert() calls below have side effects, so we need assert() - * even if we are compiling without asserts (-DNDEBUG). */ -#ifdef NDEBUG -#undef assert -#define assert(e) (void)(e) -#endif - -static redisContext *select_database(redisContext *c) { - redisReply *reply; - - /* Switch to DB 9 for testing, now that we know we can chat. */ - reply = redisCommand(c,"SELECT 9"); - assert(reply != NULL); - freeReplyObject(reply); - - /* Make sure the DB is emtpy */ - reply = redisCommand(c,"DBSIZE"); - assert(reply != NULL); - if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) { - /* Awesome, DB 9 is empty and we can continue. */ - freeReplyObject(reply); - } else { - printf("Database #9 is not empty, test can not continue\n"); - exit(1); - } - - return c; -} - -static int disconnect(redisContext *c, int keep_fd) { - redisReply *reply; - - /* Make sure we're on DB 9. */ - reply = redisCommand(c,"SELECT 9"); - assert(reply != NULL); - freeReplyObject(reply); - reply = redisCommand(c,"FLUSHDB"); - assert(reply != NULL); - freeReplyObject(reply); - - /* Free the context as well, but keep the fd if requested. */ - if (keep_fd) - return redisFreeKeepFd(c); - redisFree(c); - return -1; -} - -static redisContext *connect(struct config config) { - redisContext *c = NULL; - - if (config.type == CONN_TCP) { - c = redisConnect(config.tcp.host, config.tcp.port); - } else if (config.type == CONN_UNIX) { - c = redisConnectUnix(config.unix_sock.path); - } else if (config.type == CONN_FD) { - /* Create a dummy connection just to get an fd to inherit */ - redisContext *dummy_ctx = redisConnectUnix(config.unix_sock.path); - if (dummy_ctx) { - int fd = disconnect(dummy_ctx, 1); - printf("Connecting to inherited fd %d\n", fd); - c = redisConnectFd(fd); - } - } else { - assert(NULL); - } - - if (c == NULL) { - printf("Connection error: can't allocate redis context\n"); - exit(1); - } else if (c->err) { - printf("Connection error: %s\n", c->errstr); - redisFree(c); - exit(1); - } - - return select_database(c); -} - -static void test_format_commands(void) { - char *cmd; - int len; - - test("Format command without interpolation: "); - len = redisFormatCommand(&cmd,"SET foo bar"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - free(cmd); - - test("Format command with %%s string interpolation: "); - len = redisFormatCommand(&cmd,"SET %s %s","foo","bar"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - free(cmd); - - test("Format command with %%s and an empty string: "); - len = redisFormatCommand(&cmd,"SET %s %s","foo",""); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(0+2)); - free(cmd); - - test("Format command with an empty string in between proper interpolations: "); - len = redisFormatCommand(&cmd,"SET %s %s","","foo"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 && - len == 4+4+(3+2)+4+(0+2)+4+(3+2)); - free(cmd); - - test("Format command with %%b string interpolation: "); - len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - free(cmd); - - test("Format command with %%b and an empty string: "); - len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(0+2)); - free(cmd); - - test("Format command with literal %%: "); - len = redisFormatCommand(&cmd,"SET %% %%"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$1\r\n%\r\n$1\r\n%\r\n",len) == 0 && - len == 4+4+(3+2)+4+(1+2)+4+(1+2)); - free(cmd); - - /* Vararg width depends on the type. These tests make sure that the - * width is correctly determined using the format and subsequent varargs - * can correctly be interpolated. */ -#define INTEGER_WIDTH_TEST(fmt, type) do { \ - type value = 123; \ - test("Format command with printf-delegation (" #type "): "); \ - len = redisFormatCommand(&cmd,"key:%08" fmt " str:%s", value, "hello"); \ - test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:00000123\r\n$9\r\nstr:hello\r\n",len) == 0 && \ - len == 4+5+(12+2)+4+(9+2)); \ - free(cmd); \ -} while(0) - -#define FLOAT_WIDTH_TEST(type) do { \ - type value = 123.0; \ - test("Format command with printf-delegation (" #type "): "); \ - len = redisFormatCommand(&cmd,"key:%08.3f str:%s", value, "hello"); \ - test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:0123.000\r\n$9\r\nstr:hello\r\n",len) == 0 && \ - len == 4+5+(12+2)+4+(9+2)); \ - free(cmd); \ -} while(0) - - INTEGER_WIDTH_TEST("d", int); - INTEGER_WIDTH_TEST("hhd", char); - INTEGER_WIDTH_TEST("hd", short); - INTEGER_WIDTH_TEST("ld", long); - INTEGER_WIDTH_TEST("lld", long long); - INTEGER_WIDTH_TEST("u", unsigned int); - INTEGER_WIDTH_TEST("hhu", unsigned char); - INTEGER_WIDTH_TEST("hu", unsigned short); - INTEGER_WIDTH_TEST("lu", unsigned long); - INTEGER_WIDTH_TEST("llu", unsigned long long); - FLOAT_WIDTH_TEST(float); - FLOAT_WIDTH_TEST(double); - - test("Format command with invalid printf format: "); - len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3); - test_cond(len == -1); - - const char *argv[3]; - argv[0] = "SET"; - argv[1] = "foo\0xxx"; - argv[2] = "bar"; - size_t lens[3] = { 3, 7, 3 }; - int argc = 3; - - test("Format command by passing argc/argv without lengths: "); - len = redisFormatCommandArgv(&cmd,argc,argv,NULL); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - free(cmd); - - test("Format command by passing argc/argv with lengths: "); - len = redisFormatCommandArgv(&cmd,argc,argv,lens); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(7+2)+4+(3+2)); - free(cmd); - - sds sds_cmd; - - sds_cmd = sdsempty(); - test("Format command into sds by passing argc/argv without lengths: "); - len = redisFormatSdsCommandArgv(&sds_cmd,argc,argv,NULL); - test_cond(strncmp(sds_cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - sdsfree(sds_cmd); - - sds_cmd = sdsempty(); - test("Format command into sds by passing argc/argv with lengths: "); - len = redisFormatSdsCommandArgv(&sds_cmd,argc,argv,lens); - test_cond(strncmp(sds_cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(7+2)+4+(3+2)); - sdsfree(sds_cmd); -} - -static void test_append_formatted_commands(struct config config) { - redisContext *c; - redisReply *reply; - char *cmd; - int len; - - c = connect(config); - - test("Append format command: "); - - len = redisFormatCommand(&cmd, "SET foo bar"); - - test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK); - - assert(redisGetReply(c, (void*)&reply) == REDIS_OK); - - free(cmd); - freeReplyObject(reply); - - disconnect(c, 0); -} - -static void test_reply_reader(void) { - redisReader *reader; - void *reply; - int ret; - int i; - - test("Error handling in reply parser: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"@foo\r\n",6); - ret = redisReaderGetReply(reader,NULL); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0); - redisReaderFree(reader); - - /* when the reply already contains multiple items, they must be free'd - * on an error. valgrind will bark when this doesn't happen. */ - test("Memory cleanup in reply parser: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"*2\r\n",4); - redisReaderFeed(reader,(char*)"$5\r\nhello\r\n",11); - redisReaderFeed(reader,(char*)"@foo\r\n",6); - ret = redisReaderGetReply(reader,NULL); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0); - redisReaderFree(reader); - - test("Set error on nested multi bulks with depth > 7: "); - reader = redisReaderCreate(); - - for (i = 0; i < 9; i++) { - redisReaderFeed(reader,(char*)"*1\r\n",4); - } - - ret = redisReaderGetReply(reader,NULL); - test_cond(ret == REDIS_ERR && - strncasecmp(reader->errstr,"No support for",14) == 0); - redisReaderFree(reader); - - test("Correctly parses LLONG_MAX: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, ":9223372036854775807\r\n",22); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_INTEGER && - ((redisReply*)reply)->integer == LLONG_MAX); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when > LLONG_MAX: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, ":9223372036854775808\r\n",22); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Bad integer value") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Correctly parses LLONG_MIN: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, ":-9223372036854775808\r\n",23); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_INTEGER && - ((redisReply*)reply)->integer == LLONG_MIN); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when < LLONG_MIN: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, ":-9223372036854775809\r\n",23); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Bad integer value") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when array < -1: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, "*-2\r\n+asdf\r\n",12); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Multi-bulk length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when bulk < -1: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, "$-2\r\nasdf\r\n",11); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Bulk string length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when array > INT_MAX: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, "*9223372036854775807\r\n+asdf\r\n",29); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Multi-bulk length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - -#if LLONG_MAX > SIZE_MAX - test("Set error when bulk > SIZE_MAX: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, "$9223372036854775807\r\nasdf\r\n",28); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Bulk string length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); -#endif - - test("Works with NULL functions for reply: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"+OK\r\n",5); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS); - redisReaderFree(reader); - - test("Works when a single newline (\\r\\n) covers two calls to feed: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"+OK\r",4); - ret = redisReaderGetReply(reader,&reply); - assert(ret == REDIS_OK && reply == NULL); - redisReaderFeed(reader,(char*)"\n",1); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS); - redisReaderFree(reader); - - test("Don't reset state after protocol error: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"x",1); - ret = redisReaderGetReply(reader,&reply); - assert(ret == REDIS_ERR); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && reply == NULL); - redisReaderFree(reader); - - /* Regression test for issue #45 on GitHub. */ - test("Don't do empty allocation for empty multi bulk: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"*0\r\n",4); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_ARRAY && - ((redisReply*)reply)->elements == 0); - freeReplyObject(reply); - redisReaderFree(reader); -} - -static void test_free_null(void) { - void *redisCtx = NULL; - void *reply = NULL; - - test("Don't fail when redisFree is passed a NULL value: "); - redisFree(redisCtx); - test_cond(redisCtx == NULL); - - test("Don't fail when freeReplyObject is passed a NULL value: "); - freeReplyObject(reply); - test_cond(reply == NULL); -} - -static void test_blocking_connection_errors(void) { - redisContext *c; - - test("Returns error when host cannot be resolved: "); - c = redisConnect((char*)"idontexist.test", 6379); - test_cond(c->err == REDIS_ERR_OTHER && - (strcmp(c->errstr,"Name or service not known") == 0 || - strcmp(c->errstr,"Can't resolve: idontexist.test") == 0 || - strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 || - strcmp(c->errstr,"No address associated with hostname") == 0 || - strcmp(c->errstr,"Temporary failure in name resolution") == 0 || - strcmp(c->errstr,"hostname nor servname provided, or not known") == 0 || - strcmp(c->errstr,"no address associated with name") == 0)); - redisFree(c); - - test("Returns error when the port is not open: "); - c = redisConnect((char*)"localhost", 1); - test_cond(c->err == REDIS_ERR_IO && - strcmp(c->errstr,"Connection refused") == 0); - redisFree(c); - - test("Returns error when the unix_sock socket path doesn't accept connections: "); - c = redisConnectUnix((char*)"/tmp/idontexist.sock"); - test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */ - redisFree(c); -} - -static void test_blocking_connection(struct config config) { - redisContext *c; - redisReply *reply; - - c = connect(config); - - test("Is able to deliver commands: "); - reply = redisCommand(c,"PING"); - test_cond(reply->type == REDIS_REPLY_STATUS && - strcasecmp(reply->str,"pong") == 0) - freeReplyObject(reply); - - test("Is a able to send commands verbatim: "); - reply = redisCommand(c,"SET foo bar"); - test_cond (reply->type == REDIS_REPLY_STATUS && - strcasecmp(reply->str,"ok") == 0) - freeReplyObject(reply); - - test("%%s String interpolation works: "); - reply = redisCommand(c,"SET %s %s","foo","hello world"); - freeReplyObject(reply); - reply = redisCommand(c,"GET foo"); - test_cond(reply->type == REDIS_REPLY_STRING && - strcmp(reply->str,"hello world") == 0); - freeReplyObject(reply); - - test("%%b String interpolation works: "); - reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11); - freeReplyObject(reply); - reply = redisCommand(c,"GET foo"); - test_cond(reply->type == REDIS_REPLY_STRING && - memcmp(reply->str,"hello\x00world",11) == 0) - - test("Binary reply length is correct: "); - test_cond(reply->len == 11) - freeReplyObject(reply); - - test("Can parse nil replies: "); - reply = redisCommand(c,"GET nokey"); - test_cond(reply->type == REDIS_REPLY_NIL) - freeReplyObject(reply); - - /* test 7 */ - test("Can parse integer replies: "); - reply = redisCommand(c,"INCR mycounter"); - test_cond(reply->type == REDIS_REPLY_INTEGER && reply->integer == 1) - freeReplyObject(reply); - - test("Can parse multi bulk replies: "); - freeReplyObject(redisCommand(c,"LPUSH mylist foo")); - freeReplyObject(redisCommand(c,"LPUSH mylist bar")); - reply = redisCommand(c,"LRANGE mylist 0 -1"); - test_cond(reply->type == REDIS_REPLY_ARRAY && - reply->elements == 2 && - !memcmp(reply->element[0]->str,"bar",3) && - !memcmp(reply->element[1]->str,"foo",3)) - freeReplyObject(reply); - - /* m/e with multi bulk reply *before* other reply. - * specifically test ordering of reply items to parse. */ - test("Can handle nested multi bulk replies: "); - freeReplyObject(redisCommand(c,"MULTI")); - freeReplyObject(redisCommand(c,"LRANGE mylist 0 -1")); - freeReplyObject(redisCommand(c,"PING")); - reply = (redisCommand(c,"EXEC")); - test_cond(reply->type == REDIS_REPLY_ARRAY && - reply->elements == 2 && - reply->element[0]->type == REDIS_REPLY_ARRAY && - reply->element[0]->elements == 2 && - !memcmp(reply->element[0]->element[0]->str,"bar",3) && - !memcmp(reply->element[0]->element[1]->str,"foo",3) && - reply->element[1]->type == REDIS_REPLY_STATUS && - strcasecmp(reply->element[1]->str,"pong") == 0); - freeReplyObject(reply); - - disconnect(c, 0); -} - -static void test_blocking_connection_timeouts(struct config config) { - redisContext *c; - redisReply *reply; - ssize_t s; - const char *cmd = "DEBUG SLEEP 3\r\n"; - struct timeval tv; - - c = connect(config); - test("Successfully completes a command when the timeout is not exceeded: "); - reply = redisCommand(c,"SET foo fast"); - freeReplyObject(reply); - tv.tv_sec = 0; - tv.tv_usec = 10000; - redisSetTimeout(c, tv); - reply = redisCommand(c, "GET foo"); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && memcmp(reply->str, "fast", 4) == 0); - freeReplyObject(reply); - disconnect(c, 0); - - c = connect(config); - test("Does not return a reply when the command times out: "); - s = write(c->fd, cmd, strlen(cmd)); - tv.tv_sec = 0; - tv.tv_usec = 10000; - redisSetTimeout(c, tv); - reply = redisCommand(c, "GET foo"); - test_cond(s > 0 && reply == NULL && c->err == REDIS_ERR_IO && strcmp(c->errstr, "Resource temporarily unavailable") == 0); - freeReplyObject(reply); - - test("Reconnect properly reconnects after a timeout: "); - redisReconnect(c); - reply = redisCommand(c, "PING"); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0); - freeReplyObject(reply); - - test("Reconnect properly uses owned parameters: "); - config.tcp.host = "foo"; - config.unix_sock.path = "foo"; - redisReconnect(c); - reply = redisCommand(c, "PING"); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0); - freeReplyObject(reply); - - disconnect(c, 0); -} - -static void test_blocking_io_errors(struct config config) { - redisContext *c; - redisReply *reply; - void *_reply; - int major, minor; - - /* Connect to target given by config. */ - c = connect(config); - { - /* Find out Redis version to determine the path for the next test */ - const char *field = "redis_version:"; - char *p, *eptr; - - reply = redisCommand(c,"INFO"); - p = strstr(reply->str,field); - major = strtol(p+strlen(field),&eptr,10); - p = eptr+1; /* char next to the first "." */ - minor = strtol(p,&eptr,10); - freeReplyObject(reply); - } - - test("Returns I/O error when the connection is lost: "); - reply = redisCommand(c,"QUIT"); - if (major > 2 || (major == 2 && minor > 0)) { - /* > 2.0 returns OK on QUIT and read() should be issued once more - * to know the descriptor is at EOF. */ - test_cond(strcasecmp(reply->str,"OK") == 0 && - redisGetReply(c,&_reply) == REDIS_ERR); - freeReplyObject(reply); - } else { - test_cond(reply == NULL); - } - - /* On 2.0, QUIT will cause the connection to be closed immediately and - * the read(2) for the reply on QUIT will set the error to EOF. - * On >2.0, QUIT will return with OK and another read(2) needed to be - * issued to find out the socket was closed by the server. In both - * conditions, the error will be set to EOF. */ - assert(c->err == REDIS_ERR_EOF && - strcmp(c->errstr,"Server closed the connection") == 0); - redisFree(c); - - c = connect(config); - test("Returns I/O error on socket timeout: "); - struct timeval tv = { 0, 1000 }; - assert(redisSetTimeout(c,tv) == REDIS_OK); - test_cond(redisGetReply(c,&_reply) == REDIS_ERR && - c->err == REDIS_ERR_IO && errno == EAGAIN); - redisFree(c); -} - -static void test_invalid_timeout_errors(struct config config) { - redisContext *c; - - test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: "); - - config.tcp.timeout.tv_sec = 0; - config.tcp.timeout.tv_usec = 10000001; - - c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout); - - test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0); - redisFree(c); - - test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: "); - - config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1; - config.tcp.timeout.tv_usec = 0; - - c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout); - - test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0); - redisFree(c); -} - -static void test_throughput(struct config config) { - redisContext *c = connect(config); - redisReply **replies; - int i, num; - long long t1, t2; - - test("Throughput:\n"); - for (i = 0; i < 500; i++) - freeReplyObject(redisCommand(c,"LPUSH mylist foo")); - - num = 1000; - replies = malloc(sizeof(redisReply*)*num); - t1 = usec(); - for (i = 0; i < num; i++) { - replies[i] = redisCommand(c,"PING"); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx PING: %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = malloc(sizeof(redisReply*)*num); - t1 = usec(); - for (i = 0; i < num; i++) { - replies[i] = redisCommand(c,"LRANGE mylist 0 499"); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY); - assert(replies[i] != NULL && replies[i]->elements == 500); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx LRANGE with 500 elements: %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = malloc(sizeof(redisReply*)*num); - t1 = usec(); - for (i = 0; i < num; i++) { - replies[i] = redisCommand(c, "INCRBY incrkey %d", 1000000); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_INTEGER); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx INCRBY: %.3fs)\n", num, (t2-t1)/1000000.0); - - num = 10000; - replies = malloc(sizeof(redisReply*)*num); - for (i = 0; i < num; i++) - redisAppendCommand(c,"PING"); - t1 = usec(); - for (i = 0; i < num; i++) { - assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx PING (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = malloc(sizeof(redisReply*)*num); - for (i = 0; i < num; i++) - redisAppendCommand(c,"LRANGE mylist 0 499"); - t1 = usec(); - for (i = 0; i < num; i++) { - assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY); - assert(replies[i] != NULL && replies[i]->elements == 500); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = malloc(sizeof(redisReply*)*num); - for (i = 0; i < num; i++) - redisAppendCommand(c,"INCRBY incrkey %d", 1000000); - t1 = usec(); - for (i = 0; i < num; i++) { - assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_INTEGER); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - free(replies); - printf("\t(%dx INCRBY (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); - - disconnect(c, 0); -} - -// static long __test_callback_flags = 0; -// static void __test_callback(redisContext *c, void *privdata) { -// ((void)c); -// /* Shift to detect execution order */ -// __test_callback_flags <<= 8; -// __test_callback_flags |= (long)privdata; -// } -// -// static void __test_reply_callback(redisContext *c, redisReply *reply, void *privdata) { -// ((void)c); -// /* Shift to detect execution order */ -// __test_callback_flags <<= 8; -// __test_callback_flags |= (long)privdata; -// if (reply) freeReplyObject(reply); -// } -// -// static redisContext *__connect_nonblock() { -// /* Reset callback flags */ -// __test_callback_flags = 0; -// return redisConnectNonBlock("127.0.0.1", port, NULL); -// } -// -// static void test_nonblocking_connection() { -// redisContext *c; -// int wdone = 0; -// -// test("Calls command callback when command is issued: "); -// c = __connect_nonblock(); -// redisSetCommandCallback(c,__test_callback,(void*)1); -// redisCommand(c,"PING"); -// test_cond(__test_callback_flags == 1); -// redisFree(c); -// -// test("Calls disconnect callback on redisDisconnect: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)2); -// redisDisconnect(c); -// test_cond(__test_callback_flags == 2); -// redisFree(c); -// -// test("Calls disconnect callback and free callback on redisFree: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)2); -// redisSetFreeCallback(c,__test_callback,(void*)4); -// redisFree(c); -// test_cond(__test_callback_flags == ((2 << 8) | 4)); -// -// test("redisBufferWrite against empty write buffer: "); -// c = __connect_nonblock(); -// test_cond(redisBufferWrite(c,&wdone) == REDIS_OK && wdone == 1); -// redisFree(c); -// -// test("redisBufferWrite against not yet connected fd: "); -// c = __connect_nonblock(); -// redisCommand(c,"PING"); -// test_cond(redisBufferWrite(c,NULL) == REDIS_ERR && -// strncmp(c->error,"write:",6) == 0); -// redisFree(c); -// -// test("redisBufferWrite against closed fd: "); -// c = __connect_nonblock(); -// redisCommand(c,"PING"); -// redisDisconnect(c); -// test_cond(redisBufferWrite(c,NULL) == REDIS_ERR && -// strncmp(c->error,"write:",6) == 0); -// redisFree(c); -// -// test("Process callbacks in the right sequence: "); -// c = __connect_nonblock(); -// redisCommandWithCallback(c,__test_reply_callback,(void*)1,"PING"); -// redisCommandWithCallback(c,__test_reply_callback,(void*)2,"PING"); -// redisCommandWithCallback(c,__test_reply_callback,(void*)3,"PING"); -// -// /* Write output buffer */ -// wdone = 0; -// while(!wdone) { -// usleep(500); -// redisBufferWrite(c,&wdone); -// } -// -// /* Read until at least one callback is executed (the 3 replies will -// * arrive in a single packet, causing all callbacks to be executed in -// * a single pass). */ -// while(__test_callback_flags == 0) { -// assert(redisBufferRead(c) == REDIS_OK); -// redisProcessCallbacks(c); -// } -// test_cond(__test_callback_flags == 0x010203); -// redisFree(c); -// -// test("redisDisconnect executes pending callbacks with NULL reply: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)1); -// redisCommandWithCallback(c,__test_reply_callback,(void*)2,"PING"); -// redisDisconnect(c); -// test_cond(__test_callback_flags == 0x0201); -// redisFree(c); -// } - -int main(int argc, char **argv) { - struct config cfg = { - .tcp = { - .host = "127.0.0.1", - .port = 6379 - }, - .unix_sock = { - .path = "/tmp/redis.sock" - } - }; - int throughput = 1; - int test_inherit_fd = 1; - - /* Ignore broken pipe signal (for I/O error tests). */ - signal(SIGPIPE, SIG_IGN); - - /* Parse command line options. */ - argv++; argc--; - while (argc) { - if (argc >= 2 && !strcmp(argv[0],"-h")) { - argv++; argc--; - cfg.tcp.host = argv[0]; - } else if (argc >= 2 && !strcmp(argv[0],"-p")) { - argv++; argc--; - cfg.tcp.port = atoi(argv[0]); - } else if (argc >= 2 && !strcmp(argv[0],"-s")) { - argv++; argc--; - cfg.unix_sock.path = argv[0]; - } else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) { - throughput = 0; - } else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) { - test_inherit_fd = 0; - } else { - fprintf(stderr, "Invalid argument: %s\n", argv[0]); - exit(1); - } - argv++; argc--; - } - - test_format_commands(); - test_reply_reader(); - test_blocking_connection_errors(); - test_free_null(); - - printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port); - cfg.type = CONN_TCP; - test_blocking_connection(cfg); - test_blocking_connection_timeouts(cfg); - test_blocking_io_errors(cfg); - test_invalid_timeout_errors(cfg); - test_append_formatted_commands(cfg); - if (throughput) test_throughput(cfg); - - printf("\nTesting against Unix socket connection (%s):\n", cfg.unix_sock.path); - cfg.type = CONN_UNIX; - test_blocking_connection(cfg); - test_blocking_connection_timeouts(cfg); - test_blocking_io_errors(cfg); - if (throughput) test_throughput(cfg); - - if (test_inherit_fd) { - printf("\nTesting against inherited fd (%s):\n", cfg.unix_sock.path); - cfg.type = CONN_FD; - test_blocking_connection(cfg); - } - - - if (fails) { - printf("*** %d TESTS FAILED ***\n", fails); - return 1; - } - - printf("ALL TESTS PASSED\n"); - return 0; -} diff --git a/ext/hiredis-0.14.1/win32.h b/ext/hiredis-0.14.1/win32.h deleted file mode 100644 index 1a27c18f2..000000000 --- a/ext/hiredis-0.14.1/win32.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _WIN32_HELPER_INCLUDE -#define _WIN32_HELPER_INCLUDE -#ifdef _MSC_VER - -#ifndef inline -#define inline __inline -#endif - -#ifndef va_copy -#define va_copy(d,s) ((d) = (s)) -#endif - -#ifndef snprintf -#define snprintf c99_snprintf - -__inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) -{ - int count = -1; - - if (size != 0) - count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - -__inline int c99_snprintf(char* str, size_t size, const char* format, ...) -{ - int count; - va_list ap; - - va_start(ap, format); - count = c99_vsnprintf(str, size, format, ap); - va_end(ap); - - return count; -} -#endif - -#endif -#endif \ No newline at end of file diff --git a/ext/hiredis-1.0.2/.gitignore b/ext/hiredis-1.0.2/.gitignore deleted file mode 100644 index 056959ffe..000000000 --- a/ext/hiredis-1.0.2/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -/hiredis-test -/examples/hiredis-example* -/*.o -/*.so -/*.dylib -/*.a -/*.pc -*.dSYM -tags diff --git a/ext/hiredis-1.0.2/.travis.yml b/ext/hiredis-1.0.2/.travis.yml deleted file mode 100644 index f9a9460ff..000000000 --- a/ext/hiredis-1.0.2/.travis.yml +++ /dev/null @@ -1,131 +0,0 @@ -language: c -compiler: - - gcc - - clang - -os: - - linux - - osx - -dist: bionic - -branches: - only: - - staging - - trying - - master - - /^release\/.*$/ - -install: - - if [ "$BITS" == "64" ]; then - wget https://github.com/redis/redis/archive/6.0.6.tar.gz; - tar -xzvf 6.0.6.tar.gz; - pushd redis-6.0.6 && BUILD_TLS=yes make && export PATH=$PWD/src:$PATH && popd; - fi - -before_script: - - if [ "$TRAVIS_OS_NAME" == "osx" ]; then - curl -O https://distfiles.macports.org/MacPorts/MacPorts-2.6.2-10.13-HighSierra.pkg; - sudo installer -pkg MacPorts-2.6.2-10.13-HighSierra.pkg -target /; - export PATH=$PATH:/opt/local/bin && sudo port -v selfupdate; - sudo port -N install openssl redis; - fi; - -addons: - apt: - sources: - - sourceline: 'ppa:chris-lea/redis-server' - packages: - - libc6-dbg - - libc6-dev - - libc6:i386 - - libc6-dev-i386 - - libc6-dbg:i386 - - gcc-multilib - - g++-multilib - - libssl-dev - - libssl-dev:i386 - - valgrind - - redis - -env: - - BITS="32" - - BITS="64" - -script: - - EXTRA_CMAKE_OPTS="-DENABLE_EXAMPLES:BOOL=ON -DENABLE_SSL:BOOL=ON"; - if [ "$BITS" == "64" ]; then - EXTRA_CMAKE_OPTS="$EXTRA_CMAKE_OPTS -DENABLE_SSL_TESTS:BOOL=ON"; - fi; - if [ "$TRAVIS_OS_NAME" == "osx" ]; then - if [ "$BITS" == "32" ]; then - CFLAGS="-m32 -Werror"; - CXXFLAGS="-m32 -Werror"; - LDFLAGS="-m32"; - EXTRA_CMAKE_OPTS=; - else - CFLAGS="-Werror"; - CXXFLAGS="-Werror"; - fi; - else - TEST_PREFIX="valgrind --track-origins=yes --leak-check=full"; - if [ "$BITS" == "32" ]; then - CFLAGS="-m32 -Werror"; - CXXFLAGS="-m32 -Werror"; - LDFLAGS="-m32"; - EXTRA_CMAKE_OPTS=; - else - CFLAGS="-Werror"; - CXXFLAGS="-Werror"; - fi; - fi; - export CFLAGS CXXFLAGS LDFLAGS TEST_PREFIX EXTRA_CMAKE_OPTS - - make && make clean; - if [ "$TRAVIS_OS_NAME" == "osx" ]; then - if [ "$BITS" == "64" ]; then - OPENSSL_PREFIX="$(ls -d /usr/local/Cellar/openssl@1.1/*)" USE_SSL=1 make; - fi; - else - USE_SSL=1 make; - fi; - - mkdir build/ && cd build/ - - cmake .. ${EXTRA_CMAKE_OPTS} - - make VERBOSE=1 - - if [ "$BITS" == "64" ]; then - TEST_SSL=1 SKIPS_AS_FAILS=1 ctest -V; - else - SKIPS_AS_FAILS=1 ctest -V; - fi; - -jobs: - include: - # Windows MinGW cross compile on Linux - - os: linux - dist: xenial - compiler: mingw - addons: - apt: - packages: - - ninja-build - - gcc-mingw-w64-x86-64 - - g++-mingw-w64-x86-64 - script: - - mkdir build && cd build - - CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_WITH_INSTALL_RPATH=on - - ninja -v - - # Windows MSVC 2017 - - os: windows - compiler: msvc - env: - - MATRIX_EVAL="CC=cl.exe && CXX=cl.exe" - before_install: - - eval "${MATRIX_EVAL}" - install: - - choco install ninja - - choco install -y memurai-developer - script: - - mkdir build && cd build - - cmd.exe //C 'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat' amd64 '&&' - cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_EXAMPLES=ON '&&' ninja -v - - ./hiredis-test.exe diff --git a/ext/hiredis-1.0.2/CHANGELOG.md b/ext/hiredis-1.0.2/CHANGELOG.md deleted file mode 100644 index 2a2bc314a..000000000 --- a/ext/hiredis-1.0.2/CHANGELOG.md +++ /dev/null @@ -1,364 +0,0 @@ -## [1.0.2](https://github.com/redis/hiredis/tree/v1.0.2) - (2021-10-07) - -Announcing Hiredis v1.0.2, which fixes CVE-2021-32765 but returns the SONAME to the correct value of `1.0.0`. - -- [Revert SONAME bump](https://github.com/redis/hiredis/commit/d4e6f109a064690cde64765c654e679fea1d3548) - ([Michael Grunder](https://github.com/michael-grunder)) - -## [1.0.1](https://github.com/redis/hiredis/tree/v1.0.1) - (2021-10-04) - -This release erroneously bumped the SONAME, please use [1.0.2](https://github.com/redis/hiredis/tree/v1.0.2) - -Announcing Hiredis v1.0.1, a security release fixing CVE-2021-32765 - -- Fix for [CVE-2021-32765](https://github.com/redis/hiredis/security/advisories/GHSA-hfm9-39pp-55p2) - [commit](https://github.com/redis/hiredis/commit/76a7b10005c70babee357a7d0f2becf28ec7ed1e) - ([Yossi Gottlieb](https://github.com/yossigo)) - -_Thanks to [Yossi Gottlieb](https://github.com/yossigo) for the security fix and to [Microsoft Security Vulnerability Research](https://www.microsoft.com/en-us/msrc/msvr) for finding the bug._ :sparkling_heart: - -## [1.0.0](https://github.com/redis/hiredis/tree/v1.0.0) - (2020-08-03) - -Announcing Hiredis v1.0.0, which adds support for RESP3, SSL connections, allocator injection, and better Windows support! :tada: - -_A big thanks to everyone who helped with this release. The following list includes everyone who contributed at least five lines, sorted by lines contributed._ :sparkling_heart: - -[Michael Grunder](https://github.com/michael-grunder), [Yossi Gottlieb](https://github.com/yossigo), -[Mark Nunberg](https://github.com/mnunberg), [Marcus Geelnard](https://github.com/mbitsnbites), -[Justin Brewer](https://github.com/justinbrewer), [Valentino Geron](https://github.com/valentinogeron), -[Minun Dragonation](https://github.com/dragonation), [Omri Steiner](https://github.com/OmriSteiner), -[Sangmoon Yi](https://github.com/jman-krafton), [Jinjiazh](https://github.com/jinjiazhang), -[Odin Hultgren Van Der Horst](https://github.com/Miniwoffer), [Muhammad Zahalqa](https://github.com/tryfinally), -[Nick Rivera](https://github.com/heronr), [Qi Yang](https://github.com/movebean), -[kevin1018](https://github.com/kevin1018) - -[Full Changelog](https://github.com/redis/hiredis/compare/v0.14.1...v1.0.0) - -**BREAKING CHANGES**: - -* `redisOptions` now has two timeout fields. One for connecting, and one for commands. If you're presently using `options->timeout` you will need to change it to use `options->connect_timeout`. (See [example](https://github.com/redis/hiredis/commit/38b5ae543f5c99eb4ccabbe277770fc6bc81226f#diff-86ba39d37aa829c8c82624cce4f049fbL36)) - -* Bulk and multi-bulk lengths less than -1 or greater than `LLONG_MAX` are now protocol errors. This is consistent - with the RESP specification. On 32-bit platforms, the upper bound is lowered to `SIZE_MAX`. - -* `redisReplyObjectFunctions.createArray` now takes `size_t` for its length parameter. - -**New features:** -- Support for RESP3 - [\#697](https://github.com/redis/hiredis/pull/697), - [\#805](https://github.com/redis/hiredis/pull/805), - [\#819](https://github.com/redis/hiredis/pull/819), - [\#841](https://github.com/redis/hiredis/pull/841) - ([Yossi Gottlieb](https://github.com/yossigo), [Michael Grunder](https://github.com/michael-grunder)) -- Support for SSL connections - [\#645](https://github.com/redis/hiredis/pull/645), - [\#699](https://github.com/redis/hiredis/pull/699), - [\#702](https://github.com/redis/hiredis/pull/702), - [\#708](https://github.com/redis/hiredis/pull/708), - [\#711](https://github.com/redis/hiredis/pull/711), - [\#821](https://github.com/redis/hiredis/pull/821), - [more](https://github.com/redis/hiredis/pulls?q=is%3Apr+is%3Amerged+SSL) - ([Mark Nunberg](https://github.com/mnunberg), [Yossi Gottlieb](https://github.com/yossigo)) -- Run-time allocator injection - [\#800](https://github.com/redis/hiredis/pull/800) - ([Michael Grunder](https://github.com/michael-grunder)) -- Improved Windows support (including MinGW and Windows CI) - [\#652](https://github.com/redis/hiredis/pull/652), - [\#663](https://github.com/redis/hiredis/pull/663) - ([Marcus Geelnard](https://www.bitsnbites.eu/author/m/)) -- Adds support for distinct connect and command timeouts - [\#839](https://github.com/redis/hiredis/pull/839), - [\#829](https://github.com/redis/hiredis/pull/829) - ([Valentino Geron](https://github.com/valentinogeron)) -- Add generic pointer and destructor to `redisContext` that users can use for context. - [\#855](https://github.com/redis/hiredis/pull/855) - ([Michael Grunder](https://github.com/michael-grunder)) - -**Closed issues (that involved code changes):** - -- Makefile does not install TLS libraries [\#809](https://github.com/redis/hiredis/issues/809) -- redisConnectWithOptions should not set command timeout [\#722](https://github.com/redis/hiredis/issues/722), [\#829](https://github.com/redis/hiredis/pull/829) ([valentinogeron](https://github.com/valentinogeron)) -- Fix integer overflow in `sdsrange` [\#827](https://github.com/redis/hiredis/issues/827) -- INFO & CLUSTER commands failed when using RESP3 [\#802](https://github.com/redis/hiredis/issues/802) -- Windows compatibility patches [\#687](https://github.com/redis/hiredis/issues/687), [\#838](https://github.com/redis/hiredis/issues/838), [\#842](https://github.com/redis/hiredis/issues/842) -- RESP3 PUSH messages incorrectly use pending callback [\#825](https://github.com/redis/hiredis/issues/825) -- Asynchronous PSUBSCRIBE command fails when using RESP3 [\#815](https://github.com/redis/hiredis/issues/815) -- New SSL API [\#804](https://github.com/redis/hiredis/issues/804), [\#813](https://github.com/redis/hiredis/issues/813) -- Hard-coded limit of nested reply depth [\#794](https://github.com/redis/hiredis/issues/794) -- Fix TCP_NODELAY in Windows/OSX [\#679](https://github.com/redis/hiredis/issues/679), [\#690](https://github.com/redis/hiredis/issues/690), [\#779](https://github.com/redis/hiredis/issues/779), [\#785](https://github.com/redis/hiredis/issues/785), -- Added timers to libev adapter. [\#778](https://github.com/redis/hiredis/issues/778), [\#795](https://github.com/redis/hiredis/pull/795) -- Initialization discards const qualifier [\#777](https://github.com/redis/hiredis/issues/777) -- \[BUG\]\[MinGW64\] Error setting socket timeout [\#775](https://github.com/redis/hiredis/issues/775) -- undefined reference to hi_malloc [\#769](https://github.com/redis/hiredis/issues/769) -- hiredis pkg-config file incorrectly ignores multiarch libdir spec'n [\#767](https://github.com/redis/hiredis/issues/767) -- Don't use -G to build shared object on Solaris [\#757](https://github.com/redis/hiredis/issues/757) -- error when make USE\_SSL=1 [\#748](https://github.com/redis/hiredis/issues/748) -- Allow to change SSL Mode [\#646](https://github.com/redis/hiredis/issues/646) -- hiredis/adapters/libevent.h memleak [\#618](https://github.com/redis/hiredis/issues/618) -- redisLibuvPoll crash when server closes the connetion [\#545](https://github.com/redis/hiredis/issues/545) -- about redisAsyncDisconnect question [\#518](https://github.com/redis/hiredis/issues/518) -- hiredis adapters libuv error for help [\#508](https://github.com/redis/hiredis/issues/508) -- API/ABI changes analysis [\#506](https://github.com/redis/hiredis/issues/506) -- Memory leak patch in Redis [\#502](https://github.com/redis/hiredis/issues/502) -- Remove the depth limitation [\#421](https://github.com/redis/hiredis/issues/421) - -**Merged pull requests:** - -- Move SSL management to a distinct private pointer [\#855](https://github.com/redis/hiredis/pull/855) ([michael-grunder](https://github.com/michael-grunder)) -- Move include to sockcompat.h to maintain style [\#850](https://github.com/redis/hiredis/pull/850) ([michael-grunder](https://github.com/michael-grunder)) -- Remove erroneous tag and add license to push example [\#849](https://github.com/redis/hiredis/pull/849) ([michael-grunder](https://github.com/michael-grunder)) -- fix windows compiling with mingw [\#848](https://github.com/redis/hiredis/pull/848) ([rmalizia44](https://github.com/rmalizia44)) -- Some Windows quality of life improvements. [\#846](https://github.com/redis/hiredis/pull/846) ([michael-grunder](https://github.com/michael-grunder)) -- Use \_WIN32 define instead of WIN32 [\#845](https://github.com/redis/hiredis/pull/845) ([michael-grunder](https://github.com/michael-grunder)) -- Non Linux CI fixes [\#844](https://github.com/redis/hiredis/pull/844) ([michael-grunder](https://github.com/michael-grunder)) -- Resp3 oob push support [\#841](https://github.com/redis/hiredis/pull/841) ([michael-grunder](https://github.com/michael-grunder)) -- fix \#785: defer TCP\_NODELAY in async tcp connections [\#836](https://github.com/redis/hiredis/pull/836) ([OmriSteiner](https://github.com/OmriSteiner)) -- sdsrange overflow fix [\#830](https://github.com/redis/hiredis/pull/830) ([michael-grunder](https://github.com/michael-grunder)) -- Use explicit pointer casting for c++ compatibility [\#826](https://github.com/redis/hiredis/pull/826) ([aureus1](https://github.com/aureus1)) -- Document allocator injection and completeness fix in test.c [\#824](https://github.com/redis/hiredis/pull/824) ([michael-grunder](https://github.com/michael-grunder)) -- Use unique names for allocator struct members [\#823](https://github.com/redis/hiredis/pull/823) ([michael-grunder](https://github.com/michael-grunder)) -- New SSL API to replace redisSecureConnection\(\). [\#821](https://github.com/redis/hiredis/pull/821) ([yossigo](https://github.com/yossigo)) -- Add logic to handle RESP3 push messages [\#819](https://github.com/redis/hiredis/pull/819) ([michael-grunder](https://github.com/michael-grunder)) -- Use standrad isxdigit instead of custom helper function. [\#814](https://github.com/redis/hiredis/pull/814) ([tryfinally](https://github.com/tryfinally)) -- Fix missing SSL build/install options. [\#812](https://github.com/redis/hiredis/pull/812) ([yossigo](https://github.com/yossigo)) -- Add link to ABI tracker [\#808](https://github.com/redis/hiredis/pull/808) ([michael-grunder](https://github.com/michael-grunder)) -- Resp3 verbatim string support [\#805](https://github.com/redis/hiredis/pull/805) ([michael-grunder](https://github.com/michael-grunder)) -- Allow users to replace allocator and handle OOM everywhere. [\#800](https://github.com/redis/hiredis/pull/800) ([michael-grunder](https://github.com/michael-grunder)) -- Remove nested depth limitation. [\#797](https://github.com/redis/hiredis/pull/797) ([michael-grunder](https://github.com/michael-grunder)) -- Attempt to fix compilation on Solaris [\#796](https://github.com/redis/hiredis/pull/796) ([michael-grunder](https://github.com/michael-grunder)) -- Support timeouts in libev adapater [\#795](https://github.com/redis/hiredis/pull/795) ([michael-grunder](https://github.com/michael-grunder)) -- Fix pkgconfig when installing to a custom lib dir [\#793](https://github.com/redis/hiredis/pull/793) ([michael-grunder](https://github.com/michael-grunder)) -- Fix USE\_SSL=1 make/cmake on OSX and CMake tests [\#789](https://github.com/redis/hiredis/pull/789) ([michael-grunder](https://github.com/michael-grunder)) -- Use correct libuv call on Windows [\#784](https://github.com/redis/hiredis/pull/784) ([michael-grunder](https://github.com/michael-grunder)) -- Added CMake package config and fixed hiredis\_ssl on Windows [\#783](https://github.com/redis/hiredis/pull/783) ([michael-grunder](https://github.com/michael-grunder)) -- CMake: Set hiredis\_ssl shared object version. [\#780](https://github.com/redis/hiredis/pull/780) ([yossigo](https://github.com/yossigo)) -- Win32 tests and timeout fix [\#776](https://github.com/redis/hiredis/pull/776) ([michael-grunder](https://github.com/michael-grunder)) -- Provides an optional cleanup callback for async data. [\#768](https://github.com/redis/hiredis/pull/768) ([heronr](https://github.com/heronr)) -- Housekeeping fixes [\#764](https://github.com/redis/hiredis/pull/764) ([michael-grunder](https://github.com/michael-grunder)) -- install alloc.h [\#756](https://github.com/redis/hiredis/pull/756) ([ch1aki](https://github.com/ch1aki)) -- fix spelling mistakes [\#746](https://github.com/redis/hiredis/pull/746) ([ShooterIT](https://github.com/ShooterIT)) -- Free the reply in redisGetReply when passed NULL [\#741](https://github.com/redis/hiredis/pull/741) ([michael-grunder](https://github.com/michael-grunder)) -- Fix dead code in sslLogCallback relating to should\_log variable. [\#737](https://github.com/redis/hiredis/pull/737) ([natoscott](https://github.com/natoscott)) -- Fix typo in dict.c. [\#731](https://github.com/redis/hiredis/pull/731) ([Kevin-Xi](https://github.com/Kevin-Xi)) -- Adding an option to DISABLE\_TESTS [\#727](https://github.com/redis/hiredis/pull/727) ([pbotros](https://github.com/pbotros)) -- Update README with SSL support. [\#720](https://github.com/redis/hiredis/pull/720) ([yossigo](https://github.com/yossigo)) -- Fixes leaks in unit tests [\#715](https://github.com/redis/hiredis/pull/715) ([michael-grunder](https://github.com/michael-grunder)) -- SSL Tests [\#711](https://github.com/redis/hiredis/pull/711) ([yossigo](https://github.com/yossigo)) -- SSL Reorganization [\#708](https://github.com/redis/hiredis/pull/708) ([yossigo](https://github.com/yossigo)) -- Fix MSVC build. [\#706](https://github.com/redis/hiredis/pull/706) ([yossigo](https://github.com/yossigo)) -- SSL: Properly report SSL\_connect\(\) errors. [\#702](https://github.com/redis/hiredis/pull/702) ([yossigo](https://github.com/yossigo)) -- Silent SSL trace to stdout by default. [\#699](https://github.com/redis/hiredis/pull/699) ([yossigo](https://github.com/yossigo)) -- Port RESP3 support from Redis. [\#697](https://github.com/redis/hiredis/pull/697) ([yossigo](https://github.com/yossigo)) -- Removed whitespace before newline [\#691](https://github.com/redis/hiredis/pull/691) ([Miniwoffer](https://github.com/Miniwoffer)) -- Add install adapters header files [\#688](https://github.com/redis/hiredis/pull/688) ([kevin1018](https://github.com/kevin1018)) -- Remove unnecessary null check before free [\#684](https://github.com/redis/hiredis/pull/684) ([qlyoung](https://github.com/qlyoung)) -- redisReaderGetReply leak memory [\#671](https://github.com/redis/hiredis/pull/671) ([movebean](https://github.com/movebean)) -- fix timeout code in windows [\#670](https://github.com/redis/hiredis/pull/670) ([jman-krafton](https://github.com/jman-krafton)) -- test: fix errstr matching for musl libc [\#665](https://github.com/redis/hiredis/pull/665) ([ghost](https://github.com/ghost)) -- Windows: MinGW fixes and Windows Travis builders [\#663](https://github.com/redis/hiredis/pull/663) ([mbitsnbites](https://github.com/mbitsnbites)) -- The setsockopt and getsockopt API diffs from BSD socket and WSA one [\#662](https://github.com/redis/hiredis/pull/662) ([dragonation](https://github.com/dragonation)) -- Fix Compile Error On Windows \(Visual Studio\) [\#658](https://github.com/redis/hiredis/pull/658) ([jinjiazhang](https://github.com/jinjiazhang)) -- Fix NXDOMAIN test case [\#653](https://github.com/redis/hiredis/pull/653) ([michael-grunder](https://github.com/michael-grunder)) -- Add MinGW support [\#652](https://github.com/redis/hiredis/pull/652) ([mbitsnbites](https://github.com/mbitsnbites)) -- SSL Support [\#645](https://github.com/redis/hiredis/pull/645) ([mnunberg](https://github.com/mnunberg)) -- Fix Invalid argument after redisAsyncConnectUnix [\#644](https://github.com/redis/hiredis/pull/644) ([codehz](https://github.com/codehz)) -- Makefile: use predefined AR [\#632](https://github.com/redis/hiredis/pull/632) ([Mic92](https://github.com/Mic92)) -- FreeBSD build fix [\#628](https://github.com/redis/hiredis/pull/628) ([devnexen](https://github.com/devnexen)) -- Fix errors not propagating properly with libuv.h. [\#624](https://github.com/redis/hiredis/pull/624) ([yossigo](https://github.com/yossigo)) -- Update README.md [\#621](https://github.com/redis/hiredis/pull/621) ([Crunsher](https://github.com/Crunsher)) -- Fix redisBufferRead documentation [\#620](https://github.com/redis/hiredis/pull/620) ([hacst](https://github.com/hacst)) -- Add CPPFLAGS to REAL\_CFLAGS [\#614](https://github.com/redis/hiredis/pull/614) ([thomaslee](https://github.com/thomaslee)) -- Update createArray to take size\_t [\#597](https://github.com/redis/hiredis/pull/597) ([justinbrewer](https://github.com/justinbrewer)) -- fix common realloc mistake and add null check more [\#580](https://github.com/redis/hiredis/pull/580) ([charsyam](https://github.com/charsyam)) -- Proper error reporting for connect failures [\#578](https://github.com/redis/hiredis/pull/578) ([mnunberg](https://github.com/mnunberg)) - -\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* - -## [1.0.0-rc1](https://github.com/redis/hiredis/tree/v1.0.0-rc1) - (2020-07-29) - -_Note: There were no changes to code between v1.0.0-rc1 and v1.0.0 so see v1.0.0 for changelog_ - -### 0.14.1 (2020-03-13) - -* Adds safe allocation wrappers (CVE-2020-7105, #747, #752) (Michael Grunder) - -### 0.14.0 (2018-09-25) -**BREAKING CHANGES**: - -* Change `redisReply.len` to `size_t`, as it denotes the the size of a string - - User code should compare this to `size_t` values as well. - If it was used to compare to other values, casting might be necessary or can be removed, if casting was applied before. - -* Make string2ll static to fix conflict with Redis (Tom Lee [c3188b]) -* Use -dynamiclib instead of -shared for OSX (Ryan Schmidt [a65537]) -* Use string2ll from Redis w/added tests (Michael Grunder [7bef04, 60f622]) -* Makefile - OSX compilation fixes (Ryan Schmidt [881fcb, 0e9af8]) -* Remove redundant NULL checks (Justin Brewer [54acc8, 58e6b8]) -* Fix bulk and multi-bulk length truncation (Justin Brewer [109197]) -* Fix SIGSEGV in OpenBSD by checking for NULL before calling freeaddrinfo (Justin Brewer [546d94]) -* Several POSIX compatibility fixes (Justin Brewer [bbeab8, 49bbaa, d1c1b6]) -* Makefile - Compatibility fixes (Dimitri Vorobiev [3238cf, 12a9d1]) -* Makefile - Fix make install on FreeBSD (Zach Shipko [a2ef2b]) -* Makefile - don't assume $(INSTALL) is cp (Igor Gnatenko [725a96]) -* Separate side-effect causing function from assert and small cleanup (amallia [b46413, 3c3234]) -* Don't send negative values to `__redisAsyncCommand` (Frederik Deweerdt [706129]) -* Fix leak if setsockopt fails (Frederik Deweerdt [e21c9c]) -* Fix libevent leak (zfz [515228]) -* Clean up GCC warning (Ichito Nagata [2ec774]) -* Keep track of errno in `__redisSetErrorFromErrno()` as snprintf may use it (Jin Qing [25cd88]) -* Solaris compilation fix (Donald Whyte [41b07d]) -* Reorder linker arguments when building examples (Tustfarm-heart [06eedd]) -* Keep track of subscriptions in case of rapid subscribe/unsubscribe (Hyungjin Kim [073dc8, be76c5, d46999]) -* libuv use after free fix (Paul Scott [cbb956]) -* Properly close socket fd on reconnect attempt (WSL [64d1ec]) -* Skip valgrind in OSX tests (Jan-Erik Rediger [9deb78]) -* Various updates for Travis testing OSX (Ted Nyman [fa3774, 16a459, bc0ea5]) -* Update libevent (Chris Xin [386802]) -* Change sds.h for building in C++ projects (Ali Volkan ATLI [f5b32e]) -* Use proper format specifier in redisFormatSdsCommandArgv (Paulino Huerta, Jan-Erik Rediger [360a06, 8655a6]) -* Better handling of NULL reply in example code (Jan-Erik Rediger [1b8ed3]) -* Prevent overflow when formatting an error (Jan-Erik Rediger [0335cb]) -* Compatibility fix for strerror_r (Tom Lee [bb1747]) -* Properly detect integer parse/overflow errors (Justin Brewer [93421f]) -* Adds CI for Windows and cygwin fixes (owent, [6c53d6, 6c3e40]) -* Catch a buffer overflow when formatting the error message -* Import latest upstream sds. This breaks applications that are linked against the old hiredis v0.13 -* Fix warnings, when compiled with -Wshadow -* Make hiredis compile in Cygwin on Windows, now CI-tested -* Bulk and multi-bulk lengths less than -1 or greater than `LLONG_MAX` are now - protocol errors. This is consistent with the RESP specification. On 32-bit - platforms, the upper bound is lowered to `SIZE_MAX`. - -* Remove backwards compatibility macro's - -This removes the following old function aliases, use the new name now: - -| Old | New | -| --------------------------- | ---------------------- | -| redisReplyReaderCreate | redisReaderCreate | -| redisReplyReaderCreate | redisReaderCreate | -| redisReplyReaderFree | redisReaderFree | -| redisReplyReaderFeed | redisReaderFeed | -| redisReplyReaderGetReply | redisReaderGetReply | -| redisReplyReaderSetPrivdata | redisReaderSetPrivdata | -| redisReplyReaderGetObject | redisReaderGetObject | -| redisReplyReaderGetError | redisReaderGetError | - -* The `DEBUG` variable in the Makefile was renamed to `DEBUG_FLAGS` - -Previously it broke some builds for people that had `DEBUG` set to some arbitrary value, -due to debugging other software. -By renaming we avoid unintentional name clashes. - -Simply rename `DEBUG` to `DEBUG_FLAGS` in your environment to make it working again. - -### 0.13.3 (2015-09-16) - -* Revert "Clear `REDIS_CONNECTED` flag when connection is closed". -* Make tests pass on FreeBSD (Thanks, Giacomo Olgeni) - - -If the `REDIS_CONNECTED` flag is cleared, -the async onDisconnect callback function will never be called. -This causes problems as the disconnect is never reported back to the user. - -### 0.13.2 (2015-08-25) - -* Prevent crash on pending replies in async code (Thanks, @switch-st) -* Clear `REDIS_CONNECTED` flag when connection is closed (Thanks, Jerry Jacobs) -* Add MacOS X addapter (Thanks, @dizzus) -* Add Qt adapter (Thanks, Pietro Cerutti) -* Add Ivykis adapter (Thanks, Gergely Nagy) - -All adapters are provided as is and are only tested where possible. - -### 0.13.1 (2015-05-03) - -This is a bug fix release. -The new `reconnect` method introduced new struct members, which clashed with pre-defined names in pre-C99 code. -Another commit forced C99 compilation just to make it work, but of course this is not desirable for outside projects. -Other non-C99 code can now use hiredis as usual again. -Sorry for the inconvenience. - -* Fix memory leak in async reply handling (Salvatore Sanfilippo) -* Rename struct member to avoid name clash with pre-c99 code (Alex Balashov, ncopa) - -### 0.13.0 (2015-04-16) - -This release adds a minimal Windows compatibility layer. -The parser, standalone since v0.12.0, can now be compiled on Windows -(and thus used in other client libraries as well) - -* Windows compatibility layer for parser code (tzickel) -* Properly escape data printed to PKGCONF file (Dan Skorupski) -* Fix tests when assert() undefined (Keith Bennett, Matt Stancliff) -* Implement a reconnect method for the client context, this changes the structure of `redisContext` (Aaron Bedra) - -### 0.12.1 (2015-01-26) - -* Fix `make install`: DESTDIR support, install all required files, install PKGCONF in proper location -* Fix `make test` as 32 bit build on 64 bit platform - -### 0.12.0 (2015-01-22) - -* Add optional KeepAlive support - -* Try again on EINTR errors - -* Add libuv adapter - -* Add IPv6 support - -* Remove possibility of multiple close on same fd - -* Add ability to bind source address on connect - -* Add redisConnectFd() and redisFreeKeepFd() - -* Fix getaddrinfo() memory leak - -* Free string if it is unused (fixes memory leak) - -* Improve redisAppendCommandArgv performance 2.5x - -* Add support for SO_REUSEADDR - -* Fix redisvFormatCommand format parsing - -* Add GLib 2.0 adapter - -* Refactor reading code into read.c - -* Fix errno error buffers to not clobber errors - -* Generate pkgconf during build - -* Silence _BSD_SOURCE warnings - -* Improve digit counting for multibulk creation - - -### 0.11.0 - -* Increase the maximum multi-bulk reply depth to 7. - -* Increase the read buffer size from 2k to 16k. - -* Use poll(2) instead of select(2) to support large fds (>= 1024). - -### 0.10.1 - -* Makefile overhaul. Important to check out if you override one or more - variables using environment variables or via arguments to the "make" tool. - -* Issue #45: Fix potential memory leak for a multi bulk reply with 0 elements - being created by the default reply object functions. - -* Issue #43: Don't crash in an asynchronous context when Redis returns an error - reply after the connection has been made (this happens when the maximum - number of connections is reached). - -### 0.10.0 - -* See commit log. diff --git a/ext/hiredis-1.0.2/CMakeLists.txt b/ext/hiredis-1.0.2/CMakeLists.txt deleted file mode 100644 index f86c9b70b..000000000 --- a/ext/hiredis-1.0.2/CMakeLists.txt +++ /dev/null @@ -1,165 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.4.0) -INCLUDE(GNUInstallDirs) -PROJECT(hiredis) - -OPTION(ENABLE_SSL "Build hiredis_ssl for SSL support" OFF) -OPTION(DISABLE_TESTS "If tests should be compiled or not" OFF) -OPTION(ENABLE_SSL_TESTS, "Should we test SSL connections" OFF) - -MACRO(getVersionBit name) - SET(VERSION_REGEX "^#define ${name} (.+)$") - FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/hiredis.h" - VERSION_BIT REGEX ${VERSION_REGEX}) - STRING(REGEX REPLACE ${VERSION_REGEX} "\\1" ${name} "${VERSION_BIT}") -ENDMACRO(getVersionBit) - -getVersionBit(HIREDIS_MAJOR) -getVersionBit(HIREDIS_MINOR) -getVersionBit(HIREDIS_PATCH) -getVersionBit(HIREDIS_SONAME) -SET(VERSION "${HIREDIS_MAJOR}.${HIREDIS_MINOR}.${HIREDIS_PATCH}") -MESSAGE("Detected version: ${VERSION}") - -PROJECT(hiredis VERSION "${VERSION}") - -SET(ENABLE_EXAMPLES OFF CACHE BOOL "Enable building hiredis examples") - -SET(hiredis_sources - alloc.c - async.c - dict.c - hiredis.c - net.c - read.c - sds.c - sockcompat.c) - -SET(hiredis_sources ${hiredis_sources}) - -IF(WIN32) - ADD_COMPILE_DEFINITIONS(_CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN) -ENDIF() - -ADD_LIBRARY(hiredis SHARED ${hiredis_sources}) - -SET_TARGET_PROPERTIES(hiredis - PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE - VERSION "${HIREDIS_SONAME}") -IF(WIN32 OR MINGW) - TARGET_LINK_LIBRARIES(hiredis PRIVATE ws2_32) -ENDIF() - -TARGET_INCLUDE_DIRECTORIES(hiredis PUBLIC $ $) - -CONFIGURE_FILE(hiredis.pc.in hiredis.pc @ONLY) - -INSTALL(TARGETS hiredis - EXPORT hiredis-targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - -INSTALL(FILES hiredis.h read.h sds.h async.h alloc.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis) - -INSTALL(DIRECTORY adapters - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis) - -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredis.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) - -export(EXPORT hiredis-targets - FILE "${CMAKE_CURRENT_BINARY_DIR}/hiredis-targets.cmake" - NAMESPACE hiredis::) - -SET(CMAKE_CONF_INSTALL_DIR share/hiredis) -SET(INCLUDE_INSTALL_DIR include) -include(CMakePackageConfigHelpers) -configure_package_config_file(hiredis-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/hiredis-config.cmake - INSTALL_DESTINATION ${CMAKE_CONF_INSTALL_DIR} - PATH_VARS INCLUDE_INSTALL_DIR) - -INSTALL(EXPORT hiredis-targets - FILE hiredis-targets.cmake - NAMESPACE hiredis:: - DESTINATION ${CMAKE_CONF_INSTALL_DIR}) - -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredis-config.cmake - DESTINATION ${CMAKE_CONF_INSTALL_DIR}) - - -IF(ENABLE_SSL) - IF (NOT OPENSSL_ROOT_DIR) - IF (APPLE) - SET(OPENSSL_ROOT_DIR "/usr/local/opt/openssl") - ENDIF() - ENDIF() - FIND_PACKAGE(OpenSSL REQUIRED) - SET(hiredis_ssl_sources - ssl.c) - ADD_LIBRARY(hiredis_ssl SHARED - ${hiredis_ssl_sources}) - - IF (APPLE) - SET_PROPERTY(TARGET hiredis_ssl PROPERTY LINK_FLAGS "-Wl,-undefined -Wl,dynamic_lookup") - ENDIF() - - SET_TARGET_PROPERTIES(hiredis_ssl - PROPERTIES - WINDOWS_EXPORT_ALL_SYMBOLS TRUE - VERSION "${HIREDIS_SONAME}") - - TARGET_INCLUDE_DIRECTORIES(hiredis_ssl PRIVATE "${OPENSSL_INCLUDE_DIR}") - TARGET_LINK_LIBRARIES(hiredis_ssl PRIVATE ${OPENSSL_LIBRARIES}) - IF (WIN32 OR MINGW) - TARGET_LINK_LIBRARIES(hiredis_ssl PRIVATE hiredis) - ENDIF() - CONFIGURE_FILE(hiredis_ssl.pc.in hiredis_ssl.pc @ONLY) - - INSTALL(TARGETS hiredis_ssl - EXPORT hiredis_ssl-targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - INSTALL(FILES hiredis_ssl.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis) - - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredis_ssl.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) - - export(EXPORT hiredis_ssl-targets - FILE "${CMAKE_CURRENT_BINARY_DIR}/hiredis_ssl-targets.cmake" - NAMESPACE hiredis::) - - SET(CMAKE_CONF_INSTALL_DIR share/hiredis_ssl) - configure_package_config_file(hiredis_ssl-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/hiredis_ssl-config.cmake - INSTALL_DESTINATION ${CMAKE_CONF_INSTALL_DIR} - PATH_VARS INCLUDE_INSTALL_DIR) - - INSTALL(EXPORT hiredis_ssl-targets - FILE hiredis_ssl-targets.cmake - NAMESPACE hiredis:: - DESTINATION ${CMAKE_CONF_INSTALL_DIR}) - - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredis_ssl-config.cmake - DESTINATION ${CMAKE_CONF_INSTALL_DIR}) -ENDIF() - -IF(NOT DISABLE_TESTS) - ENABLE_TESTING() - ADD_EXECUTABLE(hiredis-test test.c) - IF(ENABLE_SSL_TESTS) - ADD_DEFINITIONS(-DHIREDIS_TEST_SSL=1) - TARGET_LINK_LIBRARIES(hiredis-test hiredis hiredis_ssl) - ELSE() - TARGET_LINK_LIBRARIES(hiredis-test hiredis) - ENDIF() - ADD_TEST(NAME hiredis-test - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test.sh) -ENDIF() - -# Add examples -IF(ENABLE_EXAMPLES) - ADD_SUBDIRECTORY(examples) -ENDIF(ENABLE_EXAMPLES) diff --git a/ext/hiredis-1.0.2/COPYING b/ext/hiredis-1.0.2/COPYING deleted file mode 100644 index a5fc97395..000000000 --- a/ext/hiredis-1.0.2/COPYING +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2009-2011, Salvatore Sanfilippo -Copyright (c) 2010-2011, Pieter Noordhuis - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of Redis nor the names of its contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/ext/hiredis-1.0.2/Makefile b/ext/hiredis-1.0.2/Makefile deleted file mode 100644 index a8d37a2eb..000000000 --- a/ext/hiredis-1.0.2/Makefile +++ /dev/null @@ -1,308 +0,0 @@ -# Hiredis Makefile -# Copyright (C) 2010-2011 Salvatore Sanfilippo -# Copyright (C) 2010-2011 Pieter Noordhuis -# This file is released under the BSD license, see the COPYING file - -OBJ=alloc.o net.o hiredis.o sds.o async.o read.o sockcompat.o -SSL_OBJ=ssl.o -EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib hiredis-example-push -ifeq ($(USE_SSL),1) -EXAMPLES+=hiredis-example-ssl hiredis-example-libevent-ssl -endif -TESTS=hiredis-test -LIBNAME=libhiredis -PKGCONFNAME=hiredis.pc -SSL_LIBNAME=libhiredis_ssl -SSL_PKGCONFNAME=hiredis_ssl.pc - -HIREDIS_MAJOR=$(shell grep HIREDIS_MAJOR hiredis.h | awk '{print $$3}') -HIREDIS_MINOR=$(shell grep HIREDIS_MINOR hiredis.h | awk '{print $$3}') -HIREDIS_PATCH=$(shell grep HIREDIS_PATCH hiredis.h | awk '{print $$3}') -HIREDIS_SONAME=$(shell grep HIREDIS_SONAME hiredis.h | awk '{print $$3}') - -# Installation related variables and target -PREFIX?=/usr/local -INCLUDE_PATH?=include/hiredis -LIBRARY_PATH?=lib -PKGCONF_PATH?=pkgconfig -INSTALL_INCLUDE_PATH= $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH) -INSTALL_LIBRARY_PATH= $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH) -INSTALL_PKGCONF_PATH= $(INSTALL_LIBRARY_PATH)/$(PKGCONF_PATH) - -# redis-server configuration used for testing -REDIS_PORT=56379 -REDIS_SERVER=redis-server -define REDIS_TEST_CONFIG - daemonize yes - pidfile /tmp/hiredis-test-redis.pid - port $(REDIS_PORT) - bind 127.0.0.1 - unixsocket /tmp/hiredis-test-redis.sock -endef -export REDIS_TEST_CONFIG - -# Fallback to gcc when $CC is not in $PATH. -CC:=$(shell sh -c 'type $${CC%% *} >/dev/null 2>/dev/null && echo $(CC) || echo gcc') -CXX:=$(shell sh -c 'type $${CXX%% *} >/dev/null 2>/dev/null && echo $(CXX) || echo g++') -OPTIMIZATION?=-O3 -WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -DEBUG_FLAGS?= -g -ggdb -REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS) -REAL_LDFLAGS=$(LDFLAGS) - -DYLIBSUFFIX=so -STLIBSUFFIX=a -DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_SONAME) -DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR) -DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX) - -DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -STLIBNAME=$(LIBNAME).$(STLIBSUFFIX) -STLIB_MAKE_CMD=$(AR) rcs - -SSL_DYLIB_MINOR_NAME=$(SSL_LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_SONAME) -SSL_DYLIB_MAJOR_NAME=$(SSL_LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR) -SSL_DYLIBNAME=$(SSL_LIBNAME).$(DYLIBSUFFIX) -SSL_STLIBNAME=$(SSL_LIBNAME).$(STLIBSUFFIX) -SSL_DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(SSL_DYLIB_MINOR_NAME) - -# Platform-specific overrides -uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') - -USE_SSL?=0 - -# This is required for test.c only -ifeq ($(USE_SSL),1) - CFLAGS+=-DHIREDIS_TEST_SSL -endif - -ifeq ($(uname_S),Linux) - SSL_LDFLAGS=-lssl -lcrypto -else - OPENSSL_PREFIX?=/usr/local/opt/openssl - CFLAGS+=-I$(OPENSSL_PREFIX)/include - SSL_LDFLAGS+=-L$(OPENSSL_PREFIX)/lib -lssl -lcrypto -endif - -ifeq ($(uname_S),SunOS) - IS_SUN_CC=$(shell sh -c '$(CC) -V 2>&1 |egrep -i -c "sun|studio"') - ifeq ($(IS_SUN_CC),1) - SUN_SHARED_FLAG=-G - else - SUN_SHARED_FLAG=-shared - endif - REAL_LDFLAGS+= -ldl -lnsl -lsocket - DYLIB_MAKE_CMD=$(CC) $(SUN_SHARED_FLAG) -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS) - SSL_DYLIB_MAKE_CMD=$(CC) $(SUN_SHARED_FLAG) -o $(SSL_DYLIBNAME) -h $(SSL_DYLIB_MINOR_NAME) $(LDFLAGS) $(SSL_LDFLAGS) -endif -ifeq ($(uname_S),Darwin) - DYLIBSUFFIX=dylib - DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX) - DYLIB_MAKE_CMD=$(CC) -dynamiclib -Wl,-install_name,$(PREFIX)/$(LIBRARY_PATH)/$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) - SSL_DYLIB_MAKE_CMD=$(CC) -dynamiclib -Wl,-install_name,$(PREFIX)/$(LIBRARY_PATH)/$(SSL_DYLIB_MINOR_NAME) -o $(SSL_DYLIBNAME) $(LDFLAGS) $(SSL_LDFLAGS) - DYLIB_PLUGIN=-Wl,-undefined -Wl,dynamic_lookup -endif - -all: $(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME) -ifeq ($(USE_SSL),1) -all: $(SSL_DYLIBNAME) $(SSL_STLIBNAME) $(SSL_PKGCONFNAME) -endif - -# Deps (use make dep to generate this) -alloc.o: alloc.c fmacros.h alloc.h -async.o: async.c fmacros.h alloc.h async.h hiredis.h read.h sds.h net.h dict.c dict.h win32.h async_private.h -dict.o: dict.c fmacros.h alloc.h dict.h -hiredis.o: hiredis.c fmacros.h hiredis.h read.h sds.h alloc.h net.h async.h win32.h -net.o: net.c fmacros.h net.h hiredis.h read.h sds.h alloc.h sockcompat.h win32.h -read.o: read.c fmacros.h alloc.h read.h sds.h win32.h -sds.o: sds.c sds.h sdsalloc.h alloc.h -sockcompat.o: sockcompat.c sockcompat.h -ssl.o: ssl.c hiredis.h read.h sds.h alloc.h async.h win32.h async_private.h -test.o: test.c fmacros.h hiredis.h read.h sds.h alloc.h net.h sockcompat.h win32.h - -$(DYLIBNAME): $(OBJ) - $(DYLIB_MAKE_CMD) -o $(DYLIBNAME) $(OBJ) $(REAL_LDFLAGS) - -$(STLIBNAME): $(OBJ) - $(STLIB_MAKE_CMD) $(STLIBNAME) $(OBJ) - -$(SSL_DYLIBNAME): $(SSL_OBJ) - $(SSL_DYLIB_MAKE_CMD) $(DYLIB_PLUGIN) -o $(SSL_DYLIBNAME) $(SSL_OBJ) $(REAL_LDFLAGS) $(LDFLAGS) $(SSL_LDFLAGS) - -$(SSL_STLIBNAME): $(SSL_OBJ) - $(STLIB_MAKE_CMD) $(SSL_STLIBNAME) $(SSL_OBJ) - -dynamic: $(DYLIBNAME) -static: $(STLIBNAME) -ifeq ($(USE_SSL),1) -dynamic: $(SSL_DYLIBNAME) -static: $(SSL_STLIBNAME) -endif - -# Binaries: -hiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -levent $(STLIBNAME) $(REAL_LDFLAGS) - -hiredis-example-libevent-ssl: examples/example-libevent-ssl.c adapters/libevent.h $(STLIBNAME) $(SSL_STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -levent $(STLIBNAME) $(SSL_STLIBNAME) $(REAL_LDFLAGS) $(SSL_LDFLAGS) - -hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -lev $(STLIBNAME) $(REAL_LDFLAGS) - -hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(shell pkg-config --cflags --libs glib-2.0) $(STLIBNAME) $(REAL_LDFLAGS) - -hiredis-example-ivykis: examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -livykis $(STLIBNAME) $(REAL_LDFLAGS) - -hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -framework CoreFoundation $(STLIBNAME) $(REAL_LDFLAGS) - -hiredis-example-ssl: examples/example-ssl.c $(STLIBNAME) $(SSL_STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(STLIBNAME) $(SSL_STLIBNAME) $(REAL_LDFLAGS) $(SSL_LDFLAGS) - - -ifndef AE_DIR -hiredis-example-ae: - @echo "Please specify AE_DIR (e.g. /src)" - @false -else -hiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(AE_DIR) $< $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o $(AE_DIR)/../deps/jemalloc/lib/libjemalloc.a -pthread $(STLIBNAME) -endif - -ifndef LIBUV_DIR -hiredis-example-libuv: - @echo "Please specify LIBUV_DIR (e.g. ../libuv/)" - @false -else -hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME) $(REAL_LDFLAGS) -endif - -ifeq ($(and $(QT_MOC),$(QT_INCLUDE_DIR),$(QT_LIBRARY_DIR)),) -hiredis-example-qt: - @echo "Please specify QT_MOC, QT_INCLUDE_DIR AND QT_LIBRARY_DIR" - @false -else -hiredis-example-qt: examples/example-qt.cpp adapters/qt.h $(STLIBNAME) - $(QT_MOC) adapters/qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \ - $(CXX) -x c++ -o qt-adapter-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore - $(QT_MOC) examples/example-qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \ - $(CXX) -x c++ -o qt-example-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore - $(CXX) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore -L$(QT_LIBRARY_DIR) qt-adapter-moc.o qt-example-moc.o $< -pthread $(STLIBNAME) -lQtCore -endif - -hiredis-example: examples/example.c $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(STLIBNAME) $(REAL_LDFLAGS) - -hiredis-example-push: examples/example-push.c $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(STLIBNAME) $(REAL_LDFLAGS) - -examples: $(EXAMPLES) - -TEST_LIBS = $(STLIBNAME) -ifeq ($(USE_SSL),1) - TEST_LIBS += $(SSL_STLIBNAME) - TEST_LDFLAGS = $(SSL_LDFLAGS) -lssl -lcrypto -lpthread -endif - -hiredis-test: test.o $(TEST_LIBS) - $(CC) -o $@ $(REAL_CFLAGS) -I. $^ $(REAL_LDFLAGS) $(TEST_LDFLAGS) - -hiredis-%: %.o $(STLIBNAME) - $(CC) $(REAL_CFLAGS) -o $@ $< $(TEST_LIBS) $(REAL_LDFLAGS) - -test: hiredis-test - ./hiredis-test - -check: hiredis-test - TEST_SSL=$(USE_SSL) ./test.sh - -.c.o: - $(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $< - -clean: - rm -rf $(DYLIBNAME) $(STLIBNAME) $(SSL_DYLIBNAME) $(SSL_STLIBNAME) $(TESTS) $(PKGCONFNAME) examples/hiredis-example* *.o *.gcda *.gcno *.gcov - -dep: - $(CC) $(CPPFLAGS) $(CFLAGS) -MM *.c - -INSTALL?= cp -pPR - -$(PKGCONFNAME): hiredis.h - @echo "Generating $@ for pkgconfig..." - @echo prefix=$(PREFIX) > $@ - @echo exec_prefix=\$${prefix} >> $@ - @echo libdir=$(PREFIX)/$(LIBRARY_PATH) >> $@ - @echo includedir=$(PREFIX)/$(INCLUDE_PATH) >> $@ - @echo >> $@ - @echo Name: hiredis >> $@ - @echo Description: Minimalistic C client library for Redis. >> $@ - @echo Version: $(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(HIREDIS_PATCH) >> $@ - @echo Libs: -L\$${libdir} -lhiredis >> $@ - @echo Cflags: -I\$${includedir} -D_FILE_OFFSET_BITS=64 >> $@ - -$(SSL_PKGCONFNAME): hiredis_ssl.h - @echo "Generating $@ for pkgconfig..." - @echo prefix=$(PREFIX) > $@ - @echo exec_prefix=\$${prefix} >> $@ - @echo libdir=$(PREFIX)/$(LIBRARY_PATH) >> $@ - @echo includedir=$(PREFIX)/$(INCLUDE_PATH) >> $@ - @echo >> $@ - @echo Name: hiredis_ssl >> $@ - @echo Description: SSL Support for hiredis. >> $@ - @echo Version: $(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(HIREDIS_PATCH) >> $@ - @echo Requires: hiredis >> $@ - @echo Libs: -L\$${libdir} -lhiredis_ssl >> $@ - @echo Libs.private: -lssl -lcrypto >> $@ - -install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME) - mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL_LIBRARY_PATH) - $(INSTALL) hiredis.h async.h read.h sds.h alloc.h $(INSTALL_INCLUDE_PATH) - $(INSTALL) adapters/*.h $(INSTALL_INCLUDE_PATH)/adapters - $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) - cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME) - $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH) - mkdir -p $(INSTALL_PKGCONF_PATH) - $(INSTALL) $(PKGCONFNAME) $(INSTALL_PKGCONF_PATH) - -ifeq ($(USE_SSL),1) -install: install-ssl - -install-ssl: $(SSL_DYLIBNAME) $(SSL_STLIBNAME) $(SSL_PKGCONFNAME) - mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH) - $(INSTALL) hiredis_ssl.h $(INSTALL_INCLUDE_PATH) - $(INSTALL) $(SSL_DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(SSL_DYLIB_MINOR_NAME) - cd $(INSTALL_LIBRARY_PATH) && ln -sf $(SSL_DYLIB_MINOR_NAME) $(SSL_DYLIBNAME) - $(INSTALL) $(SSL_STLIBNAME) $(INSTALL_LIBRARY_PATH) - mkdir -p $(INSTALL_PKGCONF_PATH) - $(INSTALL) $(SSL_PKGCONFNAME) $(INSTALL_PKGCONF_PATH) -endif - -32bit: - @echo "" - @echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386" - @echo "" - $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" - -32bit-vars: - $(eval CFLAGS=-m32) - $(eval LDFLAGS=-m32) - -gprof: - $(MAKE) CFLAGS="-pg" LDFLAGS="-pg" - -gcov: - $(MAKE) CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs" - -coverage: gcov - make check - mkdir -p tmp/lcov - lcov -d . -c -o tmp/lcov/hiredis.info - genhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info - -noopt: - $(MAKE) OPTIMIZATION="" - -.PHONY: all test check clean dep install 32bit 32bit-vars gprof gcov noopt diff --git a/ext/hiredis-1.0.2/README.md b/ext/hiredis-1.0.2/README.md deleted file mode 100644 index c544d5718..000000000 --- a/ext/hiredis-1.0.2/README.md +++ /dev/null @@ -1,664 +0,0 @@ -[![Build Status](https://travis-ci.org/redis/hiredis.png)](https://travis-ci.org/redis/hiredis) - -**This Readme reflects the latest changed in the master branch. See [v1.0.0](https://github.com/redis/hiredis/tree/v1.0.0) for the Readme and documentation for the latest release ([API/ABI history](https://abi-laboratory.pro/?view=timeline&l=hiredis)).** - -# HIREDIS - -Hiredis is a minimalistic C client library for the [Redis](http://redis.io/) database. - -It is minimalistic because it just adds minimal support for the protocol, but -at the same time it uses a high level printf-alike API in order to make it -much higher level than otherwise suggested by its minimal code base and the -lack of explicit bindings for every Redis command. - -Apart from supporting sending commands and receiving replies, it comes with -a reply parser that is decoupled from the I/O layer. It -is a stream parser designed for easy reusability, which can for instance be used -in higher level language bindings for efficient reply parsing. - -Hiredis only supports the binary-safe Redis protocol, so you can use it with any -Redis version >= 1.2.0. - -The library comes with multiple APIs. There is the -*synchronous API*, the *asynchronous API* and the *reply parsing API*. - -## Upgrading to `1.0.2` - -NOTE: v1.0.1 erroneously bumped SONAME, which is why it is skipped here. - -Version 1.0.2 is simply 1.0.0 with a fix for [CVE-2021-32765](https://github.com/redis/hiredis/security/advisories/GHSA-hfm9-39pp-55p2). They are otherwise identical. - -## Upgrading to `1.0.0` - -Version 1.0.0 marks the first stable release of Hiredis. -It includes some minor breaking changes, mostly to make the exposed API more uniform and self-explanatory. -It also bundles the updated `sds` library, to sync up with upstream and Redis. -For code changes see the [Changelog](CHANGELOG.md). - -_Note: As described below, a few member names have been changed but most applications should be able to upgrade with minor code changes and recompiling._ - -## IMPORTANT: Breaking changes from `0.14.1` -> `1.0.0` - -* `redisContext` has two additional members (`free_privdata`, and `privctx`). -* `redisOptions.timeout` has been renamed to `redisOptions.connect_timeout`, and we've added `redisOptions.command_timeout`. -* `redisReplyObjectFunctions.createArray` now takes `size_t` instead of `int` for its length parameter. - -## IMPORTANT: Breaking changes when upgrading from 0.13.x -> 0.14.x - -Bulk and multi-bulk lengths less than -1 or greater than `LLONG_MAX` are now -protocol errors. This is consistent with the RESP specification. On 32-bit -platforms, the upper bound is lowered to `SIZE_MAX`. - -Change `redisReply.len` to `size_t`, as it denotes the the size of a string - -User code should compare this to `size_t` values as well. If it was used to -compare to other values, casting might be necessary or can be removed, if -casting was applied before. - -## Upgrading from `<0.9.0` - -Version 0.9.0 is a major overhaul of hiredis in every aspect. However, upgrading existing -code using hiredis should not be a big pain. The key thing to keep in mind when -upgrading is that hiredis >= 0.9.0 uses a `redisContext*` to keep state, in contrast to -the stateless 0.0.1 that only has a file descriptor to work with. - -## Synchronous API - -To consume the synchronous API, there are only a few function calls that need to be introduced: - -```c -redisContext *redisConnect(const char *ip, int port); -void *redisCommand(redisContext *c, const char *format, ...); -void freeReplyObject(void *reply); -``` - -### Connecting - -The function `redisConnect` is used to create a so-called `redisContext`. The -context is where Hiredis holds state for a connection. The `redisContext` -struct has an integer `err` field that is non-zero when the connection is in -an error state. The field `errstr` will contain a string with a description of -the error. More information on errors can be found in the **Errors** section. -After trying to connect to Redis using `redisConnect` you should -check the `err` field to see if establishing the connection was successful: -```c -redisContext *c = redisConnect("127.0.0.1", 6379); -if (c == NULL || c->err) { - if (c) { - printf("Error: %s\n", c->errstr); - // handle error - } else { - printf("Can't allocate redis context\n"); - } -} -``` - -*Note: A `redisContext` is not thread-safe.* - -### Sending commands - -There are several ways to issue commands to Redis. The first that will be introduced is -`redisCommand`. This function takes a format similar to printf. In the simplest form, -it is used like this: -```c -reply = redisCommand(context, "SET foo bar"); -``` - -The specifier `%s` interpolates a string in the command, and uses `strlen` to -determine the length of the string: -```c -reply = redisCommand(context, "SET foo %s", value); -``` -When you need to pass binary safe strings in a command, the `%b` specifier can be -used. Together with a pointer to the string, it requires a `size_t` length argument -of the string: -```c -reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen); -``` -Internally, Hiredis splits the command in different arguments and will -convert it to the protocol used to communicate with Redis. -One or more spaces separates arguments, so you can use the specifiers -anywhere in an argument: -```c -reply = redisCommand(context, "SET key:%s %s", myid, value); -``` - -### Using replies - -The return value of `redisCommand` holds a reply when the command was -successfully executed. When an error occurs, the return value is `NULL` and -the `err` field in the context will be set (see section on **Errors**). -Once an error is returned the context cannot be reused and you should set up -a new connection. - -The standard replies that `redisCommand` are of the type `redisReply`. The -`type` field in the `redisReply` should be used to test what kind of reply -was received: - -### RESP2 - -* **`REDIS_REPLY_STATUS`**: - * The command replied with a status reply. The status string can be accessed using `reply->str`. - The length of this string can be accessed using `reply->len`. - -* **`REDIS_REPLY_ERROR`**: - * The command replied with an error. The error string can be accessed identical to `REDIS_REPLY_STATUS`. - -* **`REDIS_REPLY_INTEGER`**: - * The command replied with an integer. The integer value can be accessed using the - `reply->integer` field of type `long long`. - -* **`REDIS_REPLY_NIL`**: - * The command replied with a **nil** object. There is no data to access. - -* **`REDIS_REPLY_STRING`**: - * A bulk (string) reply. The value of the reply can be accessed using `reply->str`. - The length of this string can be accessed using `reply->len`. - -* **`REDIS_REPLY_ARRAY`**: - * A multi bulk reply. The number of elements in the multi bulk reply is stored in - `reply->elements`. Every element in the multi bulk reply is a `redisReply` object as well - and can be accessed via `reply->element[..index..]`. - Redis may reply with nested arrays but this is fully supported. - -### RESP3 - -Hiredis also supports every new `RESP3` data type which are as follows. For more information about the protocol see the `RESP3` [specification.](https://github.com/antirez/RESP3/blob/master/spec.md) - -* **`REDIS_REPLY_DOUBLE`**: - * The command replied with a double-precision floating point number. - The value is stored as a string in the `str` member, and can be converted with `strtod` or similar. - -* **`REDIS_REPLY_BOOL`**: - * A boolean true/false reply. - The value is stored in the `integer` member and will be either `0` or `1`. - -* **`REDIS_REPLY_MAP`**: - * An array with the added invariant that there will always be an even number of elements. - The MAP is functionally equivelant to `REDIS_REPLY_ARRAY` except for the previously mentioned invariant. - -* **`REDIS_REPLY_SET`**: - * An array response where each entry is unique. - Like the MAP type, the data is identical to an array response except there are no duplicate values. - -* **`REDIS_REPLY_PUSH`**: - * An array that can be generated spontaneously by Redis. - This array response will always contain at least two subelements. The first contains the type of `PUSH` message (e.g. `message`, or `invalidate`), and the second being a sub-array with the `PUSH` payload itself. - -* **`REDIS_REPLY_ATTR`**: - * An array structurally identical to a `MAP` but intended as meta-data about a reply. - _As of Redis 6.0.6 this reply type is not used in Redis_ - -* **`REDIS_REPLY_BIGNUM`**: - * A string representing an arbitrarily large signed or unsigned integer value. - The number will be encoded as a string in the `str` member of `redisReply`. - -* **`REDIS_REPLY_VERB`**: - * A verbatim string, intended to be presented to the user without modification. - The string payload is stored in the `str` memeber, and type data is stored in the `vtype` member (e.g. `txt` for raw text or `md` for markdown). - -Replies should be freed using the `freeReplyObject()` function. -Note that this function will take care of freeing sub-reply objects -contained in arrays and nested arrays, so there is no need for the user to -free the sub replies (it is actually harmful and will corrupt the memory). - -**Important:** the current version of hiredis (1.0.0) frees replies when the -asynchronous API is used. This means you should not call `freeReplyObject` when -you use this API. The reply is cleaned up by hiredis _after_ the callback -returns. We may introduce a flag to make this configurable in future versions of the library. - -### Cleaning up - -To disconnect and free the context the following function can be used: -```c -void redisFree(redisContext *c); -``` -This function immediately closes the socket and then frees the allocations done in -creating the context. - -### Sending commands (cont'd) - -Together with `redisCommand`, the function `redisCommandArgv` can be used to issue commands. -It has the following prototype: -```c -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); -``` -It takes the number of arguments `argc`, an array of strings `argv` and the lengths of the -arguments `argvlen`. For convenience, `argvlen` may be set to `NULL` and the function will -use `strlen(3)` on every argument to determine its length. Obviously, when any of the arguments -need to be binary safe, the entire array of lengths `argvlen` should be provided. - -The return value has the same semantic as `redisCommand`. - -### Pipelining - -To explain how Hiredis supports pipelining in a blocking connection, there needs to be -understanding of the internal execution flow. - -When any of the functions in the `redisCommand` family is called, Hiredis first formats the -command according to the Redis protocol. The formatted command is then put in the output buffer -of the context. This output buffer is dynamic, so it can hold any number of commands. -After the command is put in the output buffer, `redisGetReply` is called. This function has the -following two execution paths: - -1. The input buffer is non-empty: - * Try to parse a single reply from the input buffer and return it - * If no reply could be parsed, continue at *2* -2. The input buffer is empty: - * Write the **entire** output buffer to the socket - * Read from the socket until a single reply could be parsed - -The function `redisGetReply` is exported as part of the Hiredis API and can be used when a reply -is expected on the socket. To pipeline commands, the only things that needs to be done is -filling up the output buffer. For this cause, two commands can be used that are identical -to the `redisCommand` family, apart from not returning a reply: -```c -void redisAppendCommand(redisContext *c, const char *format, ...); -void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); -``` -After calling either function one or more times, `redisGetReply` can be used to receive the -subsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where -the latter means an error occurred while reading a reply. Just as with the other commands, -the `err` field in the context can be used to find out what the cause of this error is. - -The following examples shows a simple pipeline (resulting in only a single call to `write(2)` and -a single call to `read(2)`): -```c -redisReply *reply; -redisAppendCommand(context,"SET foo bar"); -redisAppendCommand(context,"GET foo"); -redisGetReply(context,(void *)&reply); // reply for SET -freeReplyObject(reply); -redisGetReply(context,(void *)&reply); // reply for GET -freeReplyObject(reply); -``` -This API can also be used to implement a blocking subscriber: -```c -reply = redisCommand(context,"SUBSCRIBE foo"); -freeReplyObject(reply); -while(redisGetReply(context,(void *)&reply) == REDIS_OK) { - // consume message - freeReplyObject(reply); -} -``` -### Errors - -When a function call is not successful, depending on the function either `NULL` or `REDIS_ERR` is -returned. The `err` field inside the context will be non-zero and set to one of the -following constants: - -* **`REDIS_ERR_IO`**: - There was an I/O error while creating the connection, trying to write - to the socket or read from the socket. If you included `errno.h` in your - application, you can use the global `errno` variable to find out what is - wrong. - -* **`REDIS_ERR_EOF`**: - The server closed the connection which resulted in an empty read. - -* **`REDIS_ERR_PROTOCOL`**: - There was an error while parsing the protocol. - -* **`REDIS_ERR_OTHER`**: - Any other error. Currently, it is only used when a specified hostname to connect - to cannot be resolved. - -In every case, the `errstr` field in the context will be set to hold a string representation -of the error. - -## Asynchronous API - -Hiredis comes with an asynchronous API that works easily with any event library. -Examples are bundled that show using Hiredis with [libev](http://software.schmorp.de/pkg/libev.html) -and [libevent](http://monkey.org/~provos/libevent/). - -### Connecting - -The function `redisAsyncConnect` can be used to establish a non-blocking connection to -Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The `err` field -should be checked after creation to see if there were errors creating the connection. -Because the connection that will be created is non-blocking, the kernel is not able to -instantly return if the specified host and port is able to accept a connection. - -*Note: A `redisAsyncContext` is not thread-safe.* - -```c -redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); -if (c->err) { - printf("Error: %s\n", c->errstr); - // handle error -} -``` - -The asynchronous context can hold a disconnect callback function that is called when the -connection is disconnected (either because of an error or per user request). This function should -have the following prototype: -```c -void(const redisAsyncContext *c, int status); -``` -On a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the -user, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `err` -field in the context can be accessed to find out the cause of the error. - -The context object is always freed after the disconnect callback fired. When a reconnect is needed, -the disconnect callback is a good point to do so. - -Setting the disconnect callback can only be done once per context. For subsequent calls it will -return `REDIS_ERR`. The function to set the disconnect callback has the following prototype: -```c -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); -``` -`ac->data` may be used to pass user data to this callback, the same can be done for redisConnectCallback. -### Sending commands and their callbacks - -In an asynchronous context, commands are automatically pipelined due to the nature of an event loop. -Therefore, unlike the synchronous API, there is only a single way to send commands. -Because commands are sent to Redis asynchronously, issuing a command requires a callback function -that is called when the reply is received. Reply callbacks should have the following prototype: -```c -void(redisAsyncContext *c, void *reply, void *privdata); -``` -The `privdata` argument can be used to curry arbitrary data to the callback from the point where -the command is initially queued for execution. - -The functions that can be used to issue commands in an asynchronous context are: -```c -int redisAsyncCommand( - redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, - const char *format, ...); -int redisAsyncCommandArgv( - redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, - int argc, const char **argv, const size_t *argvlen); -``` -Both functions work like their blocking counterparts. The return value is `REDIS_OK` when the command -was successfully added to the output buffer and `REDIS_ERR` otherwise. Example: when the connection -is being disconnected per user-request, no new commands may be added to the output buffer and `REDIS_ERR` is -returned on calls to the `redisAsyncCommand` family. - -If the reply for a command with a `NULL` callback is read, it is immediately freed. When the callback -for a command is non-`NULL`, the memory is freed immediately following the callback: the reply is only -valid for the duration of the callback. - -All pending callbacks are called with a `NULL` reply when the context encountered an error. - -### Disconnecting - -An asynchronous connection can be terminated using: -```c -void redisAsyncDisconnect(redisAsyncContext *ac); -``` -When this function is called, the connection is **not** immediately terminated. Instead, new -commands are no longer accepted and the connection is only terminated when all pending commands -have been written to the socket, their respective replies have been read and their respective -callbacks have been executed. After this, the disconnection callback is executed with the -`REDIS_OK` status and the context object is freed. - -### Hooking it up to event library *X* - -There are a few hooks that need to be set on the context object after it is created. -See the `adapters/` directory for bindings to *libev* and *libevent*. - -## Reply parsing API - -Hiredis comes with a reply parsing API that makes it easy for writing higher -level language bindings. - -The reply parsing API consists of the following functions: -```c -redisReader *redisReaderCreate(void); -void redisReaderFree(redisReader *reader); -int redisReaderFeed(redisReader *reader, const char *buf, size_t len); -int redisReaderGetReply(redisReader *reader, void **reply); -``` -The same set of functions are used internally by hiredis when creating a -normal Redis context, the above API just exposes it to the user for a direct -usage. - -### Usage - -The function `redisReaderCreate` creates a `redisReader` structure that holds a -buffer with unparsed data and state for the protocol parser. - -Incoming data -- most likely from a socket -- can be placed in the internal -buffer of the `redisReader` using `redisReaderFeed`. This function will make a -copy of the buffer pointed to by `buf` for `len` bytes. This data is parsed -when `redisReaderGetReply` is called. This function returns an integer status -and a reply object (as described above) via `void **reply`. The returned status -can be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went -wrong (either a protocol error, or an out of memory error). - -The parser limits the level of nesting for multi bulk payloads to 7. If the -multi bulk nesting level is higher than this, the parser returns an error. - -### Customizing replies - -The function `redisReaderGetReply` creates `redisReply` and makes the function -argument `reply` point to the created `redisReply` variable. For instance, if -the response of type `REDIS_REPLY_STATUS` then the `str` field of `redisReply` -will hold the status as a vanilla C string. However, the functions that are -responsible for creating instances of the `redisReply` can be customized by -setting the `fn` field on the `redisReader` struct. This should be done -immediately after creating the `redisReader`. - -For example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c) -uses customized reply object functions to create Ruby objects. - -### Reader max buffer - -Both when using the Reader API directly or when using it indirectly via a -normal Redis context, the redisReader structure uses a buffer in order to -accumulate data from the server. -Usually this buffer is destroyed when it is empty and is larger than 16 -KiB in order to avoid wasting memory in unused buffers - -However when working with very big payloads destroying the buffer may slow -down performances considerably, so it is possible to modify the max size of -an idle buffer changing the value of the `maxbuf` field of the reader structure -to the desired value. The special value of 0 means that there is no maximum -value for an idle buffer, so the buffer will never get freed. - -For instance if you have a normal Redis context you can set the maximum idle -buffer to zero (unlimited) just with: -```c -context->reader->maxbuf = 0; -``` -This should be done only in order to maximize performances when working with -large payloads. The context should be set back to `REDIS_READER_MAX_BUF` again -as soon as possible in order to prevent allocation of useless memory. - -### Reader max array elements - -By default the hiredis reply parser sets the maximum number of multi-bulk elements -to 2^32 - 1 or 4,294,967,295 entries. If you need to process multi-bulk replies -with more than this many elements you can set the value higher or to zero, meaning -unlimited with: -```c -context->reader->maxelements = 0; -``` - -## SSL/TLS Support - -### Building - -SSL/TLS support is not built by default and requires an explicit flag: - - make USE_SSL=1 - -This requires OpenSSL development package (e.g. including header files to be -available. - -When enabled, SSL/TLS support is built into extra `libhiredis_ssl.a` and -`libhiredis_ssl.so` static/dynamic libraries. This leaves the original libraries -unaffected so no additional dependencies are introduced. - -### Using it - -First, you'll need to make sure you include the SSL header file: - -```c -#include "hiredis.h" -#include "hiredis_ssl.h" -``` - -You will also need to link against `libhiredis_ssl`, **in addition** to -`libhiredis` and add `-lssl -lcrypto` to satisfy its dependencies. - -Hiredis implements SSL/TLS on top of its normal `redisContext` or -`redisAsyncContext`, so you will need to establish a connection first and then -initiate an SSL/TLS handshake. - -#### Hiredis OpenSSL Wrappers - -Before Hiredis can negotiate an SSL/TLS connection, it is necessary to -initialize OpenSSL and create a context. You can do that in two ways: - -1. Work directly with the OpenSSL API to initialize the library's global context - and create `SSL_CTX *` and `SSL *` contexts. With an `SSL *` object you can - call `redisInitiateSSL()`. -2. Work with a set of Hiredis-provided wrappers around OpenSSL, create a - `redisSSLContext` object to hold configuration and use - `redisInitiateSSLWithContext()` to initiate the SSL/TLS handshake. - -```c -/* An Hiredis SSL context. It holds SSL configuration and can be reused across - * many contexts. - */ -redisSSLContext *ssl; - -/* An error variable to indicate what went wrong, if the context fails to - * initialize. - */ -redisSSLContextError ssl_error; - -/* Initialize global OpenSSL state. - * - * You should call this only once when your app initializes, and only if - * you don't explicitly or implicitly initialize OpenSSL it elsewhere. - */ -redisInitOpenSSL(); - -/* Create SSL context */ -ssl = redisCreateSSLContext( - "cacertbundle.crt", /* File name of trusted CA/ca bundle file, optional */ - "/path/to/certs", /* Path of trusted certificates, optional */ - "client_cert.pem", /* File name of client certificate file, optional */ - "client_key.pem", /* File name of client private key, optional */ - "redis.mydomain.com", /* Server name to request (SNI), optional */ - &ssl_error - ) != REDIS_OK) { - printf("SSL error: %s\n", redisSSLContextGetError(ssl_error); - /* Abort... */ - } - -/* Create Redis context and establish connection */ -c = redisConnect("localhost", 6443); -if (c == NULL || c->err) { - /* Handle error and abort... */ -} - -/* Negotiate SSL/TLS */ -if (redisInitiateSSLWithContext(c, ssl) != REDIS_OK) { - /* Handle error, in c->err / c->errstr */ -} -``` - -## RESP3 PUSH replies -Redis 6.0 introduced PUSH replies with the reply-type `>`. These messages are generated spontaneously and can arrive at any time, so must be handled using callbacks. - -### Default behavior -Hiredis installs handlers on `redisContext` and `redisAsyncContext` by default, which will intercept and free any PUSH replies detected. This means existing code will work as-is after upgrading to Redis 6 and switching to `RESP3`. - -### Custom PUSH handler prototypes -The callback prototypes differ between `redisContext` and `redisAsyncContext`. - -#### redisContext -```c -void my_push_handler(void *privdata, void *reply) { - /* Handle the reply */ - - /* Note: We need to free the reply in our custom handler for - blocking contexts. This lets us keep the reply if - we want. */ - freeReplyObject(reply); -} -``` - -#### redisAsyncContext -```c -void my_async_push_handler(redisAsyncContext *ac, void *reply) { - /* Handle the reply */ - - /* Note: Because async hiredis always frees replies, you should - not call freeReplyObject in an async push callback. */ -} -``` - -### Installing a custom handler -There are two ways to set your own PUSH handlers. - -1. Set `push_cb` or `async_push_cb` in the `redisOptions` struct and connect with `redisConnectWithOptions` or `redisAsyncConnectWithOptions`. - ```c - redisOptions = {0}; - REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379); - options->push_cb = my_push_handler; - redisContext *context = redisConnectWithOptions(&options); - ``` -2. Call `redisSetPushCallback` or `redisAsyncSetPushCallback` on a connected context. - ```c - redisContext *context = redisConnect("127.0.0.1", 6379); - redisSetPushCallback(context, my_push_handler); - ``` - - _Note `redisSetPushCallback` and `redisAsyncSetPushCallback` both return any currently configured handler, making it easy to override and then return to the old value._ - -### Specifying no handler -If you have a unique use-case where you don't want hiredis to automatically intercept and free PUSH replies, you will want to configure no handler at all. This can be done in two ways. -1. Set the `REDIS_OPT_NO_PUSH_AUTOFREE` flag in `redisOptions` and leave the callback function pointer `NULL`. - ```c - redisOptions = {0}; - REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379); - options->options |= REDIS_OPT_NO_PUSH_AUTOFREE; - redisContext *context = redisConnectWithOptions(&options); - ``` -3. Call `redisSetPushCallback` with `NULL` once connected. - ```c - redisContext *context = redisConnect("127.0.0.1", 6379); - redisSetPushCallback(context, NULL); - ``` - - _Note: With no handler configured, calls to `redisCommand` may generate more than one reply, so this strategy is only applicable when there's some kind of blocking`redisGetReply()` loop (e.g. `MONITOR` or `SUBSCRIBE` workloads)._ - -## Allocator injection - -Hiredis uses a pass-thru structure of function pointers defined in [alloc.h](https://github.com/redis/hiredis/blob/f5d25850/alloc.h#L41) that contain the currently configured allocation and deallocation functions. By default they just point to libc (`malloc`, `calloc`, `realloc`, etc). - -### Overriding - -One can override the allocators like so: - -```c -hiredisAllocFuncs myfuncs = { - .mallocFn = my_malloc, - .callocFn = my_calloc, - .reallocFn = my_realloc, - .strdupFn = my_strdup, - .freeFn = my_free, -}; - -// Override allocators (function returns current allocators if needed) -hiredisAllocFuncs orig = hiredisSetAllocators(&myfuncs); -``` - -To reset the allocators to their default libc function simply call: - -```c -hiredisResetAllocators(); -``` - -## AUTHORS - -Salvatore Sanfilippo (antirez at gmail),\ -Pieter Noordhuis (pcnoordhuis at gmail)\ -Michael Grunder (michael dot grunder at gmail) - -_Hiredis is released under the BSD license._ diff --git a/ext/hiredis-1.0.2/adapters/ae.h b/ext/hiredis-1.0.2/adapters/ae.h deleted file mode 100644 index 660d82eb0..000000000 --- a/ext/hiredis-1.0.2/adapters/ae.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_AE_H__ -#define __HIREDIS_AE_H__ -#include -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisAeEvents { - redisAsyncContext *context; - aeEventLoop *loop; - int fd; - int reading, writing; -} redisAeEvents; - -static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) { - ((void)el); ((void)fd); ((void)mask); - - redisAeEvents *e = (redisAeEvents*)privdata; - redisAsyncHandleRead(e->context); -} - -static void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) { - ((void)el); ((void)fd); ((void)mask); - - redisAeEvents *e = (redisAeEvents*)privdata; - redisAsyncHandleWrite(e->context); -} - -static void redisAeAddRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (!e->reading) { - e->reading = 1; - aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e); - } -} - -static void redisAeDelRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (e->reading) { - e->reading = 0; - aeDeleteFileEvent(loop,e->fd,AE_READABLE); - } -} - -static void redisAeAddWrite(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (!e->writing) { - e->writing = 1; - aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e); - } -} - -static void redisAeDelWrite(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (e->writing) { - e->writing = 0; - aeDeleteFileEvent(loop,e->fd,AE_WRITABLE); - } -} - -static void redisAeCleanup(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - redisAeDelRead(privdata); - redisAeDelWrite(privdata); - hi_free(e); -} - -static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisAeEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisAeEvents*)hi_malloc(sizeof(*e)); - if (e == NULL) - return REDIS_ERR; - - e->context = ac; - e->loop = loop; - e->fd = c->fd; - e->reading = e->writing = 0; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisAeAddRead; - ac->ev.delRead = redisAeDelRead; - ac->ev.addWrite = redisAeAddWrite; - ac->ev.delWrite = redisAeDelWrite; - ac->ev.cleanup = redisAeCleanup; - ac->ev.data = e; - - return REDIS_OK; -} -#endif diff --git a/ext/hiredis-1.0.2/adapters/glib.h b/ext/hiredis-1.0.2/adapters/glib.h deleted file mode 100644 index ad59dd142..000000000 --- a/ext/hiredis-1.0.2/adapters/glib.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef __HIREDIS_GLIB_H__ -#define __HIREDIS_GLIB_H__ - -#include - -#include "../hiredis.h" -#include "../async.h" - -typedef struct -{ - GSource source; - redisAsyncContext *ac; - GPollFD poll_fd; -} RedisSource; - -static void -redis_source_add_read (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - g_return_if_fail(source); - source->poll_fd.events |= G_IO_IN; - g_main_context_wakeup(g_source_get_context((GSource *)data)); -} - -static void -redis_source_del_read (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - g_return_if_fail(source); - source->poll_fd.events &= ~G_IO_IN; - g_main_context_wakeup(g_source_get_context((GSource *)data)); -} - -static void -redis_source_add_write (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - g_return_if_fail(source); - source->poll_fd.events |= G_IO_OUT; - g_main_context_wakeup(g_source_get_context((GSource *)data)); -} - -static void -redis_source_del_write (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - g_return_if_fail(source); - source->poll_fd.events &= ~G_IO_OUT; - g_main_context_wakeup(g_source_get_context((GSource *)data)); -} - -static void -redis_source_cleanup (gpointer data) -{ - RedisSource *source = (RedisSource *)data; - - g_return_if_fail(source); - - redis_source_del_read(source); - redis_source_del_write(source); - /* - * It is not our responsibility to remove ourself from the - * current main loop. However, we will remove the GPollFD. - */ - if (source->poll_fd.fd >= 0) { - g_source_remove_poll((GSource *)data, &source->poll_fd); - source->poll_fd.fd = -1; - } -} - -static gboolean -redis_source_prepare (GSource *source, - gint *timeout_) -{ - RedisSource *redis = (RedisSource *)source; - *timeout_ = -1; - return !!(redis->poll_fd.events & redis->poll_fd.revents); -} - -static gboolean -redis_source_check (GSource *source) -{ - RedisSource *redis = (RedisSource *)source; - return !!(redis->poll_fd.events & redis->poll_fd.revents); -} - -static gboolean -redis_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - RedisSource *redis = (RedisSource *)source; - - if ((redis->poll_fd.revents & G_IO_OUT)) { - redisAsyncHandleWrite(redis->ac); - redis->poll_fd.revents &= ~G_IO_OUT; - } - - if ((redis->poll_fd.revents & G_IO_IN)) { - redisAsyncHandleRead(redis->ac); - redis->poll_fd.revents &= ~G_IO_IN; - } - - if (callback) { - return callback(user_data); - } - - return TRUE; -} - -static void -redis_source_finalize (GSource *source) -{ - RedisSource *redis = (RedisSource *)source; - - if (redis->poll_fd.fd >= 0) { - g_source_remove_poll(source, &redis->poll_fd); - redis->poll_fd.fd = -1; - } -} - -static GSource * -redis_source_new (redisAsyncContext *ac) -{ - static GSourceFuncs source_funcs = { - .prepare = redis_source_prepare, - .check = redis_source_check, - .dispatch = redis_source_dispatch, - .finalize = redis_source_finalize, - }; - redisContext *c = &ac->c; - RedisSource *source; - - g_return_val_if_fail(ac != NULL, NULL); - - source = (RedisSource *)g_source_new(&source_funcs, sizeof *source); - if (source == NULL) - return NULL; - - source->ac = ac; - source->poll_fd.fd = c->fd; - source->poll_fd.events = 0; - source->poll_fd.revents = 0; - g_source_add_poll((GSource *)source, &source->poll_fd); - - ac->ev.addRead = redis_source_add_read; - ac->ev.delRead = redis_source_del_read; - ac->ev.addWrite = redis_source_add_write; - ac->ev.delWrite = redis_source_del_write; - ac->ev.cleanup = redis_source_cleanup; - ac->ev.data = source; - - return (GSource *)source; -} - -#endif /* __HIREDIS_GLIB_H__ */ diff --git a/ext/hiredis-1.0.2/adapters/ivykis.h b/ext/hiredis-1.0.2/adapters/ivykis.h deleted file mode 100644 index 179f6ab52..000000000 --- a/ext/hiredis-1.0.2/adapters/ivykis.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef __HIREDIS_IVYKIS_H__ -#define __HIREDIS_IVYKIS_H__ -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisIvykisEvents { - redisAsyncContext *context; - struct iv_fd fd; -} redisIvykisEvents; - -static void redisIvykisReadEvent(void *arg) { - redisAsyncContext *context = (redisAsyncContext *)arg; - redisAsyncHandleRead(context); -} - -static void redisIvykisWriteEvent(void *arg) { - redisAsyncContext *context = (redisAsyncContext *)arg; - redisAsyncHandleWrite(context); -} - -static void redisIvykisAddRead(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - iv_fd_set_handler_in(&e->fd, redisIvykisReadEvent); -} - -static void redisIvykisDelRead(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - iv_fd_set_handler_in(&e->fd, NULL); -} - -static void redisIvykisAddWrite(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - iv_fd_set_handler_out(&e->fd, redisIvykisWriteEvent); -} - -static void redisIvykisDelWrite(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - iv_fd_set_handler_out(&e->fd, NULL); -} - -static void redisIvykisCleanup(void *privdata) { - redisIvykisEvents *e = (redisIvykisEvents*)privdata; - - iv_fd_unregister(&e->fd); - hi_free(e); -} - -static int redisIvykisAttach(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisIvykisEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisIvykisEvents*)hi_malloc(sizeof(*e)); - if (e == NULL) - return REDIS_ERR; - - e->context = ac; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisIvykisAddRead; - ac->ev.delRead = redisIvykisDelRead; - ac->ev.addWrite = redisIvykisAddWrite; - ac->ev.delWrite = redisIvykisDelWrite; - ac->ev.cleanup = redisIvykisCleanup; - ac->ev.data = e; - - /* Initialize and install read/write events */ - IV_FD_INIT(&e->fd); - e->fd.fd = c->fd; - e->fd.handler_in = redisIvykisReadEvent; - e->fd.handler_out = redisIvykisWriteEvent; - e->fd.handler_err = NULL; - e->fd.cookie = e->context; - - iv_fd_register(&e->fd); - - return REDIS_OK; -} -#endif diff --git a/ext/hiredis-1.0.2/adapters/libev.h b/ext/hiredis-1.0.2/adapters/libev.h deleted file mode 100644 index e1e7bbd99..000000000 --- a/ext/hiredis-1.0.2/adapters/libev.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_LIBEV_H__ -#define __HIREDIS_LIBEV_H__ -#include -#include -#include -#include "../hiredis.h" -#include "../async.h" - -typedef struct redisLibevEvents { - redisAsyncContext *context; - struct ev_loop *loop; - int reading, writing; - ev_io rev, wev; - ev_timer timer; -} redisLibevEvents; - -static void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) { -#if EV_MULTIPLICITY - ((void)loop); -#endif - ((void)revents); - - redisLibevEvents *e = (redisLibevEvents*)watcher->data; - redisAsyncHandleRead(e->context); -} - -static void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) { -#if EV_MULTIPLICITY - ((void)loop); -#endif - ((void)revents); - - redisLibevEvents *e = (redisLibevEvents*)watcher->data; - redisAsyncHandleWrite(e->context); -} - -static void redisLibevAddRead(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (!e->reading) { - e->reading = 1; - ev_io_start(EV_A_ &e->rev); - } -} - -static void redisLibevDelRead(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (e->reading) { - e->reading = 0; - ev_io_stop(EV_A_ &e->rev); - } -} - -static void redisLibevAddWrite(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (!e->writing) { - e->writing = 1; - ev_io_start(EV_A_ &e->wev); - } -} - -static void redisLibevDelWrite(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - if (e->writing) { - e->writing = 0; - ev_io_stop(EV_A_ &e->wev); - } -} - -static void redisLibevStopTimer(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - ev_timer_stop(EV_A_ &e->timer); -} - -static void redisLibevCleanup(void *privdata) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - redisLibevDelRead(privdata); - redisLibevDelWrite(privdata); - redisLibevStopTimer(privdata); - hi_free(e); -} - -static void redisLibevTimeout(EV_P_ ev_timer *timer, int revents) { - ((void)revents); - redisLibevEvents *e = (redisLibevEvents*)timer->data; - redisAsyncHandleTimeout(e->context); -} - -static void redisLibevSetTimeout(void *privdata, struct timeval tv) { - redisLibevEvents *e = (redisLibevEvents*)privdata; - struct ev_loop *loop = e->loop; - ((void)loop); - - if (!ev_is_active(&e->timer)) { - ev_init(&e->timer, redisLibevTimeout); - e->timer.data = e; - } - - e->timer.repeat = tv.tv_sec + tv.tv_usec / 1000000.00; - ev_timer_again(EV_A_ &e->timer); -} - -static int redisLibevAttach(EV_P_ redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisLibevEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisLibevEvents*)hi_calloc(1, sizeof(*e)); - if (e == NULL) - return REDIS_ERR; - - e->context = ac; -#if EV_MULTIPLICITY - e->loop = loop; -#else - e->loop = NULL; -#endif - e->rev.data = e; - e->wev.data = e; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisLibevAddRead; - ac->ev.delRead = redisLibevDelRead; - ac->ev.addWrite = redisLibevAddWrite; - ac->ev.delWrite = redisLibevDelWrite; - ac->ev.cleanup = redisLibevCleanup; - ac->ev.scheduleTimer = redisLibevSetTimeout; - ac->ev.data = e; - - /* Initialize read/write events */ - ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ); - ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE); - return REDIS_OK; -} - -#endif diff --git a/ext/hiredis-1.0.2/adapters/libevent.h b/ext/hiredis-1.0.2/adapters/libevent.h deleted file mode 100644 index 9150979bc..000000000 --- a/ext/hiredis-1.0.2/adapters/libevent.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_LIBEVENT_H__ -#define __HIREDIS_LIBEVENT_H__ -#include -#include "../hiredis.h" -#include "../async.h" - -#define REDIS_LIBEVENT_DELETED 0x01 -#define REDIS_LIBEVENT_ENTERED 0x02 - -typedef struct redisLibeventEvents { - redisAsyncContext *context; - struct event *ev; - struct event_base *base; - struct timeval tv; - short flags; - short state; -} redisLibeventEvents; - -static void redisLibeventDestroy(redisLibeventEvents *e) { - hi_free(e); -} - -static void redisLibeventHandler(int fd, short event, void *arg) { - ((void)fd); - redisLibeventEvents *e = (redisLibeventEvents*)arg; - e->state |= REDIS_LIBEVENT_ENTERED; - - #define CHECK_DELETED() if (e->state & REDIS_LIBEVENT_DELETED) {\ - redisLibeventDestroy(e);\ - return; \ - } - - if ((event & EV_TIMEOUT) && (e->state & REDIS_LIBEVENT_DELETED) == 0) { - redisAsyncHandleTimeout(e->context); - CHECK_DELETED(); - } - - if ((event & EV_READ) && e->context && (e->state & REDIS_LIBEVENT_DELETED) == 0) { - redisAsyncHandleRead(e->context); - CHECK_DELETED(); - } - - if ((event & EV_WRITE) && e->context && (e->state & REDIS_LIBEVENT_DELETED) == 0) { - redisAsyncHandleWrite(e->context); - CHECK_DELETED(); - } - - e->state &= ~REDIS_LIBEVENT_ENTERED; - #undef CHECK_DELETED -} - -static void redisLibeventUpdate(void *privdata, short flag, int isRemove) { - redisLibeventEvents *e = (redisLibeventEvents *)privdata; - const struct timeval *tv = e->tv.tv_sec || e->tv.tv_usec ? &e->tv : NULL; - - if (isRemove) { - if ((e->flags & flag) == 0) { - return; - } else { - e->flags &= ~flag; - } - } else { - if (e->flags & flag) { - return; - } else { - e->flags |= flag; - } - } - - event_del(e->ev); - event_assign(e->ev, e->base, e->context->c.fd, e->flags | EV_PERSIST, - redisLibeventHandler, privdata); - event_add(e->ev, tv); -} - -static void redisLibeventAddRead(void *privdata) { - redisLibeventUpdate(privdata, EV_READ, 0); -} - -static void redisLibeventDelRead(void *privdata) { - redisLibeventUpdate(privdata, EV_READ, 1); -} - -static void redisLibeventAddWrite(void *privdata) { - redisLibeventUpdate(privdata, EV_WRITE, 0); -} - -static void redisLibeventDelWrite(void *privdata) { - redisLibeventUpdate(privdata, EV_WRITE, 1); -} - -static void redisLibeventCleanup(void *privdata) { - redisLibeventEvents *e = (redisLibeventEvents*)privdata; - if (!e) { - return; - } - event_del(e->ev); - event_free(e->ev); - e->ev = NULL; - - if (e->state & REDIS_LIBEVENT_ENTERED) { - e->state |= REDIS_LIBEVENT_DELETED; - } else { - redisLibeventDestroy(e); - } -} - -static void redisLibeventSetTimeout(void *privdata, struct timeval tv) { - redisLibeventEvents *e = (redisLibeventEvents *)privdata; - short flags = e->flags; - e->flags = 0; - e->tv = tv; - redisLibeventUpdate(e, flags, 0); -} - -static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) { - redisContext *c = &(ac->c); - redisLibeventEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisLibeventEvents*)hi_calloc(1, sizeof(*e)); - if (e == NULL) - return REDIS_ERR; - - e->context = ac; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisLibeventAddRead; - ac->ev.delRead = redisLibeventDelRead; - ac->ev.addWrite = redisLibeventAddWrite; - ac->ev.delWrite = redisLibeventDelWrite; - ac->ev.cleanup = redisLibeventCleanup; - ac->ev.scheduleTimer = redisLibeventSetTimeout; - ac->ev.data = e; - - /* Initialize and install read/write events */ - e->ev = event_new(base, c->fd, EV_READ | EV_WRITE, redisLibeventHandler, e); - e->base = base; - return REDIS_OK; -} -#endif diff --git a/ext/hiredis-1.0.2/adapters/libuv.h b/ext/hiredis-1.0.2/adapters/libuv.h deleted file mode 100644 index c120b1b39..000000000 --- a/ext/hiredis-1.0.2/adapters/libuv.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __HIREDIS_LIBUV_H__ -#define __HIREDIS_LIBUV_H__ -#include -#include -#include "../hiredis.h" -#include "../async.h" -#include - -typedef struct redisLibuvEvents { - redisAsyncContext* context; - uv_poll_t handle; - int events; -} redisLibuvEvents; - - -static void redisLibuvPoll(uv_poll_t* handle, int status, int events) { - redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - int ev = (status ? p->events : events); - - if (p->context != NULL && (ev & UV_READABLE)) { - redisAsyncHandleRead(p->context); - } - if (p->context != NULL && (ev & UV_WRITABLE)) { - redisAsyncHandleWrite(p->context); - } -} - - -static void redisLibuvAddRead(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->events |= UV_READABLE; - - uv_poll_start(&p->handle, p->events, redisLibuvPoll); -} - - -static void redisLibuvDelRead(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->events &= ~UV_READABLE; - - if (p->events) { - uv_poll_start(&p->handle, p->events, redisLibuvPoll); - } else { - uv_poll_stop(&p->handle); - } -} - - -static void redisLibuvAddWrite(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->events |= UV_WRITABLE; - - uv_poll_start(&p->handle, p->events, redisLibuvPoll); -} - - -static void redisLibuvDelWrite(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->events &= ~UV_WRITABLE; - - if (p->events) { - uv_poll_start(&p->handle, p->events, redisLibuvPoll); - } else { - uv_poll_stop(&p->handle); - } -} - - -static void on_close(uv_handle_t* handle) { - redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - - hi_free(p); -} - - -static void redisLibuvCleanup(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->context = NULL; // indicate that context might no longer exist - uv_close((uv_handle_t*)&p->handle, on_close); -} - - -static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) { - redisContext *c = &(ac->c); - - if (ac->ev.data != NULL) { - return REDIS_ERR; - } - - ac->ev.addRead = redisLibuvAddRead; - ac->ev.delRead = redisLibuvDelRead; - ac->ev.addWrite = redisLibuvAddWrite; - ac->ev.delWrite = redisLibuvDelWrite; - ac->ev.cleanup = redisLibuvCleanup; - - redisLibuvEvents* p = (redisLibuvEvents*)hi_malloc(sizeof(*p)); - if (p == NULL) - return REDIS_ERR; - - memset(p, 0, sizeof(*p)); - - if (uv_poll_init_socket(loop, &p->handle, c->fd) != 0) { - return REDIS_ERR; - } - - ac->ev.data = p; - p->handle.data = p; - p->context = ac; - - return REDIS_OK; -} -#endif diff --git a/ext/hiredis-1.0.2/adapters/macosx.h b/ext/hiredis-1.0.2/adapters/macosx.h deleted file mode 100644 index 3c87f1b2f..000000000 --- a/ext/hiredis-1.0.2/adapters/macosx.h +++ /dev/null @@ -1,115 +0,0 @@ -// -// Created by Дмитрий Бахвалов on 13.07.15. -// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. -// - -#ifndef __HIREDIS_MACOSX_H__ -#define __HIREDIS_MACOSX_H__ - -#include - -#include "../hiredis.h" -#include "../async.h" - -typedef struct { - redisAsyncContext *context; - CFSocketRef socketRef; - CFRunLoopSourceRef sourceRef; -} RedisRunLoop; - -static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) { - if( redisRunLoop != NULL ) { - if( redisRunLoop->sourceRef != NULL ) { - CFRunLoopSourceInvalidate(redisRunLoop->sourceRef); - CFRelease(redisRunLoop->sourceRef); - } - if( redisRunLoop->socketRef != NULL ) { - CFSocketInvalidate(redisRunLoop->socketRef); - CFRelease(redisRunLoop->socketRef); - } - hi_free(redisRunLoop); - } - return REDIS_ERR; -} - -static void redisMacOSAddRead(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack); -} - -static void redisMacOSDelRead(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack); -} - -static void redisMacOSAddWrite(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack); -} - -static void redisMacOSDelWrite(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack); -} - -static void redisMacOSCleanup(void *privdata) { - RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; - freeRedisRunLoop(redisRunLoop); -} - -static void redisMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) { - redisAsyncContext* context = (redisAsyncContext*) info; - - switch (callbackType) { - case kCFSocketReadCallBack: - redisAsyncHandleRead(context); - break; - - case kCFSocketWriteCallBack: - redisAsyncHandleWrite(context); - break; - - default: - break; - } -} - -static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLoop) { - redisContext *redisCtx = &(redisAsyncCtx->c); - - /* Nothing should be attached when something is already attached */ - if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR; - - RedisRunLoop* redisRunLoop = (RedisRunLoop*) hi_calloc(1, sizeof(RedisRunLoop)); - if (redisRunLoop == NULL) - return REDIS_ERR; - - /* Setup redis stuff */ - redisRunLoop->context = redisAsyncCtx; - - redisAsyncCtx->ev.addRead = redisMacOSAddRead; - redisAsyncCtx->ev.delRead = redisMacOSDelRead; - redisAsyncCtx->ev.addWrite = redisMacOSAddWrite; - redisAsyncCtx->ev.delWrite = redisMacOSDelWrite; - redisAsyncCtx->ev.cleanup = redisMacOSCleanup; - redisAsyncCtx->ev.data = redisRunLoop; - - /* Initialize and install read/write events */ - CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL }; - - redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd, - kCFSocketReadCallBack | kCFSocketWriteCallBack, - redisMacOSAsyncCallback, - &socketCtx); - if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop); - - redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redisRunLoop->socketRef, 0); - if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop); - - CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, kCFRunLoopDefaultMode); - - return REDIS_OK; -} - -#endif - diff --git a/ext/hiredis-1.0.2/adapters/qt.h b/ext/hiredis-1.0.2/adapters/qt.h deleted file mode 100644 index 5cc02e6ce..000000000 --- a/ext/hiredis-1.0.2/adapters/qt.h +++ /dev/null @@ -1,135 +0,0 @@ -/*- - * Copyright (C) 2014 Pietro Cerutti - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef __HIREDIS_QT_H__ -#define __HIREDIS_QT_H__ -#include -#include "../async.h" - -static void RedisQtAddRead(void *); -static void RedisQtDelRead(void *); -static void RedisQtAddWrite(void *); -static void RedisQtDelWrite(void *); -static void RedisQtCleanup(void *); - -class RedisQtAdapter : public QObject { - - Q_OBJECT - - friend - void RedisQtAddRead(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->addRead(); - } - - friend - void RedisQtDelRead(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->delRead(); - } - - friend - void RedisQtAddWrite(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->addWrite(); - } - - friend - void RedisQtDelWrite(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->delWrite(); - } - - friend - void RedisQtCleanup(void * adapter) { - RedisQtAdapter * a = static_cast(adapter); - a->cleanup(); - } - - public: - RedisQtAdapter(QObject * parent = 0) - : QObject(parent), m_ctx(0), m_read(0), m_write(0) { } - - ~RedisQtAdapter() { - if (m_ctx != 0) { - m_ctx->ev.data = NULL; - } - } - - int setContext(redisAsyncContext * ac) { - if (ac->ev.data != NULL) { - return REDIS_ERR; - } - m_ctx = ac; - m_ctx->ev.data = this; - m_ctx->ev.addRead = RedisQtAddRead; - m_ctx->ev.delRead = RedisQtDelRead; - m_ctx->ev.addWrite = RedisQtAddWrite; - m_ctx->ev.delWrite = RedisQtDelWrite; - m_ctx->ev.cleanup = RedisQtCleanup; - return REDIS_OK; - } - - private: - void addRead() { - if (m_read) return; - m_read = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Read, 0); - connect(m_read, SIGNAL(activated(int)), this, SLOT(read())); - } - - void delRead() { - if (!m_read) return; - delete m_read; - m_read = 0; - } - - void addWrite() { - if (m_write) return; - m_write = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Write, 0); - connect(m_write, SIGNAL(activated(int)), this, SLOT(write())); - } - - void delWrite() { - if (!m_write) return; - delete m_write; - m_write = 0; - } - - void cleanup() { - delRead(); - delWrite(); - } - - private slots: - void read() { redisAsyncHandleRead(m_ctx); } - void write() { redisAsyncHandleWrite(m_ctx); } - - private: - redisAsyncContext * m_ctx; - QSocketNotifier * m_read; - QSocketNotifier * m_write; -}; - -#endif /* !__HIREDIS_QT_H__ */ diff --git a/ext/hiredis-1.0.2/alloc.c b/ext/hiredis-1.0.2/alloc.c deleted file mode 100644 index 7fb6b35e7..000000000 --- a/ext/hiredis-1.0.2/alloc.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2020, Michael Grunder - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include "alloc.h" -#include -#include - -hiredisAllocFuncs hiredisAllocFns = { - .mallocFn = malloc, - .callocFn = calloc, - .reallocFn = realloc, - .strdupFn = strdup, - .freeFn = free, -}; - -/* Override hiredis' allocators with ones supplied by the user */ -hiredisAllocFuncs hiredisSetAllocators(hiredisAllocFuncs *override) { - hiredisAllocFuncs orig = hiredisAllocFns; - - hiredisAllocFns = *override; - - return orig; -} - -/* Reset allocators to use libc defaults */ -void hiredisResetAllocators(void) { - hiredisAllocFns = (hiredisAllocFuncs) { - .mallocFn = malloc, - .callocFn = calloc, - .reallocFn = realloc, - .strdupFn = strdup, - .freeFn = free, - }; -} - -#ifdef _WIN32 - -void *hi_malloc(size_t size) { - return hiredisAllocFns.mallocFn(size); -} - -void *hi_calloc(size_t nmemb, size_t size) { - return hiredisAllocFns.callocFn(nmemb, size); -} - -void *hi_realloc(void *ptr, size_t size) { - return hiredisAllocFns.reallocFn(ptr, size); -} - -char *hi_strdup(const char *str) { - return hiredisAllocFns.strdupFn(str); -} - -void hi_free(void *ptr) { - hiredisAllocFns.freeFn(ptr); -} - -#endif diff --git a/ext/hiredis-1.0.2/alloc.h b/ext/hiredis-1.0.2/alloc.h deleted file mode 100644 index 34a05f49f..000000000 --- a/ext/hiredis-1.0.2/alloc.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2020, Michael Grunder - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HIREDIS_ALLOC_H -#define HIREDIS_ALLOC_H - -#include /* for size_t */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Structure pointing to our actually configured allocators */ -typedef struct hiredisAllocFuncs { - void *(*mallocFn)(size_t); - void *(*callocFn)(size_t,size_t); - void *(*reallocFn)(void*,size_t); - char *(*strdupFn)(const char*); - void (*freeFn)(void*); -} hiredisAllocFuncs; - -hiredisAllocFuncs hiredisSetAllocators(hiredisAllocFuncs *ha); -void hiredisResetAllocators(void); - -#ifndef _WIN32 - -/* Hiredis' configured allocator function pointer struct */ -extern hiredisAllocFuncs hiredisAllocFns; - -static inline void *hi_malloc(size_t size) { - return hiredisAllocFns.mallocFn(size); -} - -static inline void *hi_calloc(size_t nmemb, size_t size) { - return hiredisAllocFns.callocFn(nmemb, size); -} - -static inline void *hi_realloc(void *ptr, size_t size) { - return hiredisAllocFns.reallocFn(ptr, size); -} - -static inline char *hi_strdup(const char *str) { - return hiredisAllocFns.strdupFn(str); -} - -static inline void hi_free(void *ptr) { - hiredisAllocFns.freeFn(ptr); -} - -#else - -void *hi_malloc(size_t size); -void *hi_calloc(size_t nmemb, size_t size); -void *hi_realloc(void *ptr, size_t size); -char *hi_strdup(const char *str); -void hi_free(void *ptr); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* HIREDIS_ALLOC_H */ diff --git a/ext/hiredis-1.0.2/appveyor.yml b/ext/hiredis-1.0.2/appveyor.yml deleted file mode 100644 index 5b43fdbeb..000000000 --- a/ext/hiredis-1.0.2/appveyor.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Appveyor configuration file for CI build of hiredis on Windows (under Cygwin) -environment: - matrix: - - CYG_BASH: C:\cygwin64\bin\bash - CC: gcc - - CYG_BASH: C:\cygwin\bin\bash - CC: gcc - CFLAGS: -m32 - CXXFLAGS: -m32 - LDFLAGS: -m32 - -clone_depth: 1 - -# Attempt to ensure we don't try to convert line endings to Win32 CRLF as this will cause build to fail -init: - - git config --global core.autocrlf input - -# Install needed build dependencies -install: - - '%CYG_BASH% -lc "cygcheck -dc cygwin"' - -build_script: - - 'echo building...' - - '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include "alloc.h" -#include -#include -#ifndef _MSC_VER -#include -#endif -#include -#include -#include -#include "async.h" -#include "net.h" -#include "dict.c" -#include "sds.h" -#include "win32.h" - -#include "async_private.h" - -/* Forward declarations of hiredis.c functions */ -int __redisAppendCommand(redisContext *c, const char *cmd, size_t len); -void __redisSetError(redisContext *c, int type, const char *str); - -/* Functions managing dictionary of callbacks for pub/sub. */ -static unsigned int callbackHash(const void *key) { - return dictGenHashFunction((const unsigned char *)key, - sdslen((const sds)key)); -} - -static void *callbackValDup(void *privdata, const void *src) { - ((void) privdata); - redisCallback *dup; - - dup = hi_malloc(sizeof(*dup)); - if (dup == NULL) - return NULL; - - memcpy(dup,src,sizeof(*dup)); - return dup; -} - -static int callbackKeyCompare(void *privdata, const void *key1, const void *key2) { - int l1, l2; - ((void) privdata); - - l1 = sdslen((const sds)key1); - l2 = sdslen((const sds)key2); - if (l1 != l2) return 0; - return memcmp(key1,key2,l1) == 0; -} - -static void callbackKeyDestructor(void *privdata, void *key) { - ((void) privdata); - sdsfree((sds)key); -} - -static void callbackValDestructor(void *privdata, void *val) { - ((void) privdata); - hi_free(val); -} - -static dictType callbackDict = { - callbackHash, - NULL, - callbackValDup, - callbackKeyCompare, - callbackKeyDestructor, - callbackValDestructor -}; - -static redisAsyncContext *redisAsyncInitialize(redisContext *c) { - redisAsyncContext *ac; - dict *channels = NULL, *patterns = NULL; - - channels = dictCreate(&callbackDict,NULL); - if (channels == NULL) - goto oom; - - patterns = dictCreate(&callbackDict,NULL); - if (patterns == NULL) - goto oom; - - ac = hi_realloc(c,sizeof(redisAsyncContext)); - if (ac == NULL) - goto oom; - - c = &(ac->c); - - /* The regular connect functions will always set the flag REDIS_CONNECTED. - * For the async API, we want to wait until the first write event is - * received up before setting this flag, so reset it here. */ - c->flags &= ~REDIS_CONNECTED; - - ac->err = 0; - ac->errstr = NULL; - ac->data = NULL; - ac->dataCleanup = NULL; - - ac->ev.data = NULL; - ac->ev.addRead = NULL; - ac->ev.delRead = NULL; - ac->ev.addWrite = NULL; - ac->ev.delWrite = NULL; - ac->ev.cleanup = NULL; - ac->ev.scheduleTimer = NULL; - - ac->onConnect = NULL; - ac->onDisconnect = NULL; - - ac->replies.head = NULL; - ac->replies.tail = NULL; - ac->sub.invalid.head = NULL; - ac->sub.invalid.tail = NULL; - ac->sub.channels = channels; - ac->sub.patterns = patterns; - - return ac; -oom: - if (channels) dictRelease(channels); - if (patterns) dictRelease(patterns); - return NULL; -} - -/* We want the error field to be accessible directly instead of requiring - * an indirection to the redisContext struct. */ -static void __redisAsyncCopyError(redisAsyncContext *ac) { - if (!ac) - return; - - redisContext *c = &(ac->c); - ac->err = c->err; - ac->errstr = c->errstr; -} - -redisAsyncContext *redisAsyncConnectWithOptions(const redisOptions *options) { - redisOptions myOptions = *options; - redisContext *c; - redisAsyncContext *ac; - - /* Clear any erroneously set sync callback and flag that we don't want to - * use freeReplyObject by default. */ - myOptions.push_cb = NULL; - myOptions.options |= REDIS_OPT_NO_PUSH_AUTOFREE; - - myOptions.options |= REDIS_OPT_NONBLOCK; - c = redisConnectWithOptions(&myOptions); - if (c == NULL) { - return NULL; - } - - ac = redisAsyncInitialize(c); - if (ac == NULL) { - redisFree(c); - return NULL; - } - - /* Set any configured async push handler */ - redisAsyncSetPushCallback(ac, myOptions.async_push_cb); - - __redisAsyncCopyError(ac); - return ac; -} - -redisAsyncContext *redisAsyncConnect(const char *ip, int port) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, ip, port); - return redisAsyncConnectWithOptions(&options); -} - -redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, - const char *source_addr) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, ip, port); - options.endpoint.tcp.source_addr = source_addr; - return redisAsyncConnectWithOptions(&options); -} - -redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port, - const char *source_addr) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, ip, port); - options.options |= REDIS_OPT_REUSEADDR; - options.endpoint.tcp.source_addr = source_addr; - return redisAsyncConnectWithOptions(&options); -} - -redisAsyncContext *redisAsyncConnectUnix(const char *path) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_UNIX(&options, path); - return redisAsyncConnectWithOptions(&options); -} - -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) { - if (ac->onConnect == NULL) { - ac->onConnect = fn; - - /* The common way to detect an established connection is to wait for - * the first write event to be fired. This assumes the related event - * library functions are already set. */ - _EL_ADD_WRITE(ac); - return REDIS_OK; - } - return REDIS_ERR; -} - -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn) { - if (ac->onDisconnect == NULL) { - ac->onDisconnect = fn; - return REDIS_OK; - } - return REDIS_ERR; -} - -/* Helper functions to push/shift callbacks */ -static int __redisPushCallback(redisCallbackList *list, redisCallback *source) { - redisCallback *cb; - - /* Copy callback from stack to heap */ - cb = hi_malloc(sizeof(*cb)); - if (cb == NULL) - return REDIS_ERR_OOM; - - if (source != NULL) { - memcpy(cb,source,sizeof(*cb)); - cb->next = NULL; - } - - /* Store callback in list */ - if (list->head == NULL) - list->head = cb; - if (list->tail != NULL) - list->tail->next = cb; - list->tail = cb; - return REDIS_OK; -} - -static int __redisShiftCallback(redisCallbackList *list, redisCallback *target) { - redisCallback *cb = list->head; - if (cb != NULL) { - list->head = cb->next; - if (cb == list->tail) - list->tail = NULL; - - /* Copy callback from heap to stack */ - if (target != NULL) - memcpy(target,cb,sizeof(*cb)); - hi_free(cb); - return REDIS_OK; - } - return REDIS_ERR; -} - -static void __redisRunCallback(redisAsyncContext *ac, redisCallback *cb, redisReply *reply) { - redisContext *c = &(ac->c); - if (cb->fn != NULL) { - c->flags |= REDIS_IN_CALLBACK; - cb->fn(ac,reply,cb->privdata); - c->flags &= ~REDIS_IN_CALLBACK; - } -} - -static void __redisRunPushCallback(redisAsyncContext *ac, redisReply *reply) { - if (ac->push_cb != NULL) { - ac->c.flags |= REDIS_IN_CALLBACK; - ac->push_cb(ac, reply); - ac->c.flags &= ~REDIS_IN_CALLBACK; - } -} - -/* Helper function to free the context. */ -static void __redisAsyncFree(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisCallback cb; - dictIterator *it; - dictEntry *de; - - /* Execute pending callbacks with NULL reply. */ - while (__redisShiftCallback(&ac->replies,&cb) == REDIS_OK) - __redisRunCallback(ac,&cb,NULL); - - /* Execute callbacks for invalid commands */ - while (__redisShiftCallback(&ac->sub.invalid,&cb) == REDIS_OK) - __redisRunCallback(ac,&cb,NULL); - - /* Run subscription callbacks with NULL reply */ - if (ac->sub.channels) { - it = dictGetIterator(ac->sub.channels); - if (it != NULL) { - while ((de = dictNext(it)) != NULL) - __redisRunCallback(ac,dictGetEntryVal(de),NULL); - dictReleaseIterator(it); - } - - dictRelease(ac->sub.channels); - } - - if (ac->sub.patterns) { - it = dictGetIterator(ac->sub.patterns); - if (it != NULL) { - while ((de = dictNext(it)) != NULL) - __redisRunCallback(ac,dictGetEntryVal(de),NULL); - dictReleaseIterator(it); - } - - dictRelease(ac->sub.patterns); - } - - /* Signal event lib to clean up */ - _EL_CLEANUP(ac); - - /* Execute disconnect callback. When redisAsyncFree() initiated destroying - * this context, the status will always be REDIS_OK. */ - if (ac->onDisconnect && (c->flags & REDIS_CONNECTED)) { - if (c->flags & REDIS_FREEING) { - ac->onDisconnect(ac,REDIS_OK); - } else { - ac->onDisconnect(ac,(ac->err == 0) ? REDIS_OK : REDIS_ERR); - } - } - - if (ac->dataCleanup) { - ac->dataCleanup(ac->data); - } - - /* Cleanup self */ - redisFree(c); -} - -/* Free the async context. When this function is called from a callback, - * control needs to be returned to redisProcessCallbacks() before actual - * free'ing. To do so, a flag is set on the context which is picked up by - * redisProcessCallbacks(). Otherwise, the context is immediately free'd. */ -void redisAsyncFree(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - c->flags |= REDIS_FREEING; - if (!(c->flags & REDIS_IN_CALLBACK)) - __redisAsyncFree(ac); -} - -/* Helper function to make the disconnect happen and clean up. */ -void __redisAsyncDisconnect(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - /* Make sure error is accessible if there is any */ - __redisAsyncCopyError(ac); - - if (ac->err == 0) { - /* For clean disconnects, there should be no pending callbacks. */ - int ret = __redisShiftCallback(&ac->replies,NULL); - assert(ret == REDIS_ERR); - } else { - /* Disconnection is caused by an error, make sure that pending - * callbacks cannot call new commands. */ - c->flags |= REDIS_DISCONNECTING; - } - - /* cleanup event library on disconnect. - * this is safe to call multiple times */ - _EL_CLEANUP(ac); - - /* For non-clean disconnects, __redisAsyncFree() will execute pending - * callbacks with a NULL-reply. */ - if (!(c->flags & REDIS_NO_AUTO_FREE)) { - __redisAsyncFree(ac); - } -} - -/* Tries to do a clean disconnect from Redis, meaning it stops new commands - * from being issued, but tries to flush the output buffer and execute - * callbacks for all remaining replies. When this function is called from a - * callback, there might be more replies and we can safely defer disconnecting - * to redisProcessCallbacks(). Otherwise, we can only disconnect immediately - * when there are no pending callbacks. */ -void redisAsyncDisconnect(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - c->flags |= REDIS_DISCONNECTING; - - /** unset the auto-free flag here, because disconnect undoes this */ - c->flags &= ~REDIS_NO_AUTO_FREE; - if (!(c->flags & REDIS_IN_CALLBACK) && ac->replies.head == NULL) - __redisAsyncDisconnect(ac); -} - -static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, redisCallback *dstcb) { - redisContext *c = &(ac->c); - dict *callbacks; - redisCallback *cb; - dictEntry *de; - int pvariant; - char *stype; - sds sname; - - /* Custom reply functions are not supported for pub/sub. This will fail - * very hard when they are used... */ - if (reply->type == REDIS_REPLY_ARRAY || reply->type == REDIS_REPLY_PUSH) { - assert(reply->elements >= 2); - assert(reply->element[0]->type == REDIS_REPLY_STRING); - stype = reply->element[0]->str; - pvariant = (tolower(stype[0]) == 'p') ? 1 : 0; - - if (pvariant) - callbacks = ac->sub.patterns; - else - callbacks = ac->sub.channels; - - /* Locate the right callback */ - assert(reply->element[1]->type == REDIS_REPLY_STRING); - sname = sdsnewlen(reply->element[1]->str,reply->element[1]->len); - if (sname == NULL) - goto oom; - - de = dictFind(callbacks,sname); - if (de != NULL) { - cb = dictGetEntryVal(de); - - /* If this is an subscribe reply decrease pending counter. */ - if (strcasecmp(stype+pvariant,"subscribe") == 0) { - cb->pending_subs -= 1; - } - - memcpy(dstcb,cb,sizeof(*dstcb)); - - /* If this is an unsubscribe message, remove it. */ - if (strcasecmp(stype+pvariant,"unsubscribe") == 0) { - if (cb->pending_subs == 0) - dictDelete(callbacks,sname); - - /* If this was the last unsubscribe message, revert to - * non-subscribe mode. */ - assert(reply->element[2]->type == REDIS_REPLY_INTEGER); - - /* Unset subscribed flag only when no pipelined pending subscribe. */ - if (reply->element[2]->integer == 0 - && dictSize(ac->sub.channels) == 0 - && dictSize(ac->sub.patterns) == 0) - c->flags &= ~REDIS_SUBSCRIBED; - } - } - sdsfree(sname); - } else { - /* Shift callback for invalid commands. */ - __redisShiftCallback(&ac->sub.invalid,dstcb); - } - return REDIS_OK; -oom: - __redisSetError(&(ac->c), REDIS_ERR_OOM, "Out of memory"); - return REDIS_ERR; -} - -#define redisIsSpontaneousPushReply(r) \ - (redisIsPushReply(r) && !redisIsSubscribeReply(r)) - -static int redisIsSubscribeReply(redisReply *reply) { - char *str; - size_t len, off; - - /* We will always have at least one string with the subscribe/message type */ - if (reply->elements < 1 || reply->element[0]->type != REDIS_REPLY_STRING || - reply->element[0]->len < sizeof("message") - 1) - { - return 0; - } - - /* Get the string/len moving past 'p' if needed */ - off = tolower(reply->element[0]->str[0]) == 'p'; - str = reply->element[0]->str + off; - len = reply->element[0]->len - off; - - return !strncasecmp(str, "subscribe", len) || - !strncasecmp(str, "message", len); - -} - -void redisProcessCallbacks(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisCallback cb = {NULL, NULL, 0, NULL}; - void *reply = NULL; - int status; - - while((status = redisGetReply(c,&reply)) == REDIS_OK) { - if (reply == NULL) { - /* When the connection is being disconnected and there are - * no more replies, this is the cue to really disconnect. */ - if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0 - && ac->replies.head == NULL) { - __redisAsyncDisconnect(ac); - return; - } - - /* If monitor mode, repush callback */ - if(c->flags & REDIS_MONITORING) { - __redisPushCallback(&ac->replies,&cb); - } - - /* When the connection is not being disconnected, simply stop - * trying to get replies and wait for the next loop tick. */ - break; - } - - /* Send any non-subscribe related PUSH messages to our PUSH handler - * while allowing subscribe related PUSH messages to pass through. - * This allows existing code to be backward compatible and work in - * either RESP2 or RESP3 mode. */ - if (redisIsSpontaneousPushReply(reply)) { - __redisRunPushCallback(ac, reply); - c->reader->fn->freeObject(reply); - continue; - } - - /* Even if the context is subscribed, pending regular - * callbacks will get a reply before pub/sub messages arrive. */ - if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) { - /* - * A spontaneous reply in a not-subscribed context can be the error - * reply that is sent when a new connection exceeds the maximum - * number of allowed connections on the server side. - * - * This is seen as an error instead of a regular reply because the - * server closes the connection after sending it. - * - * To prevent the error from being overwritten by an EOF error the - * connection is closed here. See issue #43. - * - * Another possibility is that the server is loading its dataset. - * In this case we also want to close the connection, and have the - * user wait until the server is ready to take our request. - */ - if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) { - c->err = REDIS_ERR_OTHER; - snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str); - c->reader->fn->freeObject(reply); - __redisAsyncDisconnect(ac); - return; - } - /* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */ - assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING)); - if(c->flags & REDIS_SUBSCRIBED) - __redisGetSubscribeCallback(ac,reply,&cb); - } - - if (cb.fn != NULL) { - __redisRunCallback(ac,&cb,reply); - c->reader->fn->freeObject(reply); - - /* Proceed with free'ing when redisAsyncFree() was called. */ - if (c->flags & REDIS_FREEING) { - __redisAsyncFree(ac); - return; - } - } else { - /* No callback for this reply. This can either be a NULL callback, - * or there were no callbacks to begin with. Either way, don't - * abort with an error, but simply ignore it because the client - * doesn't know what the server will spit out over the wire. */ - c->reader->fn->freeObject(reply); - } - } - - /* Disconnect when there was an error reading the reply */ - if (status != REDIS_OK) - __redisAsyncDisconnect(ac); -} - -static void __redisAsyncHandleConnectFailure(redisAsyncContext *ac) { - if (ac->onConnect) ac->onConnect(ac, REDIS_ERR); - __redisAsyncDisconnect(ac); -} - -/* Internal helper function to detect socket status the first time a read or - * write event fires. When connecting was not successful, the connect callback - * is called with a REDIS_ERR status and the context is free'd. */ -static int __redisAsyncHandleConnect(redisAsyncContext *ac) { - int completed = 0; - redisContext *c = &(ac->c); - - if (redisCheckConnectDone(c, &completed) == REDIS_ERR) { - /* Error! */ - redisCheckSocketError(c); - __redisAsyncHandleConnectFailure(ac); - return REDIS_ERR; - } else if (completed == 1) { - /* connected! */ - if (c->connection_type == REDIS_CONN_TCP && - redisSetTcpNoDelay(c) == REDIS_ERR) { - __redisAsyncHandleConnectFailure(ac); - return REDIS_ERR; - } - - if (ac->onConnect) ac->onConnect(ac, REDIS_OK); - c->flags |= REDIS_CONNECTED; - return REDIS_OK; - } else { - return REDIS_OK; - } -} - -void redisAsyncRead(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - if (redisBufferRead(c) == REDIS_ERR) { - __redisAsyncDisconnect(ac); - } else { - /* Always re-schedule reads */ - _EL_ADD_READ(ac); - redisProcessCallbacks(ac); - } -} - -/* This function should be called when the socket is readable. - * It processes all replies that can be read and executes their callbacks. - */ -void redisAsyncHandleRead(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - if (!(c->flags & REDIS_CONNECTED)) { - /* Abort connect was not successful. */ - if (__redisAsyncHandleConnect(ac) != REDIS_OK) - return; - /* Try again later when the context is still not connected. */ - if (!(c->flags & REDIS_CONNECTED)) - return; - } - - c->funcs->async_read(ac); -} - -void redisAsyncWrite(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - int done = 0; - - if (redisBufferWrite(c,&done) == REDIS_ERR) { - __redisAsyncDisconnect(ac); - } else { - /* Continue writing when not done, stop writing otherwise */ - if (!done) - _EL_ADD_WRITE(ac); - else - _EL_DEL_WRITE(ac); - - /* Always schedule reads after writes */ - _EL_ADD_READ(ac); - } -} - -void redisAsyncHandleWrite(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - - if (!(c->flags & REDIS_CONNECTED)) { - /* Abort connect was not successful. */ - if (__redisAsyncHandleConnect(ac) != REDIS_OK) - return; - /* Try again later when the context is still not connected. */ - if (!(c->flags & REDIS_CONNECTED)) - return; - } - - c->funcs->async_write(ac); -} - -void redisAsyncHandleTimeout(redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisCallback cb; - - if ((c->flags & REDIS_CONNECTED) && ac->replies.head == NULL) { - /* Nothing to do - just an idle timeout */ - return; - } - - if (!c->err) { - __redisSetError(c, REDIS_ERR_TIMEOUT, "Timeout"); - } - - if (!(c->flags & REDIS_CONNECTED) && ac->onConnect) { - ac->onConnect(ac, REDIS_ERR); - } - - while (__redisShiftCallback(&ac->replies, &cb) == REDIS_OK) { - __redisRunCallback(ac, &cb, NULL); - } - - /** - * TODO: Don't automatically sever the connection, - * rather, allow to ignore responses before the queue is clear - */ - __redisAsyncDisconnect(ac); -} - -/* Sets a pointer to the first argument and its length starting at p. Returns - * the number of bytes to skip to get to the following argument. */ -static const char *nextArgument(const char *start, const char **str, size_t *len) { - const char *p = start; - if (p[0] != '$') { - p = strchr(p,'$'); - if (p == NULL) return NULL; - } - - *len = (int)strtol(p+1,NULL,10); - p = strchr(p,'\r'); - assert(p); - *str = p+2; - return p+2+(*len)+2; -} - -/* Helper function for the redisAsyncCommand* family of functions. Writes a - * formatted command to the output buffer and registers the provided callback - * function with the context. */ -static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len) { - redisContext *c = &(ac->c); - redisCallback cb; - struct dict *cbdict; - dictEntry *de; - redisCallback *existcb; - int pvariant, hasnext; - const char *cstr, *astr; - size_t clen, alen; - const char *p; - sds sname; - int ret; - - /* Don't accept new commands when the connection is about to be closed. */ - if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR; - - /* Setup callback */ - cb.fn = fn; - cb.privdata = privdata; - cb.pending_subs = 1; - - /* Find out which command will be appended. */ - p = nextArgument(cmd,&cstr,&clen); - assert(p != NULL); - hasnext = (p[0] == '$'); - pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0; - cstr += pvariant; - clen -= pvariant; - - if (hasnext && strncasecmp(cstr,"subscribe\r\n",11) == 0) { - c->flags |= REDIS_SUBSCRIBED; - - /* Add every channel/pattern to the list of subscription callbacks. */ - while ((p = nextArgument(p,&astr,&alen)) != NULL) { - sname = sdsnewlen(astr,alen); - if (sname == NULL) - goto oom; - - if (pvariant) - cbdict = ac->sub.patterns; - else - cbdict = ac->sub.channels; - - de = dictFind(cbdict,sname); - - if (de != NULL) { - existcb = dictGetEntryVal(de); - cb.pending_subs = existcb->pending_subs + 1; - } - - ret = dictReplace(cbdict,sname,&cb); - - if (ret == 0) sdsfree(sname); - } - } else if (strncasecmp(cstr,"unsubscribe\r\n",13) == 0) { - /* It is only useful to call (P)UNSUBSCRIBE when the context is - * subscribed to one or more channels or patterns. */ - if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR; - - /* (P)UNSUBSCRIBE does not have its own response: every channel or - * pattern that is unsubscribed will receive a message. This means we - * should not append a callback function for this command. */ - } else if(strncasecmp(cstr,"monitor\r\n",9) == 0) { - /* Set monitor flag and push callback */ - c->flags |= REDIS_MONITORING; - __redisPushCallback(&ac->replies,&cb); - } else { - if (c->flags & REDIS_SUBSCRIBED) - /* This will likely result in an error reply, but it needs to be - * received and passed to the callback. */ - __redisPushCallback(&ac->sub.invalid,&cb); - else - __redisPushCallback(&ac->replies,&cb); - } - - __redisAppendCommand(c,cmd,len); - - /* Always schedule a write when the write buffer is non-empty */ - _EL_ADD_WRITE(ac); - - return REDIS_OK; -oom: - __redisSetError(&(ac->c), REDIS_ERR_OOM, "Out of memory"); - return REDIS_ERR; -} - -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap) { - char *cmd; - int len; - int status; - len = redisvFormatCommand(&cmd,format,ap); - - /* We don't want to pass -1 or -2 to future functions as a length. */ - if (len < 0) - return REDIS_ERR; - - status = __redisAsyncCommand(ac,fn,privdata,cmd,len); - hi_free(cmd); - return status; -} - -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...) { - va_list ap; - int status; - va_start(ap,format); - status = redisvAsyncCommand(ac,fn,privdata,format,ap); - va_end(ap); - return status; -} - -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen) { - sds cmd; - int len; - int status; - len = redisFormatSdsCommandArgv(&cmd,argc,argv,argvlen); - if (len < 0) - return REDIS_ERR; - status = __redisAsyncCommand(ac,fn,privdata,cmd,len); - sdsfree(cmd); - return status; -} - -int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len) { - int status = __redisAsyncCommand(ac,fn,privdata,cmd,len); - return status; -} - -redisAsyncPushFn *redisAsyncSetPushCallback(redisAsyncContext *ac, redisAsyncPushFn *fn) { - redisAsyncPushFn *old = ac->push_cb; - ac->push_cb = fn; - return old; -} - -int redisAsyncSetTimeout(redisAsyncContext *ac, struct timeval tv) { - if (!ac->c.command_timeout) { - ac->c.command_timeout = hi_calloc(1, sizeof(tv)); - if (ac->c.command_timeout == NULL) { - __redisSetError(&ac->c, REDIS_ERR_OOM, "Out of memory"); - __redisAsyncCopyError(ac); - return REDIS_ERR; - } - } - - if (tv.tv_sec != ac->c.command_timeout->tv_sec || - tv.tv_usec != ac->c.command_timeout->tv_usec) - { - *ac->c.command_timeout = tv; - } - - return REDIS_OK; -} diff --git a/ext/hiredis-1.0.2/async.h b/ext/hiredis-1.0.2/async.h deleted file mode 100644 index b1d2cb263..000000000 --- a/ext/hiredis-1.0.2/async.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_ASYNC_H -#define __HIREDIS_ASYNC_H -#include "hiredis.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ -struct dict; /* dictionary header is included in async.c */ - -/* Reply callback prototype and container */ -typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); -typedef struct redisCallback { - struct redisCallback *next; /* simple singly linked list */ - redisCallbackFn *fn; - int pending_subs; - void *privdata; -} redisCallback; - -/* List of callbacks for either regular replies or pub/sub */ -typedef struct redisCallbackList { - redisCallback *head, *tail; -} redisCallbackList; - -/* Connection callback prototypes */ -typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); -typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); -typedef void(redisTimerCallback)(void *timer, void *privdata); - -/* Context for an async connection to Redis */ -typedef struct redisAsyncContext { - /* Hold the regular context, so it can be realloc'ed. */ - redisContext c; - - /* Setup error flags so they can be used directly. */ - int err; - char *errstr; - - /* Not used by hiredis */ - void *data; - void (*dataCleanup)(void *privdata); - - /* Event library data and hooks */ - struct { - void *data; - - /* Hooks that are called when the library expects to start - * reading/writing. These functions should be idempotent. */ - void (*addRead)(void *privdata); - void (*delRead)(void *privdata); - void (*addWrite)(void *privdata); - void (*delWrite)(void *privdata); - void (*cleanup)(void *privdata); - void (*scheduleTimer)(void *privdata, struct timeval tv); - } ev; - - /* Called when either the connection is terminated due to an error or per - * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */ - redisDisconnectCallback *onDisconnect; - - /* Called when the first write event was received. */ - redisConnectCallback *onConnect; - - /* Regular command callbacks */ - redisCallbackList replies; - - /* Address used for connect() */ - struct sockaddr *saddr; - size_t addrlen; - - /* Subscription callbacks */ - struct { - redisCallbackList invalid; - struct dict *channels; - struct dict *patterns; - } sub; - - /* Any configured RESP3 PUSH handler */ - redisAsyncPushFn *push_cb; -} redisAsyncContext; - -/* Functions that proxy to hiredis */ -redisAsyncContext *redisAsyncConnectWithOptions(const redisOptions *options); -redisAsyncContext *redisAsyncConnect(const char *ip, int port); -redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr); -redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port, - const char *source_addr); -redisAsyncContext *redisAsyncConnectUnix(const char *path); -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); - -redisAsyncPushFn *redisAsyncSetPushCallback(redisAsyncContext *ac, redisAsyncPushFn *fn); -int redisAsyncSetTimeout(redisAsyncContext *ac, struct timeval tv); -void redisAsyncDisconnect(redisAsyncContext *ac); -void redisAsyncFree(redisAsyncContext *ac); - -/* Handle read/write events */ -void redisAsyncHandleRead(redisAsyncContext *ac); -void redisAsyncHandleWrite(redisAsyncContext *ac); -void redisAsyncHandleTimeout(redisAsyncContext *ac); -void redisAsyncRead(redisAsyncContext *ac); -void redisAsyncWrite(redisAsyncContext *ac); - -/* Command functions for an async context. Write the command to the - * output buffer and register the provided callback. */ -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); -int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-1.0.2/async_private.h b/ext/hiredis-1.0.2/async_private.h deleted file mode 100644 index b9d23fffd..000000000 --- a/ext/hiredis-1.0.2/async_private.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_ASYNC_PRIVATE_H -#define __HIREDIS_ASYNC_PRIVATE_H - -#define _EL_ADD_READ(ctx) \ - do { \ - refreshTimeout(ctx); \ - if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \ - } while (0) -#define _EL_DEL_READ(ctx) do { \ - if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \ - } while(0) -#define _EL_ADD_WRITE(ctx) \ - do { \ - refreshTimeout(ctx); \ - if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \ - } while (0) -#define _EL_DEL_WRITE(ctx) do { \ - if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \ - } while(0) -#define _EL_CLEANUP(ctx) do { \ - if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \ - ctx->ev.cleanup = NULL; \ - } while(0); - -static inline void refreshTimeout(redisAsyncContext *ctx) { - #define REDIS_TIMER_ISSET(tvp) \ - (tvp && ((tvp)->tv_sec || (tvp)->tv_usec)) - - #define REDIS_EL_TIMER(ac, tvp) \ - if ((ac)->ev.scheduleTimer && REDIS_TIMER_ISSET(tvp)) { \ - (ac)->ev.scheduleTimer((ac)->ev.data, *(tvp)); \ - } - - if (ctx->c.flags & REDIS_CONNECTED) { - REDIS_EL_TIMER(ctx, ctx->c.command_timeout); - } else { - REDIS_EL_TIMER(ctx, ctx->c.connect_timeout); - } -} - -void __redisAsyncDisconnect(redisAsyncContext *ac); -void redisProcessCallbacks(redisAsyncContext *ac); - -#endif /* __HIREDIS_ASYNC_PRIVATE_H */ diff --git a/ext/hiredis-1.0.2/dict.c b/ext/hiredis-1.0.2/dict.c deleted file mode 100644 index 34a33ead9..000000000 --- a/ext/hiredis-1.0.2/dict.c +++ /dev/null @@ -1,352 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include "alloc.h" -#include -#include -#include -#include "dict.h" - -/* -------------------------- private prototypes ---------------------------- */ - -static int _dictExpandIfNeeded(dict *ht); -static unsigned long _dictNextPower(unsigned long size); -static int _dictKeyIndex(dict *ht, const void *key); -static int _dictInit(dict *ht, dictType *type, void *privDataPtr); - -/* -------------------------- hash functions -------------------------------- */ - -/* Generic hash function (a popular one from Bernstein). - * I tested a few and this was the best. */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len) { - unsigned int hash = 5381; - - while (len--) - hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */ - return hash; -} - -/* ----------------------------- API implementation ------------------------- */ - -/* Reset an hashtable already initialized with ht_init(). - * NOTE: This function should only called by ht_destroy(). */ -static void _dictReset(dict *ht) { - ht->table = NULL; - ht->size = 0; - ht->sizemask = 0; - ht->used = 0; -} - -/* Create a new hash table */ -static dict *dictCreate(dictType *type, void *privDataPtr) { - dict *ht = hi_malloc(sizeof(*ht)); - if (ht == NULL) - return NULL; - - _dictInit(ht,type,privDataPtr); - return ht; -} - -/* Initialize the hash table */ -static int _dictInit(dict *ht, dictType *type, void *privDataPtr) { - _dictReset(ht); - ht->type = type; - ht->privdata = privDataPtr; - return DICT_OK; -} - -/* Expand or create the hashtable */ -static int dictExpand(dict *ht, unsigned long size) { - dict n; /* the new hashtable */ - unsigned long realsize = _dictNextPower(size), i; - - /* the size is invalid if it is smaller than the number of - * elements already inside the hashtable */ - if (ht->used > size) - return DICT_ERR; - - _dictInit(&n, ht->type, ht->privdata); - n.size = realsize; - n.sizemask = realsize-1; - n.table = hi_calloc(realsize,sizeof(dictEntry*)); - if (n.table == NULL) - return DICT_ERR; - - /* Copy all the elements from the old to the new table: - * note that if the old hash table is empty ht->size is zero, - * so dictExpand just creates an hash table. */ - n.used = ht->used; - for (i = 0; i < ht->size && ht->used > 0; i++) { - dictEntry *he, *nextHe; - - if (ht->table[i] == NULL) continue; - - /* For each hash entry on this slot... */ - he = ht->table[i]; - while(he) { - unsigned int h; - - nextHe = he->next; - /* Get the new element index */ - h = dictHashKey(ht, he->key) & n.sizemask; - he->next = n.table[h]; - n.table[h] = he; - ht->used--; - /* Pass to the next element */ - he = nextHe; - } - } - assert(ht->used == 0); - hi_free(ht->table); - - /* Remap the new hashtable in the old */ - *ht = n; - return DICT_OK; -} - -/* Add an element to the target hash table */ -static int dictAdd(dict *ht, void *key, void *val) { - int index; - dictEntry *entry; - - /* Get the index of the new element, or -1 if - * the element already exists. */ - if ((index = _dictKeyIndex(ht, key)) == -1) - return DICT_ERR; - - /* Allocates the memory and stores key */ - entry = hi_malloc(sizeof(*entry)); - if (entry == NULL) - return DICT_ERR; - - entry->next = ht->table[index]; - ht->table[index] = entry; - - /* Set the hash entry fields. */ - dictSetHashKey(ht, entry, key); - dictSetHashVal(ht, entry, val); - ht->used++; - return DICT_OK; -} - -/* Add an element, discarding the old if the key already exists. - * Return 1 if the key was added from scratch, 0 if there was already an - * element with such key and dictReplace() just performed a value update - * operation. */ -static int dictReplace(dict *ht, void *key, void *val) { - dictEntry *entry, auxentry; - - /* Try to add the element. If the key - * does not exists dictAdd will succeed. */ - if (dictAdd(ht, key, val) == DICT_OK) - return 1; - /* It already exists, get the entry */ - entry = dictFind(ht, key); - if (entry == NULL) - return 0; - - /* Free the old value and set the new one */ - /* Set the new value and free the old one. Note that it is important - * to do that in this order, as the value may just be exactly the same - * as the previous one. In this context, think to reference counting, - * you want to increment (set), and then decrement (free), and not the - * reverse. */ - auxentry = *entry; - dictSetHashVal(ht, entry, val); - dictFreeEntryVal(ht, &auxentry); - return 0; -} - -/* Search and remove an element */ -static int dictDelete(dict *ht, const void *key) { - unsigned int h; - dictEntry *de, *prevde; - - if (ht->size == 0) - return DICT_ERR; - h = dictHashKey(ht, key) & ht->sizemask; - de = ht->table[h]; - - prevde = NULL; - while(de) { - if (dictCompareHashKeys(ht,key,de->key)) { - /* Unlink the element from the list */ - if (prevde) - prevde->next = de->next; - else - ht->table[h] = de->next; - - dictFreeEntryKey(ht,de); - dictFreeEntryVal(ht,de); - hi_free(de); - ht->used--; - return DICT_OK; - } - prevde = de; - de = de->next; - } - return DICT_ERR; /* not found */ -} - -/* Destroy an entire hash table */ -static int _dictClear(dict *ht) { - unsigned long i; - - /* Free all the elements */ - for (i = 0; i < ht->size && ht->used > 0; i++) { - dictEntry *he, *nextHe; - - if ((he = ht->table[i]) == NULL) continue; - while(he) { - nextHe = he->next; - dictFreeEntryKey(ht, he); - dictFreeEntryVal(ht, he); - hi_free(he); - ht->used--; - he = nextHe; - } - } - /* Free the table and the allocated cache structure */ - hi_free(ht->table); - /* Re-initialize the table */ - _dictReset(ht); - return DICT_OK; /* never fails */ -} - -/* Clear & Release the hash table */ -static void dictRelease(dict *ht) { - _dictClear(ht); - hi_free(ht); -} - -static dictEntry *dictFind(dict *ht, const void *key) { - dictEntry *he; - unsigned int h; - - if (ht->size == 0) return NULL; - h = dictHashKey(ht, key) & ht->sizemask; - he = ht->table[h]; - while(he) { - if (dictCompareHashKeys(ht, key, he->key)) - return he; - he = he->next; - } - return NULL; -} - -static dictIterator *dictGetIterator(dict *ht) { - dictIterator *iter = hi_malloc(sizeof(*iter)); - if (iter == NULL) - return NULL; - - iter->ht = ht; - iter->index = -1; - iter->entry = NULL; - iter->nextEntry = NULL; - return iter; -} - -static dictEntry *dictNext(dictIterator *iter) { - while (1) { - if (iter->entry == NULL) { - iter->index++; - if (iter->index >= - (signed)iter->ht->size) break; - iter->entry = iter->ht->table[iter->index]; - } else { - iter->entry = iter->nextEntry; - } - if (iter->entry) { - /* We need to save the 'next' here, the iterator user - * may delete the entry we are returning. */ - iter->nextEntry = iter->entry->next; - return iter->entry; - } - } - return NULL; -} - -static void dictReleaseIterator(dictIterator *iter) { - hi_free(iter); -} - -/* ------------------------- private functions ------------------------------ */ - -/* Expand the hash table if needed */ -static int _dictExpandIfNeeded(dict *ht) { - /* If the hash table is empty expand it to the initial size, - * if the table is "full" double its size. */ - if (ht->size == 0) - return dictExpand(ht, DICT_HT_INITIAL_SIZE); - if (ht->used == ht->size) - return dictExpand(ht, ht->size*2); - return DICT_OK; -} - -/* Our hash table capability is a power of two */ -static unsigned long _dictNextPower(unsigned long size) { - unsigned long i = DICT_HT_INITIAL_SIZE; - - if (size >= LONG_MAX) return LONG_MAX; - while(1) { - if (i >= size) - return i; - i *= 2; - } -} - -/* Returns the index of a free slot that can be populated with - * an hash entry for the given 'key'. - * If the key already exists, -1 is returned. */ -static int _dictKeyIndex(dict *ht, const void *key) { - unsigned int h; - dictEntry *he; - - /* Expand the hashtable if needed */ - if (_dictExpandIfNeeded(ht) == DICT_ERR) - return -1; - /* Compute the key hash value */ - h = dictHashKey(ht, key) & ht->sizemask; - /* Search if this slot does not already contain the given key */ - he = ht->table[h]; - while(he) { - if (dictCompareHashKeys(ht, key, he->key)) - return -1; - he = he->next; - } - return h; -} - diff --git a/ext/hiredis-1.0.2/dict.h b/ext/hiredis-1.0.2/dict.h deleted file mode 100644 index 95fcd280e..000000000 --- a/ext/hiredis-1.0.2/dict.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DICT_H -#define __DICT_H - -#define DICT_OK 0 -#define DICT_ERR 1 - -/* Unused arguments generate annoying warnings... */ -#define DICT_NOTUSED(V) ((void) V) - -typedef struct dictEntry { - void *key; - void *val; - struct dictEntry *next; -} dictEntry; - -typedef struct dictType { - unsigned int (*hashFunction)(const void *key); - void *(*keyDup)(void *privdata, const void *key); - void *(*valDup)(void *privdata, const void *obj); - int (*keyCompare)(void *privdata, const void *key1, const void *key2); - void (*keyDestructor)(void *privdata, void *key); - void (*valDestructor)(void *privdata, void *obj); -} dictType; - -typedef struct dict { - dictEntry **table; - dictType *type; - unsigned long size; - unsigned long sizemask; - unsigned long used; - void *privdata; -} dict; - -typedef struct dictIterator { - dict *ht; - int index; - dictEntry *entry, *nextEntry; -} dictIterator; - -/* This is the initial size of every hash table */ -#define DICT_HT_INITIAL_SIZE 4 - -/* ------------------------------- Macros ------------------------------------*/ -#define dictFreeEntryVal(ht, entry) \ - if ((ht)->type->valDestructor) \ - (ht)->type->valDestructor((ht)->privdata, (entry)->val) - -#define dictSetHashVal(ht, entry, _val_) do { \ - if ((ht)->type->valDup) \ - entry->val = (ht)->type->valDup((ht)->privdata, _val_); \ - else \ - entry->val = (_val_); \ -} while(0) - -#define dictFreeEntryKey(ht, entry) \ - if ((ht)->type->keyDestructor) \ - (ht)->type->keyDestructor((ht)->privdata, (entry)->key) - -#define dictSetHashKey(ht, entry, _key_) do { \ - if ((ht)->type->keyDup) \ - entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ - else \ - entry->key = (_key_); \ -} while(0) - -#define dictCompareHashKeys(ht, key1, key2) \ - (((ht)->type->keyCompare) ? \ - (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ - (key1) == (key2)) - -#define dictHashKey(ht, key) (ht)->type->hashFunction(key) - -#define dictGetEntryKey(he) ((he)->key) -#define dictGetEntryVal(he) ((he)->val) -#define dictSlots(ht) ((ht)->size) -#define dictSize(ht) ((ht)->used) - -/* API */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len); -static dict *dictCreate(dictType *type, void *privDataPtr); -static int dictExpand(dict *ht, unsigned long size); -static int dictAdd(dict *ht, void *key, void *val); -static int dictReplace(dict *ht, void *key, void *val); -static int dictDelete(dict *ht, const void *key); -static void dictRelease(dict *ht); -static dictEntry * dictFind(dict *ht, const void *key); -static dictIterator *dictGetIterator(dict *ht); -static dictEntry *dictNext(dictIterator *iter); -static void dictReleaseIterator(dictIterator *iter); - -#endif /* __DICT_H */ diff --git a/ext/hiredis-1.0.2/examples/CMakeLists.txt b/ext/hiredis-1.0.2/examples/CMakeLists.txt deleted file mode 100644 index 1d5bc56e0..000000000 --- a/ext/hiredis-1.0.2/examples/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -INCLUDE(FindPkgConfig) -# Check for GLib - -PKG_CHECK_MODULES(GLIB2 glib-2.0) -if (GLIB2_FOUND) - INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) - LINK_DIRECTORIES(${GLIB2_LIBRARY_DIRS}) - ADD_EXECUTABLE(example-glib example-glib.c) - TARGET_LINK_LIBRARIES(example-glib hiredis ${GLIB2_LIBRARIES}) -ENDIF(GLIB2_FOUND) - -FIND_PATH(LIBEV ev.h - HINTS /usr/local /usr/opt/local - ENV LIBEV_INCLUDE_DIR) - -if (LIBEV) - # Just compile and link with libev - ADD_EXECUTABLE(example-libev example-libev.c) - TARGET_LINK_LIBRARIES(example-libev hiredis ev) -ENDIF() - -FIND_PATH(LIBEVENT event.h) -if (LIBEVENT) - ADD_EXECUTABLE(example-libevent example-libevent) - TARGET_LINK_LIBRARIES(example-libevent hiredis event) -ENDIF() - -FIND_PATH(LIBUV uv.h) -IF (LIBUV) - ADD_EXECUTABLE(example-libuv example-libuv.c) - TARGET_LINK_LIBRARIES(example-libuv hiredis uv) -ENDIF() - -IF (APPLE) - FIND_LIBRARY(CF CoreFoundation) - ADD_EXECUTABLE(example-macosx example-macosx.c) - TARGET_LINK_LIBRARIES(example-macosx hiredis ${CF}) -ENDIF() - -IF (ENABLE_SSL) - ADD_EXECUTABLE(example-ssl example-ssl.c) - TARGET_LINK_LIBRARIES(example-ssl hiredis hiredis_ssl) -ENDIF() - -ADD_EXECUTABLE(example example.c) -TARGET_LINK_LIBRARIES(example hiredis) - -ADD_EXECUTABLE(example-push example-push.c) -TARGET_LINK_LIBRARIES(example-push hiredis) diff --git a/ext/hiredis-1.0.2/examples/example-ae.c b/ext/hiredis-1.0.2/examples/example-ae.c deleted file mode 100644 index 8efa7306a..000000000 --- a/ext/hiredis-1.0.2/examples/example-ae.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -/* Put event loop in the global scope, so it can be explicitly stopped */ -static aeEventLoop *loop; - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - aeStop(loop); - return; - } - - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - aeStop(loop); - return; - } - - printf("Disconnected...\n"); - aeStop(loop); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - loop = aeCreateEventLoop(64); - redisAeAttach(loop, c); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - aeMain(loop); - return 0; -} - diff --git a/ext/hiredis-1.0.2/examples/example-glib.c b/ext/hiredis-1.0.2/examples/example-glib.c deleted file mode 100644 index d6e10f8e8..000000000 --- a/ext/hiredis-1.0.2/examples/example-glib.c +++ /dev/null @@ -1,73 +0,0 @@ -#include - -#include -#include -#include - -static GMainLoop *mainloop; - -static void -connect_cb (const redisAsyncContext *ac G_GNUC_UNUSED, - int status) -{ - if (status != REDIS_OK) { - g_printerr("Failed to connect: %s\n", ac->errstr); - g_main_loop_quit(mainloop); - } else { - g_printerr("Connected...\n"); - } -} - -static void -disconnect_cb (const redisAsyncContext *ac G_GNUC_UNUSED, - int status) -{ - if (status != REDIS_OK) { - g_error("Failed to disconnect: %s", ac->errstr); - } else { - g_printerr("Disconnected...\n"); - g_main_loop_quit(mainloop); - } -} - -static void -command_cb(redisAsyncContext *ac, - gpointer r, - gpointer user_data G_GNUC_UNUSED) -{ - redisReply *reply = r; - - if (reply) { - g_print("REPLY: %s\n", reply->str); - } - - redisAsyncDisconnect(ac); -} - -gint -main (gint argc G_GNUC_UNUSED, - gchar *argv[] G_GNUC_UNUSED) -{ - redisAsyncContext *ac; - GMainContext *context = NULL; - GSource *source; - - ac = redisAsyncConnect("127.0.0.1", 6379); - if (ac->err) { - g_printerr("%s\n", ac->errstr); - exit(EXIT_FAILURE); - } - - source = redis_source_new(ac); - mainloop = g_main_loop_new(context, FALSE); - g_source_attach(source, context); - - redisAsyncSetConnectCallback(ac, connect_cb); - redisAsyncSetDisconnectCallback(ac, disconnect_cb); - redisAsyncCommand(ac, command_cb, NULL, "SET key 1234"); - redisAsyncCommand(ac, command_cb, NULL, "GET key"); - - g_main_loop_run(mainloop); - - return EXIT_SUCCESS; -} diff --git a/ext/hiredis-1.0.2/examples/example-ivykis.c b/ext/hiredis-1.0.2/examples/example-ivykis.c deleted file mode 100644 index f57dc3887..000000000 --- a/ext/hiredis-1.0.2/examples/example-ivykis.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif - - iv_init(); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisIvykisAttach(c); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - - iv_main(); - - iv_deinit(); - - return 0; -} diff --git a/ext/hiredis-1.0.2/examples/example-libev.c b/ext/hiredis-1.0.2/examples/example-libev.c deleted file mode 100644 index ec474306b..000000000 --- a/ext/hiredis-1.0.2/examples/example-libev.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisLibevAttach(EV_DEFAULT_ c); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - ev_loop(EV_DEFAULT_ 0); - return 0; -} diff --git a/ext/hiredis-1.0.2/examples/example-libevent-ssl.c b/ext/hiredis-1.0.2/examples/example-libevent-ssl.c deleted file mode 100644 index 7d99af1ba..000000000 --- a/ext/hiredis-1.0.2/examples/example-libevent-ssl.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif - - struct event_base *base = event_base_new(); - if (argc < 5) { - fprintf(stderr, - "Usage: %s [ca]\n", argv[0]); - exit(1); - } - - const char *value = argv[1]; - size_t nvalue = strlen(value); - - const char *hostname = argv[2]; - int port = atoi(argv[3]); - - const char *cert = argv[4]; - const char *certKey = argv[5]; - const char *caCert = argc > 5 ? argv[6] : NULL; - - redisSSLContext *ssl; - redisSSLContextError ssl_error; - - redisInitOpenSSL(); - - ssl = redisCreateSSLContext(caCert, NULL, - cert, certKey, NULL, &ssl_error); - if (!ssl) { - printf("Error: %s\n", redisSSLContextGetError(ssl_error)); - return 1; - } - - redisAsyncContext *c = redisAsyncConnect(hostname, port); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - if (redisInitiateSSLWithContext(&c->c, ssl) != REDIS_OK) { - printf("SSL Error!\n"); - exit(1); - } - - redisLibeventAttach(c,base); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", value, nvalue); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - event_base_dispatch(base); - - redisFreeSSLContext(ssl); - return 0; -} diff --git a/ext/hiredis-1.0.2/examples/example-libevent.c b/ext/hiredis-1.0.2/examples/example-libevent.c deleted file mode 100644 index 49bddd0c2..000000000 --- a/ext/hiredis-1.0.2/examples/example-libevent.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) { - if (c->errstr) { - printf("errstr: %s\n", c->errstr); - } - return; - } - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif - - struct event_base *base = event_base_new(); - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379); - struct timeval tv = {0}; - tv.tv_sec = 1; - options.connect_timeout = &tv; - - - redisAsyncContext *c = redisAsyncConnectWithOptions(&options); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisLibeventAttach(c,base); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - event_base_dispatch(base); - return 0; -} diff --git a/ext/hiredis-1.0.2/examples/example-libuv.c b/ext/hiredis-1.0.2/examples/example-libuv.c deleted file mode 100644 index cbde452b9..000000000 --- a/ext/hiredis-1.0.2/examples/example-libuv.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif - - uv_loop_t* loop = uv_default_loop(); - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisLibuvAttach(c,loop); - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - uv_run(loop, UV_RUN_DEFAULT); - return 0; -} diff --git a/ext/hiredis-1.0.2/examples/example-macosx.c b/ext/hiredis-1.0.2/examples/example-macosx.c deleted file mode 100644 index bc84ed5ba..000000000 --- a/ext/hiredis-1.0.2/examples/example-macosx.c +++ /dev/null @@ -1,66 +0,0 @@ -// -// Created by Дмитрий Бахвалов on 13.07.15. -// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. -// - -#include - -#include -#include -#include - -void getCallback(redisAsyncContext *c, void *r, void *privdata) { - redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); - - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); -} - -void connectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - printf("Connected...\n"); -} - -void disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - return; - } - CFRunLoopStop(CFRunLoopGetCurrent()); - printf("Disconnected...\n"); -} - -int main (int argc, char **argv) { - signal(SIGPIPE, SIG_IGN); - - CFRunLoopRef loop = CFRunLoopGetCurrent(); - if( !loop ) { - printf("Error: Cannot get current run loop\n"); - return 1; - } - - redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); - if (c->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", c->errstr); - return 1; - } - - redisMacOSAttach(c, loop); - - redisAsyncSetConnectCallback(c,connectCallback); - redisAsyncSetDisconnectCallback(c,disconnectCallback); - - redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); - redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); - - CFRunLoopRun(); - - return 0; -} - diff --git a/ext/hiredis-1.0.2/examples/example-push.c b/ext/hiredis-1.0.2/examples/example-push.c deleted file mode 100644 index 2d4ab4dc0..000000000 --- a/ext/hiredis-1.0.2/examples/example-push.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2020, Michael Grunder - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include -#include -#include -#include - -#define KEY_COUNT 5 - -#define panicAbort(fmt, ...) \ - do { \ - fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); \ - exit(-1); \ - } while (0) - -static void assertReplyAndFree(redisContext *context, redisReply *reply, int type) { - if (reply == NULL) - panicAbort("NULL reply from server (error: %s)", context->errstr); - - if (reply->type != type) { - if (reply->type == REDIS_REPLY_ERROR) - fprintf(stderr, "Redis Error: %s\n", reply->str); - - panicAbort("Expected reply type %d but got type %d", type, reply->type); - } - - freeReplyObject(reply); -} - -/* Switch to the RESP3 protocol and enable client tracking */ -static void enableClientTracking(redisContext *c) { - redisReply *reply = redisCommand(c, "HELLO 3"); - if (reply == NULL || c->err) { - panicAbort("NULL reply or server error (error: %s)", c->errstr); - } - - if (reply->type != REDIS_REPLY_MAP) { - fprintf(stderr, "Error: Can't send HELLO 3 command. Are you sure you're "); - fprintf(stderr, "connected to redis-server >= 6.0.0?\nRedis error: %s\n", - reply->type == REDIS_REPLY_ERROR ? reply->str : "(unknown)"); - exit(-1); - } - - freeReplyObject(reply); - - /* Enable client tracking */ - reply = redisCommand(c, "CLIENT TRACKING ON"); - assertReplyAndFree(c, reply, REDIS_REPLY_STATUS); -} - -void pushReplyHandler(void *privdata, void *r) { - redisReply *reply = r; - int *invalidations = privdata; - - /* Sanity check on the invalidation reply */ - if (reply->type != REDIS_REPLY_PUSH || reply->elements != 2 || - reply->element[1]->type != REDIS_REPLY_ARRAY || - reply->element[1]->element[0]->type != REDIS_REPLY_STRING) - { - panicAbort("%s", "Can't parse PUSH message!"); - } - - /* Increment our invalidation count */ - *invalidations += 1; - - printf("pushReplyHandler(): INVALIDATE '%s' (invalidation count: %d)\n", - reply->element[1]->element[0]->str, *invalidations); - - freeReplyObject(reply); -} - -/* We aren't actually freeing anything here, but it is included to show that we can - * have hiredis call our data destructor when freeing the context */ -void privdata_dtor(void *privdata) { - unsigned int *icount = privdata; - printf("privdata_dtor(): In context privdata dtor (invalidations: %u)\n", *icount); -} - -int main(int argc, char **argv) { - unsigned int j, invalidations = 0; - redisContext *c; - redisReply *reply; - - const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; - int port = (argc > 2) ? atoi(argv[2]) : 6379; - - redisOptions o = {0}; - REDIS_OPTIONS_SET_TCP(&o, hostname, port); - - /* Set our context privdata to the address of our invalidation counter. Each - * time our PUSH handler is called, hiredis will pass the privdata for context. - * - * This could also be done after we create the context like so: - * - * c->privdata = &invalidations; - * c->free_privdata = privdata_dtor; - */ - REDIS_OPTIONS_SET_PRIVDATA(&o, &invalidations, privdata_dtor); - - /* Set our custom PUSH message handler */ - o.push_cb = pushReplyHandler; - - c = redisConnectWithOptions(&o); - if (c == NULL || c->err) - panicAbort("Connection error: %s", c ? c->errstr : "OOM"); - - /* Enable RESP3 and turn on client tracking */ - enableClientTracking(c); - - /* Set some keys and then read them back. Once we do that, Redis will deliver - * invalidation push messages whenever the key is modified */ - for (j = 0; j < KEY_COUNT; j++) { - reply = redisCommand(c, "SET key:%d initial:%d", j, j); - assertReplyAndFree(c, reply, REDIS_REPLY_STATUS); - - reply = redisCommand(c, "GET key:%d", j); - assertReplyAndFree(c, reply, REDIS_REPLY_STRING); - } - - /* Trigger invalidation messages by updating keys we just read */ - for (j = 0; j < KEY_COUNT; j++) { - printf(" main(): SET key:%d update:%d\n", j, j); - reply = redisCommand(c, "SET key:%d update:%d", j, j); - assertReplyAndFree(c, reply, REDIS_REPLY_STATUS); - printf(" main(): SET REPLY OK\n"); - } - - printf("\nTotal detected invalidations: %d, expected: %d\n", invalidations, KEY_COUNT); - - /* PING server */ - redisFree(c); -} diff --git a/ext/hiredis-1.0.2/examples/example-qt.cpp b/ext/hiredis-1.0.2/examples/example-qt.cpp deleted file mode 100644 index f524c3f3d..000000000 --- a/ext/hiredis-1.0.2/examples/example-qt.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -using namespace std; - -#include -#include - -#include "example-qt.h" - -void getCallback(redisAsyncContext *, void * r, void * privdata) { - - redisReply * reply = static_cast(r); - ExampleQt * ex = static_cast(privdata); - if (reply == nullptr || ex == nullptr) return; - - cout << "key: " << reply->str << endl; - - ex->finish(); -} - -void ExampleQt::run() { - - m_ctx = redisAsyncConnect("localhost", 6379); - - if (m_ctx->err) { - cerr << "Error: " << m_ctx->errstr << endl; - redisAsyncFree(m_ctx); - emit finished(); - } - - m_adapter.setContext(m_ctx); - - redisAsyncCommand(m_ctx, NULL, NULL, "SET key %s", m_value); - redisAsyncCommand(m_ctx, getCallback, this, "GET key"); -} - -int main (int argc, char **argv) { - - QCoreApplication app(argc, argv); - - ExampleQt example(argv[argc-1]); - - QObject::connect(&example, SIGNAL(finished()), &app, SLOT(quit())); - QTimer::singleShot(0, &example, SLOT(run())); - - return app.exec(); -} diff --git a/ext/hiredis-1.0.2/examples/example-qt.h b/ext/hiredis-1.0.2/examples/example-qt.h deleted file mode 100644 index 374f47666..000000000 --- a/ext/hiredis-1.0.2/examples/example-qt.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __HIREDIS_EXAMPLE_QT_H -#define __HIREDIS_EXAMPLE_QT_H - -#include - -class ExampleQt : public QObject { - - Q_OBJECT - - public: - ExampleQt(const char * value, QObject * parent = 0) - : QObject(parent), m_value(value) {} - - signals: - void finished(); - - public slots: - void run(); - - private: - void finish() { emit finished(); } - - private: - const char * m_value; - redisAsyncContext * m_ctx; - RedisQtAdapter m_adapter; - - friend - void getCallback(redisAsyncContext *, void *, void *); -}; - -#endif /* !__HIREDIS_EXAMPLE_QT_H */ diff --git a/ext/hiredis-1.0.2/examples/example-ssl.c b/ext/hiredis-1.0.2/examples/example-ssl.c deleted file mode 100644 index c754177cf..000000000 --- a/ext/hiredis-1.0.2/examples/example-ssl.c +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -int main(int argc, char **argv) { - unsigned int j; - redisSSLContext *ssl; - redisSSLContextError ssl_error; - redisContext *c; - redisReply *reply; - if (argc < 4) { - printf("Usage: %s [ca]\n", argv[0]); - exit(1); - } - const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; - int port = atoi(argv[2]); - const char *cert = argv[3]; - const char *key = argv[4]; - const char *ca = argc > 4 ? argv[5] : NULL; - - redisInitOpenSSL(); - ssl = redisCreateSSLContext(ca, NULL, cert, key, NULL, &ssl_error); - if (!ssl) { - printf("SSL Context error: %s\n", - redisSSLContextGetError(ssl_error)); - exit(1); - } - - struct timeval tv = { 1, 500000 }; // 1.5 seconds - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, hostname, port); - options.connect_timeout = &tv; - c = redisConnectWithOptions(&options); - - if (c == NULL || c->err) { - if (c) { - printf("Connection error: %s\n", c->errstr); - redisFree(c); - } else { - printf("Connection error: can't allocate redis context\n"); - } - exit(1); - } - - if (redisInitiateSSLWithContext(c, ssl) != REDIS_OK) { - printf("Couldn't initialize SSL!\n"); - printf("Error: %s\n", c->errstr); - redisFree(c); - exit(1); - } - - /* PING server */ - reply = redisCommand(c,"PING"); - printf("PING: %s\n", reply->str); - freeReplyObject(reply); - - /* Set a key */ - reply = redisCommand(c,"SET %s %s", "foo", "hello world"); - printf("SET: %s\n", reply->str); - freeReplyObject(reply); - - /* Set a key using binary safe API */ - reply = redisCommand(c,"SET %b %b", "bar", (size_t) 3, "hello", (size_t) 5); - printf("SET (binary API): %s\n", reply->str); - freeReplyObject(reply); - - /* Try a GET and two INCR */ - reply = redisCommand(c,"GET foo"); - printf("GET foo: %s\n", reply->str); - freeReplyObject(reply); - - reply = redisCommand(c,"INCR counter"); - printf("INCR counter: %lld\n", reply->integer); - freeReplyObject(reply); - /* again ... */ - reply = redisCommand(c,"INCR counter"); - printf("INCR counter: %lld\n", reply->integer); - freeReplyObject(reply); - - /* Create a list of numbers, from 0 to 9 */ - reply = redisCommand(c,"DEL mylist"); - freeReplyObject(reply); - for (j = 0; j < 10; j++) { - char buf[64]; - - snprintf(buf,64,"%u",j); - reply = redisCommand(c,"LPUSH mylist element-%s", buf); - freeReplyObject(reply); - } - - /* Let's check what we have inside the list */ - reply = redisCommand(c,"LRANGE mylist 0 -1"); - if (reply->type == REDIS_REPLY_ARRAY) { - for (j = 0; j < reply->elements; j++) { - printf("%u) %s\n", j, reply->element[j]->str); - } - } - freeReplyObject(reply); - - /* Disconnects and frees the context */ - redisFree(c); - - redisFreeSSLContext(ssl); - - return 0; -} diff --git a/ext/hiredis-1.0.2/examples/example.c b/ext/hiredis-1.0.2/examples/example.c deleted file mode 100644 index 15dacbd18..000000000 --- a/ext/hiredis-1.0.2/examples/example.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include -#include - -int main(int argc, char **argv) { - unsigned int j, isunix = 0; - redisContext *c; - redisReply *reply; - const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; - - if (argc > 2) { - if (*argv[2] == 'u' || *argv[2] == 'U') { - isunix = 1; - /* in this case, host is the path to the unix socket */ - printf("Will connect to unix socket @%s\n", hostname); - } - } - - int port = (argc > 2) ? atoi(argv[2]) : 6379; - - struct timeval timeout = { 1, 500000 }; // 1.5 seconds - if (isunix) { - c = redisConnectUnixWithTimeout(hostname, timeout); - } else { - c = redisConnectWithTimeout(hostname, port, timeout); - } - if (c == NULL || c->err) { - if (c) { - printf("Connection error: %s\n", c->errstr); - redisFree(c); - } else { - printf("Connection error: can't allocate redis context\n"); - } - exit(1); - } - - /* PING server */ - reply = redisCommand(c,"PING"); - printf("PING: %s\n", reply->str); - freeReplyObject(reply); - - /* Set a key */ - reply = redisCommand(c,"SET %s %s", "foo", "hello world"); - printf("SET: %s\n", reply->str); - freeReplyObject(reply); - - /* Set a key using binary safe API */ - reply = redisCommand(c,"SET %b %b", "bar", (size_t) 3, "hello", (size_t) 5); - printf("SET (binary API): %s\n", reply->str); - freeReplyObject(reply); - - /* Try a GET and two INCR */ - reply = redisCommand(c,"GET foo"); - printf("GET foo: %s\n", reply->str); - freeReplyObject(reply); - - reply = redisCommand(c,"INCR counter"); - printf("INCR counter: %lld\n", reply->integer); - freeReplyObject(reply); - /* again ... */ - reply = redisCommand(c,"INCR counter"); - printf("INCR counter: %lld\n", reply->integer); - freeReplyObject(reply); - - /* Create a list of numbers, from 0 to 9 */ - reply = redisCommand(c,"DEL mylist"); - freeReplyObject(reply); - for (j = 0; j < 10; j++) { - char buf[64]; - - snprintf(buf,64,"%u",j); - reply = redisCommand(c,"LPUSH mylist element-%s", buf); - freeReplyObject(reply); - } - - /* Let's check what we have inside the list */ - reply = redisCommand(c,"LRANGE mylist 0 -1"); - if (reply->type == REDIS_REPLY_ARRAY) { - for (j = 0; j < reply->elements; j++) { - printf("%u) %s\n", j, reply->element[j]->str); - } - } - freeReplyObject(reply); - - /* Disconnects and frees the context */ - redisFree(c); - - return 0; -} diff --git a/ext/hiredis-1.0.2/fmacros.h b/ext/hiredis-1.0.2/fmacros.h deleted file mode 100644 index 3227faafd..000000000 --- a/ext/hiredis-1.0.2/fmacros.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __HIREDIS_FMACRO_H -#define __HIREDIS_FMACRO_H - -#define _XOPEN_SOURCE 600 -#define _POSIX_C_SOURCE 200112L - -#if defined(__APPLE__) && defined(__MACH__) -/* Enable TCP_KEEPALIVE */ -#define _DARWIN_C_SOURCE -#endif - -#endif diff --git a/ext/hiredis-1.0.2/hiredis-config.cmake.in b/ext/hiredis-1.0.2/hiredis-config.cmake.in deleted file mode 100644 index 98851dcee..000000000 --- a/ext/hiredis-1.0.2/hiredis-config.cmake.in +++ /dev/null @@ -1,13 +0,0 @@ -@PACKAGE_INIT@ - -set_and_check(hiredis_INCLUDEDIR "@PACKAGE_INCLUDE_INSTALL_DIR@") - -IF (NOT TARGET hiredis::hiredis) - INCLUDE(${CMAKE_CURRENT_LIST_DIR}/hiredis-targets.cmake) -ENDIF() - -SET(hiredis_LIBRARIES hiredis::hiredis) -SET(hiredis_INCLUDE_DIRS ${hiredis_INCLUDEDIR}) - -check_required_components(hiredis) - diff --git a/ext/hiredis-1.0.2/hiredis.c b/ext/hiredis-1.0.2/hiredis.c deleted file mode 100644 index ab0e39822..000000000 --- a/ext/hiredis-1.0.2/hiredis.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include - -#include "hiredis.h" -#include "net.h" -#include "sds.h" -#include "async.h" -#include "win32.h" - -extern int redisContextUpdateConnectTimeout(redisContext *c, const struct timeval *timeout); -extern int redisContextUpdateCommandTimeout(redisContext *c, const struct timeval *timeout); - -static redisContextFuncs redisContextDefaultFuncs = { - .free_privctx = NULL, - .async_read = redisAsyncRead, - .async_write = redisAsyncWrite, - .read = redisNetRead, - .write = redisNetWrite -}; - -static redisReply *createReplyObject(int type); -static void *createStringObject(const redisReadTask *task, char *str, size_t len); -static void *createArrayObject(const redisReadTask *task, size_t elements); -static void *createIntegerObject(const redisReadTask *task, long long value); -static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len); -static void *createNilObject(const redisReadTask *task); -static void *createBoolObject(const redisReadTask *task, int bval); - -/* Default set of functions to build the reply. Keep in mind that such a - * function returning NULL is interpreted as OOM. */ -static redisReplyObjectFunctions defaultFunctions = { - createStringObject, - createArrayObject, - createIntegerObject, - createDoubleObject, - createNilObject, - createBoolObject, - freeReplyObject -}; - -/* Create a reply object */ -static redisReply *createReplyObject(int type) { - redisReply *r = hi_calloc(1,sizeof(*r)); - - if (r == NULL) - return NULL; - - r->type = type; - return r; -} - -/* Free a reply object */ -void freeReplyObject(void *reply) { - redisReply *r = reply; - size_t j; - - if (r == NULL) - return; - - switch(r->type) { - case REDIS_REPLY_INTEGER: - break; /* Nothing to free */ - case REDIS_REPLY_ARRAY: - case REDIS_REPLY_MAP: - case REDIS_REPLY_SET: - case REDIS_REPLY_PUSH: - if (r->element != NULL) { - for (j = 0; j < r->elements; j++) - freeReplyObject(r->element[j]); - hi_free(r->element); - } - break; - case REDIS_REPLY_ERROR: - case REDIS_REPLY_STATUS: - case REDIS_REPLY_STRING: - case REDIS_REPLY_DOUBLE: - case REDIS_REPLY_VERB: - hi_free(r->str); - break; - } - hi_free(r); -} - -static void *createStringObject(const redisReadTask *task, char *str, size_t len) { - redisReply *r, *parent; - char *buf; - - r = createReplyObject(task->type); - if (r == NULL) - return NULL; - - assert(task->type == REDIS_REPLY_ERROR || - task->type == REDIS_REPLY_STATUS || - task->type == REDIS_REPLY_STRING || - task->type == REDIS_REPLY_VERB); - - /* Copy string value */ - if (task->type == REDIS_REPLY_VERB) { - buf = hi_malloc(len-4+1); /* Skip 4 bytes of verbatim type header. */ - if (buf == NULL) goto oom; - - memcpy(r->vtype,str,3); - r->vtype[3] = '\0'; - memcpy(buf,str+4,len-4); - buf[len-4] = '\0'; - r->len = len - 4; - } else { - buf = hi_malloc(len+1); - if (buf == NULL) goto oom; - - memcpy(buf,str,len); - buf[len] = '\0'; - r->len = len; - } - r->str = buf; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY || - parent->type == REDIS_REPLY_MAP || - parent->type == REDIS_REPLY_SET || - parent->type == REDIS_REPLY_PUSH); - parent->element[task->idx] = r; - } - return r; - -oom: - freeReplyObject(r); - return NULL; -} - -static void *createArrayObject(const redisReadTask *task, size_t elements) { - redisReply *r, *parent; - - r = createReplyObject(task->type); - if (r == NULL) - return NULL; - - if (elements > 0) { - if (SIZE_MAX / sizeof(redisReply*) < elements) return NULL; /* Don't overflow */ - r->element = hi_calloc(elements,sizeof(redisReply*)); - if (r->element == NULL) { - freeReplyObject(r); - return NULL; - } - } - - r->elements = elements; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY || - parent->type == REDIS_REPLY_MAP || - parent->type == REDIS_REPLY_SET || - parent->type == REDIS_REPLY_PUSH); - parent->element[task->idx] = r; - } - return r; -} - -static void *createIntegerObject(const redisReadTask *task, long long value) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_INTEGER); - if (r == NULL) - return NULL; - - r->integer = value; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY || - parent->type == REDIS_REPLY_MAP || - parent->type == REDIS_REPLY_SET || - parent->type == REDIS_REPLY_PUSH); - parent->element[task->idx] = r; - } - return r; -} - -static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_DOUBLE); - if (r == NULL) - return NULL; - - r->dval = value; - r->str = hi_malloc(len+1); - if (r->str == NULL) { - freeReplyObject(r); - return NULL; - } - - /* The double reply also has the original protocol string representing a - * double as a null terminated string. This way the caller does not need - * to format back for string conversion, especially since Redis does efforts - * to make the string more human readable avoiding the calssical double - * decimal string conversion artifacts. */ - memcpy(r->str, str, len); - r->str[len] = '\0'; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY || - parent->type == REDIS_REPLY_MAP || - parent->type == REDIS_REPLY_SET); - parent->element[task->idx] = r; - } - return r; -} - -static void *createNilObject(const redisReadTask *task) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_NIL); - if (r == NULL) - return NULL; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY || - parent->type == REDIS_REPLY_MAP || - parent->type == REDIS_REPLY_SET); - parent->element[task->idx] = r; - } - return r; -} - -static void *createBoolObject(const redisReadTask *task, int bval) { - redisReply *r, *parent; - - r = createReplyObject(REDIS_REPLY_BOOL); - if (r == NULL) - return NULL; - - r->integer = bval != 0; - - if (task->parent) { - parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY || - parent->type == REDIS_REPLY_MAP || - parent->type == REDIS_REPLY_SET); - parent->element[task->idx] = r; - } - return r; -} - -/* Return the number of digits of 'v' when converted to string in radix 10. - * Implementation borrowed from link in redis/src/util.c:string2ll(). */ -static uint32_t countDigits(uint64_t v) { - uint32_t result = 1; - for (;;) { - if (v < 10) return result; - if (v < 100) return result + 1; - if (v < 1000) return result + 2; - if (v < 10000) return result + 3; - v /= 10000U; - result += 4; - } -} - -/* Helper that calculates the bulk length given a certain string length. */ -static size_t bulklen(size_t len) { - return 1+countDigits(len)+2+len+2; -} - -int redisvFormatCommand(char **target, const char *format, va_list ap) { - const char *c = format; - char *cmd = NULL; /* final command */ - int pos; /* position in final command */ - sds curarg, newarg; /* current argument */ - int touched = 0; /* was the current argument touched? */ - char **curargv = NULL, **newargv = NULL; - int argc = 0; - int totlen = 0; - int error_type = 0; /* 0 = no error; -1 = memory error; -2 = format error */ - int j; - - /* Abort if there is not target to set */ - if (target == NULL) - return -1; - - /* Build the command string accordingly to protocol */ - curarg = sdsempty(); - if (curarg == NULL) - return -1; - - while(*c != '\0') { - if (*c != '%' || c[1] == '\0') { - if (*c == ' ') { - if (touched) { - newargv = hi_realloc(curargv,sizeof(char*)*(argc+1)); - if (newargv == NULL) goto memory_err; - curargv = newargv; - curargv[argc++] = curarg; - totlen += bulklen(sdslen(curarg)); - - /* curarg is put in argv so it can be overwritten. */ - curarg = sdsempty(); - if (curarg == NULL) goto memory_err; - touched = 0; - } - } else { - newarg = sdscatlen(curarg,c,1); - if (newarg == NULL) goto memory_err; - curarg = newarg; - touched = 1; - } - } else { - char *arg; - size_t size; - - /* Set newarg so it can be checked even if it is not touched. */ - newarg = curarg; - - switch(c[1]) { - case 's': - arg = va_arg(ap,char*); - size = strlen(arg); - if (size > 0) - newarg = sdscatlen(curarg,arg,size); - break; - case 'b': - arg = va_arg(ap,char*); - size = va_arg(ap,size_t); - if (size > 0) - newarg = sdscatlen(curarg,arg,size); - break; - case '%': - newarg = sdscat(curarg,"%"); - break; - default: - /* Try to detect printf format */ - { - static const char intfmts[] = "diouxX"; - static const char flags[] = "#0-+ "; - char _format[16]; - const char *_p = c+1; - size_t _l = 0; - va_list _cpy; - - /* Flags */ - while (*_p != '\0' && strchr(flags,*_p) != NULL) _p++; - - /* Field width */ - while (*_p != '\0' && isdigit(*_p)) _p++; - - /* Precision */ - if (*_p == '.') { - _p++; - while (*_p != '\0' && isdigit(*_p)) _p++; - } - - /* Copy va_list before consuming with va_arg */ - va_copy(_cpy,ap); - - /* Integer conversion (without modifiers) */ - if (strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); - goto fmt_valid; - } - - /* Double conversion (without modifiers) */ - if (strchr("eEfFgGaA",*_p) != NULL) { - va_arg(ap,double); - goto fmt_valid; - } - - /* Size: char */ - if (_p[0] == 'h' && _p[1] == 'h') { - _p += 2; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); /* char gets promoted to int */ - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: short */ - if (_p[0] == 'h') { - _p += 1; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,int); /* short gets promoted to int */ - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: long long */ - if (_p[0] == 'l' && _p[1] == 'l') { - _p += 2; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,long long); - goto fmt_valid; - } - goto fmt_invalid; - } - - /* Size: long */ - if (_p[0] == 'l') { - _p += 1; - if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { - va_arg(ap,long); - goto fmt_valid; - } - goto fmt_invalid; - } - - fmt_invalid: - va_end(_cpy); - goto format_err; - - fmt_valid: - _l = (_p+1)-c; - if (_l < sizeof(_format)-2) { - memcpy(_format,c,_l); - _format[_l] = '\0'; - newarg = sdscatvprintf(curarg,_format,_cpy); - - /* Update current position (note: outer blocks - * increment c twice so compensate here) */ - c = _p-1; - } - - va_end(_cpy); - break; - } - } - - if (newarg == NULL) goto memory_err; - curarg = newarg; - - touched = 1; - c++; - } - c++; - } - - /* Add the last argument if needed */ - if (touched) { - newargv = hi_realloc(curargv,sizeof(char*)*(argc+1)); - if (newargv == NULL) goto memory_err; - curargv = newargv; - curargv[argc++] = curarg; - totlen += bulklen(sdslen(curarg)); - } else { - sdsfree(curarg); - } - - /* Clear curarg because it was put in curargv or was free'd. */ - curarg = NULL; - - /* Add bytes needed to hold multi bulk count */ - totlen += 1+countDigits(argc)+2; - - /* Build the command at protocol level */ - cmd = hi_malloc(totlen+1); - if (cmd == NULL) goto memory_err; - - pos = sprintf(cmd,"*%d\r\n",argc); - for (j = 0; j < argc; j++) { - pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(curargv[j])); - memcpy(cmd+pos,curargv[j],sdslen(curargv[j])); - pos += sdslen(curargv[j]); - sdsfree(curargv[j]); - cmd[pos++] = '\r'; - cmd[pos++] = '\n'; - } - assert(pos == totlen); - cmd[pos] = '\0'; - - hi_free(curargv); - *target = cmd; - return totlen; - -format_err: - error_type = -2; - goto cleanup; - -memory_err: - error_type = -1; - goto cleanup; - -cleanup: - if (curargv) { - while(argc--) - sdsfree(curargv[argc]); - hi_free(curargv); - } - - sdsfree(curarg); - hi_free(cmd); - - return error_type; -} - -/* Format a command according to the Redis protocol. This function - * takes a format similar to printf: - * - * %s represents a C null terminated string you want to interpolate - * %b represents a binary safe string - * - * When using %b you need to provide both the pointer to the string - * and the length in bytes as a size_t. Examples: - * - * len = redisFormatCommand(target, "GET %s", mykey); - * len = redisFormatCommand(target, "SET %s %b", mykey, myval, myvallen); - */ -int redisFormatCommand(char **target, const char *format, ...) { - va_list ap; - int len; - va_start(ap,format); - len = redisvFormatCommand(target,format,ap); - va_end(ap); - - /* The API says "-1" means bad result, but we now also return "-2" in some - * cases. Force the return value to always be -1. */ - if (len < 0) - len = -1; - - return len; -} - -/* Format a command according to the Redis protocol using an sds string and - * sdscatfmt for the processing of arguments. This function takes the - * number of arguments, an array with arguments and an array with their - * lengths. If the latter is set to NULL, strlen will be used to compute the - * argument lengths. - */ -int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv, - const size_t *argvlen) -{ - sds cmd, aux; - unsigned long long totlen; - int j; - size_t len; - - /* Abort on a NULL target */ - if (target == NULL) - return -1; - - /* Calculate our total size */ - totlen = 1+countDigits(argc)+2; - for (j = 0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - totlen += bulklen(len); - } - - /* Use an SDS string for command construction */ - cmd = sdsempty(); - if (cmd == NULL) - return -1; - - /* We already know how much storage we need */ - aux = sdsMakeRoomFor(cmd, totlen); - if (aux == NULL) { - sdsfree(cmd); - return -1; - } - - cmd = aux; - - /* Construct command */ - cmd = sdscatfmt(cmd, "*%i\r\n", argc); - for (j=0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - cmd = sdscatfmt(cmd, "$%u\r\n", len); - cmd = sdscatlen(cmd, argv[j], len); - cmd = sdscatlen(cmd, "\r\n", sizeof("\r\n")-1); - } - - assert(sdslen(cmd)==totlen); - - *target = cmd; - return totlen; -} - -void redisFreeSdsCommand(sds cmd) { - sdsfree(cmd); -} - -/* Format a command according to the Redis protocol. This function takes the - * number of arguments, an array with arguments and an array with their - * lengths. If the latter is set to NULL, strlen will be used to compute the - * argument lengths. - */ -int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen) { - char *cmd = NULL; /* final command */ - int pos; /* position in final command */ - size_t len; - int totlen, j; - - /* Abort on a NULL target */ - if (target == NULL) - return -1; - - /* Calculate number of bytes needed for the command */ - totlen = 1+countDigits(argc)+2; - for (j = 0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - totlen += bulklen(len); - } - - /* Build the command at protocol level */ - cmd = hi_malloc(totlen+1); - if (cmd == NULL) - return -1; - - pos = sprintf(cmd,"*%d\r\n",argc); - for (j = 0; j < argc; j++) { - len = argvlen ? argvlen[j] : strlen(argv[j]); - pos += sprintf(cmd+pos,"$%zu\r\n",len); - memcpy(cmd+pos,argv[j],len); - pos += len; - cmd[pos++] = '\r'; - cmd[pos++] = '\n'; - } - assert(pos == totlen); - cmd[pos] = '\0'; - - *target = cmd; - return totlen; -} - -void redisFreeCommand(char *cmd) { - hi_free(cmd); -} - -void __redisSetError(redisContext *c, int type, const char *str) { - size_t len; - - c->err = type; - if (str != NULL) { - len = strlen(str); - len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1); - memcpy(c->errstr,str,len); - c->errstr[len] = '\0'; - } else { - /* Only REDIS_ERR_IO may lack a description! */ - assert(type == REDIS_ERR_IO); - strerror_r(errno, c->errstr, sizeof(c->errstr)); - } -} - -redisReader *redisReaderCreate(void) { - return redisReaderCreateWithFunctions(&defaultFunctions); -} - -static void redisPushAutoFree(void *privdata, void *reply) { - (void)privdata; - freeReplyObject(reply); -} - -static redisContext *redisContextInit(void) { - redisContext *c; - - c = hi_calloc(1, sizeof(*c)); - if (c == NULL) - return NULL; - - c->funcs = &redisContextDefaultFuncs; - - c->obuf = sdsempty(); - c->reader = redisReaderCreate(); - c->fd = REDIS_INVALID_FD; - - if (c->obuf == NULL || c->reader == NULL) { - redisFree(c); - return NULL; - } - - return c; -} - -void redisFree(redisContext *c) { - if (c == NULL) - return; - redisNetClose(c); - - sdsfree(c->obuf); - redisReaderFree(c->reader); - hi_free(c->tcp.host); - hi_free(c->tcp.source_addr); - hi_free(c->unix_sock.path); - hi_free(c->connect_timeout); - hi_free(c->command_timeout); - hi_free(c->saddr); - - if (c->privdata && c->free_privdata) - c->free_privdata(c->privdata); - - if (c->funcs->free_privctx) - c->funcs->free_privctx(c->privctx); - - memset(c, 0xff, sizeof(*c)); - hi_free(c); -} - -redisFD redisFreeKeepFd(redisContext *c) { - redisFD fd = c->fd; - c->fd = REDIS_INVALID_FD; - redisFree(c); - return fd; -} - -int redisReconnect(redisContext *c) { - c->err = 0; - memset(c->errstr, '\0', strlen(c->errstr)); - - if (c->privctx && c->funcs->free_privctx) { - c->funcs->free_privctx(c->privctx); - c->privctx = NULL; - } - - redisNetClose(c); - - sdsfree(c->obuf); - redisReaderFree(c->reader); - - c->obuf = sdsempty(); - c->reader = redisReaderCreate(); - - if (c->obuf == NULL || c->reader == NULL) { - __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); - return REDIS_ERR; - } - - int ret = REDIS_ERR; - if (c->connection_type == REDIS_CONN_TCP) { - ret = redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port, - c->connect_timeout, c->tcp.source_addr); - } else if (c->connection_type == REDIS_CONN_UNIX) { - ret = redisContextConnectUnix(c, c->unix_sock.path, c->connect_timeout); - } else { - /* Something bad happened here and shouldn't have. There isn't - enough information in the context to reconnect. */ - __redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect"); - ret = REDIS_ERR; - } - - if (c->command_timeout != NULL && (c->flags & REDIS_BLOCK) && c->fd != REDIS_INVALID_FD) { - redisContextSetTimeout(c, *c->command_timeout); - } - - return ret; -} - -redisContext *redisConnectWithOptions(const redisOptions *options) { - redisContext *c = redisContextInit(); - if (c == NULL) { - return NULL; - } - if (!(options->options & REDIS_OPT_NONBLOCK)) { - c->flags |= REDIS_BLOCK; - } - if (options->options & REDIS_OPT_REUSEADDR) { - c->flags |= REDIS_REUSEADDR; - } - if (options->options & REDIS_OPT_NOAUTOFREE) { - c->flags |= REDIS_NO_AUTO_FREE; - } - - /* Set any user supplied RESP3 PUSH handler or use freeReplyObject - * as a default unless specifically flagged that we don't want one. */ - if (options->push_cb != NULL) - redisSetPushCallback(c, options->push_cb); - else if (!(options->options & REDIS_OPT_NO_PUSH_AUTOFREE)) - redisSetPushCallback(c, redisPushAutoFree); - - c->privdata = options->privdata; - c->free_privdata = options->free_privdata; - - if (redisContextUpdateConnectTimeout(c, options->connect_timeout) != REDIS_OK || - redisContextUpdateCommandTimeout(c, options->command_timeout) != REDIS_OK) { - __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); - return c; - } - - if (options->type == REDIS_CONN_TCP) { - redisContextConnectBindTcp(c, options->endpoint.tcp.ip, - options->endpoint.tcp.port, options->connect_timeout, - options->endpoint.tcp.source_addr); - } else if (options->type == REDIS_CONN_UNIX) { - redisContextConnectUnix(c, options->endpoint.unix_socket, - options->connect_timeout); - } else if (options->type == REDIS_CONN_USERFD) { - c->fd = options->endpoint.fd; - c->flags |= REDIS_CONNECTED; - } else { - // Unknown type - FIXME - FREE - return NULL; - } - - if (options->command_timeout != NULL && (c->flags & REDIS_BLOCK) && c->fd != REDIS_INVALID_FD) { - redisContextSetTimeout(c, *options->command_timeout); - } - - return c; -} - -/* Connect to a Redis instance. On error the field error in the returned - * context will be set to the return value of the error function. - * When no set of reply functions is given, the default set will be used. */ -redisContext *redisConnect(const char *ip, int port) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, ip, port); - return redisConnectWithOptions(&options); -} - -redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, ip, port); - options.connect_timeout = &tv; - return redisConnectWithOptions(&options); -} - -redisContext *redisConnectNonBlock(const char *ip, int port) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, ip, port); - options.options |= REDIS_OPT_NONBLOCK; - return redisConnectWithOptions(&options); -} - -redisContext *redisConnectBindNonBlock(const char *ip, int port, - const char *source_addr) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, ip, port); - options.endpoint.tcp.source_addr = source_addr; - options.options |= REDIS_OPT_NONBLOCK; - return redisConnectWithOptions(&options); -} - -redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, - const char *source_addr) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, ip, port); - options.endpoint.tcp.source_addr = source_addr; - options.options |= REDIS_OPT_NONBLOCK|REDIS_OPT_REUSEADDR; - return redisConnectWithOptions(&options); -} - -redisContext *redisConnectUnix(const char *path) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_UNIX(&options, path); - return redisConnectWithOptions(&options); -} - -redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_UNIX(&options, path); - options.connect_timeout = &tv; - return redisConnectWithOptions(&options); -} - -redisContext *redisConnectUnixNonBlock(const char *path) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_UNIX(&options, path); - options.options |= REDIS_OPT_NONBLOCK; - return redisConnectWithOptions(&options); -} - -redisContext *redisConnectFd(redisFD fd) { - redisOptions options = {0}; - options.type = REDIS_CONN_USERFD; - options.endpoint.fd = fd; - return redisConnectWithOptions(&options); -} - -/* Set read/write timeout on a blocking socket. */ -int redisSetTimeout(redisContext *c, const struct timeval tv) { - if (c->flags & REDIS_BLOCK) - return redisContextSetTimeout(c,tv); - return REDIS_ERR; -} - -/* Enable connection KeepAlive. */ -int redisEnableKeepAlive(redisContext *c) { - if (redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL) != REDIS_OK) - return REDIS_ERR; - return REDIS_OK; -} - -/* Set a user provided RESP3 PUSH handler and return any old one set. */ -redisPushFn *redisSetPushCallback(redisContext *c, redisPushFn *fn) { - redisPushFn *old = c->push_cb; - c->push_cb = fn; - return old; -} - -/* Use this function to handle a read event on the descriptor. It will try - * and read some bytes from the socket and feed them to the reply parser. - * - * After this function is called, you may use redisGetReplyFromReader to - * see if there is a reply available. */ -int redisBufferRead(redisContext *c) { - char buf[1024*16]; - int nread; - - /* Return early when the context has seen an error. */ - if (c->err) - return REDIS_ERR; - - nread = c->funcs->read(c, buf, sizeof(buf)); - if (nread > 0) { - if (redisReaderFeed(c->reader, buf, nread) != REDIS_OK) { - __redisSetError(c, c->reader->err, c->reader->errstr); - return REDIS_ERR; - } else { - } - } else if (nread < 0) { - return REDIS_ERR; - } - return REDIS_OK; -} - -/* Write the output buffer to the socket. - * - * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was - * successfully written to the socket. When the buffer is empty after the - * write operation, "done" is set to 1 (if given). - * - * Returns REDIS_ERR if an error occurred trying to write and sets - * c->errstr to hold the appropriate error string. - */ -int redisBufferWrite(redisContext *c, int *done) { - - /* Return early when the context has seen an error. */ - if (c->err) - return REDIS_ERR; - - if (sdslen(c->obuf) > 0) { - ssize_t nwritten = c->funcs->write(c); - if (nwritten < 0) { - return REDIS_ERR; - } else if (nwritten > 0) { - if (nwritten == (ssize_t)sdslen(c->obuf)) { - sdsfree(c->obuf); - c->obuf = sdsempty(); - if (c->obuf == NULL) - goto oom; - } else { - if (sdsrange(c->obuf,nwritten,-1) < 0) goto oom; - } - } - } - if (done != NULL) *done = (sdslen(c->obuf) == 0); - return REDIS_OK; - -oom: - __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); - return REDIS_ERR; -} - -/* Internal helper function to try and get a reply from the reader, - * or set an error in the context otherwise. */ -int redisGetReplyFromReader(redisContext *c, void **reply) { - if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { - __redisSetError(c,c->reader->err,c->reader->errstr); - return REDIS_ERR; - } - - return REDIS_OK; -} - -/* Internal helper that returns 1 if the reply was a RESP3 PUSH - * message and we handled it with a user-provided callback. */ -static int redisHandledPushReply(redisContext *c, void *reply) { - if (reply && c->push_cb && redisIsPushReply(reply)) { - c->push_cb(c->privdata, reply); - return 1; - } - - return 0; -} - -int redisGetReply(redisContext *c, void **reply) { - int wdone = 0; - void *aux = NULL; - - /* Try to read pending replies */ - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) - return REDIS_ERR; - - /* For the blocking context, flush output buffer and read reply */ - if (aux == NULL && c->flags & REDIS_BLOCK) { - /* Write until done */ - do { - if (redisBufferWrite(c,&wdone) == REDIS_ERR) - return REDIS_ERR; - } while (!wdone); - - /* Read until there is a reply */ - do { - if (redisBufferRead(c) == REDIS_ERR) - return REDIS_ERR; - - /* We loop here in case the user has specified a RESP3 - * PUSH handler (e.g. for client tracking). */ - do { - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) - return REDIS_ERR; - } while (redisHandledPushReply(c, aux)); - } while (aux == NULL); - } - - /* Set reply or free it if we were passed NULL */ - if (reply != NULL) { - *reply = aux; - } else { - freeReplyObject(aux); - } - - return REDIS_OK; -} - - -/* Helper function for the redisAppendCommand* family of functions. - * - * Write a formatted command to the output buffer. When this family - * is used, you need to call redisGetReply yourself to retrieve - * the reply (or replies in pub/sub). - */ -int __redisAppendCommand(redisContext *c, const char *cmd, size_t len) { - sds newbuf; - - newbuf = sdscatlen(c->obuf,cmd,len); - if (newbuf == NULL) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } - - c->obuf = newbuf; - return REDIS_OK; -} - -int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len) { - - if (__redisAppendCommand(c, cmd, len) != REDIS_OK) { - return REDIS_ERR; - } - - return REDIS_OK; -} - -int redisvAppendCommand(redisContext *c, const char *format, va_list ap) { - char *cmd; - int len; - - len = redisvFormatCommand(&cmd,format,ap); - if (len == -1) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } else if (len == -2) { - __redisSetError(c,REDIS_ERR_OTHER,"Invalid format string"); - return REDIS_ERR; - } - - if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { - hi_free(cmd); - return REDIS_ERR; - } - - hi_free(cmd); - return REDIS_OK; -} - -int redisAppendCommand(redisContext *c, const char *format, ...) { - va_list ap; - int ret; - - va_start(ap,format); - ret = redisvAppendCommand(c,format,ap); - va_end(ap); - return ret; -} - -int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { - sds cmd; - int len; - - len = redisFormatSdsCommandArgv(&cmd,argc,argv,argvlen); - if (len == -1) { - __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); - return REDIS_ERR; - } - - if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { - sdsfree(cmd); - return REDIS_ERR; - } - - sdsfree(cmd); - return REDIS_OK; -} - -/* Helper function for the redisCommand* family of functions. - * - * Write a formatted command to the output buffer. If the given context is - * blocking, immediately read the reply into the "reply" pointer. When the - * context is non-blocking, the "reply" pointer will not be used and the - * command is simply appended to the write buffer. - * - * Returns the reply when a reply was successfully retrieved. Returns NULL - * otherwise. When NULL is returned in a blocking context, the error field - * in the context will be set. - */ -static void *__redisBlockForReply(redisContext *c) { - void *reply; - - if (c->flags & REDIS_BLOCK) { - if (redisGetReply(c,&reply) != REDIS_OK) - return NULL; - return reply; - } - return NULL; -} - -void *redisvCommand(redisContext *c, const char *format, va_list ap) { - if (redisvAppendCommand(c,format,ap) != REDIS_OK) - return NULL; - return __redisBlockForReply(c); -} - -void *redisCommand(redisContext *c, const char *format, ...) { - va_list ap; - va_start(ap,format); - void *reply = redisvCommand(c,format,ap); - va_end(ap); - return reply; -} - -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { - if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK) - return NULL; - return __redisBlockForReply(c); -} diff --git a/ext/hiredis-1.0.2/hiredis.h b/ext/hiredis-1.0.2/hiredis.h deleted file mode 100644 index 3bc46d992..000000000 --- a/ext/hiredis-1.0.2/hiredis.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_H -#define __HIREDIS_H -#include "read.h" -#include /* for va_list */ -#ifndef _MSC_VER -#include /* for struct timeval */ -#else -struct timeval; /* forward declaration */ -typedef long long ssize_t; -#endif -#include /* uintXX_t, etc */ -#include "sds.h" /* for sds */ -#include "alloc.h" /* for allocation wrappers */ - -#define HIREDIS_MAJOR 1 -#define HIREDIS_MINOR 0 -#define HIREDIS_PATCH 2 -#define HIREDIS_SONAME 1.0.0 - -/* Connection type can be blocking or non-blocking and is set in the - * least significant bit of the flags field in redisContext. */ -#define REDIS_BLOCK 0x1 - -/* Connection may be disconnected before being free'd. The second bit - * in the flags field is set when the context is connected. */ -#define REDIS_CONNECTED 0x2 - -/* The async API might try to disconnect cleanly and flush the output - * buffer and read all subsequent replies before disconnecting. - * This flag means no new commands can come in and the connection - * should be terminated once all replies have been read. */ -#define REDIS_DISCONNECTING 0x4 - -/* Flag specific to the async API which means that the context should be clean - * up as soon as possible. */ -#define REDIS_FREEING 0x8 - -/* Flag that is set when an async callback is executed. */ -#define REDIS_IN_CALLBACK 0x10 - -/* Flag that is set when the async context has one or more subscriptions. */ -#define REDIS_SUBSCRIBED 0x20 - -/* Flag that is set when monitor mode is active */ -#define REDIS_MONITORING 0x40 - -/* Flag that is set when we should set SO_REUSEADDR before calling bind() */ -#define REDIS_REUSEADDR 0x80 - -/** - * Flag that indicates the user does not want the context to - * be automatically freed upon error - */ -#define REDIS_NO_AUTO_FREE 0x200 - -#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ - -/* number of times we retry to connect in the case of EADDRNOTAVAIL and - * SO_REUSEADDR is being used. */ -#define REDIS_CONNECT_RETRIES 10 - -/* Forward declarations for structs defined elsewhere */ -struct redisAsyncContext; -struct redisContext; - -/* RESP3 push helpers and callback prototypes */ -#define redisIsPushReply(r) (((redisReply*)(r))->type == REDIS_REPLY_PUSH) -typedef void (redisPushFn)(void *, void *); -typedef void (redisAsyncPushFn)(struct redisAsyncContext *, void *); - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the reply object returned by redisCommand() */ -typedef struct redisReply { - int type; /* REDIS_REPLY_* */ - long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ - double dval; /* The double when type is REDIS_REPLY_DOUBLE */ - size_t len; /* Length of string */ - char *str; /* Used for REDIS_REPLY_ERROR, REDIS_REPLY_STRING - REDIS_REPLY_VERB, and REDIS_REPLY_DOUBLE (in additional to dval). */ - char vtype[4]; /* Used for REDIS_REPLY_VERB, contains the null - terminated 3 character content type, such as "txt". */ - size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ - struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ -} redisReply; - -redisReader *redisReaderCreate(void); - -/* Function to free the reply objects hiredis returns by default. */ -void freeReplyObject(void *reply); - -/* Functions to format a command according to the protocol. */ -int redisvFormatCommand(char **target, const char *format, va_list ap); -int redisFormatCommand(char **target, const char *format, ...); -int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); -int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen); -void redisFreeCommand(char *cmd); -void redisFreeSdsCommand(sds cmd); - -enum redisConnectionType { - REDIS_CONN_TCP, - REDIS_CONN_UNIX, - REDIS_CONN_USERFD -}; - -struct redisSsl; - -#define REDIS_OPT_NONBLOCK 0x01 -#define REDIS_OPT_REUSEADDR 0x02 - -/** - * Don't automatically free the async object on a connection failure, - * or other implicit conditions. Only free on an explicit call to disconnect() or free() - */ -#define REDIS_OPT_NOAUTOFREE 0x04 - -/* Don't automatically intercept and free RESP3 PUSH replies. */ -#define REDIS_OPT_NO_PUSH_AUTOFREE 0x08 - -/* In Unix systems a file descriptor is a regular signed int, with -1 - * representing an invalid descriptor. In Windows it is a SOCKET - * (32- or 64-bit unsigned integer depending on the architecture), where - * all bits set (~0) is INVALID_SOCKET. */ -#ifndef _WIN32 -typedef int redisFD; -#define REDIS_INVALID_FD -1 -#else -#ifdef _WIN64 -typedef unsigned long long redisFD; /* SOCKET = 64-bit UINT_PTR */ -#else -typedef unsigned long redisFD; /* SOCKET = 32-bit UINT_PTR */ -#endif -#define REDIS_INVALID_FD ((redisFD)(~0)) /* INVALID_SOCKET */ -#endif - -typedef struct { - /* - * the type of connection to use. This also indicates which - * `endpoint` member field to use - */ - int type; - /* bit field of REDIS_OPT_xxx */ - int options; - /* timeout value for connect operation. If NULL, no timeout is used */ - const struct timeval *connect_timeout; - /* timeout value for commands. If NULL, no timeout is used. This can be - * updated at runtime with redisSetTimeout/redisAsyncSetTimeout. */ - const struct timeval *command_timeout; - union { - /** use this field for tcp/ip connections */ - struct { - const char *source_addr; - const char *ip; - int port; - } tcp; - /** use this field for unix domain sockets */ - const char *unix_socket; - /** - * use this field to have hiredis operate an already-open - * file descriptor */ - redisFD fd; - } endpoint; - - /* Optional user defined data/destructor */ - void *privdata; - void (*free_privdata)(void *); - - /* A user defined PUSH message callback */ - redisPushFn *push_cb; - redisAsyncPushFn *async_push_cb; -} redisOptions; - -/** - * Helper macros to initialize options to their specified fields. - */ -#define REDIS_OPTIONS_SET_TCP(opts, ip_, port_) \ - (opts)->type = REDIS_CONN_TCP; \ - (opts)->endpoint.tcp.ip = ip_; \ - (opts)->endpoint.tcp.port = port_; - -#define REDIS_OPTIONS_SET_UNIX(opts, path) \ - (opts)->type = REDIS_CONN_UNIX; \ - (opts)->endpoint.unix_socket = path; - -#define REDIS_OPTIONS_SET_PRIVDATA(opts, data, dtor) \ - (opts)->privdata = data; \ - (opts)->free_privdata = dtor; \ - -typedef struct redisContextFuncs { - void (*free_privctx)(void *); - void (*async_read)(struct redisAsyncContext *); - void (*async_write)(struct redisAsyncContext *); - ssize_t (*read)(struct redisContext *, char *, size_t); - ssize_t (*write)(struct redisContext *); -} redisContextFuncs; - -/* Context for a connection to Redis */ -typedef struct redisContext { - const redisContextFuncs *funcs; /* Function table */ - - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - redisFD fd; - int flags; - char *obuf; /* Write buffer */ - redisReader *reader; /* Protocol reader */ - - enum redisConnectionType connection_type; - struct timeval *connect_timeout; - struct timeval *command_timeout; - - struct { - char *host; - char *source_addr; - int port; - } tcp; - - struct { - char *path; - } unix_sock; - - /* For non-blocking connect */ - struct sockadr *saddr; - size_t addrlen; - - /* Optional data and corresponding destructor users can use to provide - * context to a given redisContext. Not used by hiredis. */ - void *privdata; - void (*free_privdata)(void *); - - /* Internal context pointer presently used by hiredis to manage - * SSL connections. */ - void *privctx; - - /* An optional RESP3 PUSH handler */ - redisPushFn *push_cb; -} redisContext; - -redisContext *redisConnectWithOptions(const redisOptions *options); -redisContext *redisConnect(const char *ip, int port); -redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); -redisContext *redisConnectNonBlock(const char *ip, int port); -redisContext *redisConnectBindNonBlock(const char *ip, int port, - const char *source_addr); -redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, - const char *source_addr); -redisContext *redisConnectUnix(const char *path); -redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); -redisContext *redisConnectUnixNonBlock(const char *path); -redisContext *redisConnectFd(redisFD fd); - -/** - * Reconnect the given context using the saved information. - * - * This re-uses the exact same connect options as in the initial connection. - * host, ip (or path), timeout and bind address are reused, - * flags are used unmodified from the existing context. - * - * Returns REDIS_OK on successful connect or REDIS_ERR otherwise. - */ -int redisReconnect(redisContext *c); - -redisPushFn *redisSetPushCallback(redisContext *c, redisPushFn *fn); -int redisSetTimeout(redisContext *c, const struct timeval tv); -int redisEnableKeepAlive(redisContext *c); -void redisFree(redisContext *c); -redisFD redisFreeKeepFd(redisContext *c); -int redisBufferRead(redisContext *c); -int redisBufferWrite(redisContext *c, int *done); - -/* In a blocking context, this function first checks if there are unconsumed - * replies to return and returns one if so. Otherwise, it flushes the output - * buffer to the socket and reads until it has a reply. In a non-blocking - * context, it will return unconsumed replies until there are no more. */ -int redisGetReply(redisContext *c, void **reply); -int redisGetReplyFromReader(redisContext *c, void **reply); - -/* Write a formatted command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); - -/* Write a command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisvAppendCommand(redisContext *c, const char *format, va_list ap); -int redisAppendCommand(redisContext *c, const char *format, ...); -int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -/* Issue a command to Redis. In a blocking context, it is identical to calling - * redisAppendCommand, followed by redisGetReply. The function will return - * NULL if there was an error in performing the request, otherwise it will - * return the reply. In a non-blocking context, it is identical to calling - * only redisAppendCommand and will always return NULL. */ -void *redisvCommand(redisContext *c, const char *format, va_list ap); -void *redisCommand(redisContext *c, const char *format, ...); -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-1.0.2/hiredis.pc.in b/ext/hiredis-1.0.2/hiredis.pc.in deleted file mode 100644 index 91b773183..000000000 --- a/ext/hiredis-1.0.2/hiredis.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -install_libdir=@CMAKE_INSTALL_LIBDIR@ -exec_prefix=${prefix} -libdir=${exec_prefix}/${install_libdir} -includedir=${prefix}/include -pkgincludedir=${includedir}/hiredis - -Name: hiredis -Description: Minimalistic C client library for Redis. -Version: @PROJECT_VERSION@ -Libs: -L${libdir} -lhiredis -Cflags: -I${pkgincludedir} -D_FILE_OFFSET_BITS=64 diff --git a/ext/hiredis-1.0.2/hiredis_ssl-config.cmake.in b/ext/hiredis-1.0.2/hiredis_ssl-config.cmake.in deleted file mode 100644 index 9a283dfc2..000000000 --- a/ext/hiredis-1.0.2/hiredis_ssl-config.cmake.in +++ /dev/null @@ -1,13 +0,0 @@ -@PACKAGE_INIT@ - -set_and_check(hiredis_ssl_INCLUDEDIR "@PACKAGE_INCLUDE_INSTALL_DIR@") - -IF (NOT TARGET hiredis::hiredis_ssl) - INCLUDE(${CMAKE_CURRENT_LIST_DIR}/hiredis_ssl-targets.cmake) -ENDIF() - -SET(hiredis_ssl_LIBRARIES hiredis::hiredis_ssl) -SET(hiredis_ssl_INCLUDE_DIRS ${hiredis_ssl_INCLUDEDIR}) - -check_required_components(hiredis_ssl) - diff --git a/ext/hiredis-1.0.2/hiredis_ssl.h b/ext/hiredis-1.0.2/hiredis_ssl.h deleted file mode 100644 index 604efe0c1..000000000 --- a/ext/hiredis-1.0.2/hiredis_ssl.h +++ /dev/null @@ -1,127 +0,0 @@ - -/* - * Copyright (c) 2019, Redis Labs - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_SSL_H -#define __HIREDIS_SSL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the underlying struct for SSL in ssl.h, which is not included to - * keep build dependencies short here. - */ -struct ssl_st; - -/* A wrapper around OpenSSL SSL_CTX to allow easy SSL use without directly - * calling OpenSSL. - */ -typedef struct redisSSLContext redisSSLContext; - -/** - * Initialization errors that redisCreateSSLContext() may return. - */ - -typedef enum { - REDIS_SSL_CTX_NONE = 0, /* No Error */ - REDIS_SSL_CTX_CREATE_FAILED, /* Failed to create OpenSSL SSL_CTX */ - REDIS_SSL_CTX_CERT_KEY_REQUIRED, /* Client cert and key must both be specified or skipped */ - REDIS_SSL_CTX_CA_CERT_LOAD_FAILED, /* Failed to load CA Certificate or CA Path */ - REDIS_SSL_CTX_CLIENT_CERT_LOAD_FAILED, /* Failed to load client certificate */ - REDIS_SSL_CTX_PRIVATE_KEY_LOAD_FAILED /* Failed to load private key */ -} redisSSLContextError; - -/** - * Return the error message corresponding with the specified error code. - */ - -const char *redisSSLContextGetError(redisSSLContextError error); - -/** - * Helper function to initialize the OpenSSL library. - * - * OpenSSL requires one-time initialization before it can be used. Callers should - * call this function only once, and only if OpenSSL is not directly initialized - * elsewhere. - */ -int redisInitOpenSSL(void); - -/** - * Helper function to initialize an OpenSSL context that can be used - * to initiate SSL connections. - * - * cacert_filename is an optional name of a CA certificate/bundle file to load - * and use for validation. - * - * capath is an optional directory path where trusted CA certificate files are - * stored in an OpenSSL-compatible structure. - * - * cert_filename and private_key_filename are optional names of a client side - * certificate and private key files to use for authentication. They need to - * be both specified or omitted. - * - * server_name is an optional and will be used as a server name indication - * (SNI) TLS extension. - * - * If error is non-null, it will be populated in case the context creation fails - * (returning a NULL). - */ - -redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char *capath, - const char *cert_filename, const char *private_key_filename, - const char *server_name, redisSSLContextError *error); - -/** - * Free a previously created OpenSSL context. - */ -void redisFreeSSLContext(redisSSLContext *redis_ssl_ctx); - -/** - * Initiate SSL on an existing redisContext. - * - * This is similar to redisInitiateSSL() but does not require the caller - * to directly interact with OpenSSL, and instead uses a redisSSLContext - * previously created using redisCreateSSLContext(). - */ - -int redisInitiateSSLWithContext(redisContext *c, redisSSLContext *redis_ssl_ctx); - -/** - * Initiate SSL/TLS negotiation on a provided OpenSSL SSL object. - */ - -int redisInitiateSSL(redisContext *c, struct ssl_st *ssl); - -#ifdef __cplusplus -} -#endif - -#endif /* __HIREDIS_SSL_H */ diff --git a/ext/hiredis-1.0.2/hiredis_ssl.pc.in b/ext/hiredis-1.0.2/hiredis_ssl.pc.in deleted file mode 100644 index 588a978a5..000000000 --- a/ext/hiredis-1.0.2/hiredis_ssl.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include -pkgincludedir=${includedir}/hiredis - -Name: hiredis_ssl -Description: SSL Support for hiredis. -Version: @PROJECT_VERSION@ -Requires: hiredis -Libs: -L${libdir} -lhiredis_ssl -Libs.private: -lssl -lcrypto diff --git a/ext/hiredis-1.0.2/include/hiredis/alloc.h b/ext/hiredis-1.0.2/include/hiredis/alloc.h deleted file mode 100644 index 34a05f49f..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/alloc.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2020, Michael Grunder - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HIREDIS_ALLOC_H -#define HIREDIS_ALLOC_H - -#include /* for size_t */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Structure pointing to our actually configured allocators */ -typedef struct hiredisAllocFuncs { - void *(*mallocFn)(size_t); - void *(*callocFn)(size_t,size_t); - void *(*reallocFn)(void*,size_t); - char *(*strdupFn)(const char*); - void (*freeFn)(void*); -} hiredisAllocFuncs; - -hiredisAllocFuncs hiredisSetAllocators(hiredisAllocFuncs *ha); -void hiredisResetAllocators(void); - -#ifndef _WIN32 - -/* Hiredis' configured allocator function pointer struct */ -extern hiredisAllocFuncs hiredisAllocFns; - -static inline void *hi_malloc(size_t size) { - return hiredisAllocFns.mallocFn(size); -} - -static inline void *hi_calloc(size_t nmemb, size_t size) { - return hiredisAllocFns.callocFn(nmemb, size); -} - -static inline void *hi_realloc(void *ptr, size_t size) { - return hiredisAllocFns.reallocFn(ptr, size); -} - -static inline char *hi_strdup(const char *str) { - return hiredisAllocFns.strdupFn(str); -} - -static inline void hi_free(void *ptr) { - hiredisAllocFns.freeFn(ptr); -} - -#else - -void *hi_malloc(size_t size); -void *hi_calloc(size_t nmemb, size_t size); -void *hi_realloc(void *ptr, size_t size); -char *hi_strdup(const char *str); -void hi_free(void *ptr); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* HIREDIS_ALLOC_H */ diff --git a/ext/hiredis-1.0.2/include/hiredis/async.h b/ext/hiredis-1.0.2/include/hiredis/async.h deleted file mode 100644 index b1d2cb263..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/async.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_ASYNC_H -#define __HIREDIS_ASYNC_H -#include "hiredis.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ -struct dict; /* dictionary header is included in async.c */ - -/* Reply callback prototype and container */ -typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); -typedef struct redisCallback { - struct redisCallback *next; /* simple singly linked list */ - redisCallbackFn *fn; - int pending_subs; - void *privdata; -} redisCallback; - -/* List of callbacks for either regular replies or pub/sub */ -typedef struct redisCallbackList { - redisCallback *head, *tail; -} redisCallbackList; - -/* Connection callback prototypes */ -typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); -typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); -typedef void(redisTimerCallback)(void *timer, void *privdata); - -/* Context for an async connection to Redis */ -typedef struct redisAsyncContext { - /* Hold the regular context, so it can be realloc'ed. */ - redisContext c; - - /* Setup error flags so they can be used directly. */ - int err; - char *errstr; - - /* Not used by hiredis */ - void *data; - void (*dataCleanup)(void *privdata); - - /* Event library data and hooks */ - struct { - void *data; - - /* Hooks that are called when the library expects to start - * reading/writing. These functions should be idempotent. */ - void (*addRead)(void *privdata); - void (*delRead)(void *privdata); - void (*addWrite)(void *privdata); - void (*delWrite)(void *privdata); - void (*cleanup)(void *privdata); - void (*scheduleTimer)(void *privdata, struct timeval tv); - } ev; - - /* Called when either the connection is terminated due to an error or per - * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */ - redisDisconnectCallback *onDisconnect; - - /* Called when the first write event was received. */ - redisConnectCallback *onConnect; - - /* Regular command callbacks */ - redisCallbackList replies; - - /* Address used for connect() */ - struct sockaddr *saddr; - size_t addrlen; - - /* Subscription callbacks */ - struct { - redisCallbackList invalid; - struct dict *channels; - struct dict *patterns; - } sub; - - /* Any configured RESP3 PUSH handler */ - redisAsyncPushFn *push_cb; -} redisAsyncContext; - -/* Functions that proxy to hiredis */ -redisAsyncContext *redisAsyncConnectWithOptions(const redisOptions *options); -redisAsyncContext *redisAsyncConnect(const char *ip, int port); -redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr); -redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port, - const char *source_addr); -redisAsyncContext *redisAsyncConnectUnix(const char *path); -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); - -redisAsyncPushFn *redisAsyncSetPushCallback(redisAsyncContext *ac, redisAsyncPushFn *fn); -int redisAsyncSetTimeout(redisAsyncContext *ac, struct timeval tv); -void redisAsyncDisconnect(redisAsyncContext *ac); -void redisAsyncFree(redisAsyncContext *ac); - -/* Handle read/write events */ -void redisAsyncHandleRead(redisAsyncContext *ac); -void redisAsyncHandleWrite(redisAsyncContext *ac); -void redisAsyncHandleTimeout(redisAsyncContext *ac); -void redisAsyncRead(redisAsyncContext *ac); -void redisAsyncWrite(redisAsyncContext *ac); - -/* Command functions for an async context. Write the command to the - * output buffer and register the provided callback. */ -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); -int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-1.0.2/include/hiredis/async_private.h b/ext/hiredis-1.0.2/include/hiredis/async_private.h deleted file mode 100644 index b9d23fffd..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/async_private.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_ASYNC_PRIVATE_H -#define __HIREDIS_ASYNC_PRIVATE_H - -#define _EL_ADD_READ(ctx) \ - do { \ - refreshTimeout(ctx); \ - if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \ - } while (0) -#define _EL_DEL_READ(ctx) do { \ - if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \ - } while(0) -#define _EL_ADD_WRITE(ctx) \ - do { \ - refreshTimeout(ctx); \ - if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \ - } while (0) -#define _EL_DEL_WRITE(ctx) do { \ - if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \ - } while(0) -#define _EL_CLEANUP(ctx) do { \ - if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \ - ctx->ev.cleanup = NULL; \ - } while(0); - -static inline void refreshTimeout(redisAsyncContext *ctx) { - #define REDIS_TIMER_ISSET(tvp) \ - (tvp && ((tvp)->tv_sec || (tvp)->tv_usec)) - - #define REDIS_EL_TIMER(ac, tvp) \ - if ((ac)->ev.scheduleTimer && REDIS_TIMER_ISSET(tvp)) { \ - (ac)->ev.scheduleTimer((ac)->ev.data, *(tvp)); \ - } - - if (ctx->c.flags & REDIS_CONNECTED) { - REDIS_EL_TIMER(ctx, ctx->c.command_timeout); - } else { - REDIS_EL_TIMER(ctx, ctx->c.connect_timeout); - } -} - -void __redisAsyncDisconnect(redisAsyncContext *ac); -void redisProcessCallbacks(redisAsyncContext *ac); - -#endif /* __HIREDIS_ASYNC_PRIVATE_H */ diff --git a/ext/hiredis-1.0.2/include/hiredis/dict.h b/ext/hiredis-1.0.2/include/hiredis/dict.h deleted file mode 100644 index 95fcd280e..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/dict.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DICT_H -#define __DICT_H - -#define DICT_OK 0 -#define DICT_ERR 1 - -/* Unused arguments generate annoying warnings... */ -#define DICT_NOTUSED(V) ((void) V) - -typedef struct dictEntry { - void *key; - void *val; - struct dictEntry *next; -} dictEntry; - -typedef struct dictType { - unsigned int (*hashFunction)(const void *key); - void *(*keyDup)(void *privdata, const void *key); - void *(*valDup)(void *privdata, const void *obj); - int (*keyCompare)(void *privdata, const void *key1, const void *key2); - void (*keyDestructor)(void *privdata, void *key); - void (*valDestructor)(void *privdata, void *obj); -} dictType; - -typedef struct dict { - dictEntry **table; - dictType *type; - unsigned long size; - unsigned long sizemask; - unsigned long used; - void *privdata; -} dict; - -typedef struct dictIterator { - dict *ht; - int index; - dictEntry *entry, *nextEntry; -} dictIterator; - -/* This is the initial size of every hash table */ -#define DICT_HT_INITIAL_SIZE 4 - -/* ------------------------------- Macros ------------------------------------*/ -#define dictFreeEntryVal(ht, entry) \ - if ((ht)->type->valDestructor) \ - (ht)->type->valDestructor((ht)->privdata, (entry)->val) - -#define dictSetHashVal(ht, entry, _val_) do { \ - if ((ht)->type->valDup) \ - entry->val = (ht)->type->valDup((ht)->privdata, _val_); \ - else \ - entry->val = (_val_); \ -} while(0) - -#define dictFreeEntryKey(ht, entry) \ - if ((ht)->type->keyDestructor) \ - (ht)->type->keyDestructor((ht)->privdata, (entry)->key) - -#define dictSetHashKey(ht, entry, _key_) do { \ - if ((ht)->type->keyDup) \ - entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ - else \ - entry->key = (_key_); \ -} while(0) - -#define dictCompareHashKeys(ht, key1, key2) \ - (((ht)->type->keyCompare) ? \ - (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ - (key1) == (key2)) - -#define dictHashKey(ht, key) (ht)->type->hashFunction(key) - -#define dictGetEntryKey(he) ((he)->key) -#define dictGetEntryVal(he) ((he)->val) -#define dictSlots(ht) ((ht)->size) -#define dictSize(ht) ((ht)->used) - -/* API */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len); -static dict *dictCreate(dictType *type, void *privDataPtr); -static int dictExpand(dict *ht, unsigned long size); -static int dictAdd(dict *ht, void *key, void *val); -static int dictReplace(dict *ht, void *key, void *val); -static int dictDelete(dict *ht, const void *key); -static void dictRelease(dict *ht); -static dictEntry * dictFind(dict *ht, const void *key); -static dictIterator *dictGetIterator(dict *ht); -static dictEntry *dictNext(dictIterator *iter); -static void dictReleaseIterator(dictIterator *iter); - -#endif /* __DICT_H */ diff --git a/ext/hiredis-1.0.2/include/hiredis/fmacros.h b/ext/hiredis-1.0.2/include/hiredis/fmacros.h deleted file mode 100644 index 3227faafd..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/fmacros.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __HIREDIS_FMACRO_H -#define __HIREDIS_FMACRO_H - -#define _XOPEN_SOURCE 600 -#define _POSIX_C_SOURCE 200112L - -#if defined(__APPLE__) && defined(__MACH__) -/* Enable TCP_KEEPALIVE */ -#define _DARWIN_C_SOURCE -#endif - -#endif diff --git a/ext/hiredis-1.0.2/include/hiredis/hiredis.h b/ext/hiredis-1.0.2/include/hiredis/hiredis.h deleted file mode 100644 index 3bc46d992..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/hiredis.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_H -#define __HIREDIS_H -#include "read.h" -#include /* for va_list */ -#ifndef _MSC_VER -#include /* for struct timeval */ -#else -struct timeval; /* forward declaration */ -typedef long long ssize_t; -#endif -#include /* uintXX_t, etc */ -#include "sds.h" /* for sds */ -#include "alloc.h" /* for allocation wrappers */ - -#define HIREDIS_MAJOR 1 -#define HIREDIS_MINOR 0 -#define HIREDIS_PATCH 2 -#define HIREDIS_SONAME 1.0.0 - -/* Connection type can be blocking or non-blocking and is set in the - * least significant bit of the flags field in redisContext. */ -#define REDIS_BLOCK 0x1 - -/* Connection may be disconnected before being free'd. The second bit - * in the flags field is set when the context is connected. */ -#define REDIS_CONNECTED 0x2 - -/* The async API might try to disconnect cleanly and flush the output - * buffer and read all subsequent replies before disconnecting. - * This flag means no new commands can come in and the connection - * should be terminated once all replies have been read. */ -#define REDIS_DISCONNECTING 0x4 - -/* Flag specific to the async API which means that the context should be clean - * up as soon as possible. */ -#define REDIS_FREEING 0x8 - -/* Flag that is set when an async callback is executed. */ -#define REDIS_IN_CALLBACK 0x10 - -/* Flag that is set when the async context has one or more subscriptions. */ -#define REDIS_SUBSCRIBED 0x20 - -/* Flag that is set when monitor mode is active */ -#define REDIS_MONITORING 0x40 - -/* Flag that is set when we should set SO_REUSEADDR before calling bind() */ -#define REDIS_REUSEADDR 0x80 - -/** - * Flag that indicates the user does not want the context to - * be automatically freed upon error - */ -#define REDIS_NO_AUTO_FREE 0x200 - -#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ - -/* number of times we retry to connect in the case of EADDRNOTAVAIL and - * SO_REUSEADDR is being used. */ -#define REDIS_CONNECT_RETRIES 10 - -/* Forward declarations for structs defined elsewhere */ -struct redisAsyncContext; -struct redisContext; - -/* RESP3 push helpers and callback prototypes */ -#define redisIsPushReply(r) (((redisReply*)(r))->type == REDIS_REPLY_PUSH) -typedef void (redisPushFn)(void *, void *); -typedef void (redisAsyncPushFn)(struct redisAsyncContext *, void *); - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the reply object returned by redisCommand() */ -typedef struct redisReply { - int type; /* REDIS_REPLY_* */ - long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ - double dval; /* The double when type is REDIS_REPLY_DOUBLE */ - size_t len; /* Length of string */ - char *str; /* Used for REDIS_REPLY_ERROR, REDIS_REPLY_STRING - REDIS_REPLY_VERB, and REDIS_REPLY_DOUBLE (in additional to dval). */ - char vtype[4]; /* Used for REDIS_REPLY_VERB, contains the null - terminated 3 character content type, such as "txt". */ - size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ - struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ -} redisReply; - -redisReader *redisReaderCreate(void); - -/* Function to free the reply objects hiredis returns by default. */ -void freeReplyObject(void *reply); - -/* Functions to format a command according to the protocol. */ -int redisvFormatCommand(char **target, const char *format, va_list ap); -int redisFormatCommand(char **target, const char *format, ...); -int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); -int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen); -void redisFreeCommand(char *cmd); -void redisFreeSdsCommand(sds cmd); - -enum redisConnectionType { - REDIS_CONN_TCP, - REDIS_CONN_UNIX, - REDIS_CONN_USERFD -}; - -struct redisSsl; - -#define REDIS_OPT_NONBLOCK 0x01 -#define REDIS_OPT_REUSEADDR 0x02 - -/** - * Don't automatically free the async object on a connection failure, - * or other implicit conditions. Only free on an explicit call to disconnect() or free() - */ -#define REDIS_OPT_NOAUTOFREE 0x04 - -/* Don't automatically intercept and free RESP3 PUSH replies. */ -#define REDIS_OPT_NO_PUSH_AUTOFREE 0x08 - -/* In Unix systems a file descriptor is a regular signed int, with -1 - * representing an invalid descriptor. In Windows it is a SOCKET - * (32- or 64-bit unsigned integer depending on the architecture), where - * all bits set (~0) is INVALID_SOCKET. */ -#ifndef _WIN32 -typedef int redisFD; -#define REDIS_INVALID_FD -1 -#else -#ifdef _WIN64 -typedef unsigned long long redisFD; /* SOCKET = 64-bit UINT_PTR */ -#else -typedef unsigned long redisFD; /* SOCKET = 32-bit UINT_PTR */ -#endif -#define REDIS_INVALID_FD ((redisFD)(~0)) /* INVALID_SOCKET */ -#endif - -typedef struct { - /* - * the type of connection to use. This also indicates which - * `endpoint` member field to use - */ - int type; - /* bit field of REDIS_OPT_xxx */ - int options; - /* timeout value for connect operation. If NULL, no timeout is used */ - const struct timeval *connect_timeout; - /* timeout value for commands. If NULL, no timeout is used. This can be - * updated at runtime with redisSetTimeout/redisAsyncSetTimeout. */ - const struct timeval *command_timeout; - union { - /** use this field for tcp/ip connections */ - struct { - const char *source_addr; - const char *ip; - int port; - } tcp; - /** use this field for unix domain sockets */ - const char *unix_socket; - /** - * use this field to have hiredis operate an already-open - * file descriptor */ - redisFD fd; - } endpoint; - - /* Optional user defined data/destructor */ - void *privdata; - void (*free_privdata)(void *); - - /* A user defined PUSH message callback */ - redisPushFn *push_cb; - redisAsyncPushFn *async_push_cb; -} redisOptions; - -/** - * Helper macros to initialize options to their specified fields. - */ -#define REDIS_OPTIONS_SET_TCP(opts, ip_, port_) \ - (opts)->type = REDIS_CONN_TCP; \ - (opts)->endpoint.tcp.ip = ip_; \ - (opts)->endpoint.tcp.port = port_; - -#define REDIS_OPTIONS_SET_UNIX(opts, path) \ - (opts)->type = REDIS_CONN_UNIX; \ - (opts)->endpoint.unix_socket = path; - -#define REDIS_OPTIONS_SET_PRIVDATA(opts, data, dtor) \ - (opts)->privdata = data; \ - (opts)->free_privdata = dtor; \ - -typedef struct redisContextFuncs { - void (*free_privctx)(void *); - void (*async_read)(struct redisAsyncContext *); - void (*async_write)(struct redisAsyncContext *); - ssize_t (*read)(struct redisContext *, char *, size_t); - ssize_t (*write)(struct redisContext *); -} redisContextFuncs; - -/* Context for a connection to Redis */ -typedef struct redisContext { - const redisContextFuncs *funcs; /* Function table */ - - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - redisFD fd; - int flags; - char *obuf; /* Write buffer */ - redisReader *reader; /* Protocol reader */ - - enum redisConnectionType connection_type; - struct timeval *connect_timeout; - struct timeval *command_timeout; - - struct { - char *host; - char *source_addr; - int port; - } tcp; - - struct { - char *path; - } unix_sock; - - /* For non-blocking connect */ - struct sockadr *saddr; - size_t addrlen; - - /* Optional data and corresponding destructor users can use to provide - * context to a given redisContext. Not used by hiredis. */ - void *privdata; - void (*free_privdata)(void *); - - /* Internal context pointer presently used by hiredis to manage - * SSL connections. */ - void *privctx; - - /* An optional RESP3 PUSH handler */ - redisPushFn *push_cb; -} redisContext; - -redisContext *redisConnectWithOptions(const redisOptions *options); -redisContext *redisConnect(const char *ip, int port); -redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); -redisContext *redisConnectNonBlock(const char *ip, int port); -redisContext *redisConnectBindNonBlock(const char *ip, int port, - const char *source_addr); -redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, - const char *source_addr); -redisContext *redisConnectUnix(const char *path); -redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); -redisContext *redisConnectUnixNonBlock(const char *path); -redisContext *redisConnectFd(redisFD fd); - -/** - * Reconnect the given context using the saved information. - * - * This re-uses the exact same connect options as in the initial connection. - * host, ip (or path), timeout and bind address are reused, - * flags are used unmodified from the existing context. - * - * Returns REDIS_OK on successful connect or REDIS_ERR otherwise. - */ -int redisReconnect(redisContext *c); - -redisPushFn *redisSetPushCallback(redisContext *c, redisPushFn *fn); -int redisSetTimeout(redisContext *c, const struct timeval tv); -int redisEnableKeepAlive(redisContext *c); -void redisFree(redisContext *c); -redisFD redisFreeKeepFd(redisContext *c); -int redisBufferRead(redisContext *c); -int redisBufferWrite(redisContext *c, int *done); - -/* In a blocking context, this function first checks if there are unconsumed - * replies to return and returns one if so. Otherwise, it flushes the output - * buffer to the socket and reads until it has a reply. In a non-blocking - * context, it will return unconsumed replies until there are no more. */ -int redisGetReply(redisContext *c, void **reply); -int redisGetReplyFromReader(redisContext *c, void **reply); - -/* Write a formatted command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); - -/* Write a command to the output buffer. Use these functions in blocking mode - * to get a pipeline of commands. */ -int redisvAppendCommand(redisContext *c, const char *format, va_list ap); -int redisAppendCommand(redisContext *c, const char *format, ...); -int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -/* Issue a command to Redis. In a blocking context, it is identical to calling - * redisAppendCommand, followed by redisGetReply. The function will return - * NULL if there was an error in performing the request, otherwise it will - * return the reply. In a non-blocking context, it is identical to calling - * only redisAppendCommand and will always return NULL. */ -void *redisvCommand(redisContext *c, const char *format, va_list ap); -void *redisCommand(redisContext *c, const char *format, ...); -void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-1.0.2/include/hiredis/hiredis_ssl.h b/ext/hiredis-1.0.2/include/hiredis/hiredis_ssl.h deleted file mode 100644 index 604efe0c1..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/hiredis_ssl.h +++ /dev/null @@ -1,127 +0,0 @@ - -/* - * Copyright (c) 2019, Redis Labs - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_SSL_H -#define __HIREDIS_SSL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the underlying struct for SSL in ssl.h, which is not included to - * keep build dependencies short here. - */ -struct ssl_st; - -/* A wrapper around OpenSSL SSL_CTX to allow easy SSL use without directly - * calling OpenSSL. - */ -typedef struct redisSSLContext redisSSLContext; - -/** - * Initialization errors that redisCreateSSLContext() may return. - */ - -typedef enum { - REDIS_SSL_CTX_NONE = 0, /* No Error */ - REDIS_SSL_CTX_CREATE_FAILED, /* Failed to create OpenSSL SSL_CTX */ - REDIS_SSL_CTX_CERT_KEY_REQUIRED, /* Client cert and key must both be specified or skipped */ - REDIS_SSL_CTX_CA_CERT_LOAD_FAILED, /* Failed to load CA Certificate or CA Path */ - REDIS_SSL_CTX_CLIENT_CERT_LOAD_FAILED, /* Failed to load client certificate */ - REDIS_SSL_CTX_PRIVATE_KEY_LOAD_FAILED /* Failed to load private key */ -} redisSSLContextError; - -/** - * Return the error message corresponding with the specified error code. - */ - -const char *redisSSLContextGetError(redisSSLContextError error); - -/** - * Helper function to initialize the OpenSSL library. - * - * OpenSSL requires one-time initialization before it can be used. Callers should - * call this function only once, and only if OpenSSL is not directly initialized - * elsewhere. - */ -int redisInitOpenSSL(void); - -/** - * Helper function to initialize an OpenSSL context that can be used - * to initiate SSL connections. - * - * cacert_filename is an optional name of a CA certificate/bundle file to load - * and use for validation. - * - * capath is an optional directory path where trusted CA certificate files are - * stored in an OpenSSL-compatible structure. - * - * cert_filename and private_key_filename are optional names of a client side - * certificate and private key files to use for authentication. They need to - * be both specified or omitted. - * - * server_name is an optional and will be used as a server name indication - * (SNI) TLS extension. - * - * If error is non-null, it will be populated in case the context creation fails - * (returning a NULL). - */ - -redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char *capath, - const char *cert_filename, const char *private_key_filename, - const char *server_name, redisSSLContextError *error); - -/** - * Free a previously created OpenSSL context. - */ -void redisFreeSSLContext(redisSSLContext *redis_ssl_ctx); - -/** - * Initiate SSL on an existing redisContext. - * - * This is similar to redisInitiateSSL() but does not require the caller - * to directly interact with OpenSSL, and instead uses a redisSSLContext - * previously created using redisCreateSSLContext(). - */ - -int redisInitiateSSLWithContext(redisContext *c, redisSSLContext *redis_ssl_ctx); - -/** - * Initiate SSL/TLS negotiation on a provided OpenSSL SSL object. - */ - -int redisInitiateSSL(redisContext *c, struct ssl_st *ssl); - -#ifdef __cplusplus -} -#endif - -#endif /* __HIREDIS_SSL_H */ diff --git a/ext/hiredis-1.0.2/include/hiredis/net.h b/ext/hiredis-1.0.2/include/hiredis/net.h deleted file mode 100644 index 9f43283a5..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/net.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __NET_H -#define __NET_H - -#include "hiredis.h" - -void redisNetClose(redisContext *c); -ssize_t redisNetRead(redisContext *c, char *buf, size_t bufcap); -ssize_t redisNetWrite(redisContext *c); - -int redisCheckSocketError(redisContext *c); -int redisContextSetTimeout(redisContext *c, const struct timeval tv); -int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); -int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr); -int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); -int redisKeepAlive(redisContext *c, int interval); -int redisCheckConnectDone(redisContext *c, int *completed); - -int redisSetTcpNoDelay(redisContext *c); - -#endif diff --git a/ext/hiredis-1.0.2/include/hiredis/read.h b/ext/hiredis-1.0.2/include/hiredis/read.h deleted file mode 100644 index 2d74d77a5..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/read.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef __HIREDIS_READ_H -#define __HIREDIS_READ_H -#include /* for size_t */ - -#define REDIS_ERR -1 -#define REDIS_OK 0 - -/* When an error occurs, the err flag in a context is set to hold the type of - * error that occurred. REDIS_ERR_IO means there was an I/O error and you - * should use the "errno" variable to find out what is wrong. - * For other values, the "errstr" field will hold a description. */ -#define REDIS_ERR_IO 1 /* Error in read or write */ -#define REDIS_ERR_EOF 3 /* End of file */ -#define REDIS_ERR_PROTOCOL 4 /* Protocol error */ -#define REDIS_ERR_OOM 5 /* Out of memory */ -#define REDIS_ERR_TIMEOUT 6 /* Timed out */ -#define REDIS_ERR_OTHER 2 /* Everything else... */ - -#define REDIS_REPLY_STRING 1 -#define REDIS_REPLY_ARRAY 2 -#define REDIS_REPLY_INTEGER 3 -#define REDIS_REPLY_NIL 4 -#define REDIS_REPLY_STATUS 5 -#define REDIS_REPLY_ERROR 6 -#define REDIS_REPLY_DOUBLE 7 -#define REDIS_REPLY_BOOL 8 -#define REDIS_REPLY_MAP 9 -#define REDIS_REPLY_SET 10 -#define REDIS_REPLY_ATTR 11 -#define REDIS_REPLY_PUSH 12 -#define REDIS_REPLY_BIGNUM 13 -#define REDIS_REPLY_VERB 14 - -/* Default max unused reader buffer. */ -#define REDIS_READER_MAX_BUF (1024*16) - -/* Default multi-bulk element limit */ -#define REDIS_READER_MAX_ARRAY_ELEMENTS ((1LL<<32) - 1) - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct redisReadTask { - int type; - long long elements; /* number of elements in multibulk container */ - int idx; /* index in parent (array) object */ - void *obj; /* holds user-generated value for a read task */ - struct redisReadTask *parent; /* parent task */ - void *privdata; /* user-settable arbitrary field */ -} redisReadTask; - -typedef struct redisReplyObjectFunctions { - void *(*createString)(const redisReadTask*, char*, size_t); - void *(*createArray)(const redisReadTask*, size_t); - void *(*createInteger)(const redisReadTask*, long long); - void *(*createDouble)(const redisReadTask*, double, char*, size_t); - void *(*createNil)(const redisReadTask*); - void *(*createBool)(const redisReadTask*, int); - void (*freeObject)(void*); -} redisReplyObjectFunctions; - -typedef struct redisReader { - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - - char *buf; /* Read buffer */ - size_t pos; /* Buffer cursor */ - size_t len; /* Buffer length */ - size_t maxbuf; /* Max length of unused buffer */ - long long maxelements; /* Max multi-bulk elements */ - - redisReadTask **task; - int tasks; - - int ridx; /* Index of current read task */ - void *reply; /* Temporary reply pointer */ - - redisReplyObjectFunctions *fn; - void *privdata; -} redisReader; - -/* Public API for the protocol parser. */ -redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn); -void redisReaderFree(redisReader *r); -int redisReaderFeed(redisReader *r, const char *buf, size_t len); -int redisReaderGetReply(redisReader *r, void **reply); - -#define redisReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) -#define redisReaderGetObject(_r) (((redisReader*)(_r))->reply) -#define redisReaderGetError(_r) (((redisReader*)(_r))->errstr) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-1.0.2/include/hiredis/sds.h b/ext/hiredis-1.0.2/include/hiredis/sds.h deleted file mode 100644 index eda8833b5..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/sds.h +++ /dev/null @@ -1,278 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SDS_H -#define __SDS_H - -#define SDS_MAX_PREALLOC (1024*1024) -#ifdef _MSC_VER -#define __attribute__(x) -typedef long long ssize_t; -#define SSIZE_MAX (LLONG_MAX >> 1) -#endif - -#include -#include -#include - -typedef char *sds; - -/* Note: sdshdr5 is never used, we just access the flags byte directly. - * However is here to document the layout of type 5 SDS strings. */ -struct __attribute__ ((__packed__)) sdshdr5 { - unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr8 { - uint8_t len; /* used */ - uint8_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr16 { - uint16_t len; /* used */ - uint16_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr32 { - uint32_t len; /* used */ - uint32_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr64 { - uint64_t len; /* used */ - uint64_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; - -#define SDS_TYPE_5 0 -#define SDS_TYPE_8 1 -#define SDS_TYPE_16 2 -#define SDS_TYPE_32 3 -#define SDS_TYPE_64 4 -#define SDS_TYPE_MASK 7 -#define SDS_TYPE_BITS 3 -#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))); -#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) -#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) - -static inline size_t sdslen(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->len; - case SDS_TYPE_16: - return SDS_HDR(16,s)->len; - case SDS_TYPE_32: - return SDS_HDR(32,s)->len; - case SDS_TYPE_64: - return SDS_HDR(64,s)->len; - } - return 0; -} - -static inline size_t sdsavail(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: { - return 0; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - return sh->alloc - sh->len; - } - } - return 0; -} - -static inline void sdssetlen(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - *fp = (unsigned char)(SDS_TYPE_5 | (newlen << SDS_TYPE_BITS)); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len = (uint8_t)newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len = (uint16_t)newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len = (uint32_t)newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len = (uint64_t)newlen; - break; - } -} - -static inline void sdsinclen(sds s, size_t inc) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - unsigned char newlen = SDS_TYPE_5_LEN(flags)+(unsigned char)inc; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len += (uint8_t)inc; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len += (uint16_t)inc; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len += (uint32_t)inc; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len += (uint64_t)inc; - break; - } -} - -/* sdsalloc() = sdsavail() + sdslen() */ -static inline size_t sdsalloc(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->alloc; - case SDS_TYPE_16: - return SDS_HDR(16,s)->alloc; - case SDS_TYPE_32: - return SDS_HDR(32,s)->alloc; - case SDS_TYPE_64: - return SDS_HDR(64,s)->alloc; - } - return 0; -} - -static inline void sdssetalloc(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - /* Nothing to do, this type has no total allocation info. */ - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->alloc = (uint8_t)newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->alloc = (uint16_t)newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->alloc = (uint32_t)newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->alloc = (uint64_t)newlen; - break; - } -} - -sds sdsnewlen(const void *init, size_t initlen); -sds sdsnew(const char *init); -sds sdsempty(void); -sds sdsdup(const sds s); -void sdsfree(sds s); -sds sdsgrowzero(sds s, size_t len); -sds sdscatlen(sds s, const void *t, size_t len); -sds sdscat(sds s, const char *t); -sds sdscatsds(sds s, const sds t); -sds sdscpylen(sds s, const char *t, size_t len); -sds sdscpy(sds s, const char *t); - -sds sdscatvprintf(sds s, const char *fmt, va_list ap); -#ifdef __GNUC__ -sds sdscatprintf(sds s, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else -sds sdscatprintf(sds s, const char *fmt, ...); -#endif - -sds sdscatfmt(sds s, char const *fmt, ...); -sds sdstrim(sds s, const char *cset); -int sdsrange(sds s, ssize_t start, ssize_t end); -void sdsupdatelen(sds s); -void sdsclear(sds s); -int sdscmp(const sds s1, const sds s2); -sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); -void sdsfreesplitres(sds *tokens, int count); -void sdstolower(sds s); -void sdstoupper(sds s); -sds sdsfromlonglong(long long value); -sds sdscatrepr(sds s, const char *p, size_t len); -sds *sdssplitargs(const char *line, int *argc); -sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); -sds sdsjoin(char **argv, int argc, char *sep); -sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); - -/* Low level functions exposed to the user API */ -sds sdsMakeRoomFor(sds s, size_t addlen); -void sdsIncrLen(sds s, int incr); -sds sdsRemoveFreeSpace(sds s); -size_t sdsAllocSize(sds s); -void *sdsAllocPtr(sds s); - -/* Export the allocator used by SDS to the program using SDS. - * Sometimes the program SDS is linked to, may use a different set of - * allocators, but may want to allocate or free things that SDS will - * respectively free or allocate. */ -void *sds_malloc(size_t size); -void *sds_realloc(void *ptr, size_t size); -void sds_free(void *ptr); - -#ifdef REDIS_TEST -int sdsTest(int argc, char *argv[]); -#endif - -#endif diff --git a/ext/hiredis-1.0.2/include/hiredis/sdsalloc.h b/ext/hiredis-1.0.2/include/hiredis/sdsalloc.h deleted file mode 100644 index 5538dd94c..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/sdsalloc.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* SDS allocator selection. - * - * This file is used in order to change the SDS allocator at compile time. - * Just define the following defines to what you want to use. Also add - * the include of your alternate allocator if needed (not needed in order - * to use the default libc allocator). */ - -#include "alloc.h" - -#define s_malloc hi_malloc -#define s_realloc hi_realloc -#define s_free hi_free diff --git a/ext/hiredis-1.0.2/include/hiredis/sockcompat.h b/ext/hiredis-1.0.2/include/hiredis/sockcompat.h deleted file mode 100644 index 85810e848..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/sockcompat.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2019, Marcus Geelnard - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SOCKCOMPAT_H -#define __SOCKCOMPAT_H - -#ifndef _WIN32 -/* For POSIX systems we use the standard BSD socket API. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else -/* For Windows we use winsock. */ -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 /* To get WSAPoll etc. */ -#include -#include -#include -#include - -#ifdef _MSC_VER -typedef long long ssize_t; -#endif - -/* Emulate the parts of the BSD socket API that we need (override the winsock signatures). */ -int win32_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); -const char *win32_gai_strerror(int errcode); -void win32_freeaddrinfo(struct addrinfo *res); -SOCKET win32_socket(int domain, int type, int protocol); -int win32_ioctl(SOCKET fd, unsigned long request, unsigned long *argp); -int win32_bind(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen); -int win32_connect(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen); -int win32_getsockopt(SOCKET sockfd, int level, int optname, void *optval, socklen_t *optlen); -int win32_setsockopt(SOCKET sockfd, int level, int optname, const void *optval, socklen_t optlen); -int win32_close(SOCKET fd); -ssize_t win32_recv(SOCKET sockfd, void *buf, size_t len, int flags); -ssize_t win32_send(SOCKET sockfd, const void *buf, size_t len, int flags); -typedef ULONG nfds_t; -int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout); - -#ifndef REDIS_SOCKCOMPAT_IMPLEMENTATION -#define getaddrinfo(node, service, hints, res) win32_getaddrinfo(node, service, hints, res) -#undef gai_strerror -#define gai_strerror(errcode) win32_gai_strerror(errcode) -#define freeaddrinfo(res) win32_freeaddrinfo(res) -#define socket(domain, type, protocol) win32_socket(domain, type, protocol) -#define ioctl(fd, request, argp) win32_ioctl(fd, request, argp) -#define bind(sockfd, addr, addrlen) win32_bind(sockfd, addr, addrlen) -#define connect(sockfd, addr, addrlen) win32_connect(sockfd, addr, addrlen) -#define getsockopt(sockfd, level, optname, optval, optlen) win32_getsockopt(sockfd, level, optname, optval, optlen) -#define setsockopt(sockfd, level, optname, optval, optlen) win32_setsockopt(sockfd, level, optname, optval, optlen) -#define close(fd) win32_close(fd) -#define recv(sockfd, buf, len, flags) win32_recv(sockfd, buf, len, flags) -#define send(sockfd, buf, len, flags) win32_send(sockfd, buf, len, flags) -#define poll(fds, nfds, timeout) win32_poll(fds, nfds, timeout) -#endif /* REDIS_SOCKCOMPAT_IMPLEMENTATION */ -#endif /* _WIN32 */ - -#endif /* __SOCKCOMPAT_H */ diff --git a/ext/hiredis-1.0.2/include/hiredis/win32.h b/ext/hiredis-1.0.2/include/hiredis/win32.h deleted file mode 100644 index 04289c696..000000000 --- a/ext/hiredis-1.0.2/include/hiredis/win32.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _WIN32_HELPER_INCLUDE -#define _WIN32_HELPER_INCLUDE -#ifdef _MSC_VER - -#include /* for struct timeval */ - -#ifndef inline -#define inline __inline -#endif - -#ifndef strcasecmp -#define strcasecmp stricmp -#endif - -#ifndef strncasecmp -#define strncasecmp strnicmp -#endif - -#ifndef va_copy -#define va_copy(d,s) ((d) = (s)) -#endif - -#ifndef snprintf -#define snprintf c99_snprintf - -__inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) -{ - int count = -1; - - if (size != 0) - count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - -__inline int c99_snprintf(char* str, size_t size, const char* format, ...) -{ - int count; - va_list ap; - - va_start(ap, format); - count = c99_vsnprintf(str, size, format, ap); - va_end(ap); - - return count; -} -#endif -#endif /* _MSC_VER */ - -#ifdef _WIN32 -#define strerror_r(errno,buf,len) strerror_s(buf,len,errno) -#endif /* _WIN32 */ - -#endif /* _WIN32_HELPER_INCLUDE */ diff --git a/ext/hiredis-1.0.2/lib/ubuntu22.04/amd64/libhiredis.a b/ext/hiredis-1.0.2/lib/ubuntu22.04/amd64/libhiredis.a deleted file mode 100644 index af1314f01..000000000 Binary files a/ext/hiredis-1.0.2/lib/ubuntu22.04/amd64/libhiredis.a and /dev/null differ diff --git a/ext/hiredis-1.0.2/lib/ubuntu22.04/arm64/libhiredis.a b/ext/hiredis-1.0.2/lib/ubuntu22.04/arm64/libhiredis.a deleted file mode 100644 index 081c92705..000000000 Binary files a/ext/hiredis-1.0.2/lib/ubuntu22.04/arm64/libhiredis.a and /dev/null differ diff --git a/ext/hiredis-1.0.2/net.c b/ext/hiredis-1.0.2/net.c deleted file mode 100644 index c6b0e5d8e..000000000 --- a/ext/hiredis-1.0.2/net.c +++ /dev/null @@ -1,612 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "net.h" -#include "sds.h" -#include "sockcompat.h" -#include "win32.h" - -/* Defined in hiredis.c */ -void __redisSetError(redisContext *c, int type, const char *str); - -void redisNetClose(redisContext *c) { - if (c && c->fd != REDIS_INVALID_FD) { - close(c->fd); - c->fd = REDIS_INVALID_FD; - } -} - -ssize_t redisNetRead(redisContext *c, char *buf, size_t bufcap) { - ssize_t nread = recv(c->fd, buf, bufcap, 0); - if (nread == -1) { - if ((errno == EWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { - /* Try again later */ - return 0; - } else if(errno == ETIMEDOUT && (c->flags & REDIS_BLOCK)) { - /* especially in windows */ - __redisSetError(c, REDIS_ERR_TIMEOUT, "recv timeout"); - return -1; - } else { - __redisSetError(c, REDIS_ERR_IO, NULL); - return -1; - } - } else if (nread == 0) { - __redisSetError(c, REDIS_ERR_EOF, "Server closed the connection"); - return -1; - } else { - return nread; - } -} - -ssize_t redisNetWrite(redisContext *c) { - ssize_t nwritten = send(c->fd, c->obuf, sdslen(c->obuf), 0); - if (nwritten < 0) { - if ((errno == EWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { - /* Try again later */ - } else { - __redisSetError(c, REDIS_ERR_IO, NULL); - return -1; - } - } - return nwritten; -} - -static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { - int errorno = errno; /* snprintf() may change errno */ - char buf[128] = { 0 }; - size_t len = 0; - - if (prefix != NULL) - len = snprintf(buf,sizeof(buf),"%s: ",prefix); - strerror_r(errorno, (char *)(buf + len), sizeof(buf) - len); - __redisSetError(c,type,buf); -} - -static int redisSetReuseAddr(redisContext *c) { - int on = 1; - if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisNetClose(c); - return REDIS_ERR; - } - return REDIS_OK; -} - -static int redisCreateSocket(redisContext *c, int type) { - redisFD s; - if ((s = socket(type, SOCK_STREAM, 0)) == REDIS_INVALID_FD) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - c->fd = s; - if (type == AF_INET) { - if (redisSetReuseAddr(c) == REDIS_ERR) { - return REDIS_ERR; - } - } - return REDIS_OK; -} - -static int redisSetBlocking(redisContext *c, int blocking) { -#ifndef _WIN32 - int flags; - - /* Set the socket nonblocking. - * Note that fcntl(2) for F_GETFL and F_SETFL can't be - * interrupted by a signal. */ - if ((flags = fcntl(c->fd, F_GETFL)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)"); - redisNetClose(c); - return REDIS_ERR; - } - - if (blocking) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - - if (fcntl(c->fd, F_SETFL, flags) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)"); - redisNetClose(c); - return REDIS_ERR; - } -#else - u_long mode = blocking ? 0 : 1; - if (ioctl(c->fd, FIONBIO, &mode) == -1) { - __redisSetErrorFromErrno(c, REDIS_ERR_IO, "ioctl(FIONBIO)"); - redisNetClose(c); - return REDIS_ERR; - } -#endif /* _WIN32 */ - return REDIS_OK; -} - -int redisKeepAlive(redisContext *c, int interval) { - int val = 1; - redisFD fd = c->fd; - - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){ - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } - - val = interval; - -#if defined(__APPLE__) && defined(__MACH__) - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) { - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } -#else -#if defined(__GLIBC__) && !defined(__FreeBSD_kernel__) - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } - - val = interval/3; - if (val == 0) val = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } - - val = 3; - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { - __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); - return REDIS_ERR; - } -#endif -#endif - - return REDIS_OK; -} - -int redisSetTcpNoDelay(redisContext *c) { - int yes = 1; - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)"); - redisNetClose(c); - return REDIS_ERR; - } - return REDIS_OK; -} - -#define __MAX_MSEC (((LONG_MAX) - 999) / 1000) - -static int redisContextTimeoutMsec(redisContext *c, long *result) -{ - const struct timeval *timeout = c->connect_timeout; - long msec = -1; - - /* Only use timeout when not NULL. */ - if (timeout != NULL) { - if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { - *result = msec; - return REDIS_ERR; - } - - msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000); - - if (msec < 0 || msec > INT_MAX) { - msec = INT_MAX; - } - } - - *result = msec; - return REDIS_OK; -} - -static int redisContextWaitReady(redisContext *c, long msec) { - struct pollfd wfd[1]; - - wfd[0].fd = c->fd; - wfd[0].events = POLLOUT; - - if (errno == EINPROGRESS) { - int res; - - if ((res = poll(wfd, 1, msec)) == -1) { - __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); - redisNetClose(c); - return REDIS_ERR; - } else if (res == 0) { - errno = ETIMEDOUT; - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisNetClose(c); - return REDIS_ERR; - } - - if (redisCheckConnectDone(c, &res) != REDIS_OK || res == 0) { - redisCheckSocketError(c); - return REDIS_ERR; - } - - return REDIS_OK; - } - - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisNetClose(c); - return REDIS_ERR; -} - -int redisCheckConnectDone(redisContext *c, int *completed) { - int rc = connect(c->fd, (const struct sockaddr *)c->saddr, c->addrlen); - if (rc == 0) { - *completed = 1; - return REDIS_OK; - } - switch (errno) { - case EISCONN: - *completed = 1; - return REDIS_OK; - case EALREADY: - case EINPROGRESS: - case EWOULDBLOCK: - *completed = 0; - return REDIS_OK; - default: - return REDIS_ERR; - } -} - -int redisCheckSocketError(redisContext *c) { - int err = 0, errno_saved = errno; - socklen_t errlen = sizeof(err); - - if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)"); - return REDIS_ERR; - } - - if (err == 0) { - err = errno_saved; - } - - if (err) { - errno = err; - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - - return REDIS_OK; -} - -int redisContextSetTimeout(redisContext *c, const struct timeval tv) { - const void *to_ptr = &tv; - size_t to_sz = sizeof(tv); - - if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,to_ptr,to_sz) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)"); - return REDIS_ERR; - } - if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,to_ptr,to_sz) == -1) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)"); - return REDIS_ERR; - } - return REDIS_OK; -} - -int redisContextUpdateConnectTimeout(redisContext *c, const struct timeval *timeout) { - /* Same timeval struct, short circuit */ - if (c->connect_timeout == timeout) - return REDIS_OK; - - /* Allocate context timeval if we need to */ - if (c->connect_timeout == NULL) { - c->connect_timeout = hi_malloc(sizeof(*c->connect_timeout)); - if (c->connect_timeout == NULL) - return REDIS_ERR; - } - - memcpy(c->connect_timeout, timeout, sizeof(*c->connect_timeout)); - return REDIS_OK; -} - -int redisContextUpdateCommandTimeout(redisContext *c, const struct timeval *timeout) { - /* Same timeval struct, short circuit */ - if (c->command_timeout == timeout) - return REDIS_OK; - - /* Allocate context timeval if we need to */ - if (c->command_timeout == NULL) { - c->command_timeout = hi_malloc(sizeof(*c->command_timeout)); - if (c->command_timeout == NULL) - return REDIS_ERR; - } - - memcpy(c->command_timeout, timeout, sizeof(*c->command_timeout)); - return REDIS_OK; -} - -static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr) { - redisFD s; - int rv, n; - char _port[6]; /* strlen("65535"); */ - struct addrinfo hints, *servinfo, *bservinfo, *p, *b; - int blocking = (c->flags & REDIS_BLOCK); - int reuseaddr = (c->flags & REDIS_REUSEADDR); - int reuses = 0; - long timeout_msec = -1; - - servinfo = NULL; - c->connection_type = REDIS_CONN_TCP; - c->tcp.port = port; - - /* We need to take possession of the passed parameters - * to make them reusable for a reconnect. - * We also carefully check we don't free data we already own, - * as in the case of the reconnect method. - * - * This is a bit ugly, but atleast it works and doesn't leak memory. - **/ - if (c->tcp.host != addr) { - hi_free(c->tcp.host); - - c->tcp.host = hi_strdup(addr); - if (c->tcp.host == NULL) - goto oom; - } - - if (timeout) { - if (redisContextUpdateConnectTimeout(c, timeout) == REDIS_ERR) - goto oom; - } else { - hi_free(c->connect_timeout); - c->connect_timeout = NULL; - } - - if (redisContextTimeoutMsec(c, &timeout_msec) != REDIS_OK) { - __redisSetError(c, REDIS_ERR_IO, "Invalid timeout specified"); - goto error; - } - - if (source_addr == NULL) { - hi_free(c->tcp.source_addr); - c->tcp.source_addr = NULL; - } else if (c->tcp.source_addr != source_addr) { - hi_free(c->tcp.source_addr); - c->tcp.source_addr = hi_strdup(source_addr); - } - - snprintf(_port, 6, "%d", port); - memset(&hints,0,sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - /* Try with IPv6 if no IPv4 address was found. We do it in this order since - * in a Redis client you can't afford to test if you have IPv6 connectivity - * as this would add latency to every connect. Otherwise a more sensible - * route could be: Use IPv6 if both addresses are available and there is IPv6 - * connectivity. */ - if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) { - hints.ai_family = AF_INET6; - if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { - __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); - return REDIS_ERR; - } - } - for (p = servinfo; p != NULL; p = p->ai_next) { -addrretry: - if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == REDIS_INVALID_FD) - continue; - - c->fd = s; - if (redisSetBlocking(c,0) != REDIS_OK) - goto error; - if (c->tcp.source_addr) { - int bound = 0; - /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */ - if ((rv = getaddrinfo(c->tcp.source_addr, NULL, &hints, &bservinfo)) != 0) { - char buf[128]; - snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv)); - __redisSetError(c,REDIS_ERR_OTHER,buf); - goto error; - } - - if (reuseaddr) { - n = 1; - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*) &n, - sizeof(n)) < 0) { - freeaddrinfo(bservinfo); - goto error; - } - } - - for (b = bservinfo; b != NULL; b = b->ai_next) { - if (bind(s,b->ai_addr,b->ai_addrlen) != -1) { - bound = 1; - break; - } - } - freeaddrinfo(bservinfo); - if (!bound) { - char buf[128]; - snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno)); - __redisSetError(c,REDIS_ERR_OTHER,buf); - goto error; - } - } - - /* For repeat connection */ - hi_free(c->saddr); - c->saddr = hi_malloc(p->ai_addrlen); - if (c->saddr == NULL) - goto oom; - - memcpy(c->saddr, p->ai_addr, p->ai_addrlen); - c->addrlen = p->ai_addrlen; - - if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { - if (errno == EHOSTUNREACH) { - redisNetClose(c); - continue; - } else if (errno == EINPROGRESS) { - if (blocking) { - goto wait_for_ready; - } - /* This is ok. - * Note that even when it's in blocking mode, we unset blocking - * for `connect()` - */ - } else if (errno == EADDRNOTAVAIL && reuseaddr) { - if (++reuses >= REDIS_CONNECT_RETRIES) { - goto error; - } else { - redisNetClose(c); - goto addrretry; - } - } else { - wait_for_ready: - if (redisContextWaitReady(c,timeout_msec) != REDIS_OK) - goto error; - if (redisSetTcpNoDelay(c) != REDIS_OK) - goto error; - } - } - if (blocking && redisSetBlocking(c,1) != REDIS_OK) - goto error; - - c->flags |= REDIS_CONNECTED; - rv = REDIS_OK; - goto end; - } - if (p == NULL) { - char buf[128]; - snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno)); - __redisSetError(c,REDIS_ERR_OTHER,buf); - goto error; - } - -oom: - __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); -error: - rv = REDIS_ERR; -end: - if(servinfo) { - freeaddrinfo(servinfo); - } - - return rv; // Need to return REDIS_OK if alright -} - -int redisContextConnectTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout) { - return _redisContextConnectTcp(c, addr, port, timeout, NULL); -} - -int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr) { - return _redisContextConnectTcp(c, addr, port, timeout, source_addr); -} - -int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) { -#ifndef _WIN32 - int blocking = (c->flags & REDIS_BLOCK); - struct sockaddr_un *sa; - long timeout_msec = -1; - - if (redisCreateSocket(c,AF_UNIX) < 0) - return REDIS_ERR; - if (redisSetBlocking(c,0) != REDIS_OK) - return REDIS_ERR; - - c->connection_type = REDIS_CONN_UNIX; - if (c->unix_sock.path != path) { - hi_free(c->unix_sock.path); - - c->unix_sock.path = hi_strdup(path); - if (c->unix_sock.path == NULL) - goto oom; - } - - if (timeout) { - if (redisContextUpdateConnectTimeout(c, timeout) == REDIS_ERR) - goto oom; - } else { - hi_free(c->connect_timeout); - c->connect_timeout = NULL; - } - - if (redisContextTimeoutMsec(c,&timeout_msec) != REDIS_OK) - return REDIS_ERR; - - /* Don't leak sockaddr if we're reconnecting */ - if (c->saddr) hi_free(c->saddr); - - sa = (struct sockaddr_un*)(c->saddr = hi_malloc(sizeof(struct sockaddr_un))); - if (sa == NULL) - goto oom; - - c->addrlen = sizeof(struct sockaddr_un); - sa->sun_family = AF_UNIX; - strncpy(sa->sun_path, path, sizeof(sa->sun_path) - 1); - if (connect(c->fd, (struct sockaddr*)sa, sizeof(*sa)) == -1) { - if (errno == EINPROGRESS && !blocking) { - /* This is ok. */ - } else { - if (redisContextWaitReady(c,timeout_msec) != REDIS_OK) - return REDIS_ERR; - } - } - - /* Reset socket to be blocking after connect(2). */ - if (blocking && redisSetBlocking(c,1) != REDIS_OK) - return REDIS_ERR; - - c->flags |= REDIS_CONNECTED; - return REDIS_OK; -#else - /* We currently do not support Unix sockets for Windows. */ - /* TODO(m): https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ */ - errno = EPROTONOSUPPORT; - return REDIS_ERR; -#endif /* _WIN32 */ -oom: - __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); - return REDIS_ERR; -} diff --git a/ext/hiredis-1.0.2/net.h b/ext/hiredis-1.0.2/net.h deleted file mode 100644 index 9f43283a5..000000000 --- a/ext/hiredis-1.0.2/net.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2014, Pieter Noordhuis - * Copyright (c) 2015, Matt Stancliff , - * Jan-Erik Rediger - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __NET_H -#define __NET_H - -#include "hiredis.h" - -void redisNetClose(redisContext *c); -ssize_t redisNetRead(redisContext *c, char *buf, size_t bufcap); -ssize_t redisNetWrite(redisContext *c); - -int redisCheckSocketError(redisContext *c); -int redisContextSetTimeout(redisContext *c, const struct timeval tv); -int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); -int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr); -int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); -int redisKeepAlive(redisContext *c, int interval); -int redisCheckConnectDone(redisContext *c, int *completed); - -int redisSetTcpNoDelay(redisContext *c); - -#endif diff --git a/ext/hiredis-1.0.2/read.c b/ext/hiredis-1.0.2/read.c deleted file mode 100644 index 09524692b..000000000 --- a/ext/hiredis-1.0.2/read.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#ifndef _MSC_VER -#include -#include -#endif -#include -#include -#include -#include -#include - -#include "alloc.h" -#include "read.h" -#include "sds.h" -#include "win32.h" - -/* Initial size of our nested reply stack and how much we grow it when needd */ -#define REDIS_READER_STACK_SIZE 9 - -static void __redisReaderSetError(redisReader *r, int type, const char *str) { - size_t len; - - if (r->reply != NULL && r->fn && r->fn->freeObject) { - r->fn->freeObject(r->reply); - r->reply = NULL; - } - - /* Clear input buffer on errors. */ - sdsfree(r->buf); - r->buf = NULL; - r->pos = r->len = 0; - - /* Reset task stack. */ - r->ridx = -1; - - /* Set error. */ - r->err = type; - len = strlen(str); - len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1); - memcpy(r->errstr,str,len); - r->errstr[len] = '\0'; -} - -static size_t chrtos(char *buf, size_t size, char byte) { - size_t len = 0; - - switch(byte) { - case '\\': - case '"': - len = snprintf(buf,size,"\"\\%c\"",byte); - break; - case '\n': len = snprintf(buf,size,"\"\\n\""); break; - case '\r': len = snprintf(buf,size,"\"\\r\""); break; - case '\t': len = snprintf(buf,size,"\"\\t\""); break; - case '\a': len = snprintf(buf,size,"\"\\a\""); break; - case '\b': len = snprintf(buf,size,"\"\\b\""); break; - default: - if (isprint(byte)) - len = snprintf(buf,size,"\"%c\"",byte); - else - len = snprintf(buf,size,"\"\\x%02x\"",(unsigned char)byte); - break; - } - - return len; -} - -static void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) { - char cbuf[8], sbuf[128]; - - chrtos(cbuf,sizeof(cbuf),byte); - snprintf(sbuf,sizeof(sbuf), - "Protocol error, got %s as reply type byte", cbuf); - __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf); -} - -static void __redisReaderSetErrorOOM(redisReader *r) { - __redisReaderSetError(r,REDIS_ERR_OOM,"Out of memory"); -} - -static char *readBytes(redisReader *r, unsigned int bytes) { - char *p; - if (r->len-r->pos >= bytes) { - p = r->buf+r->pos; - r->pos += bytes; - return p; - } - return NULL; -} - -/* Find pointer to \r\n. */ -static char *seekNewline(char *s, size_t len) { - int pos = 0; - int _len = len-1; - - /* Position should be < len-1 because the character at "pos" should be - * followed by a \n. Note that strchr cannot be used because it doesn't - * allow to search a limited length and the buffer that is being searched - * might not have a trailing NULL character. */ - while (pos < _len) { - while(pos < _len && s[pos] != '\r') pos++; - if (pos==_len) { - /* Not found. */ - return NULL; - } else { - if (s[pos+1] == '\n') { - /* Found. */ - return s+pos; - } else { - /* Continue searching. */ - pos++; - } - } - } - return NULL; -} - -/* Convert a string into a long long. Returns REDIS_OK if the string could be - * parsed into a (non-overflowing) long long, REDIS_ERR otherwise. The value - * will be set to the parsed value when appropriate. - * - * Note that this function demands that the string strictly represents - * a long long: no spaces or other characters before or after the string - * representing the number are accepted, nor zeroes at the start if not - * for the string "0" representing the zero number. - * - * Because of its strictness, it is safe to use this function to check if - * you can convert a string into a long long, and obtain back the string - * from the number without any loss in the string representation. */ -static int string2ll(const char *s, size_t slen, long long *value) { - const char *p = s; - size_t plen = 0; - int negative = 0; - unsigned long long v; - - if (plen == slen) - return REDIS_ERR; - - /* Special case: first and only digit is 0. */ - if (slen == 1 && p[0] == '0') { - if (value != NULL) *value = 0; - return REDIS_OK; - } - - if (p[0] == '-') { - negative = 1; - p++; plen++; - - /* Abort on only a negative sign. */ - if (plen == slen) - return REDIS_ERR; - } - - /* First digit should be 1-9, otherwise the string should just be 0. */ - if (p[0] >= '1' && p[0] <= '9') { - v = p[0]-'0'; - p++; plen++; - } else if (p[0] == '0' && slen == 1) { - *value = 0; - return REDIS_OK; - } else { - return REDIS_ERR; - } - - while (plen < slen && p[0] >= '0' && p[0] <= '9') { - if (v > (ULLONG_MAX / 10)) /* Overflow. */ - return REDIS_ERR; - v *= 10; - - if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */ - return REDIS_ERR; - v += p[0]-'0'; - - p++; plen++; - } - - /* Return if not all bytes were used. */ - if (plen < slen) - return REDIS_ERR; - - if (negative) { - if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */ - return REDIS_ERR; - if (value != NULL) *value = -v; - } else { - if (v > LLONG_MAX) /* Overflow. */ - return REDIS_ERR; - if (value != NULL) *value = v; - } - return REDIS_OK; -} - -static char *readLine(redisReader *r, int *_len) { - char *p, *s; - int len; - - p = r->buf+r->pos; - s = seekNewline(p,(r->len-r->pos)); - if (s != NULL) { - len = s-(r->buf+r->pos); - r->pos += len+2; /* skip \r\n */ - if (_len) *_len = len; - return p; - } - return NULL; -} - -static void moveToNextTask(redisReader *r) { - redisReadTask *cur, *prv; - while (r->ridx >= 0) { - /* Return a.s.a.p. when the stack is now empty. */ - if (r->ridx == 0) { - r->ridx--; - return; - } - - cur = r->task[r->ridx]; - prv = r->task[r->ridx-1]; - assert(prv->type == REDIS_REPLY_ARRAY || - prv->type == REDIS_REPLY_MAP || - prv->type == REDIS_REPLY_SET || - prv->type == REDIS_REPLY_PUSH); - if (cur->idx == prv->elements-1) { - r->ridx--; - } else { - /* Reset the type because the next item can be anything */ - assert(cur->idx < prv->elements); - cur->type = -1; - cur->elements = -1; - cur->idx++; - return; - } - } -} - -static int processLineItem(redisReader *r) { - redisReadTask *cur = r->task[r->ridx]; - void *obj; - char *p; - int len; - - if ((p = readLine(r,&len)) != NULL) { - if (cur->type == REDIS_REPLY_INTEGER) { - if (r->fn && r->fn->createInteger) { - long long v; - if (string2ll(p, len, &v) == REDIS_ERR) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bad integer value"); - return REDIS_ERR; - } - obj = r->fn->createInteger(cur,v); - } else { - obj = (void*)REDIS_REPLY_INTEGER; - } - } else if (cur->type == REDIS_REPLY_DOUBLE) { - if (r->fn && r->fn->createDouble) { - char buf[326], *eptr; - double d; - - if ((size_t)len >= sizeof(buf)) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Double value is too large"); - return REDIS_ERR; - } - - memcpy(buf,p,len); - buf[len] = '\0'; - - if (strcasecmp(buf,",inf") == 0) { - d = INFINITY; /* Positive infinite. */ - } else if (strcasecmp(buf,",-inf") == 0) { - d = -INFINITY; /* Negative infinite. */ - } else { - d = strtod((char*)buf,&eptr); - if (buf[0] == '\0' || eptr[0] != '\0' || isnan(d)) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bad double value"); - return REDIS_ERR; - } - } - obj = r->fn->createDouble(cur,d,buf,len); - } else { - obj = (void*)REDIS_REPLY_DOUBLE; - } - } else if (cur->type == REDIS_REPLY_NIL) { - if (r->fn && r->fn->createNil) - obj = r->fn->createNil(cur); - else - obj = (void*)REDIS_REPLY_NIL; - } else if (cur->type == REDIS_REPLY_BOOL) { - int bval = p[0] == 't' || p[0] == 'T'; - if (r->fn && r->fn->createBool) - obj = r->fn->createBool(cur,bval); - else - obj = (void*)REDIS_REPLY_BOOL; - } else { - /* Type will be error or status. */ - if (r->fn && r->fn->createString) - obj = r->fn->createString(cur,p,len); - else - obj = (void*)(size_t)(cur->type); - } - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - /* Set reply if this is the root object. */ - if (r->ridx == 0) r->reply = obj; - moveToNextTask(r); - return REDIS_OK; - } - - return REDIS_ERR; -} - -static int processBulkItem(redisReader *r) { - redisReadTask *cur = r->task[r->ridx]; - void *obj = NULL; - char *p, *s; - long long len; - unsigned long bytelen; - int success = 0; - - p = r->buf+r->pos; - s = seekNewline(p,r->len-r->pos); - if (s != NULL) { - p = r->buf+r->pos; - bytelen = s-(r->buf+r->pos)+2; /* include \r\n */ - - if (string2ll(p, bytelen - 2, &len) == REDIS_ERR) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bad bulk string length"); - return REDIS_ERR; - } - - if (len < -1 || (LLONG_MAX > SIZE_MAX && len > (long long)SIZE_MAX)) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bulk string length out of range"); - return REDIS_ERR; - } - - if (len == -1) { - /* The nil object can always be created. */ - if (r->fn && r->fn->createNil) - obj = r->fn->createNil(cur); - else - obj = (void*)REDIS_REPLY_NIL; - success = 1; - } else { - /* Only continue when the buffer contains the entire bulk item. */ - bytelen += len+2; /* include \r\n */ - if (r->pos+bytelen <= r->len) { - if ((cur->type == REDIS_REPLY_VERB && len < 4) || - (cur->type == REDIS_REPLY_VERB && s[5] != ':')) - { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Verbatim string 4 bytes of content type are " - "missing or incorrectly encoded."); - return REDIS_ERR; - } - if (r->fn && r->fn->createString) - obj = r->fn->createString(cur,s+2,len); - else - obj = (void*)(long)cur->type; - success = 1; - } - } - - /* Proceed when obj was created. */ - if (success) { - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - r->pos += bytelen; - - /* Set reply if this is the root object. */ - if (r->ridx == 0) r->reply = obj; - moveToNextTask(r); - return REDIS_OK; - } - } - - return REDIS_ERR; -} - -static int redisReaderGrow(redisReader *r) { - redisReadTask **aux; - int newlen; - - /* Grow our stack size */ - newlen = r->tasks + REDIS_READER_STACK_SIZE; - aux = hi_realloc(r->task, sizeof(*r->task) * newlen); - if (aux == NULL) - goto oom; - - r->task = aux; - - /* Allocate new tasks */ - for (; r->tasks < newlen; r->tasks++) { - r->task[r->tasks] = hi_calloc(1, sizeof(**r->task)); - if (r->task[r->tasks] == NULL) - goto oom; - } - - return REDIS_OK; -oom: - __redisReaderSetErrorOOM(r); - return REDIS_ERR; -} - -/* Process the array, map and set types. */ -static int processAggregateItem(redisReader *r) { - redisReadTask *cur = r->task[r->ridx]; - void *obj; - char *p; - long long elements; - int root = 0, len; - - /* Set error for nested multi bulks with depth > 7 */ - if (r->ridx == r->tasks - 1) { - if (redisReaderGrow(r) == REDIS_ERR) - return REDIS_ERR; - } - - if ((p = readLine(r,&len)) != NULL) { - if (string2ll(p, len, &elements) == REDIS_ERR) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bad multi-bulk length"); - return REDIS_ERR; - } - - root = (r->ridx == 0); - - if (elements < -1 || (LLONG_MAX > SIZE_MAX && elements > SIZE_MAX) || - (r->maxelements > 0 && elements > r->maxelements)) - { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Multi-bulk length out of range"); - return REDIS_ERR; - } - - if (elements == -1) { - if (r->fn && r->fn->createNil) - obj = r->fn->createNil(cur); - else - obj = (void*)REDIS_REPLY_NIL; - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - moveToNextTask(r); - } else { - if (cur->type == REDIS_REPLY_MAP) elements *= 2; - - if (r->fn && r->fn->createArray) - obj = r->fn->createArray(cur,elements); - else - obj = (void*)(long)cur->type; - - if (obj == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } - - /* Modify task stack when there are more than 0 elements. */ - if (elements > 0) { - cur->elements = elements; - cur->obj = obj; - r->ridx++; - r->task[r->ridx]->type = -1; - r->task[r->ridx]->elements = -1; - r->task[r->ridx]->idx = 0; - r->task[r->ridx]->obj = NULL; - r->task[r->ridx]->parent = cur; - r->task[r->ridx]->privdata = r->privdata; - } else { - moveToNextTask(r); - } - } - - /* Set reply if this is the root object. */ - if (root) r->reply = obj; - return REDIS_OK; - } - - return REDIS_ERR; -} - -static int processItem(redisReader *r) { - redisReadTask *cur = r->task[r->ridx]; - char *p; - - /* check if we need to read type */ - if (cur->type < 0) { - if ((p = readBytes(r,1)) != NULL) { - switch (p[0]) { - case '-': - cur->type = REDIS_REPLY_ERROR; - break; - case '+': - cur->type = REDIS_REPLY_STATUS; - break; - case ':': - cur->type = REDIS_REPLY_INTEGER; - break; - case ',': - cur->type = REDIS_REPLY_DOUBLE; - break; - case '_': - cur->type = REDIS_REPLY_NIL; - break; - case '$': - cur->type = REDIS_REPLY_STRING; - break; - case '*': - cur->type = REDIS_REPLY_ARRAY; - break; - case '%': - cur->type = REDIS_REPLY_MAP; - break; - case '~': - cur->type = REDIS_REPLY_SET; - break; - case '#': - cur->type = REDIS_REPLY_BOOL; - break; - case '=': - cur->type = REDIS_REPLY_VERB; - break; - case '>': - cur->type = REDIS_REPLY_PUSH; - break; - default: - __redisReaderSetErrorProtocolByte(r,*p); - return REDIS_ERR; - } - } else { - /* could not consume 1 byte */ - return REDIS_ERR; - } - } - - /* process typed item */ - switch(cur->type) { - case REDIS_REPLY_ERROR: - case REDIS_REPLY_STATUS: - case REDIS_REPLY_INTEGER: - case REDIS_REPLY_DOUBLE: - case REDIS_REPLY_NIL: - case REDIS_REPLY_BOOL: - return processLineItem(r); - case REDIS_REPLY_STRING: - case REDIS_REPLY_VERB: - return processBulkItem(r); - case REDIS_REPLY_ARRAY: - case REDIS_REPLY_MAP: - case REDIS_REPLY_SET: - case REDIS_REPLY_PUSH: - return processAggregateItem(r); - default: - assert(NULL); - return REDIS_ERR; /* Avoid warning. */ - } -} - -redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn) { - redisReader *r; - - r = hi_calloc(1,sizeof(redisReader)); - if (r == NULL) - return NULL; - - r->buf = sdsempty(); - if (r->buf == NULL) - goto oom; - - r->task = hi_calloc(REDIS_READER_STACK_SIZE, sizeof(*r->task)); - if (r->task == NULL) - goto oom; - - for (; r->tasks < REDIS_READER_STACK_SIZE; r->tasks++) { - r->task[r->tasks] = hi_calloc(1, sizeof(**r->task)); - if (r->task[r->tasks] == NULL) - goto oom; - } - - r->fn = fn; - r->maxbuf = REDIS_READER_MAX_BUF; - r->maxelements = REDIS_READER_MAX_ARRAY_ELEMENTS; - r->ridx = -1; - - return r; -oom: - redisReaderFree(r); - return NULL; -} - -void redisReaderFree(redisReader *r) { - if (r == NULL) - return; - - if (r->reply != NULL && r->fn && r->fn->freeObject) - r->fn->freeObject(r->reply); - - if (r->task) { - /* We know r->task[i] is allocated if i < r->tasks */ - for (int i = 0; i < r->tasks; i++) { - hi_free(r->task[i]); - } - - hi_free(r->task); - } - - sdsfree(r->buf); - hi_free(r); -} - -int redisReaderFeed(redisReader *r, const char *buf, size_t len) { - sds newbuf; - - /* Return early when this reader is in an erroneous state. */ - if (r->err) - return REDIS_ERR; - - /* Copy the provided buffer. */ - if (buf != NULL && len >= 1) { - /* Destroy internal buffer when it is empty and is quite large. */ - if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) { - sdsfree(r->buf); - r->buf = sdsempty(); - if (r->buf == 0) goto oom; - - r->pos = 0; - } - - newbuf = sdscatlen(r->buf,buf,len); - if (newbuf == NULL) goto oom; - - r->buf = newbuf; - r->len = sdslen(r->buf); - } - - return REDIS_OK; -oom: - __redisReaderSetErrorOOM(r); - return REDIS_ERR; -} - -int redisReaderGetReply(redisReader *r, void **reply) { - /* Default target pointer to NULL. */ - if (reply != NULL) - *reply = NULL; - - /* Return early when this reader is in an erroneous state. */ - if (r->err) - return REDIS_ERR; - - /* When the buffer is empty, there will never be a reply. */ - if (r->len == 0) - return REDIS_OK; - - /* Set first item to process when the stack is empty. */ - if (r->ridx == -1) { - r->task[0]->type = -1; - r->task[0]->elements = -1; - r->task[0]->idx = -1; - r->task[0]->obj = NULL; - r->task[0]->parent = NULL; - r->task[0]->privdata = r->privdata; - r->ridx = 0; - } - - /* Process items in reply. */ - while (r->ridx >= 0) - if (processItem(r) != REDIS_OK) - break; - - /* Return ASAP when an error occurred. */ - if (r->err) - return REDIS_ERR; - - /* Discard part of the buffer when we've consumed at least 1k, to avoid - * doing unnecessary calls to memmove() in sds.c. */ - if (r->pos >= 1024) { - if (sdsrange(r->buf,r->pos,-1) < 0) return REDIS_ERR; - r->pos = 0; - r->len = sdslen(r->buf); - } - - /* Emit a reply when there is one. */ - if (r->ridx == -1) { - if (reply != NULL) { - *reply = r->reply; - } else if (r->reply != NULL && r->fn && r->fn->freeObject) { - r->fn->freeObject(r->reply); - } - r->reply = NULL; - } - return REDIS_OK; -} diff --git a/ext/hiredis-1.0.2/read.h b/ext/hiredis-1.0.2/read.h deleted file mode 100644 index 2d74d77a5..000000000 --- a/ext/hiredis-1.0.2/read.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef __HIREDIS_READ_H -#define __HIREDIS_READ_H -#include /* for size_t */ - -#define REDIS_ERR -1 -#define REDIS_OK 0 - -/* When an error occurs, the err flag in a context is set to hold the type of - * error that occurred. REDIS_ERR_IO means there was an I/O error and you - * should use the "errno" variable to find out what is wrong. - * For other values, the "errstr" field will hold a description. */ -#define REDIS_ERR_IO 1 /* Error in read or write */ -#define REDIS_ERR_EOF 3 /* End of file */ -#define REDIS_ERR_PROTOCOL 4 /* Protocol error */ -#define REDIS_ERR_OOM 5 /* Out of memory */ -#define REDIS_ERR_TIMEOUT 6 /* Timed out */ -#define REDIS_ERR_OTHER 2 /* Everything else... */ - -#define REDIS_REPLY_STRING 1 -#define REDIS_REPLY_ARRAY 2 -#define REDIS_REPLY_INTEGER 3 -#define REDIS_REPLY_NIL 4 -#define REDIS_REPLY_STATUS 5 -#define REDIS_REPLY_ERROR 6 -#define REDIS_REPLY_DOUBLE 7 -#define REDIS_REPLY_BOOL 8 -#define REDIS_REPLY_MAP 9 -#define REDIS_REPLY_SET 10 -#define REDIS_REPLY_ATTR 11 -#define REDIS_REPLY_PUSH 12 -#define REDIS_REPLY_BIGNUM 13 -#define REDIS_REPLY_VERB 14 - -/* Default max unused reader buffer. */ -#define REDIS_READER_MAX_BUF (1024*16) - -/* Default multi-bulk element limit */ -#define REDIS_READER_MAX_ARRAY_ELEMENTS ((1LL<<32) - 1) - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct redisReadTask { - int type; - long long elements; /* number of elements in multibulk container */ - int idx; /* index in parent (array) object */ - void *obj; /* holds user-generated value for a read task */ - struct redisReadTask *parent; /* parent task */ - void *privdata; /* user-settable arbitrary field */ -} redisReadTask; - -typedef struct redisReplyObjectFunctions { - void *(*createString)(const redisReadTask*, char*, size_t); - void *(*createArray)(const redisReadTask*, size_t); - void *(*createInteger)(const redisReadTask*, long long); - void *(*createDouble)(const redisReadTask*, double, char*, size_t); - void *(*createNil)(const redisReadTask*); - void *(*createBool)(const redisReadTask*, int); - void (*freeObject)(void*); -} redisReplyObjectFunctions; - -typedef struct redisReader { - int err; /* Error flags, 0 when there is no error */ - char errstr[128]; /* String representation of error when applicable */ - - char *buf; /* Read buffer */ - size_t pos; /* Buffer cursor */ - size_t len; /* Buffer length */ - size_t maxbuf; /* Max length of unused buffer */ - long long maxelements; /* Max multi-bulk elements */ - - redisReadTask **task; - int tasks; - - int ridx; /* Index of current read task */ - void *reply; /* Temporary reply pointer */ - - redisReplyObjectFunctions *fn; - void *privdata; -} redisReader; - -/* Public API for the protocol parser. */ -redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn); -void redisReaderFree(redisReader *r); -int redisReaderFeed(redisReader *r, const char *buf, size_t len); -int redisReaderGetReply(redisReader *r, void **reply); - -#define redisReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) -#define redisReaderGetObject(_r) (((redisReader*)(_r))->reply) -#define redisReaderGetError(_r) (((redisReader*)(_r))->errstr) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/hiredis-1.0.2/sds.c b/ext/hiredis-1.0.2/sds.c deleted file mode 100644 index 49d2096b7..000000000 --- a/ext/hiredis-1.0.2/sds.c +++ /dev/null @@ -1,1289 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include -#include -#include "sds.h" -#include "sdsalloc.h" - -static inline int sdsHdrSize(char type) { - switch(type&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return sizeof(struct sdshdr5); - case SDS_TYPE_8: - return sizeof(struct sdshdr8); - case SDS_TYPE_16: - return sizeof(struct sdshdr16); - case SDS_TYPE_32: - return sizeof(struct sdshdr32); - case SDS_TYPE_64: - return sizeof(struct sdshdr64); - } - return 0; -} - -static inline char sdsReqType(size_t string_size) { - if (string_size < 32) - return SDS_TYPE_5; - if (string_size < 0xff) - return SDS_TYPE_8; - if (string_size < 0xffff) - return SDS_TYPE_16; - if (string_size < 0xffffffff) - return SDS_TYPE_32; - return SDS_TYPE_64; -} - -/* Create a new sds string with the content specified by the 'init' pointer - * and 'initlen'. - * If NULL is used for 'init' the string is initialized with zero bytes. - * - * The string is always null-termined (all the sds strings are, always) so - * even if you create an sds string with: - * - * mystring = sdsnewlen("abc",3); - * - * You can print the string with printf() as there is an implicit \0 at the - * end of the string. However the string is binary safe and can contain - * \0 characters in the middle, as the length is stored in the sds header. */ -sds sdsnewlen(const void *init, size_t initlen) { - void *sh; - sds s; - char type = sdsReqType(initlen); - /* Empty strings are usually created in order to append. Use type 8 - * since type 5 is not good at this. */ - if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8; - int hdrlen = sdsHdrSize(type); - unsigned char *fp; /* flags pointer. */ - - sh = s_malloc(hdrlen+initlen+1); - if (sh == NULL) return NULL; - if (!init) - memset(sh, 0, hdrlen+initlen+1); - s = (char*)sh+hdrlen; - fp = ((unsigned char*)s)-1; - switch(type) { - case SDS_TYPE_5: { - *fp = type | (initlen << SDS_TYPE_BITS); - break; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - sh->len = initlen; - sh->alloc = initlen; - *fp = type; - break; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - sh->len = initlen; - sh->alloc = initlen; - *fp = type; - break; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - sh->len = initlen; - sh->alloc = initlen; - *fp = type; - break; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - sh->len = initlen; - sh->alloc = initlen; - *fp = type; - break; - } - } - if (initlen && init) - memcpy(s, init, initlen); - s[initlen] = '\0'; - return s; -} - -/* Create an empty (zero length) sds string. Even in this case the string - * always has an implicit null term. */ -sds sdsempty(void) { - return sdsnewlen("",0); -} - -/* Create a new sds string starting from a null terminated C string. */ -sds sdsnew(const char *init) { - size_t initlen = (init == NULL) ? 0 : strlen(init); - return sdsnewlen(init, initlen); -} - -/* Duplicate an sds string. */ -sds sdsdup(const sds s) { - return sdsnewlen(s, sdslen(s)); -} - -/* Free an sds string. No operation is performed if 's' is NULL. */ -void sdsfree(sds s) { - if (s == NULL) return; - s_free((char*)s-sdsHdrSize(s[-1])); -} - -/* Set the sds string length to the length as obtained with strlen(), so - * considering as content only up to the first null term character. - * - * This function is useful when the sds string is hacked manually in some - * way, like in the following example: - * - * s = sdsnew("foobar"); - * s[2] = '\0'; - * sdsupdatelen(s); - * printf("%d\n", sdslen(s)); - * - * The output will be "2", but if we comment out the call to sdsupdatelen() - * the output will be "6" as the string was modified but the logical length - * remains 6 bytes. */ -void sdsupdatelen(sds s) { - int reallen = strlen(s); - sdssetlen(s, reallen); -} - -/* Modify an sds string in-place to make it empty (zero length). - * However all the existing buffer is not discarded but set as free space - * so that next append operations will not require allocations up to the - * number of bytes previously available. */ -void sdsclear(sds s) { - sdssetlen(s, 0); - s[0] = '\0'; -} - -/* Enlarge the free space at the end of the sds string so that the caller - * is sure that after calling this function can overwrite up to addlen - * bytes after the end of the string, plus one more byte for nul term. - * - * Note: this does not change the *length* of the sds string as returned - * by sdslen(), but only the free buffer space we have. */ -sds sdsMakeRoomFor(sds s, size_t addlen) { - void *sh, *newsh; - size_t avail = sdsavail(s); - size_t len, newlen; - char type, oldtype = s[-1] & SDS_TYPE_MASK; - int hdrlen; - - /* Return ASAP if there is enough space left. */ - if (avail >= addlen) return s; - - len = sdslen(s); - sh = (char*)s-sdsHdrSize(oldtype); - newlen = (len+addlen); - if (newlen < SDS_MAX_PREALLOC) - newlen *= 2; - else - newlen += SDS_MAX_PREALLOC; - - type = sdsReqType(newlen); - - /* Don't use type 5: the user is appending to the string and type 5 is - * not able to remember empty space, so sdsMakeRoomFor() must be called - * at every appending operation. */ - if (type == SDS_TYPE_5) type = SDS_TYPE_8; - - hdrlen = sdsHdrSize(type); - if (oldtype==type) { - newsh = s_realloc(sh, hdrlen+newlen+1); - if (newsh == NULL) return NULL; - s = (char*)newsh+hdrlen; - } else { - /* Since the header size changes, need to move the string forward, - * and can't use realloc */ - newsh = s_malloc(hdrlen+newlen+1); - if (newsh == NULL) return NULL; - memcpy((char*)newsh+hdrlen, s, len+1); - s_free(sh); - s = (char*)newsh+hdrlen; - s[-1] = type; - sdssetlen(s, len); - } - sdssetalloc(s, newlen); - return s; -} - -/* Reallocate the sds string so that it has no free space at the end. The - * contained string remains not altered, but next concatenation operations - * will require a reallocation. - * - * After the call, the passed sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdsRemoveFreeSpace(sds s) { - void *sh, *newsh; - char type, oldtype = s[-1] & SDS_TYPE_MASK; - int hdrlen; - size_t len = sdslen(s); - sh = (char*)s-sdsHdrSize(oldtype); - - type = sdsReqType(len); - hdrlen = sdsHdrSize(type); - if (oldtype==type) { - newsh = s_realloc(sh, hdrlen+len+1); - if (newsh == NULL) return NULL; - s = (char*)newsh+hdrlen; - } else { - newsh = s_malloc(hdrlen+len+1); - if (newsh == NULL) return NULL; - memcpy((char*)newsh+hdrlen, s, len+1); - s_free(sh); - s = (char*)newsh+hdrlen; - s[-1] = type; - sdssetlen(s, len); - } - sdssetalloc(s, len); - return s; -} - -/* Return the total size of the allocation of the specifed sds string, - * including: - * 1) The sds header before the pointer. - * 2) The string. - * 3) The free buffer at the end if any. - * 4) The implicit null term. - */ -size_t sdsAllocSize(sds s) { - size_t alloc = sdsalloc(s); - return sdsHdrSize(s[-1])+alloc+1; -} - -/* Return the pointer of the actual SDS allocation (normally SDS strings - * are referenced by the start of the string buffer). */ -void *sdsAllocPtr(sds s) { - return (void*) (s-sdsHdrSize(s[-1])); -} - -/* Increment the sds length and decrements the left free space at the - * end of the string according to 'incr'. Also set the null term - * in the new end of the string. - * - * This function is used in order to fix the string length after the - * user calls sdsMakeRoomFor(), writes something after the end of - * the current string, and finally needs to set the new length. - * - * Note: it is possible to use a negative increment in order to - * right-trim the string. - * - * Usage example: - * - * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the - * following schema, to cat bytes coming from the kernel to the end of an - * sds string without copying into an intermediate buffer: - * - * oldlen = sdslen(s); - * s = sdsMakeRoomFor(s, BUFFER_SIZE); - * nread = read(fd, s+oldlen, BUFFER_SIZE); - * ... check for nread <= 0 and handle it ... - * sdsIncrLen(s, nread); - */ -void sdsIncrLen(sds s, int incr) { - unsigned char flags = s[-1]; - size_t len; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: { - unsigned char *fp = ((unsigned char*)s)-1; - unsigned char oldlen = SDS_TYPE_5_LEN(flags); - assert((incr > 0 && oldlen+incr < 32) || (incr < 0 && oldlen >= (unsigned int)(-incr))); - *fp = SDS_TYPE_5 | ((oldlen+incr) << SDS_TYPE_BITS); - len = oldlen+incr; - break; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr))); - len = (sh->len += incr); - break; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr))); - len = (sh->len += incr); - break; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - assert((incr >= 0 && sh->alloc-sh->len >= (unsigned int)incr) || (incr < 0 && sh->len >= (unsigned int)(-incr))); - len = (sh->len += incr); - break; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - assert((incr >= 0 && sh->alloc-sh->len >= (uint64_t)incr) || (incr < 0 && sh->len >= (uint64_t)(-incr))); - len = (sh->len += incr); - break; - } - default: len = 0; /* Just to avoid compilation warnings. */ - } - s[len] = '\0'; -} - -/* Grow the sds to have the specified length. Bytes that were not part of - * the original length of the sds will be set to zero. - * - * if the specified length is smaller than the current length, no operation - * is performed. */ -sds sdsgrowzero(sds s, size_t len) { - size_t curlen = sdslen(s); - - if (len <= curlen) return s; - s = sdsMakeRoomFor(s,len-curlen); - if (s == NULL) return NULL; - - /* Make sure added region doesn't contain garbage */ - memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */ - sdssetlen(s, len); - return s; -} - -/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the - * end of the specified sds string 's'. - * - * After the call, the passed sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdscatlen(sds s, const void *t, size_t len) { - size_t curlen = sdslen(s); - - s = sdsMakeRoomFor(s,len); - if (s == NULL) return NULL; - memcpy(s+curlen, t, len); - sdssetlen(s, curlen+len); - s[curlen+len] = '\0'; - return s; -} - -/* Append the specified null termianted C string to the sds string 's'. - * - * After the call, the passed sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdscat(sds s, const char *t) { - return sdscatlen(s, t, strlen(t)); -} - -/* Append the specified sds 't' to the existing sds 's'. - * - * After the call, the modified sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdscatsds(sds s, const sds t) { - return sdscatlen(s, t, sdslen(t)); -} - -/* Destructively modify the sds string 's' to hold the specified binary - * safe string pointed by 't' of length 'len' bytes. */ -sds sdscpylen(sds s, const char *t, size_t len) { - if (sdsalloc(s) < len) { - s = sdsMakeRoomFor(s,len-sdslen(s)); - if (s == NULL) return NULL; - } - memcpy(s, t, len); - s[len] = '\0'; - sdssetlen(s, len); - return s; -} - -/* Like sdscpylen() but 't' must be a null-termined string so that the length - * of the string is obtained with strlen(). */ -sds sdscpy(sds s, const char *t) { - return sdscpylen(s, t, strlen(t)); -} - -/* Helper for sdscatlonglong() doing the actual number -> string - * conversion. 's' must point to a string with room for at least - * SDS_LLSTR_SIZE bytes. - * - * The function returns the length of the null-terminated string - * representation stored at 's'. */ -#define SDS_LLSTR_SIZE 21 -int sdsll2str(char *s, long long value) { - char *p, aux; - unsigned long long v; - size_t l; - - /* Generate the string representation, this method produces - * an reversed string. */ - v = (value < 0) ? -value : value; - p = s; - do { - *p++ = '0'+(v%10); - v /= 10; - } while(v); - if (value < 0) *p++ = '-'; - - /* Compute length and add null term. */ - l = p-s; - *p = '\0'; - - /* Reverse the string. */ - p--; - while(s < p) { - aux = *s; - *s = *p; - *p = aux; - s++; - p--; - } - return l; -} - -/* Identical sdsll2str(), but for unsigned long long type. */ -int sdsull2str(char *s, unsigned long long v) { - char *p, aux; - size_t l; - - /* Generate the string representation, this method produces - * an reversed string. */ - p = s; - do { - *p++ = '0'+(v%10); - v /= 10; - } while(v); - - /* Compute length and add null term. */ - l = p-s; - *p = '\0'; - - /* Reverse the string. */ - p--; - while(s < p) { - aux = *s; - *s = *p; - *p = aux; - s++; - p--; - } - return l; -} - -/* Create an sds string from a long long value. It is much faster than: - * - * sdscatprintf(sdsempty(),"%lld\n", value); - */ -sds sdsfromlonglong(long long value) { - char buf[SDS_LLSTR_SIZE]; - int len = sdsll2str(buf,value); - - return sdsnewlen(buf,len); -} - -/* Like sdscatprintf() but gets va_list instead of being variadic. */ -sds sdscatvprintf(sds s, const char *fmt, va_list ap) { - va_list cpy; - char staticbuf[1024], *buf = staticbuf, *t; - size_t buflen = strlen(fmt)*2; - - /* We try to start using a static buffer for speed. - * If not possible we revert to heap allocation. */ - if (buflen > sizeof(staticbuf)) { - buf = s_malloc(buflen); - if (buf == NULL) return NULL; - } else { - buflen = sizeof(staticbuf); - } - - /* Try with buffers two times bigger every time we fail to - * fit the string in the current buffer size. */ - while(1) { - buf[buflen-2] = '\0'; - va_copy(cpy,ap); - vsnprintf(buf, buflen, fmt, cpy); - va_end(cpy); - if (buf[buflen-2] != '\0') { - if (buf != staticbuf) s_free(buf); - buflen *= 2; - buf = s_malloc(buflen); - if (buf == NULL) return NULL; - continue; - } - break; - } - - /* Finally concat the obtained string to the SDS string and return it. */ - t = sdscat(s, buf); - if (buf != staticbuf) s_free(buf); - return t; -} - -/* Append to the sds string 's' a string obtained using printf-alike format - * specifier. - * - * After the call, the modified sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. - * - * Example: - * - * s = sdsnew("Sum is: "); - * s = sdscatprintf(s,"%d+%d = %d",a,b,a+b). - * - * Often you need to create a string from scratch with the printf-alike - * format. When this is the need, just use sdsempty() as the target string: - * - * s = sdscatprintf(sdsempty(), "... your format ...", args); - */ -sds sdscatprintf(sds s, const char *fmt, ...) { - va_list ap; - char *t; - va_start(ap, fmt); - t = sdscatvprintf(s,fmt,ap); - va_end(ap); - return t; -} - -/* This function is similar to sdscatprintf, but much faster as it does - * not rely on sprintf() family functions implemented by the libc that - * are often very slow. Moreover directly handling the sds string as - * new data is concatenated provides a performance improvement. - * - * However this function only handles an incompatible subset of printf-alike - * format specifiers: - * - * %s - C String - * %S - SDS string - * %i - signed int - * %I - 64 bit signed integer (long long, int64_t) - * %u - unsigned int - * %U - 64 bit unsigned integer (unsigned long long, uint64_t) - * %% - Verbatim "%" character. - */ -sds sdscatfmt(sds s, char const *fmt, ...) { - const char *f = fmt; - int i; - va_list ap; - - va_start(ap,fmt); - i = sdslen(s); /* Position of the next byte to write to dest str. */ - while(*f) { - char next, *str; - size_t l; - long long num; - unsigned long long unum; - - /* Make sure there is always space for at least 1 char. */ - if (sdsavail(s)==0) { - s = sdsMakeRoomFor(s,1); - if (s == NULL) goto fmt_error; - } - - switch(*f) { - case '%': - next = *(f+1); - f++; - switch(next) { - case 's': - case 'S': - str = va_arg(ap,char*); - l = (next == 's') ? strlen(str) : sdslen(str); - if (sdsavail(s) < l) { - s = sdsMakeRoomFor(s,l); - if (s == NULL) goto fmt_error; - } - memcpy(s+i,str,l); - sdsinclen(s,l); - i += l; - break; - case 'i': - case 'I': - if (next == 'i') - num = va_arg(ap,int); - else - num = va_arg(ap,long long); - { - char buf[SDS_LLSTR_SIZE]; - l = sdsll2str(buf,num); - if (sdsavail(s) < l) { - s = sdsMakeRoomFor(s,l); - if (s == NULL) goto fmt_error; - } - memcpy(s+i,buf,l); - sdsinclen(s,l); - i += l; - } - break; - case 'u': - case 'U': - if (next == 'u') - unum = va_arg(ap,unsigned int); - else - unum = va_arg(ap,unsigned long long); - { - char buf[SDS_LLSTR_SIZE]; - l = sdsull2str(buf,unum); - if (sdsavail(s) < l) { - s = sdsMakeRoomFor(s,l); - if (s == NULL) goto fmt_error; - } - memcpy(s+i,buf,l); - sdsinclen(s,l); - i += l; - } - break; - default: /* Handle %% and generally %. */ - s[i++] = next; - sdsinclen(s,1); - break; - } - break; - default: - s[i++] = *f; - sdsinclen(s,1); - break; - } - f++; - } - va_end(ap); - - /* Add null-term */ - s[i] = '\0'; - return s; - -fmt_error: - va_end(ap); - return NULL; -} - -/* Remove the part of the string from left and from right composed just of - * contiguous characters found in 'cset', that is a null terminted C string. - * - * After the call, the modified sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. - * - * Example: - * - * s = sdsnew("AA...AA.a.aa.aHelloWorld :::"); - * s = sdstrim(s,"Aa. :"); - * printf("%s\n", s); - * - * Output will be just "Hello World". - */ -sds sdstrim(sds s, const char *cset) { - char *start, *end, *sp, *ep; - size_t len; - - sp = start = s; - ep = end = s+sdslen(s)-1; - while(sp <= end && strchr(cset, *sp)) sp++; - while(ep > sp && strchr(cset, *ep)) ep--; - len = (sp > ep) ? 0 : ((ep-sp)+1); - if (s != sp) memmove(s, sp, len); - s[len] = '\0'; - sdssetlen(s,len); - return s; -} - -/* Turn the string into a smaller (or equal) string containing only the - * substring specified by the 'start' and 'end' indexes. - * - * start and end can be negative, where -1 means the last character of the - * string, -2 the penultimate character, and so forth. - * - * The interval is inclusive, so the start and end characters will be part - * of the resulting string. - * - * The string is modified in-place. - * - * Return value: - * -1 (error) if sdslen(s) is larger than maximum positive ssize_t value. - * 0 on success. - * - * Example: - * - * s = sdsnew("Hello World"); - * sdsrange(s,1,-1); => "ello World" - */ -int sdsrange(sds s, ssize_t start, ssize_t end) { - size_t newlen, len = sdslen(s); - if (len > SSIZE_MAX) return -1; - - if (len == 0) return 0; - if (start < 0) { - start = len+start; - if (start < 0) start = 0; - } - if (end < 0) { - end = len+end; - if (end < 0) end = 0; - } - newlen = (start > end) ? 0 : (end-start)+1; - if (newlen != 0) { - if (start >= (ssize_t)len) { - newlen = 0; - } else if (end >= (ssize_t)len) { - end = len-1; - newlen = (start > end) ? 0 : (end-start)+1; - } - } else { - start = 0; - } - if (start && newlen) memmove(s, s+start, newlen); - s[newlen] = 0; - sdssetlen(s,newlen); - return 0; -} - -/* Apply tolower() to every character of the sds string 's'. */ -void sdstolower(sds s) { - int len = sdslen(s), j; - - for (j = 0; j < len; j++) s[j] = tolower(s[j]); -} - -/* Apply toupper() to every character of the sds string 's'. */ -void sdstoupper(sds s) { - int len = sdslen(s), j; - - for (j = 0; j < len; j++) s[j] = toupper(s[j]); -} - -/* Compare two sds strings s1 and s2 with memcmp(). - * - * Return value: - * - * positive if s1 > s2. - * negative if s1 < s2. - * 0 if s1 and s2 are exactly the same binary string. - * - * If two strings share exactly the same prefix, but one of the two has - * additional characters, the longer string is considered to be greater than - * the smaller one. */ -int sdscmp(const sds s1, const sds s2) { - size_t l1, l2, minlen; - int cmp; - - l1 = sdslen(s1); - l2 = sdslen(s2); - minlen = (l1 < l2) ? l1 : l2; - cmp = memcmp(s1,s2,minlen); - if (cmp == 0) return l1-l2; - return cmp; -} - -/* Split 's' with separator in 'sep'. An array - * of sds strings is returned. *count will be set - * by reference to the number of tokens returned. - * - * On out of memory, zero length string, zero length - * separator, NULL is returned. - * - * Note that 'sep' is able to split a string using - * a multi-character separator. For example - * sdssplit("foo_-_bar","_-_"); will return two - * elements "foo" and "bar". - * - * This version of the function is binary-safe but - * requires length arguments. sdssplit() is just the - * same function but for zero-terminated strings. - */ -sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) { - int elements = 0, slots = 5, start = 0, j; - sds *tokens; - - if (seplen < 1 || len < 0) return NULL; - - tokens = s_malloc(sizeof(sds)*slots); - if (tokens == NULL) return NULL; - - if (len == 0) { - *count = 0; - return tokens; - } - for (j = 0; j < (len-(seplen-1)); j++) { - /* make sure there is room for the next element and the final one */ - if (slots < elements+2) { - sds *newtokens; - - slots *= 2; - newtokens = s_realloc(tokens,sizeof(sds)*slots); - if (newtokens == NULL) goto cleanup; - tokens = newtokens; - } - /* search the separator */ - if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) { - tokens[elements] = sdsnewlen(s+start,j-start); - if (tokens[elements] == NULL) goto cleanup; - elements++; - start = j+seplen; - j = j+seplen-1; /* skip the separator */ - } - } - /* Add the final element. We are sure there is room in the tokens array. */ - tokens[elements] = sdsnewlen(s+start,len-start); - if (tokens[elements] == NULL) goto cleanup; - elements++; - *count = elements; - return tokens; - -cleanup: - { - int i; - for (i = 0; i < elements; i++) sdsfree(tokens[i]); - s_free(tokens); - *count = 0; - return NULL; - } -} - -/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */ -void sdsfreesplitres(sds *tokens, int count) { - if (!tokens) return; - while(count--) - sdsfree(tokens[count]); - s_free(tokens); -} - -/* Append to the sds string "s" an escaped string representation where - * all the non-printable characters (tested with isprint()) are turned into - * escapes in the form "\n\r\a...." or "\x". - * - * After the call, the modified sds string is no longer valid and all the - * references must be substituted with the new pointer returned by the call. */ -sds sdscatrepr(sds s, const char *p, size_t len) { - s = sdscatlen(s,"\"",1); - while(len--) { - switch(*p) { - case '\\': - case '"': - s = sdscatprintf(s,"\\%c",*p); - break; - case '\n': s = sdscatlen(s,"\\n",2); break; - case '\r': s = sdscatlen(s,"\\r",2); break; - case '\t': s = sdscatlen(s,"\\t",2); break; - case '\a': s = sdscatlen(s,"\\a",2); break; - case '\b': s = sdscatlen(s,"\\b",2); break; - default: - if (isprint(*p)) - s = sdscatprintf(s,"%c",*p); - else - s = sdscatprintf(s,"\\x%02x",(unsigned char)*p); - break; - } - p++; - } - return sdscatlen(s,"\"",1); -} - -/* Helper function for sdssplitargs() that converts a hex digit into an - * integer from 0 to 15 */ -int hex_digit_to_int(char c) { - switch(c) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; - default: return 0; - } -} - -/* Split a line into arguments, where every argument can be in the - * following programming-language REPL-alike form: - * - * foo bar "newline are supported\n" and "\xff\x00otherstuff" - * - * The number of arguments is stored into *argc, and an array - * of sds is returned. - * - * The caller should free the resulting array of sds strings with - * sdsfreesplitres(). - * - * Note that sdscatrepr() is able to convert back a string into - * a quoted string in the same format sdssplitargs() is able to parse. - * - * The function returns the allocated tokens on success, even when the - * input string is empty, or NULL if the input contains unbalanced - * quotes or closed quotes followed by non space characters - * as in: "foo"bar or "foo' - */ -sds *sdssplitargs(const char *line, int *argc) { - const char *p = line; - char *current = NULL; - char **vector = NULL; - - *argc = 0; - while(1) { - /* skip blanks */ - while(*p && isspace(*p)) p++; - if (*p) { - /* get a token */ - int inq=0; /* set to 1 if we are in "quotes" */ - int insq=0; /* set to 1 if we are in 'single quotes' */ - int done=0; - - if (current == NULL) current = sdsempty(); - while(!done) { - if (inq) { - if (*p == '\\' && *(p+1) == 'x' && - isxdigit(*(p+2)) && - isxdigit(*(p+3))) - { - unsigned char byte; - - byte = (hex_digit_to_int(*(p+2))*16)+ - hex_digit_to_int(*(p+3)); - current = sdscatlen(current,(char*)&byte,1); - p += 3; - } else if (*p == '\\' && *(p+1)) { - char c; - - p++; - switch(*p) { - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'b': c = '\b'; break; - case 'a': c = '\a'; break; - default: c = *p; break; - } - current = sdscatlen(current,&c,1); - } else if (*p == '"') { - /* closing quote must be followed by a space or - * nothing at all. */ - if (*(p+1) && !isspace(*(p+1))) goto err; - done=1; - } else if (!*p) { - /* unterminated quotes */ - goto err; - } else { - current = sdscatlen(current,p,1); - } - } else if (insq) { - if (*p == '\\' && *(p+1) == '\'') { - p++; - current = sdscatlen(current,"'",1); - } else if (*p == '\'') { - /* closing quote must be followed by a space or - * nothing at all. */ - if (*(p+1) && !isspace(*(p+1))) goto err; - done=1; - } else if (!*p) { - /* unterminated quotes */ - goto err; - } else { - current = sdscatlen(current,p,1); - } - } else { - switch(*p) { - case ' ': - case '\n': - case '\r': - case '\t': - case '\0': - done=1; - break; - case '"': - inq=1; - break; - case '\'': - insq=1; - break; - default: - current = sdscatlen(current,p,1); - break; - } - } - if (*p) p++; - } - /* add the token to the vector */ - { - char **new_vector = s_realloc(vector,((*argc)+1)*sizeof(char*)); - if (new_vector == NULL) { - s_free(vector); - return NULL; - } - - vector = new_vector; - vector[*argc] = current; - (*argc)++; - current = NULL; - } - } else { - /* Even on empty input string return something not NULL. */ - if (vector == NULL) vector = s_malloc(sizeof(void*)); - return vector; - } - } - -err: - while((*argc)--) - sdsfree(vector[*argc]); - s_free(vector); - if (current) sdsfree(current); - *argc = 0; - return NULL; -} - -/* Modify the string substituting all the occurrences of the set of - * characters specified in the 'from' string to the corresponding character - * in the 'to' array. - * - * For instance: sdsmapchars(mystring, "ho", "01", 2) - * will have the effect of turning the string "hello" into "0ell1". - * - * The function returns the sds string pointer, that is always the same - * as the input pointer since no resize is needed. */ -sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) { - size_t j, i, l = sdslen(s); - - for (j = 0; j < l; j++) { - for (i = 0; i < setlen; i++) { - if (s[j] == from[i]) { - s[j] = to[i]; - break; - } - } - } - return s; -} - -/* Join an array of C strings using the specified separator (also a C string). - * Returns the result as an sds string. */ -sds sdsjoin(char **argv, int argc, char *sep) { - sds join = sdsempty(); - int j; - - for (j = 0; j < argc; j++) { - join = sdscat(join, argv[j]); - if (j != argc-1) join = sdscat(join,sep); - } - return join; -} - -/* Like sdsjoin, but joins an array of SDS strings. */ -sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) { - sds join = sdsempty(); - int j; - - for (j = 0; j < argc; j++) { - join = sdscatsds(join, argv[j]); - if (j != argc-1) join = sdscatlen(join,sep,seplen); - } - return join; -} - -/* Wrappers to the allocators used by SDS. Note that SDS will actually - * just use the macros defined into sdsalloc.h in order to avoid to pay - * the overhead of function calls. Here we define these wrappers only for - * the programs SDS is linked to, if they want to touch the SDS internals - * even if they use a different allocator. */ -void *sds_malloc(size_t size) { return s_malloc(size); } -void *sds_realloc(void *ptr, size_t size) { return s_realloc(ptr,size); } -void sds_free(void *ptr) { s_free(ptr); } - -#if defined(SDS_TEST_MAIN) -#include -#include "testhelp.h" -#include "limits.h" - -#define UNUSED(x) (void)(x) -int sdsTest(void) { - { - sds x = sdsnew("foo"), y; - - test_cond("Create a string and obtain the length", - sdslen(x) == 3 && memcmp(x,"foo\0",4) == 0) - - sdsfree(x); - x = sdsnewlen("foo",2); - test_cond("Create a string with specified length", - sdslen(x) == 2 && memcmp(x,"fo\0",3) == 0) - - x = sdscat(x,"bar"); - test_cond("Strings concatenation", - sdslen(x) == 5 && memcmp(x,"fobar\0",6) == 0); - - x = sdscpy(x,"a"); - test_cond("sdscpy() against an originally longer string", - sdslen(x) == 1 && memcmp(x,"a\0",2) == 0) - - x = sdscpy(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk"); - test_cond("sdscpy() against an originally shorter string", - sdslen(x) == 33 && - memcmp(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\0",33) == 0) - - sdsfree(x); - x = sdscatprintf(sdsempty(),"%d",123); - test_cond("sdscatprintf() seems working in the base case", - sdslen(x) == 3 && memcmp(x,"123\0",4) == 0) - - sdsfree(x); - x = sdsnew("--"); - x = sdscatfmt(x, "Hello %s World %I,%I--", "Hi!", LLONG_MIN,LLONG_MAX); - test_cond("sdscatfmt() seems working in the base case", - sdslen(x) == 60 && - memcmp(x,"--Hello Hi! World -9223372036854775808," - "9223372036854775807--",60) == 0) - printf("[%s]\n",x); - - sdsfree(x); - x = sdsnew("--"); - x = sdscatfmt(x, "%u,%U--", UINT_MAX, ULLONG_MAX); - test_cond("sdscatfmt() seems working with unsigned numbers", - sdslen(x) == 35 && - memcmp(x,"--4294967295,18446744073709551615--",35) == 0) - - sdsfree(x); - x = sdsnew(" x "); - sdstrim(x," x"); - test_cond("sdstrim() works when all chars match", - sdslen(x) == 0) - - sdsfree(x); - x = sdsnew(" x "); - sdstrim(x," "); - test_cond("sdstrim() works when a single char remains", - sdslen(x) == 1 && x[0] == 'x') - - sdsfree(x); - x = sdsnew("xxciaoyyy"); - sdstrim(x,"xy"); - test_cond("sdstrim() correctly trims characters", - sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0) - - y = sdsdup(x); - sdsrange(y,1,1); - test_cond("sdsrange(...,1,1)", - sdslen(y) == 1 && memcmp(y,"i\0",2) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,1,-1); - test_cond("sdsrange(...,1,-1)", - sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,-2,-1); - test_cond("sdsrange(...,-2,-1)", - sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,2,1); - test_cond("sdsrange(...,2,1)", - sdslen(y) == 0 && memcmp(y,"\0",1) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,1,100); - test_cond("sdsrange(...,1,100)", - sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0) - - sdsfree(y); - y = sdsdup(x); - sdsrange(y,100,100); - test_cond("sdsrange(...,100,100)", - sdslen(y) == 0 && memcmp(y,"\0",1) == 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("foo"); - y = sdsnew("foa"); - test_cond("sdscmp(foo,foa)", sdscmp(x,y) > 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("bar"); - y = sdsnew("bar"); - test_cond("sdscmp(bar,bar)", sdscmp(x,y) == 0) - - sdsfree(y); - sdsfree(x); - x = sdsnew("aar"); - y = sdsnew("bar"); - test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0) - - sdsfree(y); - sdsfree(x); - x = sdsnewlen("\a\n\0foo\r",7); - y = sdscatrepr(sdsempty(),x,sdslen(x)); - test_cond("sdscatrepr(...data...)", - memcmp(y,"\"\\a\\n\\x00foo\\r\"",15) == 0) - - { - unsigned int oldfree; - char *p; - int step = 10, j, i; - - sdsfree(x); - sdsfree(y); - x = sdsnew("0"); - test_cond("sdsnew() free/len buffers", sdslen(x) == 1 && sdsavail(x) == 0); - - /* Run the test a few times in order to hit the first two - * SDS header types. */ - for (i = 0; i < 10; i++) { - int oldlen = sdslen(x); - x = sdsMakeRoomFor(x,step); - int type = x[-1]&SDS_TYPE_MASK; - - test_cond("sdsMakeRoomFor() len", sdslen(x) == oldlen); - if (type != SDS_TYPE_5) { - test_cond("sdsMakeRoomFor() free", sdsavail(x) >= step); - oldfree = sdsavail(x); - } - p = x+oldlen; - for (j = 0; j < step; j++) { - p[j] = 'A'+j; - } - sdsIncrLen(x,step); - } - test_cond("sdsMakeRoomFor() content", - memcmp("0ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ",x,101) == 0); - test_cond("sdsMakeRoomFor() final length",sdslen(x)==101); - - sdsfree(x); - } - } - test_report() - return 0; -} -#endif - -#ifdef SDS_TEST_MAIN -int main(void) { - return sdsTest(); -} -#endif diff --git a/ext/hiredis-1.0.2/sds.h b/ext/hiredis-1.0.2/sds.h deleted file mode 100644 index eda8833b5..000000000 --- a/ext/hiredis-1.0.2/sds.h +++ /dev/null @@ -1,278 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SDS_H -#define __SDS_H - -#define SDS_MAX_PREALLOC (1024*1024) -#ifdef _MSC_VER -#define __attribute__(x) -typedef long long ssize_t; -#define SSIZE_MAX (LLONG_MAX >> 1) -#endif - -#include -#include -#include - -typedef char *sds; - -/* Note: sdshdr5 is never used, we just access the flags byte directly. - * However is here to document the layout of type 5 SDS strings. */ -struct __attribute__ ((__packed__)) sdshdr5 { - unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr8 { - uint8_t len; /* used */ - uint8_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr16 { - uint16_t len; /* used */ - uint16_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr32 { - uint32_t len; /* used */ - uint32_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr64 { - uint64_t len; /* used */ - uint64_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; - -#define SDS_TYPE_5 0 -#define SDS_TYPE_8 1 -#define SDS_TYPE_16 2 -#define SDS_TYPE_32 3 -#define SDS_TYPE_64 4 -#define SDS_TYPE_MASK 7 -#define SDS_TYPE_BITS 3 -#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))); -#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) -#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) - -static inline size_t sdslen(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->len; - case SDS_TYPE_16: - return SDS_HDR(16,s)->len; - case SDS_TYPE_32: - return SDS_HDR(32,s)->len; - case SDS_TYPE_64: - return SDS_HDR(64,s)->len; - } - return 0; -} - -static inline size_t sdsavail(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: { - return 0; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - return sh->alloc - sh->len; - } - } - return 0; -} - -static inline void sdssetlen(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - *fp = (unsigned char)(SDS_TYPE_5 | (newlen << SDS_TYPE_BITS)); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len = (uint8_t)newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len = (uint16_t)newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len = (uint32_t)newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len = (uint64_t)newlen; - break; - } -} - -static inline void sdsinclen(sds s, size_t inc) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - unsigned char newlen = SDS_TYPE_5_LEN(flags)+(unsigned char)inc; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len += (uint8_t)inc; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len += (uint16_t)inc; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len += (uint32_t)inc; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len += (uint64_t)inc; - break; - } -} - -/* sdsalloc() = sdsavail() + sdslen() */ -static inline size_t sdsalloc(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->alloc; - case SDS_TYPE_16: - return SDS_HDR(16,s)->alloc; - case SDS_TYPE_32: - return SDS_HDR(32,s)->alloc; - case SDS_TYPE_64: - return SDS_HDR(64,s)->alloc; - } - return 0; -} - -static inline void sdssetalloc(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - /* Nothing to do, this type has no total allocation info. */ - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->alloc = (uint8_t)newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->alloc = (uint16_t)newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->alloc = (uint32_t)newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->alloc = (uint64_t)newlen; - break; - } -} - -sds sdsnewlen(const void *init, size_t initlen); -sds sdsnew(const char *init); -sds sdsempty(void); -sds sdsdup(const sds s); -void sdsfree(sds s); -sds sdsgrowzero(sds s, size_t len); -sds sdscatlen(sds s, const void *t, size_t len); -sds sdscat(sds s, const char *t); -sds sdscatsds(sds s, const sds t); -sds sdscpylen(sds s, const char *t, size_t len); -sds sdscpy(sds s, const char *t); - -sds sdscatvprintf(sds s, const char *fmt, va_list ap); -#ifdef __GNUC__ -sds sdscatprintf(sds s, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else -sds sdscatprintf(sds s, const char *fmt, ...); -#endif - -sds sdscatfmt(sds s, char const *fmt, ...); -sds sdstrim(sds s, const char *cset); -int sdsrange(sds s, ssize_t start, ssize_t end); -void sdsupdatelen(sds s); -void sdsclear(sds s); -int sdscmp(const sds s1, const sds s2); -sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); -void sdsfreesplitres(sds *tokens, int count); -void sdstolower(sds s); -void sdstoupper(sds s); -sds sdsfromlonglong(long long value); -sds sdscatrepr(sds s, const char *p, size_t len); -sds *sdssplitargs(const char *line, int *argc); -sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); -sds sdsjoin(char **argv, int argc, char *sep); -sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); - -/* Low level functions exposed to the user API */ -sds sdsMakeRoomFor(sds s, size_t addlen); -void sdsIncrLen(sds s, int incr); -sds sdsRemoveFreeSpace(sds s); -size_t sdsAllocSize(sds s); -void *sdsAllocPtr(sds s); - -/* Export the allocator used by SDS to the program using SDS. - * Sometimes the program SDS is linked to, may use a different set of - * allocators, but may want to allocate or free things that SDS will - * respectively free or allocate. */ -void *sds_malloc(size_t size); -void *sds_realloc(void *ptr, size_t size); -void sds_free(void *ptr); - -#ifdef REDIS_TEST -int sdsTest(int argc, char *argv[]); -#endif - -#endif diff --git a/ext/hiredis-1.0.2/sdsalloc.h b/ext/hiredis-1.0.2/sdsalloc.h deleted file mode 100644 index 5538dd94c..000000000 --- a/ext/hiredis-1.0.2/sdsalloc.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* SDS allocator selection. - * - * This file is used in order to change the SDS allocator at compile time. - * Just define the following defines to what you want to use. Also add - * the include of your alternate allocator if needed (not needed in order - * to use the default libc allocator). */ - -#include "alloc.h" - -#define s_malloc hi_malloc -#define s_realloc hi_realloc -#define s_free hi_free diff --git a/ext/hiredis-1.0.2/sockcompat.c b/ext/hiredis-1.0.2/sockcompat.c deleted file mode 100644 index f99d14b05..000000000 --- a/ext/hiredis-1.0.2/sockcompat.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2019, Marcus Geelnard - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#define REDIS_SOCKCOMPAT_IMPLEMENTATION -#include "sockcompat.h" - -#ifdef _WIN32 -static int _wsaErrorToErrno(int err) { - switch (err) { - case WSAEWOULDBLOCK: - return EWOULDBLOCK; - case WSAEINPROGRESS: - return EINPROGRESS; - case WSAEALREADY: - return EALREADY; - case WSAENOTSOCK: - return ENOTSOCK; - case WSAEDESTADDRREQ: - return EDESTADDRREQ; - case WSAEMSGSIZE: - return EMSGSIZE; - case WSAEPROTOTYPE: - return EPROTOTYPE; - case WSAENOPROTOOPT: - return ENOPROTOOPT; - case WSAEPROTONOSUPPORT: - return EPROTONOSUPPORT; - case WSAEOPNOTSUPP: - return EOPNOTSUPP; - case WSAEAFNOSUPPORT: - return EAFNOSUPPORT; - case WSAEADDRINUSE: - return EADDRINUSE; - case WSAEADDRNOTAVAIL: - return EADDRNOTAVAIL; - case WSAENETDOWN: - return ENETDOWN; - case WSAENETUNREACH: - return ENETUNREACH; - case WSAENETRESET: - return ENETRESET; - case WSAECONNABORTED: - return ECONNABORTED; - case WSAECONNRESET: - return ECONNRESET; - case WSAENOBUFS: - return ENOBUFS; - case WSAEISCONN: - return EISCONN; - case WSAENOTCONN: - return ENOTCONN; - case WSAETIMEDOUT: - return ETIMEDOUT; - case WSAECONNREFUSED: - return ECONNREFUSED; - case WSAELOOP: - return ELOOP; - case WSAENAMETOOLONG: - return ENAMETOOLONG; - case WSAEHOSTUNREACH: - return EHOSTUNREACH; - case WSAENOTEMPTY: - return ENOTEMPTY; - default: - /* We just return a generic I/O error if we could not find a relevant error. */ - return EIO; - } -} - -static void _updateErrno(int success) { - errno = success ? 0 : _wsaErrorToErrno(WSAGetLastError()); -} - -static int _initWinsock() { - static int s_initialized = 0; - if (!s_initialized) { - static WSADATA wsadata; - int err = WSAStartup(MAKEWORD(2,2), &wsadata); - if (err != 0) { - errno = _wsaErrorToErrno(err); - return 0; - } - s_initialized = 1; - } - return 1; -} - -int win32_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { - /* Note: This function is likely to be called before other functions, so run init here. */ - if (!_initWinsock()) { - return EAI_FAIL; - } - - switch (getaddrinfo(node, service, hints, res)) { - case 0: return 0; - case WSATRY_AGAIN: return EAI_AGAIN; - case WSAEINVAL: return EAI_BADFLAGS; - case WSAEAFNOSUPPORT: return EAI_FAMILY; - case WSA_NOT_ENOUGH_MEMORY: return EAI_MEMORY; - case WSAHOST_NOT_FOUND: return EAI_NONAME; - case WSATYPE_NOT_FOUND: return EAI_SERVICE; - case WSAESOCKTNOSUPPORT: return EAI_SOCKTYPE; - default: return EAI_FAIL; /* Including WSANO_RECOVERY */ - } -} - -const char *win32_gai_strerror(int errcode) { - switch (errcode) { - case 0: errcode = 0; break; - case EAI_AGAIN: errcode = WSATRY_AGAIN; break; - case EAI_BADFLAGS: errcode = WSAEINVAL; break; - case EAI_FAMILY: errcode = WSAEAFNOSUPPORT; break; - case EAI_MEMORY: errcode = WSA_NOT_ENOUGH_MEMORY; break; - case EAI_NONAME: errcode = WSAHOST_NOT_FOUND; break; - case EAI_SERVICE: errcode = WSATYPE_NOT_FOUND; break; - case EAI_SOCKTYPE: errcode = WSAESOCKTNOSUPPORT; break; - default: errcode = WSANO_RECOVERY; break; /* Including EAI_FAIL */ - } - return gai_strerror(errcode); -} - -void win32_freeaddrinfo(struct addrinfo *res) { - freeaddrinfo(res); -} - -SOCKET win32_socket(int domain, int type, int protocol) { - SOCKET s; - - /* Note: This function is likely to be called before other functions, so run init here. */ - if (!_initWinsock()) { - return INVALID_SOCKET; - } - - _updateErrno((s = socket(domain, type, protocol)) != INVALID_SOCKET); - return s; -} - -int win32_ioctl(SOCKET fd, unsigned long request, unsigned long *argp) { - int ret = ioctlsocket(fd, (long)request, argp); - _updateErrno(ret != SOCKET_ERROR); - return ret != SOCKET_ERROR ? ret : -1; -} - -int win32_bind(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen) { - int ret = bind(sockfd, addr, addrlen); - _updateErrno(ret != SOCKET_ERROR); - return ret != SOCKET_ERROR ? ret : -1; -} - -int win32_connect(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen) { - int ret = connect(sockfd, addr, addrlen); - _updateErrno(ret != SOCKET_ERROR); - - /* For Winsock connect(), the WSAEWOULDBLOCK error means the same thing as - * EINPROGRESS for POSIX connect(), so we do that translation to keep POSIX - * logic consistent. */ - if (errno == EWOULDBLOCK) { - errno = EINPROGRESS; - } - - return ret != SOCKET_ERROR ? ret : -1; -} - -int win32_getsockopt(SOCKET sockfd, int level, int optname, void *optval, socklen_t *optlen) { - int ret = 0; - if ((level == SOL_SOCKET) && ((optname == SO_RCVTIMEO) || (optname == SO_SNDTIMEO))) { - if (*optlen >= sizeof (struct timeval)) { - struct timeval *tv = optval; - DWORD timeout = 0; - socklen_t dwlen = 0; - ret = getsockopt(sockfd, level, optname, (char *)&timeout, &dwlen); - tv->tv_sec = timeout / 1000; - tv->tv_usec = (timeout * 1000) % 1000000; - } else { - ret = WSAEFAULT; - } - *optlen = sizeof (struct timeval); - } else { - ret = getsockopt(sockfd, level, optname, (char*)optval, optlen); - } - _updateErrno(ret != SOCKET_ERROR); - return ret != SOCKET_ERROR ? ret : -1; -} - -int win32_setsockopt(SOCKET sockfd, int level, int optname, const void *optval, socklen_t optlen) { - int ret = 0; - if ((level == SOL_SOCKET) && ((optname == SO_RCVTIMEO) || (optname == SO_SNDTIMEO))) { - const struct timeval *tv = optval; - DWORD timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000; - ret = setsockopt(sockfd, level, optname, (const char*)&timeout, sizeof(DWORD)); - } else { - ret = setsockopt(sockfd, level, optname, (const char*)optval, optlen); - } - _updateErrno(ret != SOCKET_ERROR); - return ret != SOCKET_ERROR ? ret : -1; -} - -int win32_close(SOCKET fd) { - int ret = closesocket(fd); - _updateErrno(ret != SOCKET_ERROR); - return ret != SOCKET_ERROR ? ret : -1; -} - -ssize_t win32_recv(SOCKET sockfd, void *buf, size_t len, int flags) { - int ret = recv(sockfd, (char*)buf, (int)len, flags); - _updateErrno(ret != SOCKET_ERROR); - return ret != SOCKET_ERROR ? ret : -1; -} - -ssize_t win32_send(SOCKET sockfd, const void *buf, size_t len, int flags) { - int ret = send(sockfd, (const char*)buf, (int)len, flags); - _updateErrno(ret != SOCKET_ERROR); - return ret != SOCKET_ERROR ? ret : -1; -} - -int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout) { - int ret = WSAPoll(fds, nfds, timeout); - _updateErrno(ret != SOCKET_ERROR); - return ret != SOCKET_ERROR ? ret : -1; -} -#endif /* _WIN32 */ diff --git a/ext/hiredis-1.0.2/sockcompat.h b/ext/hiredis-1.0.2/sockcompat.h deleted file mode 100644 index 85810e848..000000000 --- a/ext/hiredis-1.0.2/sockcompat.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2019, Marcus Geelnard - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SOCKCOMPAT_H -#define __SOCKCOMPAT_H - -#ifndef _WIN32 -/* For POSIX systems we use the standard BSD socket API. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else -/* For Windows we use winsock. */ -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 /* To get WSAPoll etc. */ -#include -#include -#include -#include - -#ifdef _MSC_VER -typedef long long ssize_t; -#endif - -/* Emulate the parts of the BSD socket API that we need (override the winsock signatures). */ -int win32_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); -const char *win32_gai_strerror(int errcode); -void win32_freeaddrinfo(struct addrinfo *res); -SOCKET win32_socket(int domain, int type, int protocol); -int win32_ioctl(SOCKET fd, unsigned long request, unsigned long *argp); -int win32_bind(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen); -int win32_connect(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen); -int win32_getsockopt(SOCKET sockfd, int level, int optname, void *optval, socklen_t *optlen); -int win32_setsockopt(SOCKET sockfd, int level, int optname, const void *optval, socklen_t optlen); -int win32_close(SOCKET fd); -ssize_t win32_recv(SOCKET sockfd, void *buf, size_t len, int flags); -ssize_t win32_send(SOCKET sockfd, const void *buf, size_t len, int flags); -typedef ULONG nfds_t; -int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout); - -#ifndef REDIS_SOCKCOMPAT_IMPLEMENTATION -#define getaddrinfo(node, service, hints, res) win32_getaddrinfo(node, service, hints, res) -#undef gai_strerror -#define gai_strerror(errcode) win32_gai_strerror(errcode) -#define freeaddrinfo(res) win32_freeaddrinfo(res) -#define socket(domain, type, protocol) win32_socket(domain, type, protocol) -#define ioctl(fd, request, argp) win32_ioctl(fd, request, argp) -#define bind(sockfd, addr, addrlen) win32_bind(sockfd, addr, addrlen) -#define connect(sockfd, addr, addrlen) win32_connect(sockfd, addr, addrlen) -#define getsockopt(sockfd, level, optname, optval, optlen) win32_getsockopt(sockfd, level, optname, optval, optlen) -#define setsockopt(sockfd, level, optname, optval, optlen) win32_setsockopt(sockfd, level, optname, optval, optlen) -#define close(fd) win32_close(fd) -#define recv(sockfd, buf, len, flags) win32_recv(sockfd, buf, len, flags) -#define send(sockfd, buf, len, flags) win32_send(sockfd, buf, len, flags) -#define poll(fds, nfds, timeout) win32_poll(fds, nfds, timeout) -#endif /* REDIS_SOCKCOMPAT_IMPLEMENTATION */ -#endif /* _WIN32 */ - -#endif /* __SOCKCOMPAT_H */ diff --git a/ext/hiredis-1.0.2/ssl.c b/ext/hiredis-1.0.2/ssl.c deleted file mode 100644 index 7df58fbde..000000000 --- a/ext/hiredis-1.0.2/ssl.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * Copyright (c) 2019, Redis Labs - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "hiredis.h" -#include "async.h" - -#include -#include -#include -#ifdef _WIN32 -#include -#else -#include -#endif - -#include -#include - -#include "win32.h" -#include "async_private.h" -#include "hiredis_ssl.h" - -void __redisSetError(redisContext *c, int type, const char *str); - -struct redisSSLContext { - /* Associated OpenSSL SSL_CTX as created by redisCreateSSLContext() */ - SSL_CTX *ssl_ctx; - - /* Requested SNI, or NULL */ - char *server_name; -}; - -/* The SSL connection context is attached to SSL/TLS connections as a privdata. */ -typedef struct redisSSL { - /** - * OpenSSL SSL object. - */ - SSL *ssl; - - /** - * SSL_write() requires to be called again with the same arguments it was - * previously called with in the event of an SSL_read/SSL_write situation - */ - size_t lastLen; - - /** Whether the SSL layer requires read (possibly before a write) */ - int wantRead; - - /** - * Whether a write was requested prior to a read. If set, the write() - * should resume whenever a read takes place, if possible - */ - int pendingWrite; -} redisSSL; - -/* Forward declaration */ -redisContextFuncs redisContextSSLFuncs; - -/** - * OpenSSL global initialization and locking handling callbacks. - * Note that this is only required for OpenSSL < 1.1.0. - */ - -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#define HIREDIS_USE_CRYPTO_LOCKS -#endif - -#ifdef HIREDIS_USE_CRYPTO_LOCKS -#ifdef _WIN32 -typedef CRITICAL_SECTION sslLockType; -static void sslLockInit(sslLockType* l) { - InitializeCriticalSection(l); -} -static void sslLockAcquire(sslLockType* l) { - EnterCriticalSection(l); -} -static void sslLockRelease(sslLockType* l) { - LeaveCriticalSection(l); -} -#else -typedef pthread_mutex_t sslLockType; -static void sslLockInit(sslLockType *l) { - pthread_mutex_init(l, NULL); -} -static void sslLockAcquire(sslLockType *l) { - pthread_mutex_lock(l); -} -static void sslLockRelease(sslLockType *l) { - pthread_mutex_unlock(l); -} -#endif - -static sslLockType* ossl_locks; - -static void opensslDoLock(int mode, int lkid, const char *f, int line) { - sslLockType *l = ossl_locks + lkid; - - if (mode & CRYPTO_LOCK) { - sslLockAcquire(l); - } else { - sslLockRelease(l); - } - - (void)f; - (void)line; -} - -static int initOpensslLocks(void) { - unsigned ii, nlocks; - if (CRYPTO_get_locking_callback() != NULL) { - /* Someone already set the callback before us. Don't destroy it! */ - return REDIS_OK; - } - nlocks = CRYPTO_num_locks(); - ossl_locks = hi_malloc(sizeof(*ossl_locks) * nlocks); - if (ossl_locks == NULL) - return REDIS_ERR; - - for (ii = 0; ii < nlocks; ii++) { - sslLockInit(ossl_locks + ii); - } - CRYPTO_set_locking_callback(opensslDoLock); - return REDIS_OK; -} -#endif /* HIREDIS_USE_CRYPTO_LOCKS */ - -int redisInitOpenSSL(void) -{ - SSL_library_init(); -#ifdef HIREDIS_USE_CRYPTO_LOCKS - initOpensslLocks(); -#endif - - return REDIS_OK; -} - -/** - * redisSSLContext helper context destruction. - */ - -const char *redisSSLContextGetError(redisSSLContextError error) -{ - switch (error) { - case REDIS_SSL_CTX_NONE: - return "No Error"; - case REDIS_SSL_CTX_CREATE_FAILED: - return "Failed to create OpenSSL SSL_CTX"; - case REDIS_SSL_CTX_CERT_KEY_REQUIRED: - return "Client cert and key must both be specified or skipped"; - case REDIS_SSL_CTX_CA_CERT_LOAD_FAILED: - return "Failed to load CA Certificate or CA Path"; - case REDIS_SSL_CTX_CLIENT_CERT_LOAD_FAILED: - return "Failed to load client certificate"; - case REDIS_SSL_CTX_PRIVATE_KEY_LOAD_FAILED: - return "Failed to load private key"; - default: - return "Unknown error code"; - } -} - -void redisFreeSSLContext(redisSSLContext *ctx) -{ - if (!ctx) - return; - - if (ctx->server_name) { - hi_free(ctx->server_name); - ctx->server_name = NULL; - } - - if (ctx->ssl_ctx) { - SSL_CTX_free(ctx->ssl_ctx); - ctx->ssl_ctx = NULL; - } - - hi_free(ctx); -} - - -/** - * redisSSLContext helper context initialization. - */ - -redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char *capath, - const char *cert_filename, const char *private_key_filename, - const char *server_name, redisSSLContextError *error) -{ - redisSSLContext *ctx = hi_calloc(1, sizeof(redisSSLContext)); - if (ctx == NULL) - goto error; - - ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); - if (!ctx->ssl_ctx) { - if (error) *error = REDIS_SSL_CTX_CREATE_FAILED; - goto error; - } - - SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); - SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL); - - if ((cert_filename != NULL && private_key_filename == NULL) || - (private_key_filename != NULL && cert_filename == NULL)) { - if (error) *error = REDIS_SSL_CTX_CERT_KEY_REQUIRED; - goto error; - } - - if (capath || cacert_filename) { - if (!SSL_CTX_load_verify_locations(ctx->ssl_ctx, cacert_filename, capath)) { - if (error) *error = REDIS_SSL_CTX_CA_CERT_LOAD_FAILED; - goto error; - } - } - - if (cert_filename) { - if (!SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, cert_filename)) { - if (error) *error = REDIS_SSL_CTX_CLIENT_CERT_LOAD_FAILED; - goto error; - } - if (!SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, private_key_filename, SSL_FILETYPE_PEM)) { - if (error) *error = REDIS_SSL_CTX_PRIVATE_KEY_LOAD_FAILED; - goto error; - } - } - - if (server_name) - ctx->server_name = hi_strdup(server_name); - - return ctx; - -error: - redisFreeSSLContext(ctx); - return NULL; -} - -/** - * SSL Connection initialization. - */ - - -static int redisSSLConnect(redisContext *c, SSL *ssl) { - if (c->privctx) { - __redisSetError(c, REDIS_ERR_OTHER, "redisContext was already associated"); - return REDIS_ERR; - } - - redisSSL *rssl = hi_calloc(1, sizeof(redisSSL)); - if (rssl == NULL) { - __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); - return REDIS_ERR; - } - - c->funcs = &redisContextSSLFuncs; - rssl->ssl = ssl; - - SSL_set_mode(rssl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - SSL_set_fd(rssl->ssl, c->fd); - SSL_set_connect_state(rssl->ssl); - - ERR_clear_error(); - int rv = SSL_connect(rssl->ssl); - if (rv == 1) { - c->privctx = rssl; - return REDIS_OK; - } - - rv = SSL_get_error(rssl->ssl, rv); - if (((c->flags & REDIS_BLOCK) == 0) && - (rv == SSL_ERROR_WANT_READ || rv == SSL_ERROR_WANT_WRITE)) { - c->privctx = rssl; - return REDIS_OK; - } - - if (c->err == 0) { - char err[512]; - if (rv == SSL_ERROR_SYSCALL) - snprintf(err,sizeof(err)-1,"SSL_connect failed: %s",strerror(errno)); - else { - unsigned long e = ERR_peek_last_error(); - snprintf(err,sizeof(err)-1,"SSL_connect failed: %s", - ERR_reason_error_string(e)); - } - __redisSetError(c, REDIS_ERR_IO, err); - } - - hi_free(rssl); - return REDIS_ERR; -} - -/** - * A wrapper around redisSSLConnect() for users who manage their own context and - * create their own SSL object. - */ - -int redisInitiateSSL(redisContext *c, SSL *ssl) { - return redisSSLConnect(c, ssl); -} - -/** - * A wrapper around redisSSLConnect() for users who use redisSSLContext and don't - * manage their own SSL objects. - */ - -int redisInitiateSSLWithContext(redisContext *c, redisSSLContext *redis_ssl_ctx) -{ - if (!c || !redis_ssl_ctx) - return REDIS_ERR; - - /* We want to verify that redisSSLConnect() won't fail on this, as it will - * not own the SSL object in that case and we'll end up leaking. - */ - if (c->privctx) - return REDIS_ERR; - - SSL *ssl = SSL_new(redis_ssl_ctx->ssl_ctx); - if (!ssl) { - __redisSetError(c, REDIS_ERR_OTHER, "Couldn't create new SSL instance"); - goto error; - } - - if (redis_ssl_ctx->server_name) { - if (!SSL_set_tlsext_host_name(ssl, redis_ssl_ctx->server_name)) { - __redisSetError(c, REDIS_ERR_OTHER, "Failed to set server_name/SNI"); - goto error; - } - } - - return redisSSLConnect(c, ssl); - -error: - if (ssl) - SSL_free(ssl); - return REDIS_ERR; -} - -static int maybeCheckWant(redisSSL *rssl, int rv) { - /** - * If the error is WANT_READ or WANT_WRITE, the appropriate flags are set - * and true is returned. False is returned otherwise - */ - if (rv == SSL_ERROR_WANT_READ) { - rssl->wantRead = 1; - return 1; - } else if (rv == SSL_ERROR_WANT_WRITE) { - rssl->pendingWrite = 1; - return 1; - } else { - return 0; - } -} - -/** - * Implementation of redisContextFuncs for SSL connections. - */ - -static void redisSSLFree(void *privctx){ - redisSSL *rsc = privctx; - - if (!rsc) return; - if (rsc->ssl) { - SSL_free(rsc->ssl); - rsc->ssl = NULL; - } - hi_free(rsc); -} - -static ssize_t redisSSLRead(redisContext *c, char *buf, size_t bufcap) { - redisSSL *rssl = c->privctx; - - int nread = SSL_read(rssl->ssl, buf, bufcap); - if (nread > 0) { - return nread; - } else if (nread == 0) { - __redisSetError(c, REDIS_ERR_EOF, "Server closed the connection"); - return -1; - } else { - int err = SSL_get_error(rssl->ssl, nread); - if (c->flags & REDIS_BLOCK) { - /** - * In blocking mode, we should never end up in a situation where - * we get an error without it being an actual error, except - * in the case of EINTR, which can be spuriously received from - * debuggers or whatever. - */ - if (errno == EINTR) { - return 0; - } else { - const char *msg = NULL; - if (errno == EAGAIN) { - msg = "Resource temporarily unavailable"; - } - __redisSetError(c, REDIS_ERR_IO, msg); - return -1; - } - } - - /** - * We can very well get an EWOULDBLOCK/EAGAIN, however - */ - if (maybeCheckWant(rssl, err)) { - return 0; - } else { - __redisSetError(c, REDIS_ERR_IO, NULL); - return -1; - } - } -} - -static ssize_t redisSSLWrite(redisContext *c) { - redisSSL *rssl = c->privctx; - - size_t len = rssl->lastLen ? rssl->lastLen : sdslen(c->obuf); - int rv = SSL_write(rssl->ssl, c->obuf, len); - - if (rv > 0) { - rssl->lastLen = 0; - } else if (rv < 0) { - rssl->lastLen = len; - - int err = SSL_get_error(rssl->ssl, rv); - if ((c->flags & REDIS_BLOCK) == 0 && maybeCheckWant(rssl, err)) { - return 0; - } else { - __redisSetError(c, REDIS_ERR_IO, NULL); - return -1; - } - } - return rv; -} - -static void redisSSLAsyncRead(redisAsyncContext *ac) { - int rv; - redisSSL *rssl = ac->c.privctx; - redisContext *c = &ac->c; - - rssl->wantRead = 0; - - if (rssl->pendingWrite) { - int done; - - /* This is probably just a write event */ - rssl->pendingWrite = 0; - rv = redisBufferWrite(c, &done); - if (rv == REDIS_ERR) { - __redisAsyncDisconnect(ac); - return; - } else if (!done) { - _EL_ADD_WRITE(ac); - } - } - - rv = redisBufferRead(c); - if (rv == REDIS_ERR) { - __redisAsyncDisconnect(ac); - } else { - _EL_ADD_READ(ac); - redisProcessCallbacks(ac); - } -} - -static void redisSSLAsyncWrite(redisAsyncContext *ac) { - int rv, done = 0; - redisSSL *rssl = ac->c.privctx; - redisContext *c = &ac->c; - - rssl->pendingWrite = 0; - rv = redisBufferWrite(c, &done); - if (rv == REDIS_ERR) { - __redisAsyncDisconnect(ac); - return; - } - - if (!done) { - if (rssl->wantRead) { - /* Need to read-before-write */ - rssl->pendingWrite = 1; - _EL_DEL_WRITE(ac); - } else { - /* No extra reads needed, just need to write more */ - _EL_ADD_WRITE(ac); - } - } else { - /* Already done! */ - _EL_DEL_WRITE(ac); - } - - /* Always reschedule a read */ - _EL_ADD_READ(ac); -} - -redisContextFuncs redisContextSSLFuncs = { - .free_privctx = redisSSLFree, - .async_read = redisSSLAsyncRead, - .async_write = redisSSLAsyncWrite, - .read = redisSSLRead, - .write = redisSSLWrite -}; - diff --git a/ext/hiredis-1.0.2/test.c b/ext/hiredis-1.0.2/test.c deleted file mode 100644 index 397f5640e..000000000 --- a/ext/hiredis-1.0.2/test.c +++ /dev/null @@ -1,1401 +0,0 @@ -#include "fmacros.h" -#include "sockcompat.h" -#include -#include -#include -#ifndef _WIN32 -#include -#include -#endif -#include -#include -#include -#include - -#include "hiredis.h" -#include "async.h" -#ifdef HIREDIS_TEST_SSL -#include "hiredis_ssl.h" -#endif -#include "net.h" -#include "win32.h" - -enum connection_type { - CONN_TCP, - CONN_UNIX, - CONN_FD, - CONN_SSL -}; - -struct config { - enum connection_type type; - - struct { - const char *host; - int port; - struct timeval timeout; - } tcp; - - struct { - const char *path; - } unix_sock; - - struct { - const char *host; - int port; - const char *ca_cert; - const char *cert; - const char *key; - } ssl; -}; - -struct privdata { - int dtor_counter; -}; - -#ifdef HIREDIS_TEST_SSL -redisSSLContext *_ssl_ctx = NULL; -#endif - -/* The following lines make up our testing "framework" :) */ -static int tests = 0, fails = 0, skips = 0; -#define test(_s) { printf("#%02d ", ++tests); printf(_s); } -#define test_cond(_c) if(_c) printf("\033[0;32mPASSED\033[0;0m\n"); else {printf("\033[0;31mFAILED\033[0;0m\n"); fails++;} -#define test_skipped() { printf("\033[01;33mSKIPPED\033[0;0m\n"); skips++; } - -static long long usec(void) { -#ifndef _MSC_VER - struct timeval tv; - gettimeofday(&tv,NULL); - return (((long long)tv.tv_sec)*1000000)+tv.tv_usec; -#else - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - return (((long long)ft.dwHighDateTime << 32) | ft.dwLowDateTime) / 10; -#endif -} - -/* The assert() calls below have side effects, so we need assert() - * even if we are compiling without asserts (-DNDEBUG). */ -#ifdef NDEBUG -#undef assert -#define assert(e) (void)(e) -#endif - -/* Helper to extract Redis version information. Aborts on any failure. */ -#define REDIS_VERSION_FIELD "redis_version:" -void get_redis_version(redisContext *c, int *majorptr, int *minorptr) { - redisReply *reply; - char *eptr, *s, *e; - int major, minor; - - reply = redisCommand(c, "INFO"); - if (reply == NULL || c->err || reply->type != REDIS_REPLY_STRING) - goto abort; - if ((s = strstr(reply->str, REDIS_VERSION_FIELD)) == NULL) - goto abort; - - s += strlen(REDIS_VERSION_FIELD); - - /* We need a field terminator and at least 'x.y.z' (5) bytes of data */ - if ((e = strstr(s, "\r\n")) == NULL || (e - s) < 5) - goto abort; - - /* Extract version info */ - major = strtol(s, &eptr, 10); - if (*eptr != '.') goto abort; - minor = strtol(eptr+1, NULL, 10); - - /* Push info the caller wants */ - if (majorptr) *majorptr = major; - if (minorptr) *minorptr = minor; - - freeReplyObject(reply); - return; - -abort: - freeReplyObject(reply); - fprintf(stderr, "Error: Cannot determine Redis version, aborting\n"); - exit(1); -} - -static redisContext *select_database(redisContext *c) { - redisReply *reply; - - /* Switch to DB 9 for testing, now that we know we can chat. */ - reply = redisCommand(c,"SELECT 9"); - assert(reply != NULL); - freeReplyObject(reply); - - /* Make sure the DB is emtpy */ - reply = redisCommand(c,"DBSIZE"); - assert(reply != NULL); - if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) { - /* Awesome, DB 9 is empty and we can continue. */ - freeReplyObject(reply); - } else { - printf("Database #9 is not empty, test can not continue\n"); - exit(1); - } - - return c; -} - -/* Switch protocol */ -static void send_hello(redisContext *c, int version) { - redisReply *reply; - int expected; - - reply = redisCommand(c, "HELLO %d", version); - expected = version == 3 ? REDIS_REPLY_MAP : REDIS_REPLY_ARRAY; - assert(reply != NULL && reply->type == expected); - freeReplyObject(reply); -} - -/* Togggle client tracking */ -static void send_client_tracking(redisContext *c, const char *str) { - redisReply *reply; - - reply = redisCommand(c, "CLIENT TRACKING %s", str); - assert(reply != NULL && reply->type == REDIS_REPLY_STATUS); - freeReplyObject(reply); -} - -static int disconnect(redisContext *c, int keep_fd) { - redisReply *reply; - - /* Make sure we're on DB 9. */ - reply = redisCommand(c,"SELECT 9"); - assert(reply != NULL); - freeReplyObject(reply); - reply = redisCommand(c,"FLUSHDB"); - assert(reply != NULL); - freeReplyObject(reply); - - /* Free the context as well, but keep the fd if requested. */ - if (keep_fd) - return redisFreeKeepFd(c); - redisFree(c); - return -1; -} - -static void do_ssl_handshake(redisContext *c) { -#ifdef HIREDIS_TEST_SSL - redisInitiateSSLWithContext(c, _ssl_ctx); - if (c->err) { - printf("SSL error: %s\n", c->errstr); - redisFree(c); - exit(1); - } -#else - (void) c; -#endif -} - -static redisContext *do_connect(struct config config) { - redisContext *c = NULL; - - if (config.type == CONN_TCP) { - c = redisConnect(config.tcp.host, config.tcp.port); - } else if (config.type == CONN_SSL) { - c = redisConnect(config.ssl.host, config.ssl.port); - } else if (config.type == CONN_UNIX) { - c = redisConnectUnix(config.unix_sock.path); - } else if (config.type == CONN_FD) { - /* Create a dummy connection just to get an fd to inherit */ - redisContext *dummy_ctx = redisConnectUnix(config.unix_sock.path); - if (dummy_ctx) { - int fd = disconnect(dummy_ctx, 1); - printf("Connecting to inherited fd %d\n", fd); - c = redisConnectFd(fd); - } - } else { - assert(NULL); - } - - if (c == NULL) { - printf("Connection error: can't allocate redis context\n"); - exit(1); - } else if (c->err) { - printf("Connection error: %s\n", c->errstr); - redisFree(c); - exit(1); - } - - if (config.type == CONN_SSL) { - do_ssl_handshake(c); - } - - return select_database(c); -} - -static void do_reconnect(redisContext *c, struct config config) { - redisReconnect(c); - - if (config.type == CONN_SSL) { - do_ssl_handshake(c); - } -} - -static void test_format_commands(void) { - char *cmd; - int len; - - test("Format command without interpolation: "); - len = redisFormatCommand(&cmd,"SET foo bar"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - hi_free(cmd); - - test("Format command with %%s string interpolation: "); - len = redisFormatCommand(&cmd,"SET %s %s","foo","bar"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - hi_free(cmd); - - test("Format command with %%s and an empty string: "); - len = redisFormatCommand(&cmd,"SET %s %s","foo",""); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(0+2)); - hi_free(cmd); - - test("Format command with an empty string in between proper interpolations: "); - len = redisFormatCommand(&cmd,"SET %s %s","","foo"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 && - len == 4+4+(3+2)+4+(0+2)+4+(3+2)); - hi_free(cmd); - - test("Format command with %%b string interpolation: "); - len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - hi_free(cmd); - - test("Format command with %%b and an empty string: "); - len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(0+2)); - hi_free(cmd); - - test("Format command with literal %%: "); - len = redisFormatCommand(&cmd,"SET %% %%"); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$1\r\n%\r\n$1\r\n%\r\n",len) == 0 && - len == 4+4+(3+2)+4+(1+2)+4+(1+2)); - hi_free(cmd); - - /* Vararg width depends on the type. These tests make sure that the - * width is correctly determined using the format and subsequent varargs - * can correctly be interpolated. */ -#define INTEGER_WIDTH_TEST(fmt, type) do { \ - type value = 123; \ - test("Format command with printf-delegation (" #type "): "); \ - len = redisFormatCommand(&cmd,"key:%08" fmt " str:%s", value, "hello"); \ - test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:00000123\r\n$9\r\nstr:hello\r\n",len) == 0 && \ - len == 4+5+(12+2)+4+(9+2)); \ - hi_free(cmd); \ -} while(0) - -#define FLOAT_WIDTH_TEST(type) do { \ - type value = 123.0; \ - test("Format command with printf-delegation (" #type "): "); \ - len = redisFormatCommand(&cmd,"key:%08.3f str:%s", value, "hello"); \ - test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:0123.000\r\n$9\r\nstr:hello\r\n",len) == 0 && \ - len == 4+5+(12+2)+4+(9+2)); \ - hi_free(cmd); \ -} while(0) - - INTEGER_WIDTH_TEST("d", int); - INTEGER_WIDTH_TEST("hhd", char); - INTEGER_WIDTH_TEST("hd", short); - INTEGER_WIDTH_TEST("ld", long); - INTEGER_WIDTH_TEST("lld", long long); - INTEGER_WIDTH_TEST("u", unsigned int); - INTEGER_WIDTH_TEST("hhu", unsigned char); - INTEGER_WIDTH_TEST("hu", unsigned short); - INTEGER_WIDTH_TEST("lu", unsigned long); - INTEGER_WIDTH_TEST("llu", unsigned long long); - FLOAT_WIDTH_TEST(float); - FLOAT_WIDTH_TEST(double); - - test("Format command with invalid printf format: "); - len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3); - test_cond(len == -1); - - const char *argv[3]; - argv[0] = "SET"; - argv[1] = "foo\0xxx"; - argv[2] = "bar"; - size_t lens[3] = { 3, 7, 3 }; - int argc = 3; - - test("Format command by passing argc/argv without lengths: "); - len = redisFormatCommandArgv(&cmd,argc,argv,NULL); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - hi_free(cmd); - - test("Format command by passing argc/argv with lengths: "); - len = redisFormatCommandArgv(&cmd,argc,argv,lens); - test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(7+2)+4+(3+2)); - hi_free(cmd); - - sds sds_cmd; - - sds_cmd = NULL; - test("Format command into sds by passing argc/argv without lengths: "); - len = redisFormatSdsCommandArgv(&sds_cmd,argc,argv,NULL); - test_cond(strncmp(sds_cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(3+2)+4+(3+2)); - sdsfree(sds_cmd); - - sds_cmd = NULL; - test("Format command into sds by passing argc/argv with lengths: "); - len = redisFormatSdsCommandArgv(&sds_cmd,argc,argv,lens); - test_cond(strncmp(sds_cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 && - len == 4+4+(3+2)+4+(7+2)+4+(3+2)); - sdsfree(sds_cmd); -} - -static void test_append_formatted_commands(struct config config) { - redisContext *c; - redisReply *reply; - char *cmd; - int len; - - c = do_connect(config); - - test("Append format command: "); - - len = redisFormatCommand(&cmd, "SET foo bar"); - - test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK); - - assert(redisGetReply(c, (void*)&reply) == REDIS_OK); - - hi_free(cmd); - freeReplyObject(reply); - - disconnect(c, 0); -} - -static void test_reply_reader(void) { - redisReader *reader; - void *reply, *root; - int ret; - int i; - - test("Error handling in reply parser: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"@foo\r\n",6); - ret = redisReaderGetReply(reader,NULL); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0); - redisReaderFree(reader); - - /* when the reply already contains multiple items, they must be free'd - * on an error. valgrind will bark when this doesn't happen. */ - test("Memory cleanup in reply parser: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"*2\r\n",4); - redisReaderFeed(reader,(char*)"$5\r\nhello\r\n",11); - redisReaderFeed(reader,(char*)"@foo\r\n",6); - ret = redisReaderGetReply(reader,NULL); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0); - redisReaderFree(reader); - - reader = redisReaderCreate(); - test("Can handle arbitrarily nested multi-bulks: "); - for (i = 0; i < 128; i++) { - redisReaderFeed(reader,(char*)"*1\r\n", 4); - } - redisReaderFeed(reader,(char*)"$6\r\nLOLWUT\r\n",12); - ret = redisReaderGetReply(reader,&reply); - root = reply; /* Keep track of the root reply */ - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_ARRAY && - ((redisReply*)reply)->elements == 1); - - test("Can parse arbitrarily nested multi-bulks correctly: "); - while(i--) { - assert(reply != NULL && ((redisReply*)reply)->type == REDIS_REPLY_ARRAY); - reply = ((redisReply*)reply)->element[0]; - } - test_cond(((redisReply*)reply)->type == REDIS_REPLY_STRING && - !memcmp(((redisReply*)reply)->str, "LOLWUT", 6)); - freeReplyObject(root); - redisReaderFree(reader); - - test("Correctly parses LLONG_MAX: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, ":9223372036854775807\r\n",22); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_INTEGER && - ((redisReply*)reply)->integer == LLONG_MAX); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when > LLONG_MAX: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, ":9223372036854775808\r\n",22); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Bad integer value") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Correctly parses LLONG_MIN: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, ":-9223372036854775808\r\n",23); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_INTEGER && - ((redisReply*)reply)->integer == LLONG_MIN); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when < LLONG_MIN: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, ":-9223372036854775809\r\n",23); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Bad integer value") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when array < -1: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, "*-2\r\n+asdf\r\n",12); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Multi-bulk length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when bulk < -1: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, "$-2\r\nasdf\r\n",11); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Bulk string length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Can configure maximum multi-bulk elements: "); - reader = redisReaderCreate(); - reader->maxelements = 1024; - redisReaderFeed(reader, "*1025\r\n", 7); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr, "Multi-bulk length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Multi-bulk never overflows regardless of maxelements: "); - size_t bad_mbulk_len = (SIZE_MAX / sizeof(void *)) + 3; - char bad_mbulk_reply[100]; - snprintf(bad_mbulk_reply, sizeof(bad_mbulk_reply), "*%llu\r\n+asdf\r\n", - (unsigned long long) bad_mbulk_len); - - reader = redisReaderCreate(); - reader->maxelements = 0; /* Don't rely on default limit */ - redisReaderFeed(reader, bad_mbulk_reply, strlen(bad_mbulk_reply)); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && strcasecmp(reader->errstr, "Out of memory") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - -#if LLONG_MAX > SIZE_MAX - test("Set error when array > SIZE_MAX: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, "*9223372036854775807\r\n+asdf\r\n",29); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Multi-bulk length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - test("Set error when bulk > SIZE_MAX: "); - reader = redisReaderCreate(); - redisReaderFeed(reader, "$9223372036854775807\r\nasdf\r\n",28); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && - strcasecmp(reader->errstr,"Bulk string length out of range") == 0); - freeReplyObject(reply); - redisReaderFree(reader); -#endif - - test("Works with NULL functions for reply: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"+OK\r\n",5); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS); - redisReaderFree(reader); - - test("Works when a single newline (\\r\\n) covers two calls to feed: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"+OK\r",4); - ret = redisReaderGetReply(reader,&reply); - assert(ret == REDIS_OK && reply == NULL); - redisReaderFeed(reader,(char*)"\n",1); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS); - redisReaderFree(reader); - - test("Don't reset state after protocol error: "); - reader = redisReaderCreate(); - reader->fn = NULL; - redisReaderFeed(reader,(char*)"x",1); - ret = redisReaderGetReply(reader,&reply); - assert(ret == REDIS_ERR); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_ERR && reply == NULL); - redisReaderFree(reader); - - /* Regression test for issue #45 on GitHub. */ - test("Don't do empty allocation for empty multi bulk: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"*0\r\n",4); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_ARRAY && - ((redisReply*)reply)->elements == 0); - freeReplyObject(reply); - redisReaderFree(reader); - - /* RESP3 verbatim strings (GitHub issue #802) */ - test("Can parse RESP3 verbatim strings: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)"=10\r\ntxt:LOLWUT\r\n",17); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_VERB && - !memcmp(((redisReply*)reply)->str,"LOLWUT", 6)); - freeReplyObject(reply); - redisReaderFree(reader); - - /* RESP3 push messages (Github issue #815) */ - test("Can parse RESP3 push messages: "); - reader = redisReaderCreate(); - redisReaderFeed(reader,(char*)">2\r\n$6\r\nLOLWUT\r\n:42\r\n",21); - ret = redisReaderGetReply(reader,&reply); - test_cond(ret == REDIS_OK && - ((redisReply*)reply)->type == REDIS_REPLY_PUSH && - ((redisReply*)reply)->elements == 2 && - ((redisReply*)reply)->element[0]->type == REDIS_REPLY_STRING && - !memcmp(((redisReply*)reply)->element[0]->str,"LOLWUT",6) && - ((redisReply*)reply)->element[1]->type == REDIS_REPLY_INTEGER && - ((redisReply*)reply)->element[1]->integer == 42); - freeReplyObject(reply); - redisReaderFree(reader); -} - -static void test_free_null(void) { - void *redisCtx = NULL; - void *reply = NULL; - - test("Don't fail when redisFree is passed a NULL value: "); - redisFree(redisCtx); - test_cond(redisCtx == NULL); - - test("Don't fail when freeReplyObject is passed a NULL value: "); - freeReplyObject(reply); - test_cond(reply == NULL); -} - -static void *hi_malloc_fail(size_t size) { - (void)size; - return NULL; -} - -static void *hi_calloc_fail(size_t nmemb, size_t size) { - (void)nmemb; - (void)size; - return NULL; -} - -static void *hi_realloc_fail(void *ptr, size_t size) { - (void)ptr; - (void)size; - return NULL; -} - -static void test_allocator_injection(void) { - hiredisAllocFuncs ha = { - .mallocFn = hi_malloc_fail, - .callocFn = hi_calloc_fail, - .reallocFn = hi_realloc_fail, - .strdupFn = strdup, - .freeFn = free, - }; - - // Override hiredis allocators - hiredisSetAllocators(&ha); - - test("redisContext uses injected allocators: "); - redisContext *c = redisConnect("localhost", 6379); - test_cond(c == NULL); - - test("redisReader uses injected allocators: "); - redisReader *reader = redisReaderCreate(); - test_cond(reader == NULL); - - // Return allocators to default - hiredisResetAllocators(); -} - -#define HIREDIS_BAD_DOMAIN "idontexist-noreally.com" -static void test_blocking_connection_errors(void) { - redisContext *c; - struct addrinfo hints = {.ai_family = AF_INET}; - struct addrinfo *ai_tmp = NULL; - - int rv = getaddrinfo(HIREDIS_BAD_DOMAIN, "6379", &hints, &ai_tmp); - if (rv != 0) { - // Address does *not* exist - test("Returns error when host cannot be resolved: "); - // First see if this domain name *actually* resolves to NXDOMAIN - c = redisConnect(HIREDIS_BAD_DOMAIN, 6379); - test_cond( - c->err == REDIS_ERR_OTHER && - (strcmp(c->errstr, "Name or service not known") == 0 || - strcmp(c->errstr, "Can't resolve: " HIREDIS_BAD_DOMAIN) == 0 || - strcmp(c->errstr, "Name does not resolve") == 0 || - strcmp(c->errstr, "nodename nor servname provided, or not known") == 0 || - strcmp(c->errstr, "No address associated with hostname") == 0 || - strcmp(c->errstr, "Temporary failure in name resolution") == 0 || - strcmp(c->errstr, "hostname nor servname provided, or not known") == 0 || - strcmp(c->errstr, "no address associated with name") == 0 || - strcmp(c->errstr, "No such host is known. ") == 0)); - redisFree(c); - } else { - printf("Skipping NXDOMAIN test. Found evil ISP!\n"); - freeaddrinfo(ai_tmp); - } - -#ifndef _WIN32 - test("Returns error when the port is not open: "); - c = redisConnect((char*)"localhost", 1); - test_cond(c->err == REDIS_ERR_IO && - strcmp(c->errstr,"Connection refused") == 0); - redisFree(c); - - test("Returns error when the unix_sock socket path doesn't accept connections: "); - c = redisConnectUnix((char*)"/tmp/idontexist.sock"); - test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */ - redisFree(c); -#endif -} - -/* Dummy push handler */ -void push_handler(void *privdata, void *reply) { - int *counter = privdata; - freeReplyObject(reply); - *counter += 1; -} - -/* Dummy function just to test setting a callback with redisOptions */ -void push_handler_async(redisAsyncContext *ac, void *reply) { - (void)ac; - (void)reply; -} - -static void test_resp3_push_handler(redisContext *c) { - redisPushFn *old = NULL; - redisReply *reply; - void *privdata; - int n = 0; - - /* Switch to RESP3 and turn on client tracking */ - send_hello(c, 3); - send_client_tracking(c, "ON"); - privdata = c->privdata; - c->privdata = &n; - - reply = redisCommand(c, "GET key:0"); - assert(reply != NULL); - freeReplyObject(reply); - - test("RESP3 PUSH messages are handled out of band by default: "); - reply = redisCommand(c, "SET key:0 val:0"); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS); - freeReplyObject(reply); - - assert((reply = redisCommand(c, "GET key:0")) != NULL); - freeReplyObject(reply); - - old = redisSetPushCallback(c, push_handler); - test("We can set a custom RESP3 PUSH handler: "); - reply = redisCommand(c, "SET key:0 val:0"); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && n == 1); - freeReplyObject(reply); - - /* Unset the push callback and generate an invalidate message making - * sure it is not handled out of band. */ - test("With no handler, PUSH replies come in-band: "); - redisSetPushCallback(c, NULL); - assert((reply = redisCommand(c, "GET key:0")) != NULL); - freeReplyObject(reply); - assert((reply = redisCommand(c, "SET key:0 invalid")) != NULL); - test_cond(reply->type == REDIS_REPLY_PUSH); - freeReplyObject(reply); - - test("With no PUSH handler, no replies are lost: "); - assert(redisGetReply(c, (void**)&reply) == REDIS_OK); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS); - freeReplyObject(reply); - - /* Return to the originally set PUSH handler */ - assert(old != NULL); - redisSetPushCallback(c, old); - - /* Switch back to RESP2 and disable tracking */ - c->privdata = privdata; - send_client_tracking(c, "OFF"); - send_hello(c, 2); -} - -redisOptions get_redis_tcp_options(struct config config) { - redisOptions options = {0}; - REDIS_OPTIONS_SET_TCP(&options, config.tcp.host, config.tcp.port); - return options; -} - -static void test_resp3_push_options(struct config config) { - redisAsyncContext *ac; - redisContext *c; - redisOptions options; - - test("We set a default RESP3 handler for redisContext: "); - options = get_redis_tcp_options(config); - assert((c = redisConnectWithOptions(&options)) != NULL); - test_cond(c->push_cb != NULL); - redisFree(c); - - test("We don't set a default RESP3 push handler for redisAsyncContext: "); - options = get_redis_tcp_options(config); - assert((ac = redisAsyncConnectWithOptions(&options)) != NULL); - test_cond(ac->c.push_cb == NULL); - redisAsyncFree(ac); - - test("Our REDIS_OPT_NO_PUSH_AUTOFREE flag works: "); - options = get_redis_tcp_options(config); - options.options |= REDIS_OPT_NO_PUSH_AUTOFREE; - assert((c = redisConnectWithOptions(&options)) != NULL); - test_cond(c->push_cb == NULL); - redisFree(c); - - test("We can use redisOptions to set a custom PUSH handler for redisContext: "); - options = get_redis_tcp_options(config); - options.push_cb = push_handler; - assert((c = redisConnectWithOptions(&options)) != NULL); - test_cond(c->push_cb == push_handler); - redisFree(c); - - test("We can use redisOptions to set a custom PUSH handler for redisAsyncContext: "); - options = get_redis_tcp_options(config); - options.async_push_cb = push_handler_async; - assert((ac = redisAsyncConnectWithOptions(&options)) != NULL); - test_cond(ac->push_cb == push_handler_async); - redisAsyncFree(ac); -} - -void free_privdata(void *privdata) { - struct privdata *data = privdata; - data->dtor_counter++; -} - -static void test_privdata_hooks(struct config config) { - struct privdata data = {0}; - redisOptions options; - redisContext *c; - - test("We can use redisOptions to set privdata: "); - options = get_redis_tcp_options(config); - REDIS_OPTIONS_SET_PRIVDATA(&options, &data, free_privdata); - assert((c = redisConnectWithOptions(&options)) != NULL); - test_cond(c->privdata == &data); - - test("Our privdata destructor fires when we free the context: "); - redisFree(c); - test_cond(data.dtor_counter == 1); -} - -static void test_blocking_connection(struct config config) { - redisContext *c; - redisReply *reply; - int major; - - c = do_connect(config); - - test("Is able to deliver commands: "); - reply = redisCommand(c,"PING"); - test_cond(reply->type == REDIS_REPLY_STATUS && - strcasecmp(reply->str,"pong") == 0) - freeReplyObject(reply); - - test("Is a able to send commands verbatim: "); - reply = redisCommand(c,"SET foo bar"); - test_cond (reply->type == REDIS_REPLY_STATUS && - strcasecmp(reply->str,"ok") == 0) - freeReplyObject(reply); - - test("%%s String interpolation works: "); - reply = redisCommand(c,"SET %s %s","foo","hello world"); - freeReplyObject(reply); - reply = redisCommand(c,"GET foo"); - test_cond(reply->type == REDIS_REPLY_STRING && - strcmp(reply->str,"hello world") == 0); - freeReplyObject(reply); - - test("%%b String interpolation works: "); - reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11); - freeReplyObject(reply); - reply = redisCommand(c,"GET foo"); - test_cond(reply->type == REDIS_REPLY_STRING && - memcmp(reply->str,"hello\x00world",11) == 0) - - test("Binary reply length is correct: "); - test_cond(reply->len == 11) - freeReplyObject(reply); - - test("Can parse nil replies: "); - reply = redisCommand(c,"GET nokey"); - test_cond(reply->type == REDIS_REPLY_NIL) - freeReplyObject(reply); - - /* test 7 */ - test("Can parse integer replies: "); - reply = redisCommand(c,"INCR mycounter"); - test_cond(reply->type == REDIS_REPLY_INTEGER && reply->integer == 1) - freeReplyObject(reply); - - test("Can parse multi bulk replies: "); - freeReplyObject(redisCommand(c,"LPUSH mylist foo")); - freeReplyObject(redisCommand(c,"LPUSH mylist bar")); - reply = redisCommand(c,"LRANGE mylist 0 -1"); - test_cond(reply->type == REDIS_REPLY_ARRAY && - reply->elements == 2 && - !memcmp(reply->element[0]->str,"bar",3) && - !memcmp(reply->element[1]->str,"foo",3)) - freeReplyObject(reply); - - /* m/e with multi bulk reply *before* other reply. - * specifically test ordering of reply items to parse. */ - test("Can handle nested multi bulk replies: "); - freeReplyObject(redisCommand(c,"MULTI")); - freeReplyObject(redisCommand(c,"LRANGE mylist 0 -1")); - freeReplyObject(redisCommand(c,"PING")); - reply = (redisCommand(c,"EXEC")); - test_cond(reply->type == REDIS_REPLY_ARRAY && - reply->elements == 2 && - reply->element[0]->type == REDIS_REPLY_ARRAY && - reply->element[0]->elements == 2 && - !memcmp(reply->element[0]->element[0]->str,"bar",3) && - !memcmp(reply->element[0]->element[1]->str,"foo",3) && - reply->element[1]->type == REDIS_REPLY_STATUS && - strcasecmp(reply->element[1]->str,"pong") == 0); - freeReplyObject(reply); - - /* Make sure passing NULL to redisGetReply is safe */ - test("Can pass NULL to redisGetReply: "); - assert(redisAppendCommand(c, "PING") == REDIS_OK); - test_cond(redisGetReply(c, NULL) == REDIS_OK); - - get_redis_version(c, &major, NULL); - if (major >= 6) test_resp3_push_handler(c); - test_resp3_push_options(config); - - test_privdata_hooks(config); - - disconnect(c, 0); -} - -/* Send DEBUG SLEEP 0 to detect if we have this command */ -static int detect_debug_sleep(redisContext *c) { - int detected; - redisReply *reply = redisCommand(c, "DEBUG SLEEP 0\r\n"); - - if (reply == NULL || c->err) { - const char *cause = c->err ? c->errstr : "(none)"; - fprintf(stderr, "Error testing for DEBUG SLEEP (Redis error: %s), exiting\n", cause); - exit(-1); - } - - detected = reply->type == REDIS_REPLY_STATUS; - freeReplyObject(reply); - - return detected; -} - -static void test_blocking_connection_timeouts(struct config config) { - redisContext *c; - redisReply *reply; - ssize_t s; - const char *sleep_cmd = "DEBUG SLEEP 3\r\n"; - struct timeval tv; - - c = do_connect(config); - test("Successfully completes a command when the timeout is not exceeded: "); - reply = redisCommand(c,"SET foo fast"); - freeReplyObject(reply); - tv.tv_sec = 0; - tv.tv_usec = 10000; - redisSetTimeout(c, tv); - reply = redisCommand(c, "GET foo"); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && memcmp(reply->str, "fast", 4) == 0); - freeReplyObject(reply); - disconnect(c, 0); - - c = do_connect(config); - test("Does not return a reply when the command times out: "); - if (detect_debug_sleep(c)) { - redisAppendFormattedCommand(c, sleep_cmd, strlen(sleep_cmd)); - s = c->funcs->write(c); - tv.tv_sec = 0; - tv.tv_usec = 10000; - redisSetTimeout(c, tv); - reply = redisCommand(c, "GET foo"); -#ifndef _WIN32 - test_cond(s > 0 && reply == NULL && c->err == REDIS_ERR_IO && - strcmp(c->errstr, "Resource temporarily unavailable") == 0); -#else - test_cond(s > 0 && reply == NULL && c->err == REDIS_ERR_TIMEOUT && - strcmp(c->errstr, "recv timeout") == 0); -#endif - freeReplyObject(reply); - } else { - test_skipped(); - } - - test("Reconnect properly reconnects after a timeout: "); - do_reconnect(c, config); - reply = redisCommand(c, "PING"); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0); - freeReplyObject(reply); - - test("Reconnect properly uses owned parameters: "); - config.tcp.host = "foo"; - config.unix_sock.path = "foo"; - do_reconnect(c, config); - reply = redisCommand(c, "PING"); - test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0); - freeReplyObject(reply); - - disconnect(c, 0); -} - -static void test_blocking_io_errors(struct config config) { - redisContext *c; - redisReply *reply; - void *_reply; - int major, minor; - - /* Connect to target given by config. */ - c = do_connect(config); - get_redis_version(c, &major, &minor); - - test("Returns I/O error when the connection is lost: "); - reply = redisCommand(c,"QUIT"); - if (major > 2 || (major == 2 && minor > 0)) { - /* > 2.0 returns OK on QUIT and read() should be issued once more - * to know the descriptor is at EOF. */ - test_cond(strcasecmp(reply->str,"OK") == 0 && - redisGetReply(c,&_reply) == REDIS_ERR); - freeReplyObject(reply); - } else { - test_cond(reply == NULL); - } - -#ifndef _WIN32 - /* On 2.0, QUIT will cause the connection to be closed immediately and - * the read(2) for the reply on QUIT will set the error to EOF. - * On >2.0, QUIT will return with OK and another read(2) needed to be - * issued to find out the socket was closed by the server. In both - * conditions, the error will be set to EOF. */ - assert(c->err == REDIS_ERR_EOF && - strcmp(c->errstr,"Server closed the connection") == 0); -#endif - redisFree(c); - - c = do_connect(config); - test("Returns I/O error on socket timeout: "); - struct timeval tv = { 0, 1000 }; - assert(redisSetTimeout(c,tv) == REDIS_OK); - int respcode = redisGetReply(c,&_reply); -#ifndef _WIN32 - test_cond(respcode == REDIS_ERR && c->err == REDIS_ERR_IO && errno == EAGAIN); -#else - test_cond(respcode == REDIS_ERR && c->err == REDIS_ERR_TIMEOUT); -#endif - redisFree(c); -} - -static void test_invalid_timeout_errors(struct config config) { - redisContext *c; - - test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: "); - - config.tcp.timeout.tv_sec = 0; - config.tcp.timeout.tv_usec = 10000001; - - c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout); - - test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0); - redisFree(c); - - test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: "); - - config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1; - config.tcp.timeout.tv_usec = 0; - - c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout); - - test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0); - redisFree(c); -} - -/* Wrap malloc to abort on failure so OOM checks don't make the test logic - * harder to follow. */ -void *hi_malloc_safe(size_t size) { - void *ptr = hi_malloc(size); - if (ptr == NULL) { - fprintf(stderr, "Error: Out of memory\n"); - exit(-1); - } - - return ptr; -} - -static void test_throughput(struct config config) { - redisContext *c = do_connect(config); - redisReply **replies; - int i, num; - long long t1, t2; - - test("Throughput:\n"); - for (i = 0; i < 500; i++) - freeReplyObject(redisCommand(c,"LPUSH mylist foo")); - - num = 1000; - replies = hi_malloc_safe(sizeof(redisReply*)*num); - t1 = usec(); - for (i = 0; i < num; i++) { - replies[i] = redisCommand(c,"PING"); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - hi_free(replies); - printf("\t(%dx PING: %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = hi_malloc_safe(sizeof(redisReply*)*num); - t1 = usec(); - for (i = 0; i < num; i++) { - replies[i] = redisCommand(c,"LRANGE mylist 0 499"); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY); - assert(replies[i] != NULL && replies[i]->elements == 500); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - hi_free(replies); - printf("\t(%dx LRANGE with 500 elements: %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = hi_malloc_safe(sizeof(redisReply*)*num); - t1 = usec(); - for (i = 0; i < num; i++) { - replies[i] = redisCommand(c, "INCRBY incrkey %d", 1000000); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_INTEGER); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - hi_free(replies); - printf("\t(%dx INCRBY: %.3fs)\n", num, (t2-t1)/1000000.0); - - num = 10000; - replies = hi_malloc_safe(sizeof(redisReply*)*num); - for (i = 0; i < num; i++) - redisAppendCommand(c,"PING"); - t1 = usec(); - for (i = 0; i < num; i++) { - assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - hi_free(replies); - printf("\t(%dx PING (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = hi_malloc_safe(sizeof(redisReply*)*num); - for (i = 0; i < num; i++) - redisAppendCommand(c,"LRANGE mylist 0 499"); - t1 = usec(); - for (i = 0; i < num; i++) { - assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY); - assert(replies[i] != NULL && replies[i]->elements == 500); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - hi_free(replies); - printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); - - replies = hi_malloc_safe(sizeof(redisReply*)*num); - for (i = 0; i < num; i++) - redisAppendCommand(c,"INCRBY incrkey %d", 1000000); - t1 = usec(); - for (i = 0; i < num; i++) { - assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK); - assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_INTEGER); - } - t2 = usec(); - for (i = 0; i < num; i++) freeReplyObject(replies[i]); - hi_free(replies); - printf("\t(%dx INCRBY (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); - - disconnect(c, 0); -} - -// static long __test_callback_flags = 0; -// static void __test_callback(redisContext *c, void *privdata) { -// ((void)c); -// /* Shift to detect execution order */ -// __test_callback_flags <<= 8; -// __test_callback_flags |= (long)privdata; -// } -// -// static void __test_reply_callback(redisContext *c, redisReply *reply, void *privdata) { -// ((void)c); -// /* Shift to detect execution order */ -// __test_callback_flags <<= 8; -// __test_callback_flags |= (long)privdata; -// if (reply) freeReplyObject(reply); -// } -// -// static redisContext *__connect_nonblock() { -// /* Reset callback flags */ -// __test_callback_flags = 0; -// return redisConnectNonBlock("127.0.0.1", port, NULL); -// } -// -// static void test_nonblocking_connection() { -// redisContext *c; -// int wdone = 0; -// -// test("Calls command callback when command is issued: "); -// c = __connect_nonblock(); -// redisSetCommandCallback(c,__test_callback,(void*)1); -// redisCommand(c,"PING"); -// test_cond(__test_callback_flags == 1); -// redisFree(c); -// -// test("Calls disconnect callback on redisDisconnect: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)2); -// redisDisconnect(c); -// test_cond(__test_callback_flags == 2); -// redisFree(c); -// -// test("Calls disconnect callback and free callback on redisFree: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)2); -// redisSetFreeCallback(c,__test_callback,(void*)4); -// redisFree(c); -// test_cond(__test_callback_flags == ((2 << 8) | 4)); -// -// test("redisBufferWrite against empty write buffer: "); -// c = __connect_nonblock(); -// test_cond(redisBufferWrite(c,&wdone) == REDIS_OK && wdone == 1); -// redisFree(c); -// -// test("redisBufferWrite against not yet connected fd: "); -// c = __connect_nonblock(); -// redisCommand(c,"PING"); -// test_cond(redisBufferWrite(c,NULL) == REDIS_ERR && -// strncmp(c->error,"write:",6) == 0); -// redisFree(c); -// -// test("redisBufferWrite against closed fd: "); -// c = __connect_nonblock(); -// redisCommand(c,"PING"); -// redisDisconnect(c); -// test_cond(redisBufferWrite(c,NULL) == REDIS_ERR && -// strncmp(c->error,"write:",6) == 0); -// redisFree(c); -// -// test("Process callbacks in the right sequence: "); -// c = __connect_nonblock(); -// redisCommandWithCallback(c,__test_reply_callback,(void*)1,"PING"); -// redisCommandWithCallback(c,__test_reply_callback,(void*)2,"PING"); -// redisCommandWithCallback(c,__test_reply_callback,(void*)3,"PING"); -// -// /* Write output buffer */ -// wdone = 0; -// while(!wdone) { -// usleep(500); -// redisBufferWrite(c,&wdone); -// } -// -// /* Read until at least one callback is executed (the 3 replies will -// * arrive in a single packet, causing all callbacks to be executed in -// * a single pass). */ -// while(__test_callback_flags == 0) { -// assert(redisBufferRead(c) == REDIS_OK); -// redisProcessCallbacks(c); -// } -// test_cond(__test_callback_flags == 0x010203); -// redisFree(c); -// -// test("redisDisconnect executes pending callbacks with NULL reply: "); -// c = __connect_nonblock(); -// redisSetDisconnectCallback(c,__test_callback,(void*)1); -// redisCommandWithCallback(c,__test_reply_callback,(void*)2,"PING"); -// redisDisconnect(c); -// test_cond(__test_callback_flags == 0x0201); -// redisFree(c); -// } - -int main(int argc, char **argv) { - struct config cfg = { - .tcp = { - .host = "127.0.0.1", - .port = 6379 - }, - .unix_sock = { - .path = "/tmp/redis.sock" - } - }; - int throughput = 1; - int test_inherit_fd = 1; - int skips_as_fails = 0; - int test_unix_socket; - - /* Parse command line options. */ - argv++; argc--; - while (argc) { - if (argc >= 2 && !strcmp(argv[0],"-h")) { - argv++; argc--; - cfg.tcp.host = argv[0]; - } else if (argc >= 2 && !strcmp(argv[0],"-p")) { - argv++; argc--; - cfg.tcp.port = atoi(argv[0]); - } else if (argc >= 2 && !strcmp(argv[0],"-s")) { - argv++; argc--; - cfg.unix_sock.path = argv[0]; - } else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) { - throughput = 0; - } else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) { - test_inherit_fd = 0; - } else if (argc >= 1 && !strcmp(argv[0],"--skips-as-fails")) { - skips_as_fails = 1; -#ifdef HIREDIS_TEST_SSL - } else if (argc >= 2 && !strcmp(argv[0],"--ssl-port")) { - argv++; argc--; - cfg.ssl.port = atoi(argv[0]); - } else if (argc >= 2 && !strcmp(argv[0],"--ssl-host")) { - argv++; argc--; - cfg.ssl.host = argv[0]; - } else if (argc >= 2 && !strcmp(argv[0],"--ssl-ca-cert")) { - argv++; argc--; - cfg.ssl.ca_cert = argv[0]; - } else if (argc >= 2 && !strcmp(argv[0],"--ssl-cert")) { - argv++; argc--; - cfg.ssl.cert = argv[0]; - } else if (argc >= 2 && !strcmp(argv[0],"--ssl-key")) { - argv++; argc--; - cfg.ssl.key = argv[0]; -#endif - } else { - fprintf(stderr, "Invalid argument: %s\n", argv[0]); - exit(1); - } - argv++; argc--; - } - -#ifndef _WIN32 - /* Ignore broken pipe signal (for I/O error tests). */ - signal(SIGPIPE, SIG_IGN); - - test_unix_socket = access(cfg.unix_sock.path, F_OK) == 0; - -#else - /* Unix sockets don't exist in Windows */ - test_unix_socket = 0; -#endif - - test_allocator_injection(); - - test_format_commands(); - test_reply_reader(); - test_blocking_connection_errors(); - test_free_null(); - - printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port); - cfg.type = CONN_TCP; - test_blocking_connection(cfg); - test_blocking_connection_timeouts(cfg); - test_blocking_io_errors(cfg); - test_invalid_timeout_errors(cfg); - test_append_formatted_commands(cfg); - if (throughput) test_throughput(cfg); - - printf("\nTesting against Unix socket connection (%s): ", cfg.unix_sock.path); - if (test_unix_socket) { - printf("\n"); - cfg.type = CONN_UNIX; - test_blocking_connection(cfg); - test_blocking_connection_timeouts(cfg); - test_blocking_io_errors(cfg); - if (throughput) test_throughput(cfg); - } else { - test_skipped(); - } - -#ifdef HIREDIS_TEST_SSL - if (cfg.ssl.port && cfg.ssl.host) { - - redisInitOpenSSL(); - _ssl_ctx = redisCreateSSLContext(cfg.ssl.ca_cert, NULL, cfg.ssl.cert, cfg.ssl.key, NULL, NULL); - assert(_ssl_ctx != NULL); - - printf("\nTesting against SSL connection (%s:%d):\n", cfg.ssl.host, cfg.ssl.port); - cfg.type = CONN_SSL; - - test_blocking_connection(cfg); - test_blocking_connection_timeouts(cfg); - test_blocking_io_errors(cfg); - test_invalid_timeout_errors(cfg); - test_append_formatted_commands(cfg); - if (throughput) test_throughput(cfg); - - redisFreeSSLContext(_ssl_ctx); - _ssl_ctx = NULL; - } -#endif - - if (test_inherit_fd) { - printf("\nTesting against inherited fd (%s): ", cfg.unix_sock.path); - if (test_unix_socket) { - printf("\n"); - cfg.type = CONN_FD; - test_blocking_connection(cfg); - } else { - test_skipped(); - } - } - - if (fails || (skips_as_fails && skips)) { - printf("*** %d TESTS FAILED ***\n", fails); - if (skips) { - printf("*** %d TESTS SKIPPED ***\n", skips); - } - return 1; - } - - printf("ALL TESTS PASSED (%d skipped)\n", skips); - return 0; -} diff --git a/ext/hiredis-1.0.2/test.sh b/ext/hiredis-1.0.2/test.sh deleted file mode 100755 index c72bcb0dc..000000000 --- a/ext/hiredis-1.0.2/test.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh -ue - -REDIS_SERVER=${REDIS_SERVER:-redis-server} -REDIS_PORT=${REDIS_PORT:-56379} -REDIS_SSL_PORT=${REDIS_SSL_PORT:-56443} -TEST_SSL=${TEST_SSL:-0} -SKIPS_AS_FAILS=${SKIPS_AS_FAILS-:0} -SSL_TEST_ARGS= -SKIPS_ARG= - -tmpdir=$(mktemp -d) -PID_FILE=${tmpdir}/hiredis-test-redis.pid -SOCK_FILE=${tmpdir}/hiredis-test-redis.sock - -if [ "$TEST_SSL" = "1" ]; then - SSL_CA_CERT=${tmpdir}/ca.crt - SSL_CA_KEY=${tmpdir}/ca.key - SSL_CERT=${tmpdir}/redis.crt - SSL_KEY=${tmpdir}/redis.key - - openssl genrsa -out ${tmpdir}/ca.key 4096 - openssl req \ - -x509 -new -nodes -sha256 \ - -key ${SSL_CA_KEY} \ - -days 3650 \ - -subj '/CN=Hiredis Test CA' \ - -out ${SSL_CA_CERT} - openssl genrsa -out ${SSL_KEY} 2048 - openssl req \ - -new -sha256 \ - -key ${SSL_KEY} \ - -subj '/CN=Hiredis Test Cert' | \ - openssl x509 \ - -req -sha256 \ - -CA ${SSL_CA_CERT} \ - -CAkey ${SSL_CA_KEY} \ - -CAserial ${tmpdir}/ca.txt \ - -CAcreateserial \ - -days 365 \ - -out ${SSL_CERT} - - SSL_TEST_ARGS="--ssl-host 127.0.0.1 --ssl-port ${REDIS_SSL_PORT} --ssl-ca-cert ${SSL_CA_CERT} --ssl-cert ${SSL_CERT} --ssl-key ${SSL_KEY}" -fi - -cleanup() { - set +e - kill $(cat ${PID_FILE}) - rm -rf ${tmpdir} -} -trap cleanup INT TERM EXIT - -cat > ${tmpdir}/redis.conf <> ${tmpdir}/redis.conf < /* for struct timeval */ - -#ifndef inline -#define inline __inline -#endif - -#ifndef strcasecmp -#define strcasecmp stricmp -#endif - -#ifndef strncasecmp -#define strncasecmp strnicmp -#endif - -#ifndef va_copy -#define va_copy(d,s) ((d) = (s)) -#endif - -#ifndef snprintf -#define snprintf c99_snprintf - -__inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) -{ - int count = -1; - - if (size != 0) - count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - -__inline int c99_snprintf(char* str, size_t size, const char* format, ...) -{ - int count; - va_list ap; - - va_start(ap, format); - count = c99_vsnprintf(str, size, format, ap); - va_end(ap); - - return count; -} -#endif -#endif /* _MSC_VER */ - -#ifdef _WIN32 -#define strerror_r(errno,buf,len) strerror_s(buf,len,errno) -#endif /* _WIN32 */ - -#endif /* _WIN32_HELPER_INCLUDE */ diff --git a/ext/http-parser/AUTHORS b/ext/http-parser/AUTHORS index 5323b685c..29cdbb16d 100644 --- a/ext/http-parser/AUTHORS +++ b/ext/http-parser/AUTHORS @@ -61,8 +61,3 @@ Marc O'Morain Jeff Pinner Timothy J Fontaine Akagi201 -Romain Giraud -Jay Satiro -Arne Steen -Kjell Schubert -Olivier Mengué diff --git a/ext/http-parser/README.md b/ext/http-parser/README.md deleted file mode 100644 index 439b30998..000000000 --- a/ext/http-parser/README.md +++ /dev/null @@ -1,246 +0,0 @@ -HTTP Parser -=========== - -[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser) - -This is a parser for HTTP messages written in C. It parses both requests and -responses. The parser is designed to be used in performance HTTP -applications. It does not make any syscalls nor allocations, it does not -buffer data, it can be interrupted at anytime. Depending on your -architecture, it only requires about 40 bytes of data per message -stream (in a web server that is per connection). - -Features: - - * No dependencies - * Handles persistent streams (keep-alive). - * Decodes chunked encoding. - * Upgrade support - * Defends against buffer overflow attacks. - -The parser extracts the following information from HTTP messages: - - * Header fields and values - * Content-Length - * Request method - * Response status code - * Transfer-Encoding - * HTTP version - * Request URL - * Message body - - -Usage ------ - -One `http_parser` object is used per TCP connection. Initialize the struct -using `http_parser_init()` and set the callbacks. That might look something -like this for a request parser: -```c -http_parser_settings settings; -settings.on_url = my_url_callback; -settings.on_header_field = my_header_field_callback; -/* ... */ - -http_parser *parser = malloc(sizeof(http_parser)); -http_parser_init(parser, HTTP_REQUEST); -parser->data = my_socket; -``` - -When data is received on the socket execute the parser and check for errors. - -```c -size_t len = 80*1024, nparsed; -char buf[len]; -ssize_t recved; - -recved = recv(fd, buf, len, 0); - -if (recved < 0) { - /* Handle error. */ -} - -/* Start up / continue the parser. - * Note we pass recved==0 to signal that EOF has been received. - */ -nparsed = http_parser_execute(parser, &settings, buf, recved); - -if (parser->upgrade) { - /* handle new protocol */ -} else if (nparsed != recved) { - /* Handle error. Usually just close the connection. */ -} -``` - -HTTP needs to know where the end of the stream is. For example, sometimes -servers send responses without Content-Length and expect the client to -consume input (for the body) until EOF. To tell http_parser about EOF, give -`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors -can still be encountered during an EOF, so one must still be prepared -to receive them. - -Scalar valued message information such as `status_code`, `method`, and the -HTTP version are stored in the parser structure. This data is only -temporally stored in `http_parser` and gets reset on each new message. If -this information is needed later, copy it out of the structure during the -`headers_complete` callback. - -The parser decodes the transfer-encoding for both requests and responses -transparently. That is, a chunked encoding is decoded before being sent to -the on_body callback. - - -The Special Problem of Upgrade ------------------------------- - -HTTP supports upgrading the connection to a different protocol. An -increasingly common example of this is the WebSocket protocol which sends -a request like - - GET /demo HTTP/1.1 - Upgrade: WebSocket - Connection: Upgrade - Host: example.com - Origin: http://example.com - WebSocket-Protocol: sample - -followed by non-HTTP data. - -(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the -WebSocket protocol.) - -To support this, the parser will treat this as a normal HTTP message without a -body, issuing both on_headers_complete and on_message_complete callbacks. However -http_parser_execute() will stop parsing at the end of the headers and return. - -The user is expected to check if `parser->upgrade` has been set to 1 after -`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied -offset by the return value of `http_parser_execute()`. - - -Callbacks ---------- - -During the `http_parser_execute()` call, the callbacks set in -`http_parser_settings` will be executed. The parser maintains state and -never looks behind, so buffering the data is not necessary. If you need to -save certain data for later usage, you can do that from the callbacks. - -There are two types of callbacks: - -* notification `typedef int (*http_cb) (http_parser*);` - Callbacks: on_message_begin, on_headers_complete, on_message_complete. -* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);` - Callbacks: (requests only) on_url, - (common) on_header_field, on_header_value, on_body; - -Callbacks must return 0 on success. Returning a non-zero value indicates -error to the parser, making it exit immediately. - -For cases where it is necessary to pass local information to/from a callback, -the `http_parser` object's `data` field can be used. -An example of such a case is when using threads to handle a socket connection, -parse a request, and then give a response over that socket. By instantiation -of a thread-local struct containing relevant data (e.g. accepted socket, -allocated memory for callbacks to write into, etc), a parser's callbacks are -able to communicate data between the scope of the thread and the scope of the -callback in a threadsafe manner. This allows http-parser to be used in -multi-threaded contexts. - -Example: -```c - typedef struct { - socket_t sock; - void* buffer; - int buf_len; - } custom_data_t; - - -int my_url_callback(http_parser* parser, const char *at, size_t length) { - /* access to thread local custom_data_t struct. - Use this access save parsed data for later use into thread local - buffer, or communicate over socket - */ - parser->data; - ... - return 0; -} - -... - -void http_parser_thread(socket_t sock) { - int nparsed = 0; - /* allocate memory for user data */ - custom_data_t *my_data = malloc(sizeof(custom_data_t)); - - /* some information for use by callbacks. - * achieves thread -> callback information flow */ - my_data->sock = sock; - - /* instantiate a thread-local parser */ - http_parser *parser = malloc(sizeof(http_parser)); - http_parser_init(parser, HTTP_REQUEST); /* initialise parser */ - /* this custom data reference is accessible through the reference to the - parser supplied to callback functions */ - parser->data = my_data; - - http_parser_settings settings; /* set up callbacks */ - settings.on_url = my_url_callback; - - /* execute parser */ - nparsed = http_parser_execute(parser, &settings, buf, recved); - - ... - /* parsed information copied from callback. - can now perform action on data copied into thread-local memory from callbacks. - achieves callback -> thread information flow */ - my_data->buffer; - ... -} - -``` - -In case you parse HTTP message in chunks (i.e. `read()` request line -from socket, parse, read half headers, parse, etc) your data callbacks -may be called more than once. Http-parser guarantees that data pointer is only -valid for the lifetime of callback. You can also `read()` into a heap allocated -buffer to avoid copying memory around if this fits your application. - -Reading headers may be a tricky task if you read/parse headers partially. -Basically, you need to remember whether last header callback was field or value -and apply the following logic: - - (on_header_field and on_header_value shortened to on_h_*) - ------------------------ ------------ -------------------------------------------- - | State (prev. callback) | Callback | Description/action | - ------------------------ ------------ -------------------------------------------- - | nothing (first call) | on_h_field | Allocate new buffer and copy callback data | - | | | into it | - ------------------------ ------------ -------------------------------------------- - | value | on_h_field | New header started. | - | | | Copy current name,value buffers to headers | - | | | list and allocate new buffer for new name | - ------------------------ ------------ -------------------------------------------- - | field | on_h_field | Previous name continues. Reallocate name | - | | | buffer and append callback data to it | - ------------------------ ------------ -------------------------------------------- - | field | on_h_value | Value for current header started. Allocate | - | | | new buffer and copy callback data to it | - ------------------------ ------------ -------------------------------------------- - | value | on_h_value | Value continues. Reallocate value buffer | - | | | and append callback data to it | - ------------------------ ------------ -------------------------------------------- - - -Parsing URLs ------------- - -A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`. -Users of this library may wish to use it to parse URLs constructed from -consecutive `on_url` callbacks. - -See examples of reading in headers: - -* [partial example](http://gist.github.com/155877) in C -* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C -* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript diff --git a/ext/http-parser/http_parser.c b/ext/http-parser/http_parser.c index 895bf0c73..a113c7f5e 100644 --- a/ext/http-parser/http_parser.c +++ b/ext/http-parser/http_parser.c @@ -123,7 +123,7 @@ do { \ FOR##_mark = NULL; \ } \ } while (0) - + /* Run the data callback FOR and consume the current byte */ #define CALLBACK_DATA(FOR) \ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) @@ -440,7 +440,7 @@ enum http_host_state * character or %x80-FF **/ #define IS_HEADER_CHAR(ch) \ - (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) + (ch == CR || ch == LF || ch == 9 || (ch > 31 && ch != 127)) #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) @@ -1007,40 +1007,89 @@ reexecute: UPDATE_STATE(s_req_spaces_before_url); } else if (ch == matcher[parser->index]) { ; /* nada */ - } else if (IS_ALPHA(ch)) { - - switch (parser->method << 16 | parser->index << 8 | ch) { -#define XX(meth, pos, ch, new_meth) \ - case (HTTP_##meth << 16 | pos << 8 | ch): \ - parser->method = HTTP_##new_meth; break; - - XX(POST, 1, 'U', PUT) - XX(POST, 1, 'A', PATCH) - XX(CONNECT, 1, 'H', CHECKOUT) - XX(CONNECT, 2, 'P', COPY) - XX(MKCOL, 1, 'O', MOVE) - XX(MKCOL, 1, 'E', MERGE) - XX(MKCOL, 2, 'A', MKACTIVITY) - XX(MKCOL, 3, 'A', MKCALENDAR) - XX(SUBSCRIBE, 1, 'E', SEARCH) - XX(REPORT, 2, 'B', REBIND) - XX(POST, 1, 'R', PROPFIND) - XX(PROPFIND, 4, 'P', PROPPATCH) - XX(PUT, 2, 'R', PURGE) - XX(LOCK, 1, 'I', LINK) - XX(UNLOCK, 2, 'S', UNSUBSCRIBE) - XX(UNLOCK, 2, 'B', UNBIND) - XX(UNLOCK, 3, 'I', UNLINK) -#undef XX - - default: + } else if (parser->method == HTTP_CONNECT) { + if (parser->index == 1 && ch == 'H') { + parser->method = HTTP_CHECKOUT; + } else if (parser->index == 2 && ch == 'P') { + parser->method = HTTP_COPY; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->method == HTTP_MKCOL) { + if (parser->index == 1 && ch == 'O') { + parser->method = HTTP_MOVE; + } else if (parser->index == 1 && ch == 'E') { + parser->method = HTTP_MERGE; + } else if (parser->index == 1 && ch == '-') { + parser->method = HTTP_MSEARCH; + } else if (parser->index == 2 && ch == 'A') { + parser->method = HTTP_MKACTIVITY; + } else if (parser->index == 3 && ch == 'A') { + parser->method = HTTP_MKCALENDAR; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->method == HTTP_SUBSCRIBE) { + if (parser->index == 1 && ch == 'E') { + parser->method = HTTP_SEARCH; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->method == HTTP_REPORT) { + if (parser->index == 2 && ch == 'B') { + parser->method = HTTP_REBIND; + } else { SET_ERRNO(HPE_INVALID_METHOD); goto error; + } + } else if (parser->index == 1) { + if (parser->method == HTTP_POST) { + if (ch == 'R') { + parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */ + } else if (ch == 'U') { + parser->method = HTTP_PUT; /* or HTTP_PURGE */ + } else if (ch == 'A') { + parser->method = HTTP_PATCH; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->method == HTTP_LOCK) { + if (ch == 'I') { + parser->method = HTTP_LINK; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } } - } else if (ch == '-' && - parser->index == 1 && - parser->method == HTTP_MKCOL) { - parser->method = HTTP_MSEARCH; + } else if (parser->index == 2) { + if (parser->method == HTTP_PUT) { + if (ch == 'R') { + parser->method = HTTP_PURGE; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->method == HTTP_UNLOCK) { + if (ch == 'S') { + parser->method = HTTP_UNSUBSCRIBE; + } else if(ch == 'B') { + parser->method = HTTP_UNBIND; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') { + parser->method = HTTP_PROPPATCH; + } else if (parser->index == 3 && parser->method == HTTP_UNLOCK && ch == 'I') { + parser->method = HTTP_UNLINK; } else { SET_ERRNO(HPE_INVALID_METHOD); goto error; @@ -1366,7 +1415,12 @@ reexecute: || c != CONTENT_LENGTH[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { + if (parser->flags & F_CONTENTLENGTH) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } parser->header_state = h_content_length; + parser->flags |= F_CONTENTLENGTH; } break; @@ -1469,12 +1523,6 @@ reexecute: goto error; } - if (parser->flags & F_CONTENTLENGTH) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - - parser->flags |= F_CONTENTLENGTH; parser->content_length = ch - '0'; break; @@ -1813,9 +1861,6 @@ reexecute: case 0: break; - case 2: - parser->upgrade = 1; - case 1: parser->flags |= F_SKIPBODY; break; @@ -2254,13 +2299,12 @@ http_parse_host_char(enum http_host_state s, const char ch) { static int http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { + //assert(u->field_set & (1 << UF_HOST)); enum http_host_state s; const char *p; size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; - assert(u->field_set & (1 << UF_HOST)); - u->field_data[UF_HOST].len = 0; s = found_at ? s_http_userinfo_start : s_http_host_start; diff --git a/ext/http-parser/http_parser.h b/ext/http-parser/http_parser.h index 45c72a078..e33c0620a 100644 --- a/ext/http-parser/http_parser.h +++ b/ext/http-parser/http_parser.h @@ -26,7 +26,7 @@ extern "C" { /* Also update SONAME in the Makefile whenever you change these. */ #define HTTP_PARSER_VERSION_MAJOR 2 -#define HTTP_PARSER_VERSION_MINOR 7 +#define HTTP_PARSER_VERSION_MINOR 6 #define HTTP_PARSER_VERSION_PATCH 1 #include @@ -77,11 +77,6 @@ typedef struct http_parser_settings http_parser_settings; * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: * chunked' headers that indicate the presence of a body. * - * Returning `2` from on_headers_complete will tell parser that it should not - * expect neither a body nor any futher responses on this connection. This is - * useful for handling responses to a CONNECT request which may not contain - * `Upgrade` or `Connection: upgrade` headers. - * * http_data_cb does not return data chunks. It will be called arbitrarily * many times for each string. E.G. you might get 10 callbacks for "on_url" * each providing just a few characters more data. @@ -90,76 +85,6 @@ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); typedef int (*http_cb) (http_parser*); -/* Status Codes */ -#define HTTP_STATUS_MAP(XX) \ - XX(100, CONTINUE, Continue) \ - XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \ - XX(102, PROCESSING, Processing) \ - XX(200, OK, OK) \ - XX(201, CREATED, Created) \ - XX(202, ACCEPTED, Accepted) \ - XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \ - XX(204, NO_CONTENT, No Content) \ - XX(205, RESET_CONTENT, Reset Content) \ - XX(206, PARTIAL_CONTENT, Partial Content) \ - XX(207, MULTI_STATUS, Multi-Status) \ - XX(208, ALREADY_REPORTED, Already Reported) \ - XX(226, IM_USED, IM Used) \ - XX(300, MULTIPLE_CHOICES, Multiple Choices) \ - XX(301, MOVED_PERMANENTLY, Moved Permanently) \ - XX(302, FOUND, Found) \ - XX(303, SEE_OTHER, See Other) \ - XX(304, NOT_MODIFIED, Not Modified) \ - XX(305, USE_PROXY, Use Proxy) \ - XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \ - XX(308, PERMANENT_REDIRECT, Permanent Redirect) \ - XX(400, BAD_REQUEST, Bad Request) \ - XX(401, UNAUTHORIZED, Unauthorized) \ - XX(402, PAYMENT_REQUIRED, Payment Required) \ - XX(403, FORBIDDEN, Forbidden) \ - XX(404, NOT_FOUND, Not Found) \ - XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \ - XX(406, NOT_ACCEPTABLE, Not Acceptable) \ - XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \ - XX(408, REQUEST_TIMEOUT, Request Timeout) \ - XX(409, CONFLICT, Conflict) \ - XX(410, GONE, Gone) \ - XX(411, LENGTH_REQUIRED, Length Required) \ - XX(412, PRECONDITION_FAILED, Precondition Failed) \ - XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \ - XX(414, URI_TOO_LONG, URI Too Long) \ - XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \ - XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \ - XX(417, EXPECTATION_FAILED, Expectation Failed) \ - XX(421, MISDIRECTED_REQUEST, Misdirected Request) \ - XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \ - XX(423, LOCKED, Locked) \ - XX(424, FAILED_DEPENDENCY, Failed Dependency) \ - XX(426, UPGRADE_REQUIRED, Upgrade Required) \ - XX(428, PRECONDITION_REQUIRED, Precondition Required) \ - XX(429, TOO_MANY_REQUESTS, Too Many Requests) \ - XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \ - XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \ - XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \ - XX(501, NOT_IMPLEMENTED, Not Implemented) \ - XX(502, BAD_GATEWAY, Bad Gateway) \ - XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \ - XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \ - XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \ - XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \ - XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \ - XX(508, LOOP_DETECTED, Loop Detected) \ - XX(510, NOT_EXTENDED, Not Extended) \ - XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \ - -enum http_status - { -#define XX(num, name, string) HTTP_STATUS_##name = num, - HTTP_STATUS_MAP(XX) -#undef XX - }; - - /* Request Methods */ #define HTTP_METHOD_MAP(XX) \ XX(0, DELETE, DELETE) \ diff --git a/ext/inja/LICENSE b/ext/inja/LICENSE deleted file mode 100644 index 9e06bea07..000000000 --- a/ext/inja/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018-2021 Berscheid - -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. diff --git a/ext/inja/README.md b/ext/inja/README.md deleted file mode 100644 index 9d66a2c28..000000000 --- a/ext/inja/README.md +++ /dev/null @@ -1,391 +0,0 @@ -[
](https://github.com/pantor/inja/releases) - -

- - CI Status - - - - Documentation Status - - - - - - - - Github Releases - - - - Github Issues - - - - GitHub License - -

- -Inja is a template engine for modern C++, loosely inspired by [jinja](http://jinja.pocoo.org) for python. It has an easy and yet powerful template syntax with all variables, loops, conditions, includes, callbacks, and comments you need, nested and combined as you like. Inja uses the wonderful [json](https://github.com/nlohmann/json) library by nlohmann for data input. Most importantly, inja needs only two header files, which is (nearly) as trivial as integration in C++ can get. Of course, everything is tested on all relevant compilers. Here is what it looks like: - -```.cpp -json data; -data["name"] = "world"; - -inja::render("Hello {{ name }}!", data); // Returns "Hello world!" -``` - -## Integration - -Inja is a headers only library, which can be downloaded from the [releases](https://github.com/pantor/inja/releases) or directly from the `include/` or `single_include/` folder. Inja uses `nlohmann/json.hpp` (>= v3.8.0) as its single dependency, so make sure it can be included from `inja.hpp`. json can be downloaded [here](https://github.com/nlohmann/json/releases). Then integration is as easy as: - -```.cpp -#include - -// Just for convenience -using namespace inja; -``` - -If you are using the [Meson Build System](http://mesonbuild.com), then you can wrap this repository as a subproject. - -If you are using [Conan](https://conan.io) to manage your dependencies, have a look at [this repository](https://github.com/DEGoodmanWilson/conan-inja). Please file issues [here](https://github.com/DEGoodmanWilson/conan-inja/issues) if you experience problems with the packages. - -You can also integrate inja in your project using [Hunter](https://github.com/cpp-pm/hunter), a package manager for C++. - -If you are using [vcpkg](https://github.com/Microsoft/vcpkg) on your project for external dependencies, then you can use the [inja package](https://github.com/Microsoft/vcpkg/tree/master/ports/inja). Please see the vcpkg project for any issues regarding the packaging. - -If you are using [cget](https://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install pantor/inja`. A specific version can be installed with `cget install pantor/inja@v2.1.0`. - -On macOS, you can install inja via [Homebrew](https://formulae.brew.sh/formula/inja#default) and `brew install inja`. - -If you are using [conda](https://docs.conda.io/en/latest/), you can install the latest version from [conda-forge](https://anaconda.org/conda-forge/inja) with `conda install -c conda-forge inja`. - -## Tutorial - -This tutorial will give you an idea how to use inja. It will explain the most important concepts and give practical advices using examples and executable code. Beside this tutorial, you may check out the [documentation](https://pantor.github.io/inja). - -### Template Rendering - -The basic template rendering takes a template as a `std::string` and a `json` object for all data. It returns the rendered template as an `std::string`. - -```.cpp -json data; -data["name"] = "world"; - -render("Hello {{ name }}!", data); // Returns std::string "Hello world!" -render_to(std::cout, "Hello {{ name }}!", data); // Writes "Hello world!" to stream -``` - -For more advanced usage, an environment is recommended. -```.cpp -Environment env; - -// Render a string with json data -std::string result = env.render("Hello {{ name }}!", data); // "Hello world!" - -// Or directly read a template file -Template temp = env.parse_template("./templates/greeting.txt"); -std::string result = env.render(temp, data); // "Hello world!" - -data["name"] = "Inja"; -std::string result = env.render(temp, data); // "Hello Inja!" - -// Or read the template file (and/or the json file) directly from the environment -result = env.render_file("./templates/greeting.txt", data); -result = env.render_file_with_json_file("./templates/greeting.txt", "./data.json"); - -// Or write a rendered template file -env.write(temp, data, "./result.txt"); -env.write_with_json_file("./templates/greeting.txt", "./data.json", "./result.txt"); -``` - -The environment class can be configured to your needs. -```.cpp -// With default settings -Environment env_default; - -// With global path to template files and where files will be saved -Environment env_1 {"../path/templates/"}; - -// With separate input and output path -Environment env_2 {"../path/templates/", "../path/results/"}; - -// With other opening and closing strings (here the defaults) -env.set_expression("{{", "}}"); // Expressions -env.set_comment("{#", "#}"); // Comments -env.set_statement("{%", "%}"); // Statements {% %} for many things, see below -env.set_line_statement("##"); // Line statements ## (just an opener) -``` - -### Variables - -Variables are rendered within the `{{ ... }}` expressions. -```.cpp -json data; -data["neighbour"] = "Peter"; -data["guests"] = {"Jeff", "Tom", "Patrick"}; -data["time"]["start"] = 16; -data["time"]["end"] = 22; - -// Indexing in array -render("{{ guests.1 }}", data); // "Tom" - -// Objects -render("{{ time.start }} to {{ time.end + 1 }}pm", data); // "16 to 23pm" -``` -If no variable is found, valid JSON is printed directly, otherwise an `inja::RenderError` is thrown. - -### Statements - -Statements can be written either with the `{% ... %}` syntax or the `##` syntax for entire lines. Note that `##` needs to start the line without indentation. The most important statements are loops, conditions and file includes. All statements can be nested. - -#### Loops - -```.cpp -// Combining loops and line statements -render(R"(Guest List: -## for guest in guests - {{ loop.index1 }}: {{ guest }} -## endfor )", data) - -/* Guest List: - 1: Jeff - 2: Tom - 3: Patrick */ -``` -In a loop, the special variables `loop.index (number)`, `loop.index1 (number)`, `loop.is_first (boolean)` and `loop.is_last (boolean)` are defined. In nested loops, the parent loop variables are available e.g. via `loop.parent.index`. You can also iterate over objects like `{% for key, value in time %}`. - -#### Conditions - -Conditions support the typical if, else if and else statements. Following conditions are for example possible: -```.cpp -// Standard comparisons with a variable -render("{% if time.hour >= 20 %}Serve{% else if time.hour >= 18 %}Make{% endif %} dinner.", data); // Serve dinner. - -// Variable in list -render("{% if neighbour in guests %}Turn up the music!{% endif %}", data); // Turn up the music! - -// Logical operations -render("{% if guest_count < (3+2) and all_tired %}Sleepy...{% else %}Keep going...{% endif %}", data); // Sleepy... - -// Negations -render("{% if not guest_count %}The End{% endif %}", data); // The End -``` - -#### Includes - -You can either include other in-memory templates or from the file system. -```.cpp -// To include in-memory templates, add them to the environment first -inja::Template content_template = env.parse("Hello {{ neighbour }}!"); -env.include_template("content", content_template); -env.render("Content: {% include \"content\" %}", data); // "Content: Hello Peter!" - -// Other template files are included relative from the current file location -render("{% include \"footer.html\" %}", data); -``` -If a corresponding template could not be found in the file system, the *include callback* is called: -```.cpp -// The callback takes the current path and the wanted include name and returns a template -env.set_include_callback([&env](const std::string& path, const std::string& template_name) { - return env.parse("Hello {{ neighbour }} from " + template_name); -}); - -// You can disable to search for templates in the file system via -env.set_search_included_templates_in_files(false); -``` - -Inja will throw an `inja::RenderError` if an included file is not found and no callback is specified. To disable this error, you can call `env.set_throw_at_missing_includes(false)`. - -#### Assignments - -Variables can also be defined within the template using the set statment. -```.cpp -render("{% set new_hour=23 %}{{ new_hour }}pm", data); // "23pm" -render("{% set time.start=18 %}{{ time.start }}pm", data); // using json pointers -``` - -Assignments only set the value within the rendering context; they do not modify the json object passed into the `render` call. - -### Functions - -A few functions are implemented within the inja template syntax. They can be called with -```.cpp -// Upper and lower function, for string cases -render("Hello {{ upper(neighbour) }}!", data); // "Hello PETER!" -render("Hello {{ lower(neighbour) }}!", data); // "Hello peter!" - -// Range function, useful for loops -render("{% for i in range(4) %}{{ loop.index1 }}{% endfor %}", data); // "1234" -render("{% for i in range(3) %}{{ at(guests, i) }} {% endfor %}", data); // "Jeff Tom Patrick " - -// Length function (please don't combine with range, use list directly...) -render("I count {{ length(guests) }} guests.", data); // "I count 3 guests." - -// Get first and last element in a list -render("{{ first(guests) }} was first.", data); // "Jeff was first." -render("{{ last(guests) }} was last.", data); // "Patir was last." - -// Sort a list -render("{{ sort([3,2,1]) }}", data); // "[1,2,3]" -render("{{ sort(guests) }}", data); // "[\"Jeff\", \"Patrick\", \"Tom\"]" - -// Join a list with a separator -render("{{ join([1,2,3], \" + \") }}", data); // "1 + 2 + 3" -render("{{ join(guests, \", \") }}", data); // "Jeff, Patrick, Tom" - -// Round numbers to a given precision -render("{{ round(3.1415, 0) }}", data); // 3 -render("{{ round(3.1415, 3) }}", data); // 3.142 - -// Check if a value is odd, even or divisible by a number -render("{{ odd(42) }}", data); // false -render("{{ even(42) }}", data); // true -render("{{ divisibleBy(42, 7) }}", data); // true - -// Maximum and minimum values from a list -render("{{ max([1, 2, 3]) }}", data); // 3 -render("{{ min([-2.4, -1.2, 4.5]) }}", data); // -2.4 - -// Convert strings to numbers -render("{{ int(\"2\") == 2 }}", data); // true -render("{{ float(\"1.8\") > 2 }}", data); // false - -// Set default values if variables are not defined -render("Hello {{ default(neighbour, \"my friend\") }}!", data); // "Hello Peter!" -render("Hello {{ default(colleague, \"my friend\") }}!", data); // "Hello my friend!" - -// Access an objects value dynamically -render("{{ at(time, \"start\") }} to {{ time.end }}", data); // "16 to 22" - -// Check if a key exists in an object -render("{{ exists(\"guests\") }}", data); // "true" -render("{{ exists(\"city\") }}", data); // "false" -render("{{ existsIn(time, \"start\") }}", data); // "true" -render("{{ existsIn(time, neighbour) }}", data); // "false" - -// Check if a key is a specific type -render("{{ isString(neighbour) }}", data); // "true" -render("{{ isArray(guests) }}", data); // "true" -// Implemented type checks: isArray, isBoolean, isFloat, isInteger, isNumber, isObject, isString, -``` - -### Callbacks - -You can create your own and more complex functions with callbacks. These are implemented with `std::function`, so you can for example use C++ lambdas. Inja `Arguments` are a vector of json pointers. -```.cpp -Environment env; - -/* - * Callbacks are defined by its: - * - name, - * - (optional) number of arguments, - * - callback function. - */ -env.add_callback("double", 1, [](Arguments& args) { - int number = args.at(0)->get(); // Adapt the index and type of the argument - return 2 * number; -}); - -// You can then use a callback like a regular function -env.render("{{ double(16) }}", data); // "32" - -// Inja falls back to variadic callbacks if the number of expected arguments is omitted. -env.add_callback("argmax", [](Arguments& args) { - auto result = std::max_element(args.begin(), args.end(), [](const json* a, const json* b) { return *a < *b;}); - return std::distance(args.begin(), result); -}); -env.render("{{ argmax(4, 2, 6) }}", data); // "2" -env.render("{{ argmax(0, 2, 6, 8, 3) }}", data); // "3" - -// A callback without argument can be used like a dynamic variable: -std::string greet = "Hello"; -env.add_callback("double-greetings", 0, [greet](Arguments args) { - return greet + " " + greet + "!"; -}); -env.render("{{ double-greetings }}", data); // "Hello Hello!" -``` -You can also add a void callback without return variable, e.g. for debugging: -```.cpp -env.add_void_callback("log", 1, [greet](Arguments args) { - std::cout << "logging: " << args[0] << std::endl; -}); -env.render("{{ log(neighbour) }}", data); // Prints nothing to result, only to cout... -``` - -### Template Inheritance - -Template inheritance allows you to build a base *skeleton* template that contains all the common elements and defines blocks that child templates can override. Lets show an example: The base template -```.html - - - - {% block head %} - - {% block title %}{% endblock %} - My Webpage - {% endblock %} - - -
{% block content %}{% endblock %}
- - -``` -contains three `blocks` that child templates can fill in. The child template -```.html -{% extends "base.html" %} -{% block title %}Index{% endblock %} -{% block head %} - {{ super() }} - -{% endblock %} -{% block content %} -

Index

-

- Welcome to my blog! -

-{% endblock %} -``` -calls a parent template with the `extends` keyword; it should be the first element in the template. It is possible to render the contents of the parent block by calling `super()`. In the case of multiple levels of `{% extends %}`, super references may be called with an argument (e.g. `super(2)`) to skip levels in the inheritance tree. - -### Whitespace Control - -In the default configuration, no whitespace is removed while rendering the file. To support a more readable template style, you can configure the environment to control whitespaces before and after a statement automatically. While enabling `set_trim_blocks` removes the first newline after a statement, `set_lstrip_blocks` strips tabs and spaces from the beginning of a line to the start of a block. - -```.cpp -Environment env; -env.set_trim_blocks(true); -env.set_lstrip_blocks(true); -``` - -With both `trim_blocks` and `lstrip_blocks` enabled, you can put statements on their own lines. Furthermore, you can also strip whitespaces for both statements and expressions by hand. If you add a minus sign (`-`) to the start or end, the whitespaces before or after that block will be removed: - -```.cpp -render("Hello {{- name -}} !", data); // "Hello Inja!" -render("{% if neighbour in guests -%} I was there{% endif -%} !", data); // Renders without any whitespaces -``` - -Stripping behind a statement or expression also removes any newlines. - -### Comments - -Comments can be written with the `{# ... #}` syntax. -```.cpp -render("Hello{# Todo #}!", data); // "Hello!" -``` - -### Exceptions - -Inja uses exceptions to handle ill-formed template input. However, exceptions can be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `INJA_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. - - -## Supported compilers - -Inja uses the `string_view` feature of the C++17 STL. Currently, the following compilers are tested: - -- GCC 7 - 11 (and possibly later) -- Clang 5 - 12 (and possibly later) -- Microsoft Visual C++ 2017 15.0 - 2022 (and possibly later) - -A list of supported compiler / os versions can be found in the [CI definition](https://github.com/pantor/inja/blob/master/.github/workflows/ci.yml). diff --git a/ext/inja/inja.hpp b/ext/inja/inja.hpp deleted file mode 100644 index 5b469745f..000000000 --- a/ext/inja/inja.hpp +++ /dev/null @@ -1,2949 +0,0 @@ -/* - ___ _ Version 3.3 - |_ _|_ __ (_) __ _ https://github.com/pantor/inja - | || '_ \ | |/ _` | Licensed under the MIT License . - | || | | || | (_| | - |___|_| |_|/ |\__,_| Copyright (c) 2018-2021 Lars Berscheid - |__/ -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. -*/ - -#ifndef INCLUDE_INJA_INJA_HPP_ -#define INCLUDE_INJA_INJA_HPP_ - -#include - -namespace inja { -#ifndef INJA_DATA_TYPE -using json = nlohmann::json; -#else -using json = INJA_DATA_TYPE; -#endif -} // namespace inja - -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(INJA_NOEXCEPTION) -#ifndef INJA_THROW -#define INJA_THROW(exception) throw exception -#endif -#else -#include -#ifndef INJA_THROW -#define INJA_THROW(exception) \ - std::abort(); \ - std::ignore = exception -#endif -#ifndef INJA_NOEXCEPTION -#define INJA_NOEXCEPTION -#endif -#endif - -// #include "environment.hpp" -#ifndef INCLUDE_INJA_ENVIRONMENT_HPP_ -#define INCLUDE_INJA_ENVIRONMENT_HPP_ - -#include -#include -#include -#include -#include -#include - -// #include "config.hpp" -#ifndef INCLUDE_INJA_CONFIG_HPP_ -#define INCLUDE_INJA_CONFIG_HPP_ - -#include -#include - -// #include "template.hpp" -#ifndef INCLUDE_INJA_TEMPLATE_HPP_ -#define INCLUDE_INJA_TEMPLATE_HPP_ - -#include -#include -#include -#include - -// #include "node.hpp" -#ifndef INCLUDE_INJA_NODE_HPP_ -#define INCLUDE_INJA_NODE_HPP_ - -#include -#include -#include - -// #include "function_storage.hpp" -#ifndef INCLUDE_INJA_FUNCTION_STORAGE_HPP_ -#define INCLUDE_INJA_FUNCTION_STORAGE_HPP_ - -#include -#include - -namespace inja { - -using Arguments = std::vector; -using CallbackFunction = std::function; -using VoidCallbackFunction = std::function; - -/*! - * \brief Class for builtin functions and user-defined callbacks. - */ -class FunctionStorage { -public: - enum class Operation { - Not, - And, - Or, - In, - Equal, - NotEqual, - Greater, - GreaterEqual, - Less, - LessEqual, - Add, - Subtract, - Multiplication, - Division, - Power, - Modulo, - AtId, - At, - Default, - DivisibleBy, - Even, - Exists, - ExistsInObject, - First, - Float, - Int, - IsArray, - IsBoolean, - IsFloat, - IsInteger, - IsNumber, - IsObject, - IsString, - Last, - Length, - Lower, - Max, - Min, - Odd, - Range, - Round, - Sort, - Upper, - Super, - Join, - Callback, - ParenLeft, - ParenRight, - None, - }; - - struct FunctionData { - explicit FunctionData(const Operation& op, const CallbackFunction& cb = CallbackFunction {}): operation(op), callback(cb) {} - const Operation operation; - const CallbackFunction callback; - }; - -private: - const int VARIADIC {-1}; - - std::map, FunctionData> function_storage = { - {std::make_pair("at", 2), FunctionData {Operation::At}}, - {std::make_pair("default", 2), FunctionData {Operation::Default}}, - {std::make_pair("divisibleBy", 2), FunctionData {Operation::DivisibleBy}}, - {std::make_pair("even", 1), FunctionData {Operation::Even}}, - {std::make_pair("exists", 1), FunctionData {Operation::Exists}}, - {std::make_pair("existsIn", 2), FunctionData {Operation::ExistsInObject}}, - {std::make_pair("first", 1), FunctionData {Operation::First}}, - {std::make_pair("float", 1), FunctionData {Operation::Float}}, - {std::make_pair("int", 1), FunctionData {Operation::Int}}, - {std::make_pair("isArray", 1), FunctionData {Operation::IsArray}}, - {std::make_pair("isBoolean", 1), FunctionData {Operation::IsBoolean}}, - {std::make_pair("isFloat", 1), FunctionData {Operation::IsFloat}}, - {std::make_pair("isInteger", 1), FunctionData {Operation::IsInteger}}, - {std::make_pair("isNumber", 1), FunctionData {Operation::IsNumber}}, - {std::make_pair("isObject", 1), FunctionData {Operation::IsObject}}, - {std::make_pair("isString", 1), FunctionData {Operation::IsString}}, - {std::make_pair("last", 1), FunctionData {Operation::Last}}, - {std::make_pair("length", 1), FunctionData {Operation::Length}}, - {std::make_pair("lower", 1), FunctionData {Operation::Lower}}, - {std::make_pair("max", 1), FunctionData {Operation::Max}}, - {std::make_pair("min", 1), FunctionData {Operation::Min}}, - {std::make_pair("odd", 1), FunctionData {Operation::Odd}}, - {std::make_pair("range", 1), FunctionData {Operation::Range}}, - {std::make_pair("round", 2), FunctionData {Operation::Round}}, - {std::make_pair("sort", 1), FunctionData {Operation::Sort}}, - {std::make_pair("upper", 1), FunctionData {Operation::Upper}}, - {std::make_pair("super", 0), FunctionData {Operation::Super}}, - {std::make_pair("super", 1), FunctionData {Operation::Super}}, - {std::make_pair("join", 2), FunctionData {Operation::Join}}, - }; - -public: - void add_builtin(std::string_view name, int num_args, Operation op) { - function_storage.emplace(std::make_pair(static_cast(name), num_args), FunctionData {op}); - } - - void add_callback(std::string_view name, int num_args, const CallbackFunction& callback) { - function_storage.emplace(std::make_pair(static_cast(name), num_args), FunctionData {Operation::Callback, callback}); - } - - FunctionData find_function(std::string_view name, int num_args) const { - auto it = function_storage.find(std::make_pair(static_cast(name), num_args)); - if (it != function_storage.end()) { - return it->second; - - // Find variadic function - } else if (num_args > 0) { - it = function_storage.find(std::make_pair(static_cast(name), VARIADIC)); - if (it != function_storage.end()) { - return it->second; - } - } - - return FunctionData {Operation::None}; - } -}; - -} // namespace inja - -#endif // INCLUDE_INJA_FUNCTION_STORAGE_HPP_ - -// #include "utils.hpp" -#ifndef INCLUDE_INJA_UTILS_HPP_ -#define INCLUDE_INJA_UTILS_HPP_ - -#include -#include -#include -#include -#include - -// #include "exceptions.hpp" -#ifndef INCLUDE_INJA_EXCEPTIONS_HPP_ -#define INCLUDE_INJA_EXCEPTIONS_HPP_ - -#include -#include - -namespace inja { - -struct SourceLocation { - size_t line; - size_t column; -}; - -struct InjaError : public std::runtime_error { - const std::string type; - const std::string message; - - const SourceLocation location; - - explicit InjaError(const std::string& type, const std::string& message) - : std::runtime_error("[inja.exception." + type + "] " + message), type(type), message(message), location({0, 0}) {} - - explicit InjaError(const std::string& type, const std::string& message, SourceLocation location) - : std::runtime_error("[inja.exception." + type + "] (at " + std::to_string(location.line) + ":" + std::to_string(location.column) + ") " + message), - type(type), message(message), location(location) {} -}; - -struct ParserError : public InjaError { - explicit ParserError(const std::string& message, SourceLocation location): InjaError("parser_error", message, location) {} -}; - -struct RenderError : public InjaError { - explicit RenderError(const std::string& message, SourceLocation location): InjaError("render_error", message, location) {} -}; - -struct FileError : public InjaError { - explicit FileError(const std::string& message): InjaError("file_error", message) {} - explicit FileError(const std::string& message, SourceLocation location): InjaError("file_error", message, location) {} -}; - -struct DataError : public InjaError { - explicit DataError(const std::string& message, SourceLocation location): InjaError("data_error", message, location) {} -}; - -} // namespace inja - -#endif // INCLUDE_INJA_EXCEPTIONS_HPP_ - - -namespace inja { - -namespace string_view { -inline std::string_view slice(std::string_view view, size_t start, size_t end) { - start = std::min(start, view.size()); - end = std::min(std::max(start, end), view.size()); - return view.substr(start, end - start); -} - -inline std::pair split(std::string_view view, char Separator) { - size_t idx = view.find(Separator); - if (idx == std::string_view::npos) { - return std::make_pair(view, std::string_view()); - } - return std::make_pair(slice(view, 0, idx), slice(view, idx + 1, std::string_view::npos)); -} - -inline bool starts_with(std::string_view view, std::string_view prefix) { - return (view.size() >= prefix.size() && view.compare(0, prefix.size(), prefix) == 0); -} -} // namespace string_view - -inline SourceLocation get_source_location(std::string_view content, size_t pos) { - // Get line and offset position (starts at 1:1) - auto sliced = string_view::slice(content, 0, pos); - std::size_t last_newline = sliced.rfind("\n"); - - if (last_newline == std::string_view::npos) { - return {1, sliced.length() + 1}; - } - - // Count newlines - size_t count_lines = 0; - size_t search_start = 0; - while (search_start <= sliced.size()) { - search_start = sliced.find("\n", search_start) + 1; - if (search_start == 0) { - break; - } - count_lines += 1; - } - - return {count_lines + 1, sliced.length() - last_newline}; -} - -inline void replace_substring(std::string& s, const std::string& f, const std::string& t) { - if (f.empty()) { - return; - } - for (auto pos = s.find(f); // find first occurrence of f - pos != std::string::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} -} - -} // namespace inja - -#endif // INCLUDE_INJA_UTILS_HPP_ - - -namespace inja { - -class NodeVisitor; -class BlockNode; -class TextNode; -class ExpressionNode; -class LiteralNode; -class DataNode; -class FunctionNode; -class ExpressionListNode; -class StatementNode; -class ForStatementNode; -class ForArrayStatementNode; -class ForObjectStatementNode; -class IfStatementNode; -class IncludeStatementNode; -class ExtendsStatementNode; -class BlockStatementNode; -class SetStatementNode; - -class NodeVisitor { -public: - virtual ~NodeVisitor() = default; - - virtual void visit(const BlockNode& node) = 0; - virtual void visit(const TextNode& node) = 0; - virtual void visit(const ExpressionNode& node) = 0; - virtual void visit(const LiteralNode& node) = 0; - virtual void visit(const DataNode& node) = 0; - virtual void visit(const FunctionNode& node) = 0; - virtual void visit(const ExpressionListNode& node) = 0; - virtual void visit(const StatementNode& node) = 0; - virtual void visit(const ForStatementNode& node) = 0; - virtual void visit(const ForArrayStatementNode& node) = 0; - virtual void visit(const ForObjectStatementNode& node) = 0; - virtual void visit(const IfStatementNode& node) = 0; - virtual void visit(const IncludeStatementNode& node) = 0; - virtual void visit(const ExtendsStatementNode& node) = 0; - virtual void visit(const BlockStatementNode& node) = 0; - virtual void visit(const SetStatementNode& node) = 0; -}; - -/*! - * \brief Base node class for the abstract syntax tree (AST). - */ -class AstNode { -public: - virtual void accept(NodeVisitor& v) const = 0; - - size_t pos; - - AstNode(size_t pos): pos(pos) {} - virtual ~AstNode() {} -}; - -class BlockNode : public AstNode { -public: - std::vector> nodes; - - explicit BlockNode(): AstNode(0) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class TextNode : public AstNode { -public: - const size_t length; - - explicit TextNode(size_t pos, size_t length): AstNode(pos), length(length) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class ExpressionNode : public AstNode { -public: - explicit ExpressionNode(size_t pos): AstNode(pos) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class LiteralNode : public ExpressionNode { -public: - const json value; - - explicit LiteralNode(std::string_view data_text, size_t pos): ExpressionNode(pos), value(json::parse(data_text)) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class DataNode : public ExpressionNode { -public: - const std::string name; - const json::json_pointer ptr; - - static std::string convert_dot_to_ptr(std::string_view ptr_name) { - std::string result; - do { - std::string_view part; - std::tie(part, ptr_name) = string_view::split(ptr_name, '.'); - result.push_back('/'); - result.append(part.begin(), part.end()); - } while (!ptr_name.empty()); - return result; - } - - explicit DataNode(std::string_view ptr_name, size_t pos): ExpressionNode(pos), name(ptr_name), ptr(json::json_pointer(convert_dot_to_ptr(ptr_name))) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class FunctionNode : public ExpressionNode { - using Op = FunctionStorage::Operation; - -public: - enum class Associativity { - Left, - Right, - }; - - unsigned int precedence; - Associativity associativity; - - Op operation; - - std::string name; - int number_args; // Should also be negative -> -1 for unknown number - std::vector> arguments; - CallbackFunction callback; - - explicit FunctionNode(std::string_view name, size_t pos) - : ExpressionNode(pos), precedence(8), associativity(Associativity::Left), operation(Op::Callback), name(name), number_args(1) {} - explicit FunctionNode(Op operation, size_t pos): ExpressionNode(pos), operation(operation), number_args(1) { - switch (operation) { - case Op::Not: { - number_args = 1; - precedence = 4; - associativity = Associativity::Left; - } break; - case Op::And: { - number_args = 2; - precedence = 1; - associativity = Associativity::Left; - } break; - case Op::Or: { - number_args = 2; - precedence = 1; - associativity = Associativity::Left; - } break; - case Op::In: { - number_args = 2; - precedence = 2; - associativity = Associativity::Left; - } break; - case Op::Equal: { - number_args = 2; - precedence = 2; - associativity = Associativity::Left; - } break; - case Op::NotEqual: { - number_args = 2; - precedence = 2; - associativity = Associativity::Left; - } break; - case Op::Greater: { - number_args = 2; - precedence = 2; - associativity = Associativity::Left; - } break; - case Op::GreaterEqual: { - number_args = 2; - precedence = 2; - associativity = Associativity::Left; - } break; - case Op::Less: { - number_args = 2; - precedence = 2; - associativity = Associativity::Left; - } break; - case Op::LessEqual: { - number_args = 2; - precedence = 2; - associativity = Associativity::Left; - } break; - case Op::Add: { - number_args = 2; - precedence = 3; - associativity = Associativity::Left; - } break; - case Op::Subtract: { - number_args = 2; - precedence = 3; - associativity = Associativity::Left; - } break; - case Op::Multiplication: { - number_args = 2; - precedence = 4; - associativity = Associativity::Left; - } break; - case Op::Division: { - number_args = 2; - precedence = 4; - associativity = Associativity::Left; - } break; - case Op::Power: { - number_args = 2; - precedence = 5; - associativity = Associativity::Right; - } break; - case Op::Modulo: { - number_args = 2; - precedence = 4; - associativity = Associativity::Left; - } break; - case Op::AtId: { - number_args = 2; - precedence = 8; - associativity = Associativity::Left; - } break; - default: { - precedence = 1; - associativity = Associativity::Left; - } - } - } - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class ExpressionListNode : public AstNode { -public: - std::shared_ptr root; - - explicit ExpressionListNode(): AstNode(0) {} - explicit ExpressionListNode(size_t pos): AstNode(pos) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class StatementNode : public AstNode { -public: - StatementNode(size_t pos): AstNode(pos) {} - - virtual void accept(NodeVisitor& v) const = 0; -}; - -class ForStatementNode : public StatementNode { -public: - ExpressionListNode condition; - BlockNode body; - BlockNode* const parent; - - ForStatementNode(BlockNode* const parent, size_t pos): StatementNode(pos), parent(parent) {} - - virtual void accept(NodeVisitor& v) const = 0; -}; - -class ForArrayStatementNode : public ForStatementNode { -public: - const std::string value; - - explicit ForArrayStatementNode(const std::string& value, BlockNode* const parent, size_t pos): ForStatementNode(parent, pos), value(value) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class ForObjectStatementNode : public ForStatementNode { -public: - const std::string key; - const std::string value; - - explicit ForObjectStatementNode(const std::string& key, const std::string& value, BlockNode* const parent, size_t pos) - : ForStatementNode(parent, pos), key(key), value(value) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class IfStatementNode : public StatementNode { -public: - ExpressionListNode condition; - BlockNode true_statement; - BlockNode false_statement; - BlockNode* const parent; - - const bool is_nested; - bool has_false_statement {false}; - - explicit IfStatementNode(BlockNode* const parent, size_t pos): StatementNode(pos), parent(parent), is_nested(false) {} - explicit IfStatementNode(bool is_nested, BlockNode* const parent, size_t pos): StatementNode(pos), parent(parent), is_nested(is_nested) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class IncludeStatementNode : public StatementNode { -public: - const std::string file; - - explicit IncludeStatementNode(const std::string& file, size_t pos): StatementNode(pos), file(file) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -class ExtendsStatementNode : public StatementNode { -public: - const std::string file; - - explicit ExtendsStatementNode(const std::string& file, size_t pos): StatementNode(pos), file(file) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - }; -}; - -class BlockStatementNode : public StatementNode { -public: - const std::string name; - BlockNode block; - BlockNode* const parent; - - explicit BlockStatementNode(BlockNode* const parent, const std::string& name, size_t pos): StatementNode(pos), name(name), parent(parent) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - }; -}; - -class SetStatementNode : public StatementNode { -public: - const std::string key; - ExpressionListNode expression; - - explicit SetStatementNode(const std::string& key, size_t pos): StatementNode(pos), key(key) {} - - void accept(NodeVisitor& v) const { - v.visit(*this); - } -}; - -} // namespace inja - -#endif // INCLUDE_INJA_NODE_HPP_ - -// #include "statistics.hpp" -#ifndef INCLUDE_INJA_STATISTICS_HPP_ -#define INCLUDE_INJA_STATISTICS_HPP_ - -// #include "node.hpp" - - -namespace inja { - -/*! - * \brief A class for counting statistics on a Template. - */ -class StatisticsVisitor : public NodeVisitor { - void visit(const BlockNode& node) { - for (auto& n : node.nodes) { - n->accept(*this); - } - } - - void visit(const TextNode&) {} - void visit(const ExpressionNode&) {} - void visit(const LiteralNode&) {} - - void visit(const DataNode&) { - variable_counter += 1; - } - - void visit(const FunctionNode& node) { - for (auto& n : node.arguments) { - n->accept(*this); - } - } - - void visit(const ExpressionListNode& node) { - node.root->accept(*this); - } - - void visit(const StatementNode&) {} - void visit(const ForStatementNode&) {} - - void visit(const ForArrayStatementNode& node) { - node.condition.accept(*this); - node.body.accept(*this); - } - - void visit(const ForObjectStatementNode& node) { - node.condition.accept(*this); - node.body.accept(*this); - } - - void visit(const IfStatementNode& node) { - node.condition.accept(*this); - node.true_statement.accept(*this); - node.false_statement.accept(*this); - } - - void visit(const IncludeStatementNode&) {} - - void visit(const ExtendsStatementNode&) {} - - void visit(const BlockStatementNode& node) { - node.block.accept(*this); - } - - void visit(const SetStatementNode&) {} - -public: - unsigned int variable_counter; - - explicit StatisticsVisitor(): variable_counter(0) {} -}; - -} // namespace inja - -#endif // INCLUDE_INJA_STATISTICS_HPP_ - - -namespace inja { - -/*! - * \brief The main inja Template. - */ -struct Template { - BlockNode root; - std::string content; - std::map> block_storage; - - explicit Template() {} - explicit Template(const std::string& content): content(content) {} - - /// Return number of variables (total number, not distinct ones) in the template - int count_variables() { - auto statistic_visitor = StatisticsVisitor(); - root.accept(statistic_visitor); - return statistic_visitor.variable_counter; - } -}; - -using TemplateStorage = std::map; - -} // namespace inja - -#endif // INCLUDE_INJA_TEMPLATE_HPP_ - - -namespace inja { - -/*! - * \brief Class for lexer configuration. - */ -struct LexerConfig { - std::string statement_open {"{%"}; - std::string statement_open_no_lstrip {"{%+"}; - std::string statement_open_force_lstrip {"{%-"}; - std::string statement_close {"%}"}; - std::string statement_close_force_rstrip {"-%}"}; - std::string line_statement {"##"}; - std::string expression_open {"{{"}; - std::string expression_open_force_lstrip {"{{-"}; - std::string expression_close {"}}"}; - std::string expression_close_force_rstrip {"-}}"}; - std::string comment_open {"{#"}; - std::string comment_open_force_lstrip {"{#-"}; - std::string comment_close {"#}"}; - std::string comment_close_force_rstrip {"-#}"}; - std::string open_chars {"#{"}; - - bool trim_blocks {false}; - bool lstrip_blocks {false}; - - void update_open_chars() { - open_chars = ""; - if (open_chars.find(line_statement[0]) == std::string::npos) { - open_chars += line_statement[0]; - } - if (open_chars.find(statement_open[0]) == std::string::npos) { - open_chars += statement_open[0]; - } - if (open_chars.find(statement_open_no_lstrip[0]) == std::string::npos) { - open_chars += statement_open_no_lstrip[0]; - } - if (open_chars.find(statement_open_force_lstrip[0]) == std::string::npos) { - open_chars += statement_open_force_lstrip[0]; - } - if (open_chars.find(expression_open[0]) == std::string::npos) { - open_chars += expression_open[0]; - } - if (open_chars.find(expression_open_force_lstrip[0]) == std::string::npos) { - open_chars += expression_open_force_lstrip[0]; - } - if (open_chars.find(comment_open[0]) == std::string::npos) { - open_chars += comment_open[0]; - } - if (open_chars.find(comment_open_force_lstrip[0]) == std::string::npos) { - open_chars += comment_open_force_lstrip[0]; - } - } -}; - -/*! - * \brief Class for parser configuration. - */ -struct ParserConfig { - bool search_included_templates_in_files {true}; - - std::function include_callback; -}; - -/*! - * \brief Class for render configuration. - */ -struct RenderConfig { - bool throw_at_missing_includes {true}; -}; - -} // namespace inja - -#endif // INCLUDE_INJA_CONFIG_HPP_ - -// #include "function_storage.hpp" - -// #include "parser.hpp" -#ifndef INCLUDE_INJA_PARSER_HPP_ -#define INCLUDE_INJA_PARSER_HPP_ - -#include -#include -#include -#include -#include - -// #include "config.hpp" - -// #include "exceptions.hpp" - -// #include "function_storage.hpp" - -// #include "lexer.hpp" -#ifndef INCLUDE_INJA_LEXER_HPP_ -#define INCLUDE_INJA_LEXER_HPP_ - -#include -#include - -// #include "config.hpp" - -// #include "token.hpp" -#ifndef INCLUDE_INJA_TOKEN_HPP_ -#define INCLUDE_INJA_TOKEN_HPP_ - -#include -#include - -namespace inja { - -/*! - * \brief Helper-class for the inja Lexer. - */ -struct Token { - enum class Kind { - Text, - ExpressionOpen, // {{ - ExpressionClose, // }} - LineStatementOpen, // ## - LineStatementClose, // \n - StatementOpen, // {% - StatementClose, // %} - CommentOpen, // {# - CommentClose, // #} - Id, // this, this.foo - Number, // 1, 2, -1, 5.2, -5.3 - String, // "this" - Plus, // + - Minus, // - - Times, // * - Slash, // / - Percent, // % - Power, // ^ - Comma, // , - Dot, // . - Colon, // : - LeftParen, // ( - RightParen, // ) - LeftBracket, // [ - RightBracket, // ] - LeftBrace, // { - RightBrace, // } - Equal, // == - NotEqual, // != - GreaterThan, // > - GreaterEqual, // >= - LessThan, // < - LessEqual, // <= - Unknown, - Eof, - }; - - Kind kind {Kind::Unknown}; - std::string_view text; - - explicit constexpr Token() = default; - explicit constexpr Token(Kind kind, std::string_view text): kind(kind), text(text) {} - - std::string describe() const { - switch (kind) { - case Kind::Text: - return ""; - case Kind::LineStatementClose: - return ""; - case Kind::Eof: - return ""; - default: - return static_cast(text); - } - } -}; - -} // namespace inja - -#endif // INCLUDE_INJA_TOKEN_HPP_ - -// #include "utils.hpp" - - -namespace inja { - -/*! - * \brief Class for lexing an inja Template. - */ -class Lexer { - enum class State { - Text, - ExpressionStart, - ExpressionStartForceLstrip, - ExpressionBody, - LineStart, - LineBody, - StatementStart, - StatementStartNoLstrip, - StatementStartForceLstrip, - StatementBody, - CommentStart, - CommentStartForceLstrip, - CommentBody, - }; - - enum class MinusState { - Operator, - Number, - }; - - const LexerConfig& config; - - State state; - MinusState minus_state; - std::string_view m_in; - size_t tok_start; - size_t pos; - - Token scan_body(std::string_view close, Token::Kind closeKind, std::string_view close_trim = std::string_view(), bool trim = false) { - again: - // skip whitespace (except for \n as it might be a close) - if (tok_start >= m_in.size()) { - return make_token(Token::Kind::Eof); - } - const char ch = m_in[tok_start]; - if (ch == ' ' || ch == '\t' || ch == '\r') { - tok_start += 1; - goto again; - } - - // check for close - if (!close_trim.empty() && inja::string_view::starts_with(m_in.substr(tok_start), close_trim)) { - state = State::Text; - pos = tok_start + close_trim.size(); - const Token tok = make_token(closeKind); - skip_whitespaces_and_newlines(); - return tok; - } - - if (inja::string_view::starts_with(m_in.substr(tok_start), close)) { - state = State::Text; - pos = tok_start + close.size(); - const Token tok = make_token(closeKind); - if (trim) { - skip_whitespaces_and_first_newline(); - } - return tok; - } - - // skip \n - if (ch == '\n') { - tok_start += 1; - goto again; - } - - pos = tok_start + 1; - if (std::isalpha(ch)) { - minus_state = MinusState::Operator; - return scan_id(); - } - - const MinusState current_minus_state = minus_state; - if (minus_state == MinusState::Operator) { - minus_state = MinusState::Number; - } - - switch (ch) { - case '+': - return make_token(Token::Kind::Plus); - case '-': - if (current_minus_state == MinusState::Operator) { - return make_token(Token::Kind::Minus); - } - return scan_number(); - case '*': - return make_token(Token::Kind::Times); - case '/': - return make_token(Token::Kind::Slash); - case '^': - return make_token(Token::Kind::Power); - case '%': - return make_token(Token::Kind::Percent); - case '.': - return make_token(Token::Kind::Dot); - case ',': - return make_token(Token::Kind::Comma); - case ':': - return make_token(Token::Kind::Colon); - case '(': - return make_token(Token::Kind::LeftParen); - case ')': - minus_state = MinusState::Operator; - return make_token(Token::Kind::RightParen); - case '[': - return make_token(Token::Kind::LeftBracket); - case ']': - minus_state = MinusState::Operator; - return make_token(Token::Kind::RightBracket); - case '{': - return make_token(Token::Kind::LeftBrace); - case '}': - minus_state = MinusState::Operator; - return make_token(Token::Kind::RightBrace); - case '>': - if (pos < m_in.size() && m_in[pos] == '=') { - pos += 1; - return make_token(Token::Kind::GreaterEqual); - } - return make_token(Token::Kind::GreaterThan); - case '<': - if (pos < m_in.size() && m_in[pos] == '=') { - pos += 1; - return make_token(Token::Kind::LessEqual); - } - return make_token(Token::Kind::LessThan); - case '=': - if (pos < m_in.size() && m_in[pos] == '=') { - pos += 1; - return make_token(Token::Kind::Equal); - } - return make_token(Token::Kind::Unknown); - case '!': - if (pos < m_in.size() && m_in[pos] == '=') { - pos += 1; - return make_token(Token::Kind::NotEqual); - } - return make_token(Token::Kind::Unknown); - case '\"': - return scan_string(); - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - minus_state = MinusState::Operator; - return scan_number(); - case '_': - case '@': - case '$': - minus_state = MinusState::Operator; - return scan_id(); - default: - return make_token(Token::Kind::Unknown); - } - } - - Token scan_id() { - for (;;) { - if (pos >= m_in.size()) { - break; - } - const char ch = m_in[pos]; - if (!std::isalnum(ch) && ch != '.' && ch != '/' && ch != '_' && ch != '-') { - break; - } - pos += 1; - } - return make_token(Token::Kind::Id); - } - - Token scan_number() { - for (;;) { - if (pos >= m_in.size()) { - break; - } - const char ch = m_in[pos]; - // be very permissive in lexer (we'll catch errors when conversion happens) - if (!(std::isdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' || (ch == '+' && (pos == 0 || m_in[pos-1] == 'e' || m_in[pos-1] == 'E')) || (ch == '-' && (pos == 0 || m_in[pos-1] == 'e' || m_in[pos-1] == 'E')))) { - break; - } - pos += 1; - } - return make_token(Token::Kind::Number); - } - - Token scan_string() { - bool escape {false}; - for (;;) { - if (pos >= m_in.size()) { - break; - } - const char ch = m_in[pos++]; - if (ch == '\\') { - escape = true; - } else if (!escape && ch == m_in[tok_start]) { - break; - } else { - escape = false; - } - } - return make_token(Token::Kind::String); - } - - Token make_token(Token::Kind kind) const { - return Token(kind, string_view::slice(m_in, tok_start, pos)); - } - - void skip_whitespaces_and_newlines() { - if (pos < m_in.size()) { - while (pos < m_in.size() && (m_in[pos] == ' ' || m_in[pos] == '\t' || m_in[pos] == '\n' || m_in[pos] == '\r')) { - pos += 1; - } - } - } - - void skip_whitespaces_and_first_newline() { - if (pos < m_in.size()) { - while (pos < m_in.size() && (m_in[pos] == ' ' || m_in[pos] == '\t')) { - pos += 1; - } - } - - if (pos < m_in.size()) { - const char ch = m_in[pos]; - if (ch == '\n') { - pos += 1; - } else if (ch == '\r') { - pos += 1; - if (pos < m_in.size() && m_in[pos] == '\n') { - pos += 1; - } - } - } - } - - static std::string_view clear_final_line_if_whitespace(std::string_view text) { - std::string_view result = text; - while (!result.empty()) { - const char ch = result.back(); - if (ch == ' ' || ch == '\t') { - result.remove_suffix(1); - } else if (ch == '\n' || ch == '\r') { - break; - } else { - return text; - } - } - return result; - } - -public: - explicit Lexer(const LexerConfig& config): config(config), state(State::Text), minus_state(MinusState::Number) {} - - SourceLocation current_position() const { - return get_source_location(m_in, tok_start); - } - - void start(std::string_view input) { - m_in = input; - tok_start = 0; - pos = 0; - state = State::Text; - minus_state = MinusState::Number; - - // Consume byte order mark (BOM) for UTF-8 - if (inja::string_view::starts_with(m_in, "\xEF\xBB\xBF")) { - m_in = m_in.substr(3); - } - } - - Token scan() { - tok_start = pos; - - again: - if (tok_start >= m_in.size()) { - return make_token(Token::Kind::Eof); - } - - switch (state) { - default: - case State::Text: { - // fast-scan to first open character - const size_t open_start = m_in.substr(pos).find_first_of(config.open_chars); - if (open_start == std::string_view::npos) { - // didn't find open, return remaining text as text token - pos = m_in.size(); - return make_token(Token::Kind::Text); - } - pos += open_start; - - // try to match one of the opening sequences, and get the close - std::string_view open_str = m_in.substr(pos); - bool must_lstrip = false; - if (inja::string_view::starts_with(open_str, config.expression_open)) { - if (inja::string_view::starts_with(open_str, config.expression_open_force_lstrip)) { - state = State::ExpressionStartForceLstrip; - must_lstrip = true; - } else { - state = State::ExpressionStart; - } - } else if (inja::string_view::starts_with(open_str, config.statement_open)) { - if (inja::string_view::starts_with(open_str, config.statement_open_no_lstrip)) { - state = State::StatementStartNoLstrip; - } else if (inja::string_view::starts_with(open_str, config.statement_open_force_lstrip)) { - state = State::StatementStartForceLstrip; - must_lstrip = true; - } else { - state = State::StatementStart; - must_lstrip = config.lstrip_blocks; - } - } else if (inja::string_view::starts_with(open_str, config.comment_open)) { - if (inja::string_view::starts_with(open_str, config.comment_open_force_lstrip)) { - state = State::CommentStartForceLstrip; - must_lstrip = true; - } else { - state = State::CommentStart; - must_lstrip = config.lstrip_blocks; - } - } else if ((pos == 0 || m_in[pos - 1] == '\n') && inja::string_view::starts_with(open_str, config.line_statement)) { - state = State::LineStart; - } else { - pos += 1; // wasn't actually an opening sequence - goto again; - } - - std::string_view text = string_view::slice(m_in, tok_start, pos); - if (must_lstrip) { - text = clear_final_line_if_whitespace(text); - } - - if (text.empty()) { - goto again; // don't generate empty token - } - return Token(Token::Kind::Text, text); - } - case State::ExpressionStart: { - state = State::ExpressionBody; - pos += config.expression_open.size(); - return make_token(Token::Kind::ExpressionOpen); - } - case State::ExpressionStartForceLstrip: { - state = State::ExpressionBody; - pos += config.expression_open_force_lstrip.size(); - return make_token(Token::Kind::ExpressionOpen); - } - case State::LineStart: { - state = State::LineBody; - pos += config.line_statement.size(); - return make_token(Token::Kind::LineStatementOpen); - } - case State::StatementStart: { - state = State::StatementBody; - pos += config.statement_open.size(); - return make_token(Token::Kind::StatementOpen); - } - case State::StatementStartNoLstrip: { - state = State::StatementBody; - pos += config.statement_open_no_lstrip.size(); - return make_token(Token::Kind::StatementOpen); - } - case State::StatementStartForceLstrip: { - state = State::StatementBody; - pos += config.statement_open_force_lstrip.size(); - return make_token(Token::Kind::StatementOpen); - } - case State::CommentStart: { - state = State::CommentBody; - pos += config.comment_open.size(); - return make_token(Token::Kind::CommentOpen); - } - case State::CommentStartForceLstrip: { - state = State::CommentBody; - pos += config.comment_open_force_lstrip.size(); - return make_token(Token::Kind::CommentOpen); - } - case State::ExpressionBody: - return scan_body(config.expression_close, Token::Kind::ExpressionClose, config.expression_close_force_rstrip); - case State::LineBody: - return scan_body("\n", Token::Kind::LineStatementClose); - case State::StatementBody: - return scan_body(config.statement_close, Token::Kind::StatementClose, config.statement_close_force_rstrip, config.trim_blocks); - case State::CommentBody: { - // fast-scan to comment close - const size_t end = m_in.substr(pos).find(config.comment_close); - if (end == std::string_view::npos) { - pos = m_in.size(); - return make_token(Token::Kind::Eof); - } - - // Check for trim pattern - const bool must_rstrip = inja::string_view::starts_with(m_in.substr(pos + end - 1), config.comment_close_force_rstrip); - - // return the entire comment in the close token - state = State::Text; - pos += end + config.comment_close.size(); - Token tok = make_token(Token::Kind::CommentClose); - - if (must_rstrip || config.trim_blocks) { - skip_whitespaces_and_first_newline(); - } - return tok; - } - } - } - - const LexerConfig& get_config() const { - return config; - } -}; - -} // namespace inja - -#endif // INCLUDE_INJA_LEXER_HPP_ - -// #include "node.hpp" - -// #include "template.hpp" - -// #include "token.hpp" - -// #include "utils.hpp" - - -namespace inja { - -/*! - * \brief Class for parsing an inja Template. - */ -class Parser { - const ParserConfig& config; - - Lexer lexer; - TemplateStorage& template_storage; - const FunctionStorage& function_storage; - - Token tok, peek_tok; - bool have_peek_tok {false}; - - size_t current_paren_level {0}; - size_t current_bracket_level {0}; - size_t current_brace_level {0}; - - std::string_view literal_start; - - BlockNode* current_block {nullptr}; - ExpressionListNode* current_expression_list {nullptr}; - std::stack> function_stack; - std::vector> arguments; - - std::stack> operator_stack; - std::stack if_statement_stack; - std::stack for_statement_stack; - std::stack block_statement_stack; - - inline void throw_parser_error(const std::string& message) const { - INJA_THROW(ParserError(message, lexer.current_position())); - } - - inline void get_next_token() { - if (have_peek_tok) { - tok = peek_tok; - have_peek_tok = false; - } else { - tok = lexer.scan(); - } - } - - inline void get_peek_token() { - if (!have_peek_tok) { - peek_tok = lexer.scan(); - have_peek_tok = true; - } - } - - inline void add_literal(const char* content_ptr) { - std::string_view data_text(literal_start.data(), tok.text.data() - literal_start.data() + tok.text.size()); - arguments.emplace_back(std::make_shared(data_text, data_text.data() - content_ptr)); - } - - inline void add_operator() { - auto function = operator_stack.top(); - operator_stack.pop(); - - for (int i = 0; i < function->number_args; ++i) { - function->arguments.insert(function->arguments.begin(), arguments.back()); - arguments.pop_back(); - } - arguments.emplace_back(function); - } - - void add_to_template_storage(std::string_view path, std::string& template_name) { - if (template_storage.find(template_name) != template_storage.end()) { - return; - } - - std::string original_path = static_cast(path); - std::string original_name = template_name; - - if (config.search_included_templates_in_files) { - // Build the relative path - template_name = original_path + original_name; - if (template_name.compare(0, 2, "./") == 0) { - template_name.erase(0, 2); - } - - if (template_storage.find(template_name) == template_storage.end()) { - // Load file - std::ifstream file; - file.open(template_name); - if (!file.fail()) { - std::string text((std::istreambuf_iterator(file)), std::istreambuf_iterator()); - - auto include_template = Template(text); - template_storage.emplace(template_name, include_template); - parse_into_template(template_storage[template_name], template_name); - return; - } else if (!config.include_callback) { - INJA_THROW(FileError("failed accessing file at '" + template_name + "'")); - } - } - } - - // Try include callback - if (config.include_callback) { - auto include_template = config.include_callback(original_path, original_name); - template_storage.emplace(template_name, include_template); - } - } - - std::string parse_filename(const Token& tok) const { - if (tok.kind != Token::Kind::String) { - throw_parser_error("expected string, got '" + tok.describe() + "'"); - } - - if (tok.text.length() < 2) { - throw_parser_error("expected filename, got '" + static_cast(tok.text) + "'"); - } - - // Remove first and last character "" - return std::string {tok.text.substr(1, tok.text.length() - 2)}; - } - - bool parse_expression(Template& tmpl, Token::Kind closing) { - while (tok.kind != closing && tok.kind != Token::Kind::Eof) { - // Literals - switch (tok.kind) { - case Token::Kind::String: { - if (current_brace_level == 0 && current_bracket_level == 0) { - literal_start = tok.text; - add_literal(tmpl.content.c_str()); - } - } break; - case Token::Kind::Number: { - if (current_brace_level == 0 && current_bracket_level == 0) { - literal_start = tok.text; - add_literal(tmpl.content.c_str()); - } - } break; - case Token::Kind::LeftBracket: { - if (current_brace_level == 0 && current_bracket_level == 0) { - literal_start = tok.text; - } - current_bracket_level += 1; - } break; - case Token::Kind::LeftBrace: { - if (current_brace_level == 0 && current_bracket_level == 0) { - literal_start = tok.text; - } - current_brace_level += 1; - } break; - case Token::Kind::RightBracket: { - if (current_bracket_level == 0) { - throw_parser_error("unexpected ']'"); - } - - current_bracket_level -= 1; - if (current_brace_level == 0 && current_bracket_level == 0) { - add_literal(tmpl.content.c_str()); - } - } break; - case Token::Kind::RightBrace: { - if (current_brace_level == 0) { - throw_parser_error("unexpected '}'"); - } - - current_brace_level -= 1; - if (current_brace_level == 0 && current_bracket_level == 0) { - add_literal(tmpl.content.c_str()); - } - } break; - case Token::Kind::Id: { - get_peek_token(); - - // Data Literal - if (tok.text == static_cast("true") || tok.text == static_cast("false") || - tok.text == static_cast("null")) { - if (current_brace_level == 0 && current_bracket_level == 0) { - literal_start = tok.text; - add_literal(tmpl.content.c_str()); - } - - // Operator - } else if (tok.text == "and" || tok.text == "or" || tok.text == "in" || tok.text == "not") { - goto parse_operator; - - // Functions - } else if (peek_tok.kind == Token::Kind::LeftParen) { - operator_stack.emplace(std::make_shared(static_cast(tok.text), tok.text.data() - tmpl.content.c_str())); - function_stack.emplace(operator_stack.top().get(), current_paren_level); - - // Variables - } else { - arguments.emplace_back(std::make_shared(static_cast(tok.text), tok.text.data() - tmpl.content.c_str())); - } - - // Operators - } break; - case Token::Kind::Equal: - case Token::Kind::NotEqual: - case Token::Kind::GreaterThan: - case Token::Kind::GreaterEqual: - case Token::Kind::LessThan: - case Token::Kind::LessEqual: - case Token::Kind::Plus: - case Token::Kind::Minus: - case Token::Kind::Times: - case Token::Kind::Slash: - case Token::Kind::Power: - case Token::Kind::Percent: - case Token::Kind::Dot: { - - parse_operator: - FunctionStorage::Operation operation; - switch (tok.kind) { - case Token::Kind::Id: { - if (tok.text == "and") { - operation = FunctionStorage::Operation::And; - } else if (tok.text == "or") { - operation = FunctionStorage::Operation::Or; - } else if (tok.text == "in") { - operation = FunctionStorage::Operation::In; - } else if (tok.text == "not") { - operation = FunctionStorage::Operation::Not; - } else { - throw_parser_error("unknown operator in parser."); - } - } break; - case Token::Kind::Equal: { - operation = FunctionStorage::Operation::Equal; - } break; - case Token::Kind::NotEqual: { - operation = FunctionStorage::Operation::NotEqual; - } break; - case Token::Kind::GreaterThan: { - operation = FunctionStorage::Operation::Greater; - } break; - case Token::Kind::GreaterEqual: { - operation = FunctionStorage::Operation::GreaterEqual; - } break; - case Token::Kind::LessThan: { - operation = FunctionStorage::Operation::Less; - } break; - case Token::Kind::LessEqual: { - operation = FunctionStorage::Operation::LessEqual; - } break; - case Token::Kind::Plus: { - operation = FunctionStorage::Operation::Add; - } break; - case Token::Kind::Minus: { - operation = FunctionStorage::Operation::Subtract; - } break; - case Token::Kind::Times: { - operation = FunctionStorage::Operation::Multiplication; - } break; - case Token::Kind::Slash: { - operation = FunctionStorage::Operation::Division; - } break; - case Token::Kind::Power: { - operation = FunctionStorage::Operation::Power; - } break; - case Token::Kind::Percent: { - operation = FunctionStorage::Operation::Modulo; - } break; - case Token::Kind::Dot: { - operation = FunctionStorage::Operation::AtId; - } break; - default: { - throw_parser_error("unknown operator in parser."); - } - } - auto function_node = std::make_shared(operation, tok.text.data() - tmpl.content.c_str()); - - while (!operator_stack.empty() && - ((operator_stack.top()->precedence > function_node->precedence) || - (operator_stack.top()->precedence == function_node->precedence && function_node->associativity == FunctionNode::Associativity::Left)) && - (operator_stack.top()->operation != FunctionStorage::Operation::ParenLeft)) { - add_operator(); - } - - operator_stack.emplace(function_node); - } break; - case Token::Kind::Comma: { - if (current_brace_level == 0 && current_bracket_level == 0) { - if (function_stack.empty()) { - throw_parser_error("unexpected ','"); - } - - function_stack.top().first->number_args += 1; - } - } break; - case Token::Kind::Colon: { - if (current_brace_level == 0 && current_bracket_level == 0) { - throw_parser_error("unexpected ':'"); - } - } break; - case Token::Kind::LeftParen: { - current_paren_level += 1; - operator_stack.emplace(std::make_shared(FunctionStorage::Operation::ParenLeft, tok.text.data() - tmpl.content.c_str())); - - get_peek_token(); - if (peek_tok.kind == Token::Kind::RightParen) { - if (!function_stack.empty() && function_stack.top().second == current_paren_level - 1) { - function_stack.top().first->number_args = 0; - } - } - } break; - case Token::Kind::RightParen: { - current_paren_level -= 1; - while (!operator_stack.empty() && operator_stack.top()->operation != FunctionStorage::Operation::ParenLeft) { - add_operator(); - } - - if (!operator_stack.empty() && operator_stack.top()->operation == FunctionStorage::Operation::ParenLeft) { - operator_stack.pop(); - } - - if (!function_stack.empty() && function_stack.top().second == current_paren_level) { - auto func = function_stack.top().first; - auto function_data = function_storage.find_function(func->name, func->number_args); - if (function_data.operation == FunctionStorage::Operation::None) { - throw_parser_error("unknown function " + func->name); - } - func->operation = function_data.operation; - if (function_data.operation == FunctionStorage::Operation::Callback) { - func->callback = function_data.callback; - } - - if (operator_stack.empty()) { - throw_parser_error("internal error at function " + func->name); - } - - add_operator(); - function_stack.pop(); - } - } - default: - break; - } - - get_next_token(); - } - - while (!operator_stack.empty()) { - add_operator(); - } - - if (arguments.size() == 1) { - current_expression_list->root = arguments[0]; - arguments = {}; - } else if (arguments.size() > 1) { - throw_parser_error("malformed expression"); - } - - return true; - } - - bool parse_statement(Template& tmpl, Token::Kind closing, std::string_view path) { - if (tok.kind != Token::Kind::Id) { - return false; - } - - if (tok.text == static_cast("if")) { - get_next_token(); - - auto if_statement_node = std::make_shared(current_block, tok.text.data() - tmpl.content.c_str()); - current_block->nodes.emplace_back(if_statement_node); - if_statement_stack.emplace(if_statement_node.get()); - current_block = &if_statement_node->true_statement; - current_expression_list = &if_statement_node->condition; - - if (!parse_expression(tmpl, closing)) { - return false; - } - } else if (tok.text == static_cast("else")) { - if (if_statement_stack.empty()) { - throw_parser_error("else without matching if"); - } - auto& if_statement_data = if_statement_stack.top(); - get_next_token(); - - if_statement_data->has_false_statement = true; - current_block = &if_statement_data->false_statement; - - // Chained else if - if (tok.kind == Token::Kind::Id && tok.text == static_cast("if")) { - get_next_token(); - - auto if_statement_node = std::make_shared(true, current_block, tok.text.data() - tmpl.content.c_str()); - current_block->nodes.emplace_back(if_statement_node); - if_statement_stack.emplace(if_statement_node.get()); - current_block = &if_statement_node->true_statement; - current_expression_list = &if_statement_node->condition; - - if (!parse_expression(tmpl, closing)) { - return false; - } - } - } else if (tok.text == static_cast("endif")) { - if (if_statement_stack.empty()) { - throw_parser_error("endif without matching if"); - } - - // Nested if statements - while (if_statement_stack.top()->is_nested) { - if_statement_stack.pop(); - } - - auto& if_statement_data = if_statement_stack.top(); - get_next_token(); - - current_block = if_statement_data->parent; - if_statement_stack.pop(); - } else if (tok.text == static_cast("block")) { - get_next_token(); - - if (tok.kind != Token::Kind::Id) { - throw_parser_error("expected block name, got '" + tok.describe() + "'"); - } - - const std::string block_name = static_cast(tok.text); - - auto block_statement_node = std::make_shared(current_block, block_name, tok.text.data() - tmpl.content.c_str()); - current_block->nodes.emplace_back(block_statement_node); - block_statement_stack.emplace(block_statement_node.get()); - current_block = &block_statement_node->block; - auto success = tmpl.block_storage.emplace(block_name, block_statement_node); - if (!success.second) { - throw_parser_error("block with the name '" + block_name + "' does already exist"); - } - - get_next_token(); - } else if (tok.text == static_cast("endblock")) { - if (block_statement_stack.empty()) { - throw_parser_error("endblock without matching block"); - } - - auto& block_statement_data = block_statement_stack.top(); - get_next_token(); - - current_block = block_statement_data->parent; - block_statement_stack.pop(); - } else if (tok.text == static_cast("for")) { - get_next_token(); - - // options: for a in arr; for a, b in obj - if (tok.kind != Token::Kind::Id) { - throw_parser_error("expected id, got '" + tok.describe() + "'"); - } - - Token value_token = tok; - get_next_token(); - - // Object type - std::shared_ptr for_statement_node; - if (tok.kind == Token::Kind::Comma) { - get_next_token(); - if (tok.kind != Token::Kind::Id) { - throw_parser_error("expected id, got '" + tok.describe() + "'"); - } - - Token key_token = std::move(value_token); - value_token = tok; - get_next_token(); - - for_statement_node = std::make_shared(static_cast(key_token.text), static_cast(value_token.text), - current_block, tok.text.data() - tmpl.content.c_str()); - - // Array type - } else { - for_statement_node = - std::make_shared(static_cast(value_token.text), current_block, tok.text.data() - tmpl.content.c_str()); - } - - current_block->nodes.emplace_back(for_statement_node); - for_statement_stack.emplace(for_statement_node.get()); - current_block = &for_statement_node->body; - current_expression_list = &for_statement_node->condition; - - if (tok.kind != Token::Kind::Id || tok.text != static_cast("in")) { - throw_parser_error("expected 'in', got '" + tok.describe() + "'"); - } - get_next_token(); - - if (!parse_expression(tmpl, closing)) { - return false; - } - } else if (tok.text == static_cast("endfor")) { - if (for_statement_stack.empty()) { - throw_parser_error("endfor without matching for"); - } - - auto& for_statement_data = for_statement_stack.top(); - get_next_token(); - - current_block = for_statement_data->parent; - for_statement_stack.pop(); - } else if (tok.text == static_cast("include")) { - get_next_token(); - - std::string template_name = parse_filename(tok); - add_to_template_storage(path, template_name); - - current_block->nodes.emplace_back(std::make_shared(template_name, tok.text.data() - tmpl.content.c_str())); - - get_next_token(); - } else if (tok.text == static_cast("extends")) { - get_next_token(); - - std::string template_name = parse_filename(tok); - add_to_template_storage(path, template_name); - - current_block->nodes.emplace_back(std::make_shared(template_name, tok.text.data() - tmpl.content.c_str())); - - get_next_token(); - } else if (tok.text == static_cast("set")) { - get_next_token(); - - if (tok.kind != Token::Kind::Id) { - throw_parser_error("expected variable name, got '" + tok.describe() + "'"); - } - - std::string key = static_cast(tok.text); - get_next_token(); - - auto set_statement_node = std::make_shared(key, tok.text.data() - tmpl.content.c_str()); - current_block->nodes.emplace_back(set_statement_node); - current_expression_list = &set_statement_node->expression; - - if (tok.text != static_cast("=")) { - throw_parser_error("expected '=', got '" + tok.describe() + "'"); - } - get_next_token(); - - if (!parse_expression(tmpl, closing)) { - return false; - } - } else { - return false; - } - return true; - } - - void parse_into(Template& tmpl, std::string_view path) { - lexer.start(tmpl.content); - current_block = &tmpl.root; - - for (;;) { - get_next_token(); - switch (tok.kind) { - case Token::Kind::Eof: { - if (!if_statement_stack.empty()) { - throw_parser_error("unmatched if"); - } - if (!for_statement_stack.empty()) { - throw_parser_error("unmatched for"); - } - } - return; - case Token::Kind::Text: { - current_block->nodes.emplace_back(std::make_shared(tok.text.data() - tmpl.content.c_str(), tok.text.size())); - } break; - case Token::Kind::StatementOpen: { - get_next_token(); - if (!parse_statement(tmpl, Token::Kind::StatementClose, path)) { - throw_parser_error("expected statement, got '" + tok.describe() + "'"); - } - if (tok.kind != Token::Kind::StatementClose) { - throw_parser_error("expected statement close, got '" + tok.describe() + "'"); - } - } break; - case Token::Kind::LineStatementOpen: { - get_next_token(); - if (!parse_statement(tmpl, Token::Kind::LineStatementClose, path)) { - throw_parser_error("expected statement, got '" + tok.describe() + "'"); - } - if (tok.kind != Token::Kind::LineStatementClose && tok.kind != Token::Kind::Eof) { - throw_parser_error("expected line statement close, got '" + tok.describe() + "'"); - } - } break; - case Token::Kind::ExpressionOpen: { - get_next_token(); - - auto expression_list_node = std::make_shared(tok.text.data() - tmpl.content.c_str()); - current_block->nodes.emplace_back(expression_list_node); - current_expression_list = expression_list_node.get(); - - if (!parse_expression(tmpl, Token::Kind::ExpressionClose)) { - throw_parser_error("expected expression, got '" + tok.describe() + "'"); - } - - if (tok.kind != Token::Kind::ExpressionClose) { - throw_parser_error("expected expression close, got '" + tok.describe() + "'"); - } - } break; - case Token::Kind::CommentOpen: { - get_next_token(); - if (tok.kind != Token::Kind::CommentClose) { - throw_parser_error("expected comment close, got '" + tok.describe() + "'"); - } - } break; - default: { - throw_parser_error("unexpected token '" + tok.describe() + "'"); - } break; - } - } - } - -public: - explicit Parser(const ParserConfig& parser_config, const LexerConfig& lexer_config, TemplateStorage& template_storage, - const FunctionStorage& function_storage) - : config(parser_config), lexer(lexer_config), template_storage(template_storage), function_storage(function_storage) {} - - Template parse(std::string_view input, std::string_view path) { - auto result = Template(static_cast(input)); - parse_into(result, path); - return result; - } - - Template parse(std::string_view input) { - return parse(input, "./"); - } - - void parse_into_template(Template& tmpl, std::string_view filename) { - std::string_view path = filename.substr(0, filename.find_last_of("/\\") + 1); - - // StringRef path = sys::path::parent_path(filename); - auto sub_parser = Parser(config, lexer.get_config(), template_storage, function_storage); - sub_parser.parse_into(tmpl, path); - } - - std::string load_file(const std::string& filename) { - std::ifstream file; - file.open(filename); - if (file.fail()) { - INJA_THROW(FileError("failed accessing file at '" + filename + "'")); - } - std::string text((std::istreambuf_iterator(file)), std::istreambuf_iterator()); - return text; - } -}; - -} // namespace inja - -#endif // INCLUDE_INJA_PARSER_HPP_ - -// #include "renderer.hpp" -#ifndef INCLUDE_INJA_RENDERER_HPP_ -#define INCLUDE_INJA_RENDERER_HPP_ - -#include -#include -#include -#include -#include - -// #include "config.hpp" - -// #include "exceptions.hpp" - -// #include "node.hpp" - -// #include "template.hpp" - -// #include "utils.hpp" - - -namespace inja { - -/*! - * \brief Class for rendering a Template with data. - */ -class Renderer : public NodeVisitor { - using Op = FunctionStorage::Operation; - - const RenderConfig config; - const TemplateStorage& template_storage; - const FunctionStorage& function_storage; - - const Template* current_template; - size_t current_level {0}; - std::vector template_stack; - std::vector block_statement_stack; - - const json* data_input; - std::ostream* output_stream; - - json additional_data; - json* current_loop_data = &additional_data["loop"]; - - std::vector> data_tmp_stack; - std::stack data_eval_stack; - std::stack not_found_stack; - - bool break_rendering {false}; - - static bool truthy(const json* data) { - if (data->is_boolean()) { - return data->get(); - } else if (data->is_number()) { - return (*data != 0); - } else if (data->is_null()) { - return false; - } - return !data->empty(); - } - - void print_data(const std::shared_ptr value) { - if (value->is_string()) { - *output_stream << value->get_ref(); - } else if (value->is_number_integer()) { - *output_stream << value->get(); - } else if (value->is_null()) { - } else { - *output_stream << value->dump(); - } - } - - const std::shared_ptr eval_expression_list(const ExpressionListNode& expression_list) { - if (!expression_list.root) { - throw_renderer_error("empty expression", expression_list); - } - - expression_list.root->accept(*this); - - if (data_eval_stack.empty()) { - throw_renderer_error("empty expression", expression_list); - } else if (data_eval_stack.size() != 1) { - throw_renderer_error("malformed expression", expression_list); - } - - const auto result = data_eval_stack.top(); - data_eval_stack.pop(); - - if (!result) { - if (not_found_stack.empty()) { - throw_renderer_error("expression could not be evaluated", expression_list); - } - - auto node = not_found_stack.top(); - not_found_stack.pop(); - - throw_renderer_error("variable '" + static_cast(node->name) + "' not found", *node); - } - return std::make_shared(*result); - } - - void throw_renderer_error(const std::string& message, const AstNode& node) { - SourceLocation loc = get_source_location(current_template->content, node.pos); - INJA_THROW(RenderError(message, loc)); - } - - void make_result(const json&& result) { - auto result_ptr = std::make_shared(result); - data_tmp_stack.push_back(result_ptr); - data_eval_stack.push(result_ptr.get()); - } - - template std::array get_arguments(const FunctionNode& node) { - if (node.arguments.size() < N_start + N) { - throw_renderer_error("function needs " + std::to_string(N_start + N) + " variables, but has only found " + std::to_string(node.arguments.size()), node); - } - - for (size_t i = N_start; i < N_start + N; i += 1) { - node.arguments[i]->accept(*this); - } - - if (data_eval_stack.size() < N) { - throw_renderer_error("function needs " + std::to_string(N) + " variables, but has only found " + std::to_string(data_eval_stack.size()), node); - } - - std::array result; - for (size_t i = 0; i < N; i += 1) { - result[N - i - 1] = data_eval_stack.top(); - data_eval_stack.pop(); - - if (!result[N - i - 1]) { - const auto data_node = not_found_stack.top(); - not_found_stack.pop(); - - if (throw_not_found) { - throw_renderer_error("variable '" + static_cast(data_node->name) + "' not found", *data_node); - } - } - } - return result; - } - - template Arguments get_argument_vector(const FunctionNode& node) { - const size_t N = node.arguments.size(); - for (auto a : node.arguments) { - a->accept(*this); - } - - if (data_eval_stack.size() < N) { - throw_renderer_error("function needs " + std::to_string(N) + " variables, but has only found " + std::to_string(data_eval_stack.size()), node); - } - - Arguments result {N}; - for (size_t i = 0; i < N; i += 1) { - result[N - i - 1] = data_eval_stack.top(); - data_eval_stack.pop(); - - if (!result[N - i - 1]) { - const auto data_node = not_found_stack.top(); - not_found_stack.pop(); - - if (throw_not_found) { - throw_renderer_error("variable '" + static_cast(data_node->name) + "' not found", *data_node); - } - } - } - return result; - } - - void visit(const BlockNode& node) { - for (auto& n : node.nodes) { - n->accept(*this); - - if (break_rendering) { - break; - } - } - } - - void visit(const TextNode& node) { - output_stream->write(current_template->content.c_str() + node.pos, node.length); - } - - void visit(const ExpressionNode&) {} - - void visit(const LiteralNode& node) { - data_eval_stack.push(&node.value); - } - - void visit(const DataNode& node) { - if (additional_data.contains(node.ptr)) { - data_eval_stack.push(&(additional_data[node.ptr])); - } else if (data_input->contains(node.ptr)) { - data_eval_stack.push(&(*data_input)[node.ptr]); - } else { - // Try to evaluate as a no-argument callback - const auto function_data = function_storage.find_function(node.name, 0); - if (function_data.operation == FunctionStorage::Operation::Callback) { - Arguments empty_args {}; - const auto value = std::make_shared(function_data.callback(empty_args)); - data_tmp_stack.push_back(value); - data_eval_stack.push(value.get()); - } else { - data_eval_stack.push(nullptr); - not_found_stack.emplace(&node); - } - } - } - - void visit(const FunctionNode& node) { - switch (node.operation) { - case Op::Not: { - const auto args = get_arguments<1>(node); - make_result(!truthy(args[0])); - } break; - case Op::And: { - make_result(truthy(get_arguments<1, 0>(node)[0]) && truthy(get_arguments<1, 1>(node)[0])); - } break; - case Op::Or: { - make_result(truthy(get_arguments<1, 0>(node)[0]) || truthy(get_arguments<1, 1>(node)[0])); - } break; - case Op::In: { - const auto args = get_arguments<2>(node); - make_result(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end()); - } break; - case Op::Equal: { - const auto args = get_arguments<2>(node); - make_result(*args[0] == *args[1]); - } break; - case Op::NotEqual: { - const auto args = get_arguments<2>(node); - make_result(*args[0] != *args[1]); - } break; - case Op::Greater: { - const auto args = get_arguments<2>(node); - make_result(*args[0] > *args[1]); - } break; - case Op::GreaterEqual: { - const auto args = get_arguments<2>(node); - make_result(*args[0] >= *args[1]); - } break; - case Op::Less: { - const auto args = get_arguments<2>(node); - make_result(*args[0] < *args[1]); - } break; - case Op::LessEqual: { - const auto args = get_arguments<2>(node); - make_result(*args[0] <= *args[1]); - } break; - case Op::Add: { - const auto args = get_arguments<2>(node); - if (args[0]->is_string() && args[1]->is_string()) { - make_result(args[0]->get_ref() + args[1]->get_ref()); - } else if (args[0]->is_number_integer() && args[1]->is_number_integer()) { - make_result(args[0]->get() + args[1]->get()); - } else { - make_result(args[0]->get() + args[1]->get()); - } - } break; - case Op::Subtract: { - const auto args = get_arguments<2>(node); - if (args[0]->is_number_integer() && args[1]->is_number_integer()) { - make_result(args[0]->get() - args[1]->get()); - } else { - make_result(args[0]->get() - args[1]->get()); - } - } break; - case Op::Multiplication: { - const auto args = get_arguments<2>(node); - if (args[0]->is_number_integer() && args[1]->is_number_integer()) { - make_result(args[0]->get() * args[1]->get()); - } else { - make_result(args[0]->get() * args[1]->get()); - } - } break; - case Op::Division: { - const auto args = get_arguments<2>(node); - if (args[1]->get() == 0) { - throw_renderer_error("division by zero", node); - } - make_result(args[0]->get() / args[1]->get()); - } break; - case Op::Power: { - const auto args = get_arguments<2>(node); - if (args[0]->is_number_integer() && args[1]->get() >= 0) { - int result = static_cast(std::pow(args[0]->get(), args[1]->get())); - make_result(result); - } else { - double result = std::pow(args[0]->get(), args[1]->get()); - make_result(result); - } - } break; - case Op::Modulo: { - const auto args = get_arguments<2>(node); - make_result(args[0]->get() % args[1]->get()); - } break; - case Op::AtId: { - const auto container = get_arguments<1, 0, false>(node)[0]; - node.arguments[1]->accept(*this); - if (not_found_stack.empty()) { - throw_renderer_error("could not find element with given name", node); - } - const auto id_node = not_found_stack.top(); - not_found_stack.pop(); - data_eval_stack.pop(); - data_eval_stack.push(&container->at(id_node->name)); - } break; - case Op::At: { - const auto args = get_arguments<2>(node); - if (args[0]->is_object()) { - data_eval_stack.push(&args[0]->at(args[1]->get())); - } else { - data_eval_stack.push(&args[0]->at(args[1]->get())); - } - } break; - case Op::Default: { - const auto test_arg = get_arguments<1, 0, false>(node)[0]; - data_eval_stack.push(test_arg ? test_arg : get_arguments<1, 1>(node)[0]); - } break; - case Op::DivisibleBy: { - const auto args = get_arguments<2>(node); - const int divisor = args[1]->get(); - make_result((divisor != 0) && (args[0]->get() % divisor == 0)); - } break; - case Op::Even: { - make_result(get_arguments<1>(node)[0]->get() % 2 == 0); - } break; - case Op::Exists: { - auto&& name = get_arguments<1>(node)[0]->get_ref(); - make_result(data_input->contains(json::json_pointer(DataNode::convert_dot_to_ptr(name)))); - } break; - case Op::ExistsInObject: { - const auto args = get_arguments<2>(node); - auto&& name = args[1]->get_ref(); - make_result(args[0]->find(name) != args[0]->end()); - } break; - case Op::First: { - const auto result = &get_arguments<1>(node)[0]->front(); - data_eval_stack.push(result); - } break; - case Op::Float: { - make_result(std::stod(get_arguments<1>(node)[0]->get_ref())); - } break; - case Op::Int: { - make_result(std::stoi(get_arguments<1>(node)[0]->get_ref())); - } break; - case Op::Last: { - const auto result = &get_arguments<1>(node)[0]->back(); - data_eval_stack.push(result); - } break; - case Op::Length: { - const auto val = get_arguments<1>(node)[0]; - if (val->is_string()) { - make_result(val->get_ref().length()); - } else { - make_result(val->size()); - } - } break; - case Op::Lower: { - std::string result = get_arguments<1>(node)[0]->get(); - std::transform(result.begin(), result.end(), result.begin(), ::tolower); - make_result(std::move(result)); - } break; - case Op::Max: { - const auto args = get_arguments<1>(node); - const auto result = std::max_element(args[0]->begin(), args[0]->end()); - data_eval_stack.push(&(*result)); - } break; - case Op::Min: { - const auto args = get_arguments<1>(node); - const auto result = std::min_element(args[0]->begin(), args[0]->end()); - data_eval_stack.push(&(*result)); - } break; - case Op::Odd: { - make_result(get_arguments<1>(node)[0]->get() % 2 != 0); - } break; - case Op::Range: { - std::vector result(get_arguments<1>(node)[0]->get()); - std::iota(result.begin(), result.end(), 0); - make_result(std::move(result)); - } break; - case Op::Round: { - const auto args = get_arguments<2>(node); - const int precision = args[1]->get(); - const double result = std::round(args[0]->get() * std::pow(10.0, precision)) / std::pow(10.0, precision); - if (precision == 0) { - make_result(int(result)); - } else { - make_result(result); - } - } break; - case Op::Sort: { - auto result_ptr = std::make_shared(get_arguments<1>(node)[0]->get>()); - std::sort(result_ptr->begin(), result_ptr->end()); - data_tmp_stack.push_back(result_ptr); - data_eval_stack.push(result_ptr.get()); - } break; - case Op::Upper: { - std::string result = get_arguments<1>(node)[0]->get(); - std::transform(result.begin(), result.end(), result.begin(), ::toupper); - make_result(std::move(result)); - } break; - case Op::IsBoolean: { - make_result(get_arguments<1>(node)[0]->is_boolean()); - } break; - case Op::IsNumber: { - make_result(get_arguments<1>(node)[0]->is_number()); - } break; - case Op::IsInteger: { - make_result(get_arguments<1>(node)[0]->is_number_integer()); - } break; - case Op::IsFloat: { - make_result(get_arguments<1>(node)[0]->is_number_float()); - } break; - case Op::IsObject: { - make_result(get_arguments<1>(node)[0]->is_object()); - } break; - case Op::IsArray: { - make_result(get_arguments<1>(node)[0]->is_array()); - } break; - case Op::IsString: { - make_result(get_arguments<1>(node)[0]->is_string()); - } break; - case Op::Callback: { - auto args = get_argument_vector(node); - make_result(node.callback(args)); - } break; - case Op::Super: { - const auto args = get_argument_vector(node); - const size_t old_level = current_level; - const size_t level_diff = (args.size() == 1) ? args[0]->get() : 1; - const size_t level = current_level + level_diff; - - if (block_statement_stack.empty()) { - throw_renderer_error("super() call is not within a block", node); - } - - if (level < 1 || level > template_stack.size() - 1) { - throw_renderer_error("level of super() call does not match parent templates (between 1 and " + std::to_string(template_stack.size() - 1) + ")", node); - } - - const auto current_block_statement = block_statement_stack.back(); - const Template* new_template = template_stack.at(level); - const Template* old_template = current_template; - const auto block_it = new_template->block_storage.find(current_block_statement->name); - if (block_it != new_template->block_storage.end()) { - current_template = new_template; - current_level = level; - block_it->second->block.accept(*this); - current_level = old_level; - current_template = old_template; - } else { - throw_renderer_error("could not find block with name '" + current_block_statement->name + "'", node); - } - make_result(nullptr); - } break; - case Op::Join: { - const auto args = get_arguments<2>(node); - const auto separator = args[1]->get(); - std::ostringstream os; - std::string sep; - for (const auto& value : *args[0]) { - os << sep; - if (value.is_string()) { - os << value.get(); // otherwise the value is surrounded with "" - } else { - os << value.dump(); - } - sep = separator; - } - make_result(os.str()); - } break; - case Op::ParenLeft: - case Op::ParenRight: - case Op::None: - break; - } - } - - void visit(const ExpressionListNode& node) { - print_data(eval_expression_list(node)); - } - - void visit(const StatementNode&) {} - - void visit(const ForStatementNode&) {} - - void visit(const ForArrayStatementNode& node) { - const auto result = eval_expression_list(node.condition); - if (!result->is_array()) { - throw_renderer_error("object must be an array", node); - } - - if (!current_loop_data->empty()) { - auto tmp = *current_loop_data; // Because of clang-3 - (*current_loop_data)["parent"] = std::move(tmp); - } - - size_t index = 0; - (*current_loop_data)["is_first"] = true; - (*current_loop_data)["is_last"] = (result->size() <= 1); - for (auto it = result->begin(); it != result->end(); ++it) { - additional_data[static_cast(node.value)] = *it; - - (*current_loop_data)["index"] = index; - (*current_loop_data)["index1"] = index + 1; - if (index == 1) { - (*current_loop_data)["is_first"] = false; - } - if (index == result->size() - 1) { - (*current_loop_data)["is_last"] = true; - } - - node.body.accept(*this); - ++index; - } - - additional_data[static_cast(node.value)].clear(); - if (!(*current_loop_data)["parent"].empty()) { - const auto tmp = (*current_loop_data)["parent"]; - *current_loop_data = std::move(tmp); - } else { - current_loop_data = &additional_data["loop"]; - } - } - - void visit(const ForObjectStatementNode& node) { - const auto result = eval_expression_list(node.condition); - if (!result->is_object()) { - throw_renderer_error("object must be an object", node); - } - - if (!current_loop_data->empty()) { - (*current_loop_data)["parent"] = std::move(*current_loop_data); - } - - size_t index = 0; - (*current_loop_data)["is_first"] = true; - (*current_loop_data)["is_last"] = (result->size() <= 1); - for (auto it = result->begin(); it != result->end(); ++it) { - additional_data[static_cast(node.key)] = it.key(); - additional_data[static_cast(node.value)] = it.value(); - - (*current_loop_data)["index"] = index; - (*current_loop_data)["index1"] = index + 1; - if (index == 1) { - (*current_loop_data)["is_first"] = false; - } - if (index == result->size() - 1) { - (*current_loop_data)["is_last"] = true; - } - - node.body.accept(*this); - ++index; - } - - additional_data[static_cast(node.key)].clear(); - additional_data[static_cast(node.value)].clear(); - if (!(*current_loop_data)["parent"].empty()) { - *current_loop_data = std::move((*current_loop_data)["parent"]); - } else { - current_loop_data = &additional_data["loop"]; - } - } - - void visit(const IfStatementNode& node) { - const auto result = eval_expression_list(node.condition); - if (truthy(result.get())) { - node.true_statement.accept(*this); - } else if (node.has_false_statement) { - node.false_statement.accept(*this); - } - } - - void visit(const IncludeStatementNode& node) { - auto sub_renderer = Renderer(config, template_storage, function_storage); - const auto included_template_it = template_storage.find(node.file); - if (included_template_it != template_storage.end()) { - sub_renderer.render_to(*output_stream, included_template_it->second, *data_input, &additional_data); - } else if (config.throw_at_missing_includes) { - throw_renderer_error("include '" + node.file + "' not found", node); - } - } - - void visit(const ExtendsStatementNode& node) { - const auto included_template_it = template_storage.find(node.file); - if (included_template_it != template_storage.end()) { - const Template* parent_template = &included_template_it->second; - render_to(*output_stream, *parent_template, *data_input, &additional_data); - break_rendering = true; - } else if (config.throw_at_missing_includes) { - throw_renderer_error("extends '" + node.file + "' not found", node); - } - } - - void visit(const BlockStatementNode& node) { - const size_t old_level = current_level; - current_level = 0; - current_template = template_stack.front(); - const auto block_it = current_template->block_storage.find(node.name); - if (block_it != current_template->block_storage.end()) { - block_statement_stack.emplace_back(&node); - block_it->second->block.accept(*this); - block_statement_stack.pop_back(); - } - current_level = old_level; - current_template = template_stack.back(); - } - - void visit(const SetStatementNode& node) { - std::string ptr = node.key; - replace_substring(ptr, ".", "/"); - ptr = "/" + ptr; - additional_data[json::json_pointer(ptr)] = *eval_expression_list(node.expression); - } - -public: - Renderer(const RenderConfig& config, const TemplateStorage& template_storage, const FunctionStorage& function_storage) - : config(config), template_storage(template_storage), function_storage(function_storage) {} - - void render_to(std::ostream& os, const Template& tmpl, const json& data, json* loop_data = nullptr) { - output_stream = &os; - current_template = &tmpl; - data_input = &data; - if (loop_data) { - additional_data = *loop_data; - current_loop_data = &additional_data["loop"]; - } - - template_stack.emplace_back(current_template); - current_template->root.accept(*this); - - data_tmp_stack.clear(); - } -}; - -} // namespace inja - -#endif // INCLUDE_INJA_RENDERER_HPP_ - -// #include "template.hpp" - -// #include "utils.hpp" - - -namespace inja { - -/*! - * \brief Class for changing the configuration. - */ -class Environment { - std::string input_path; - std::string output_path; - - LexerConfig lexer_config; - ParserConfig parser_config; - RenderConfig render_config; - - FunctionStorage function_storage; - TemplateStorage template_storage; - -public: - Environment(): Environment("") {} - - explicit Environment(const std::string& global_path): input_path(global_path), output_path(global_path) {} - - Environment(const std::string& input_path, const std::string& output_path): input_path(input_path), output_path(output_path) {} - - /// Sets the opener and closer for template statements - void set_statement(const std::string& open, const std::string& close) { - lexer_config.statement_open = open; - lexer_config.statement_open_no_lstrip = open + "+"; - lexer_config.statement_open_force_lstrip = open + "-"; - lexer_config.statement_close = close; - lexer_config.statement_close_force_rstrip = "-" + close; - lexer_config.update_open_chars(); - } - - /// Sets the opener for template line statements - void set_line_statement(const std::string& open) { - lexer_config.line_statement = open; - lexer_config.update_open_chars(); - } - - /// Sets the opener and closer for template expressions - void set_expression(const std::string& open, const std::string& close) { - lexer_config.expression_open = open; - lexer_config.expression_open_force_lstrip = open + "-"; - lexer_config.expression_close = close; - lexer_config.expression_close_force_rstrip = "-" + close; - lexer_config.update_open_chars(); - } - - /// Sets the opener and closer for template comments - void set_comment(const std::string& open, const std::string& close) { - lexer_config.comment_open = open; - lexer_config.comment_open_force_lstrip = open + "-"; - lexer_config.comment_close = close; - lexer_config.comment_close_force_rstrip = "-" + close; - lexer_config.update_open_chars(); - } - - /// Sets whether to remove the first newline after a block - void set_trim_blocks(bool trim_blocks) { - lexer_config.trim_blocks = trim_blocks; - } - - /// Sets whether to strip the spaces and tabs from the start of a line to a block - void set_lstrip_blocks(bool lstrip_blocks) { - lexer_config.lstrip_blocks = lstrip_blocks; - } - - /// Sets the element notation syntax - void set_search_included_templates_in_files(bool search_in_files) { - parser_config.search_included_templates_in_files = search_in_files; - } - - /// Sets whether a missing include will throw an error - void set_throw_at_missing_includes(bool will_throw) { - render_config.throw_at_missing_includes = will_throw; - } - - Template parse(std::string_view input) { - Parser parser(parser_config, lexer_config, template_storage, function_storage); - return parser.parse(input); - } - - Template parse_template(const std::string& filename) { - Parser parser(parser_config, lexer_config, template_storage, function_storage); - auto result = Template(parser.load_file(input_path + static_cast(filename))); - parser.parse_into_template(result, input_path + static_cast(filename)); - return result; - } - - Template parse_file(const std::string& filename) { - return parse_template(filename); - } - - std::string render(std::string_view input, const json& data) { - return render(parse(input), data); - } - - std::string render(const Template& tmpl, const json& data) { - std::stringstream os; - render_to(os, tmpl, data); - return os.str(); - } - - std::string render_file(const std::string& filename, const json& data) { - return render(parse_template(filename), data); - } - - std::string render_file_with_json_file(const std::string& filename, const std::string& filename_data) { - const json data = load_json(filename_data); - return render_file(filename, data); - } - - void write(const std::string& filename, const json& data, const std::string& filename_out) { - std::ofstream file(output_path + filename_out); - file << render_file(filename, data); - file.close(); - } - - void write(const Template& temp, const json& data, const std::string& filename_out) { - std::ofstream file(output_path + filename_out); - file << render(temp, data); - file.close(); - } - - void write_with_json_file(const std::string& filename, const std::string& filename_data, const std::string& filename_out) { - const json data = load_json(filename_data); - write(filename, data, filename_out); - } - - void write_with_json_file(const Template& temp, const std::string& filename_data, const std::string& filename_out) { - const json data = load_json(filename_data); - write(temp, data, filename_out); - } - - std::ostream& render_to(std::ostream& os, const Template& tmpl, const json& data) { - Renderer(render_config, template_storage, function_storage).render_to(os, tmpl, data); - return os; - } - - std::string load_file(const std::string& filename) { - Parser parser(parser_config, lexer_config, template_storage, function_storage); - return parser.load_file(input_path + filename); - } - - json load_json(const std::string& filename) { - std::ifstream file; - file.open(input_path + filename); - if (file.fail()) { - INJA_THROW(FileError("failed accessing file at '" + input_path + filename + "'")); - } - - return json::parse(std::istreambuf_iterator(file), std::istreambuf_iterator()); - } - - /*! - @brief Adds a variadic callback - */ - void add_callback(const std::string& name, const CallbackFunction& callback) { - add_callback(name, -1, callback); - } - - /*! - @brief Adds a variadic void callback - */ - void add_void_callback(const std::string& name, const VoidCallbackFunction& callback) { - add_void_callback(name, -1, callback); - } - - /*! - @brief Adds a callback with given number or arguments - */ - void add_callback(const std::string& name, int num_args, const CallbackFunction& callback) { - function_storage.add_callback(name, num_args, callback); - } - - /*! - @brief Adds a void callback with given number or arguments - */ - void add_void_callback(const std::string& name, int num_args, const VoidCallbackFunction& callback) { - function_storage.add_callback(name, num_args, [callback](Arguments& args) { - callback(args); - return json(); - }); - } - - /** Includes a template with a given name into the environment. - * Then, a template can be rendered in another template using the - * include "" syntax. - */ - void include_template(const std::string& name, const Template& tmpl) { - template_storage[name] = tmpl; - } - - /*! - @brief Sets a function that is called when an included file is not found - */ - void set_include_callback(const std::function& callback) { - parser_config.include_callback = callback; - } -}; - -/*! -@brief render with default settings to a string -*/ -inline std::string render(std::string_view input, const json& data) { - return Environment().render(input, data); -} - -/*! -@brief render with default settings to the given output stream -*/ -inline void render_to(std::ostream& os, std::string_view input, const json& data) { - Environment env; - env.render_to(os, env.parse(input), data); -} - -} // namespace inja - -#endif // INCLUDE_INJA_ENVIRONMENT_HPP_ - -// #include "exceptions.hpp" - -// #include "parser.hpp" - -// #include "renderer.hpp" - -// #include "template.hpp" - - -#endif // INCLUDE_INJA_INJA_HPP_ diff --git a/pkg/asustor/zerotier/CONTROL/pre-install.sh b/ext/installfiles/linux/DEBIAN/conffiles old mode 100755 new mode 100644 similarity index 100% rename from pkg/asustor/zerotier/CONTROL/pre-install.sh rename to ext/installfiles/linux/DEBIAN/conffiles diff --git a/ext/installfiles/linux/DEBIAN/control.in b/ext/installfiles/linux/DEBIAN/control.in new file mode 100644 index 000000000..d1b5a8c16 --- /dev/null +++ b/ext/installfiles/linux/DEBIAN/control.in @@ -0,0 +1,12 @@ +Package: zerotier-one +Architecture: __ARCH__ +Maintainer: ZeroTier, Inc. +Priority: optional +Version: __VERSION__ +Installed-Size: 1024 +Homepage: https://github.com/zerotier/ZeroTierOne +Description: ZeroTier One network virtualization service + ZeroTier One is a fast, secure, and easy to use peer to peer network + virtualization engine that provides global-scale software defined + networking to any device or application. Visit https://www.zerotier.com/ + for more information. diff --git a/ext/installfiles/linux/RPM/README.md b/ext/installfiles/linux/RPM/README.md new file mode 100644 index 000000000..21ad0a1b9 --- /dev/null +++ b/ext/installfiles/linux/RPM/README.md @@ -0,0 +1,24 @@ +This folder contains two spec files which enable building of various RPM packages for ZeroTier. + +#zerotier-one.spec.in +This file contains the information to build an RPM from the bash based binary installer of ZeroTier. The resulting RPM cannot be recompiled to different architectures. + +#zerotier.spec +This spec file is a “standard” RPM spec file. It fits to the common rpmbuild process, SRPM and differnt architectures are supported too. The spec file can be used to build two packages: the standard zerotier and the zerotier-controller. It supports some of the build options exposed in the original Linux makefile: + +> `rpmbuild -ba zerotier.spec` #builds the standard zerotier package, this is what you need in most of the cases + +> `rpmbuild -ba zerotier.spec --with controller` #builds the zerotier-controller package + +> `rpmbuild -ba zerotier.spec --with debug` #builds the zerotier package with debug enable<>d + +> `rpmbuild -ba zerotier.spec --with miniupnpc` #builds the zerotier package with miniupnpc enabled + +> `rpmbuild -ba zerotier.spec --with cluster` #builds the zerotier package with cluster enabled + + +####Build environment preparation +As zerotier is not distributed in tar.gz format at the moment, the %prep section of the spec file takes care about the prepartion of an rpmbuild compatible tar.gz. + + + diff --git a/ext/installfiles/linux/RPM/zerotier-one.spec.in b/ext/installfiles/linux/RPM/zerotier-one.spec.in new file mode 100644 index 000000000..1ec3d42a3 --- /dev/null +++ b/ext/installfiles/linux/RPM/zerotier-one.spec.in @@ -0,0 +1,34 @@ +Name: zerotier-one +Summary: ZeroTier One network virtualization service +Version: __VERSION__ +Release: 1%{?dist} +License: GPLv3 +URL: https://www.zerotier.com/ + +%description +ZeroTier One creates virtual Ethernet networks that work anywhere and everywhere. +Visit https://www.zerotier.com/ for more information. + +%prep +mkdir -p $RPM_BUILD_ROOT/var/lib/zerotier-one/updates.d +cp -f $OLDPWD/__INSTALLER__ $RPM_BUILD_ROOT/var/lib/zerotier-one/updates.d + +%pre +mkdir -p /var/lib/zerotier-one/updates.d + +%files +/var/lib/zerotier-one/updates.d/__INSTALLER__ + +%post +chmod 0755 /var/lib/zerotier-one/updates.d/__INSTALLER__ +/var/lib/zerotier-one/updates.d/__INSTALLER__ >>/dev/null 2>&1 + +%preun +if [ "$1" -lt 1 ]; then + /var/lib/zerotier-one/uninstall.sh >>/dev/null 2>&1 +fi + +%clean +cp -f %{_rpmdir}/%{_arch}/%{name}-%{version}-%{release}.%{_arch}.rpm $OLDPWD +rm -f %{_rpmdir}/%{_arch}/%{name}-%{version}-%{release}.%{_arch}.rpm +rm -rf $RPM_BUILD_ROOT diff --git a/ext/installfiles/linux/RPM/zerotier.spec b/ext/installfiles/linux/RPM/zerotier.spec new file mode 100755 index 000000000..41230f0e3 --- /dev/null +++ b/ext/installfiles/linux/RPM/zerotier.spec @@ -0,0 +1,194 @@ +# add --with controller option to build controller (builds zerotier-controller package) +%bcond_with controller +# add --with miniupnpc option to enable the miniupnpc option during build +%bcond_with miniupnpc +# add --with cluster option to enable the cluster option during build +%bcond_with cluster +# add --with debug option to enable the debug option during build +%bcond_with debug +%if %{with controller} +Name:zerotier-controller +Conflicts:zerotier +%else +Name:zerotier +Conflicts:zerotier-controller +%endif +Version: 1.1.4 +Release: 1 +Summary: Network Virtualization Everywhere https://www.zerotier.com/ +Group: network +License: GPLv3 +BuildRoot: %{_tmppath}/%{name}-root +Provides: zerotier-one +Source0: http:///download/%{name}-%{version}.tar.gz +BuildRequires: gcc-c++ +BuildRequires: make +BuildRequires: gcc +%if %{with server} +BuildRequires: sqlite-devel +BuildRequires: wget +BuildRequires: unzip +Requires: sqlite +%endif +%description +ZeroTier One creates virtual Ethernet networks that work anywhere and everywhere. +Visit https://www.zerotier.com/ for more information. + +%prep +cd `mktemp -d` +wget -O master.zip https://github.com/zerotier/ZeroTierOne/archive/master.zip +unzip master.zip +mv ZeroTierOne-master zerotier-1.1.4 +ln -s zerotier-1.1.4 zerotier-controller-1.1.4 +tar zcvf zerotier-1.1.4.tar.gz zerotier-1.1.4 zerotier-controller-1.1.4 +ln -s zerotier-1.1.4.tar.gz zerotier-controller-1.1.4.tar.gz +mv zero*.tar.gz ~/rpmbuild/SOURCES +cd - +%setup -q + +%build +%if %{with miniupnpc} +ZT_USE_MINIUPNPC=1; export ZT_USE_MINIUPNPC; +%endif + +%if %{with controller} +ZT_ENABLE_NETWORK_CONTROLLER=1; export ZT_ENABLE_NETWORK_CONTROLLER; +%endif + +%if %{with cluster} +export ZT_ENABLE_CLUSTER=1 +%endif + +%if %{with debug} +export ZT_DEBUG=1 +%endif + +make + +%install + + +rm -rf $RPM_BUILD_ROOT +rm -f $RPM_BUILD_ROOT%{_prefix}/bin/zerotier-idtool $RPM_BUILD_ROOT%{_prefix}/bin/zerotier-idtool +echo 'Install...' +mkdir -p $RPM_BUILD_ROOT%{_vardir}/lib/zerotier-one/initfiles/{init.d,systemd} +install -m 0755 -D zerotier-one -t $RPM_BUILD_ROOT%{_vardir}/lib/zerotier-one/ +install -m 0755 -D ext/installfiles/linux/init.d/* -t $RPM_BUILD_ROOT%{_vardir}/lib/zerotier-one/initfiles/init.d/ +install -m 0755 -D ext/installfiles/linux/systemd/* -t $RPM_BUILD_ROOT%{_vardir}/lib/zerotier-one/initfiles/systemd/ + + + +%posttrans +echo -n 'Getting version of new install... ' +newVersion=`/var/lib/zerotier-one/zerotier-one -v` +echo $newVersion + +echo 'Creating symlinks...' + +rm -f /usr/bin/zerotier-cli /usr/bin/zerotier-idtool +ln -sf /var/lib/zerotier-one/zerotier-one /usr/bin/zerotier-cli +ln -sf /var/lib/zerotier-one/zerotier-one /usr/bin/zerotier-idtool +echo 'Installing zerotier-one service...' + +SYSTEMDUNITDIR= +if [ -e /bin/systemctl -o -e /usr/bin/systemctl -o -e /usr/local/bin/systemctl -o -e /sbin/systemctl -o -e /usr/sbin/systemctl ]; then + # Second check: test if systemd appears to actually be running. Apparently Ubuntu + # thought it was a good idea to ship with systemd installed but not used. Issue #133 + if [ -d /var/run/systemd/system -o -d /run/systemd/system ]; then + if [ -e /usr/bin/pkg-config ]; then + SYSTEMDUNITDIR=`/usr/bin/pkg-config systemd --variable=systemdsystemunitdir` + fi + if [ -z "$SYSTEMDUNITDIR" -o ! -d "$SYSTEMDUNITDIR" ]; then + if [ -d /usr/lib/systemd/system ]; then + SYSTEMDUNITDIR=/usr/lib/systemd/system + fi + if [ -d /etc/systemd/system ]; then + SYSTEMDUNITDIR=/etc/systemd/system + fi + fi + fi +fi + +if [ -n "$SYSTEMDUNITDIR" -a -d "$SYSTEMDUNITDIR" ]; then + # SYSTEMD + + # If this was updated or upgraded from an init.d based system, clean up the old + # init.d stuff before installing directly via systemd. + if [ -f /etc/init.d/zerotier-one ]; then + if [ -e /sbin/chkconfig -o -e /usr/sbin/chkconfig -o -e /bin/chkconfig -o -e /usr/bin/chkconfig ]; then + chkconfig zerotier-one off + fi + rm -f /etc/init.d/zerotier-one + fi + + cp -f /var/lib/zerotier-one/initfiles/systemd/zerotier-one.service "$SYSTEMDUNITDIR/zerotier-one.service" + chown 0 "$SYSTEMDUNITDIR/zerotier-one.service" + chgrp 0 "$SYSTEMDUNITDIR/zerotier-one.service" + chmod 0755 "$SYSTEMDUNITDIR/zerotier-one.service" + + systemctl enable zerotier-one.service + + echo + echo 'Done! Installed and service configured to start at system boot.' + echo + echo "To start now or restart the service if it's already running:" + echo ' sudo systemctl restart zerotier-one.service' +else + # SYSV INIT -- also covers upstart which supports SysVinit backward compatibility + + cp -f /var/lib/zerotier-one/initfiles/init.d/zerotier-one /etc/init.d/zerotier-one + chmod 0755 /etc/init.d/zerotier-one + + if [ -f /sbin/chkconfig -o -f /usr/sbin/chkconfig -o -f /usr/bin/chkconfig -o -f /bin/chkconfig ]; then + chkconfig zerotier-one on + else + # Yes Virginia, some systems lack chkconfig. + if [ -d /etc/rc0.d ]; then + rm -f /etc/rc0.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc0.d/K89zerotier-one + fi + if [ -d /etc/rc1.d ]; then + rm -f /etc/rc1.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc1.d/K89zerotier-one + fi + if [ -d /etc/rc2.d ]; then + rm -f /etc/rc2.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc2.d/S11zerotier-one + fi + if [ -d /etc/rc3.d ]; then + rm -f /etc/rc3.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc3.d/S11zerotier-one + fi + if [ -d /etc/rc4.d ]; then + rm -f /etc/rc4.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc4.d/S11zerotier-one + fi + if [ -d /etc/rc5.d ]; then + rm -f /etc/rc5.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc5.d/S11zerotier-one + fi + if [ -d /etc/rc6.d ]; then + rm -f /etc/rc6.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc6.d/K89zerotier-one + fi + fi + echo + echo 'Done! Installed and service configured to start at system boot.' + echo + echo "To start now or restart the service if it's already running:" + echo ' sudo service zerotier-one restart' +fi +%preun +/sbin/chkconfig --del zerotier-one +rm -f /usr/bin/zerotier-cli /usr/bin/zerotier-idtool + +%clean +rm -rf $RPM_BUILD_ROOT +%files +%{_vardir}/lib/zerotier-one/zerotier-one +%{_vardir}/lib/zerotier-one/initfiles/systemd/zerotier-one.service +%{_vardir}/lib/zerotier-one/initfiles/init.d/zerotier-one + +%changelog +* Fri Feb 26 2016 Kristof Imre Szabo 1.1.4-1 +- initial package diff --git a/ext/installfiles/linux/buildinstaller.sh b/ext/installfiles/linux/buildinstaller.sh new file mode 100755 index 000000000..21f2f73ed --- /dev/null +++ b/ext/installfiles/linux/buildinstaller.sh @@ -0,0 +1,134 @@ +#!/bin/bash + +# This script builds the installer for *nix systems. Windows must do everything +# completely differently, as usual. + +export PATH=/bin:/usr/bin:/sbin:/usr/sbin + +if [ ! -f zerotier-one ]; then + echo "Could not find 'zerotier-one' binary, please build before running this script." + exit 2 +fi + +machine=`uname -m` +system=`uname -s` + +vmajor=`cat version.h | grep -F ZEROTIER_ONE_VERSION_MAJOR | cut -d ' ' -f 3` +vminor=`cat version.h | grep -F ZEROTIER_ONE_VERSION_MINOR | cut -d ' ' -f 3` +revision=`cat version.h | grep -F ZEROTIER_ONE_VERSION_REVISION | cut -d ' ' -f 3` + +if [ -z "$vmajor" -o -z "$vminor" -o -z "$revision" ]; then + echo "Unable to extract version info from version.h, aborting installer build." + exit 2 +fi + +rm -rf build-installer +mkdir build-installer + +case "$system" in + + Linux) + # Canonicalize $machine for some architectures... we use x86 + # and x64 for Intel stuff. ARM and others should be fine if + # we ever ship officially for those. + debian_arch=$machine + case "$machine" in + i386|i486|i586|i686) + machine="x86" + debian_arch="i386" + ;; + x86_64|amd64|x64) + machine="x64" + debian_arch="amd64" + ;; + armv6l|arm|armhf|arm7l|armv7l) + machine="armv6l" + debian_arch="armhf" + ;; + esac + + echo "Assembling Linux installer for $machine and version $vmajor.$vminor.$revision" + + mkdir -p 'build-installer/var/lib/zerotier-one/ui' + cp -fp 'ext/installfiles/linux/uninstall.sh' 'build-installer/var/lib/zerotier-one' + cp -fp 'zerotier-one' 'build-installer/var/lib/zerotier-one' + for f in ui/*.html ui/*.js ui/*.css ui/*.jsx ; do + cp -fp "$f" 'build-installer/var/lib/zerotier-one/ui' + done + mkdir -p 'build-installer/tmp' + cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/tmp/init.d_zerotier-one' + cp -fp 'ext/installfiles/linux/systemd/zerotier-one.service' 'build-installer/tmp/systemd_zerotier-one.service' + + targ="ZeroTierOneInstaller-linux-${machine}-${vmajor}_${vminor}_${revision}" + # Use gzip in Linux since some minimal Linux systems do not have bunzip2 + rm -f build-installer-tmp.tar.gz + cd build-installer + tar -cf - * | gzip -9 >../build-installer-tmp.tar.gz + cd .. + rm -f $targ + cat ext/installfiles/linux/install.tmpl.sh build-installer-tmp.tar.gz >$targ + chmod 0755 $targ + rm -f build-installer-tmp.tar.gz + ls -l $targ + + if [ -f /usr/bin/dpkg-deb -a "$UID" -eq 0 ]; then + echo + echo Found dpkg-deb and you are root, trying to build Debian package. + + rm -rf build-installer-deb + + debbase="build-installer-deb/zerotier-one_${vmajor}.${vminor}.${revision}_$debian_arch" + debfolder="${debbase}/DEBIAN" + mkdir -p $debfolder + + cat 'ext/installfiles/linux/DEBIAN/control.in' | sed "s/__VERSION__/${vmajor}.${vminor}.${revision}/" | sed "s/__ARCH__/${debian_arch}/" >$debfolder/control + cat $debfolder/control + cp -f 'ext/installfiles/linux/DEBIAN/conffiles' "${debfolder}/conffiles" + + mkdir -p "${debbase}/var/lib/zerotier-one/updates.d" + cp -f $targ "${debbase}/var/lib/zerotier-one/updates.d" + + rm -f "${debfolder}/postinst" "${debfolder}/prerm" + + echo '#!/bin/bash' >${debfolder}/postinst + echo "/var/lib/zerotier-one/updates.d/${targ} >>/dev/null 2>&1" >>${debfolder}/postinst + echo "/bin/rm -f /var/lib/zerotier-one/updates.d/*" >>${debfolder}/postinst + chmod a+x ${debfolder}/postinst + + echo '#!/bin/bash' >${debfolder}/prerm + echo 'export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin' >>${debfolder}/prerm + echo 'if [ "$1" != "upgrade" ]; then' >>${debfolder}/prerm + echo ' /var/lib/zerotier-one/uninstall.sh >>/dev/null 2>&1' >>${debfolder}/prerm + echo 'fi' >>${debfolder}/prerm + chmod a+x ${debfolder}/prerm + + dpkg-deb --build $debbase + + mv -f build-installer-deb/*.deb . + rm -rf build-installer-deb + fi + + if [ -f /usr/bin/rpmbuild ]; then + echo + echo Found rpmbuild, trying to build RedHat/CentOS package. + + rm -f /tmp/zerotier-one.spec + curr_dir=`pwd` + cat ext/installfiles/linux/RPM/zerotier-one.spec.in | sed "s/__VERSION__/${vmajor}.${vminor}.${revision}/g" | sed "s/__INSTALLER__/${targ}/g" >/tmp/zerotier-one.spec + + rpmbuild -ba /tmp/zerotier-one.spec + + rm -f /tmp/zerotier-one.spec + fi + + ;; + + *) + echo "Unsupported platform: $system" + exit 2 + +esac + +rm -rf build-installer + +exit 0 diff --git a/ext/installfiles/linux/init.d/zerotier-one b/ext/installfiles/linux/init.d/zerotier-one new file mode 100755 index 000000000..b0a8aa418 --- /dev/null +++ b/ext/installfiles/linux/init.d/zerotier-one @@ -0,0 +1,113 @@ +#!/bin/sh +# +# zerotier-one Virtual distributed Ethernet service +# +# chkconfig: 2345 11 89 +# description: ZeroTier One provides public and private distributed ethernet \ +# networks. See https://www.zerotier.com/ for more information. + +### BEGIN INIT INFO +# Provides: zerotier-one +# Required-Start: $local_fs $network +# Required-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start ZeroTier One +# Description: ZeroTier One provides public and private distributed ethernet \ +# networks. See https://www.zerotier.com/ for more information. +### END INIT INFO + +# +# This script is written to avoid distro-specific dependencies, so it does not +# use the rc bash script libraries found on some systems. It should work on +# just about anything. +# + +zthome=/var/lib/zerotier-one + +# Add $zthome to path so we can invoke zerotier-one naked, makes it look +# better in a ps listing. +export PATH=/bin:/usr/bin:/sbin:/usr/sbin:$zthome + +if [ "`id -u`" -ne 0 ]; then + echo "Init script must be called as root." + exit 4 +fi + +if [ ! -f "$zthome/zerotier-one" ]; then + echo "ZeroTier One is not installed in $zthome." + exit 5 +fi + +pid=0 +if [ -f "$zthome/zerotier-one.pid" ]; then + pid=`cat $zthome/zerotier-one.pid` +fi + +running=0 +if [ "$pid" -gt 0 ]; then + exepath=`readlink /proc/$pid/exe 2>/dev/null | grep zerotier-one` + if [ -n "$exepath" ]; then + running=1 + fi +fi + +case "$1" in + start) + if [ $running -gt 0 ]; then + echo "ZeroTier One already running." + exit 0 + fi + echo "Starting ZeroTier One..." + zerotier-one -d + ;; + stop) + if [ $running -gt 0 ]; then + echo "Stopping ZeroTier One..." + kill -TERM $pid + sleep 0.25 + if [ -f "$zthome/zerotier-one.pid" ]; then + sleep 0.5 + fi + if [ -f "$zthome/zerotier-one.pid" ]; then + sleep 1 + fi + if [ -f "$zthome/zerotier-one.pid" ]; then + kill -KILL $pid >>/dev/null 2>&1 + rm -f "$zthome/zerotier-one.pid" + fi + else + echo "ZeroTier One is not running." + fi + ;; + restart|reload|force-reload|condrestart|try-restart) + echo "Restarting ZeroTier One..." + if [ $running -gt 0 ]; then + kill -TERM $pid >>/dev/null 2>&1 + fi + sleep 0.25 + if [ -f "$zthome/zerotier-one.pid" ]; then + sleep 0.5 + fi + if [ -f "$zthome/zerotier-one.pid" ]; then + sleep 1 + fi + if [ -f "$zthome/zerotier-one.pid" ]; then + kill -KILL $pid >>/dev/null 2>&1 + rm -f "$zthome/zerotier-one.pid" + fi + zerotier-one -d + ;; + status) + if [ $running -gt 0 ]; then + exit 0 + else + exit 3 + fi + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac + +exit 0 diff --git a/ext/installfiles/linux/install.tmpl.sh b/ext/installfiles/linux/install.tmpl.sh new file mode 100644 index 000000000..2d18d24ce --- /dev/null +++ b/ext/installfiles/linux/install.tmpl.sh @@ -0,0 +1,182 @@ +#!/bin/bash + +export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin +shopt -s expand_aliases + +dryRun=0 + +echo "*** ZeroTier One install/update ***" +echo + +if [ "$UID" -ne 0 ]; then + echo "Not running as root so doing dry run (no modifications to system)..." + dryRun=1 +fi + +if [ $dryRun -gt 0 ]; then + alias ln="echo '>> ln'" + alias rm="echo '>> rm'" + alias mv="echo '>> mv'" + alias cp="echo '>> cp'" + alias chown="echo '>> chown'" + alias chgrp="echo '>> chgrp'" + alias chmod="echo '>> chmod'" + alias chkconfig="echo '>> chkconfig'" + alias zerotier-cli="echo '>> zerotier-cli'" + alias service="echo '>> service'" + alias systemctl="echo '>> systemctl'" +fi + +scriptPath="`dirname "$0"`/`basename "$0"`" +if [ ! -r "$scriptPath" ]; then + scriptPath="$0" + if [ ! -r "$scriptPath" ]; then + echo "Installer cannot determine its own path; $scriptPath is not readable." + exit 2 + fi +fi + +# Check for systemd vs. old school SysV init +SYSTEMDUNITDIR= +if [ -e /bin/systemctl -o -e /usr/bin/systemctl -o -e /usr/local/bin/systemctl -o -e /sbin/systemctl -o -e /usr/sbin/systemctl ]; then + # Second check: test if systemd appears to actually be running. Apparently Ubuntu + # thought it was a good idea to ship with systemd installed but not used. Issue #133 + if [ -d /var/run/systemd/system -o -d /run/systemd/system ]; then + if [ -e /usr/bin/pkg-config ]; then + SYSTEMDUNITDIR=`/usr/bin/pkg-config systemd --variable=systemdsystemunitdir` + fi + if [ -z "$SYSTEMDUNITDIR" -o ! -d "$SYSTEMDUNITDIR" ]; then + if [ -d /usr/lib/systemd/system ]; then + SYSTEMDUNITDIR=/usr/lib/systemd/system + fi + if [ -d /etc/systemd/system ]; then + SYSTEMDUNITDIR=/etc/systemd/system + fi + fi + fi +fi + +# Find the end of this script, which is where we have appended binary data. +endMarkerIndex=`grep -a -b -E '^################' "$scriptPath" | head -c 16 | cut -d : -f 1` +if [ "$endMarkerIndex" -le 100 ]; then + echo 'Internal error: unable to find end of script / start of binary data marker.' + exit 2 +fi +blobStart=`expr $endMarkerIndex + 17` +if [ "$blobStart" -le "$endMarkerIndex" ]; then + echo 'Internal error: unable to find end of script / start of binary data marker.' + exit 2 +fi + +echo -n 'Getting version of existing install... ' +origVersion=NONE +if [ -x /var/lib/zerotier-one/zerotier-one ]; then + origVersion=`/var/lib/zerotier-one/zerotier-one -v` +fi +echo $origVersion + +echo 'Extracting files...' +if [ $dryRun -gt 0 ]; then + echo ">> tail -c +$blobStart \"$scriptPath\" | gunzip -c | tar -xvop -C / -f -" + tail -c +$blobStart "$scriptPath" | gunzip -c | tar -t -f - | sed 's/^/>> /' +else + tail -c +$blobStart "$scriptPath" | gunzip -c | tar -xvop --no-overwrite-dir -C / -f - +fi + +if [ $dryRun -eq 0 -a ! -x "/var/lib/zerotier-one/zerotier-one" ]; then + echo 'Archive extraction failed, cannot find zerotier-one binary in "/var/lib/zerotier-one".' + exit 2 +fi + +echo -n 'Getting version of new install... ' +newVersion=`/var/lib/zerotier-one/zerotier-one -v` +echo $newVersion + +echo 'Creating symlinks...' + +rm -f /usr/bin/zerotier-cli /usr/bin/zerotier-idtool +ln -sf /var/lib/zerotier-one/zerotier-one /usr/bin/zerotier-cli +ln -sf /var/lib/zerotier-one/zerotier-one /usr/bin/zerotier-idtool + +echo 'Installing zerotier-one service...' + +if [ -n "$SYSTEMDUNITDIR" -a -d "$SYSTEMDUNITDIR" ]; then + # SYSTEMD + + # If this was updated or upgraded from an init.d based system, clean up the old + # init.d stuff before installing directly via systemd. + if [ -f /etc/init.d/zerotier-one ]; then + if [ -e /sbin/chkconfig -o -e /usr/sbin/chkconfig -o -e /bin/chkconfig -o -e /usr/bin/chkconfig ]; then + chkconfig zerotier-one off + fi + rm -f /etc/init.d/zerotier-one + fi + + cp -f /tmp/systemd_zerotier-one.service "$SYSTEMDUNITDIR/zerotier-one.service" + chown 0 "$SYSTEMDUNITDIR/zerotier-one.service" + chgrp 0 "$SYSTEMDUNITDIR/zerotier-one.service" + chmod 0644 "$SYSTEMDUNITDIR/zerotier-one.service" + rm -f /tmp/systemd_zerotier-one.service /tmp/init.d_zerotier-one + + systemctl enable zerotier-one.service + + echo + echo 'Done! Installed and service configured to start at system boot.' + echo + echo "To start now or restart the service if it's already running:" + echo ' sudo systemctl restart zerotier-one.service' +else + # SYSV INIT -- also covers upstart which supports SysVinit backward compatibility + + cp -f /tmp/init.d_zerotier-one /etc/init.d/zerotier-one + chmod 0755 /etc/init.d/zerotier-one + rm -f /tmp/systemd_zerotier-one.service /tmp/init.d_zerotier-one + + if [ -f /sbin/chkconfig -o -f /usr/sbin/chkconfig -o -f /usr/bin/chkconfig -o -f /bin/chkconfig ]; then + chkconfig zerotier-one on + else + # Yes Virginia, some systems lack chkconfig. + if [ -d /etc/rc0.d ]; then + rm -f /etc/rc0.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc0.d/K89zerotier-one + fi + if [ -d /etc/rc1.d ]; then + rm -f /etc/rc1.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc1.d/K89zerotier-one + fi + if [ -d /etc/rc2.d ]; then + rm -f /etc/rc2.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc2.d/S11zerotier-one + fi + if [ -d /etc/rc3.d ]; then + rm -f /etc/rc3.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc3.d/S11zerotier-one + fi + if [ -d /etc/rc4.d ]; then + rm -f /etc/rc4.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc4.d/S11zerotier-one + fi + if [ -d /etc/rc5.d ]; then + rm -f /etc/rc5.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc5.d/S11zerotier-one + fi + if [ -d /etc/rc6.d ]; then + rm -f /etc/rc6.d/???zerotier-one + ln -sf /etc/init.d/zerotier-one /etc/rc6.d/K89zerotier-one + fi + fi + + echo + echo 'Done! Installed and service configured to start at system boot.' + echo + echo "To start now or restart the service if it's already running:" + echo ' sudo service zerotier-one restart' +fi + +exit 0 + +# Do not remove the last line or add a carriage return to it! The installer +# looks for an unterminated line beginning with 16 #'s in itself to find +# the binary blob data, which is appended after it. + +################ \ No newline at end of file diff --git a/ext/installfiles/linux/systemd/zerotier-one.service b/ext/installfiles/linux/systemd/zerotier-one.service new file mode 100644 index 000000000..c4a1c4d29 --- /dev/null +++ b/ext/installfiles/linux/systemd/zerotier-one.service @@ -0,0 +1,11 @@ +[Unit] +Description=ZeroTier One +After=network.target + +[Service] +ExecStart=/var/lib/zerotier-one/zerotier-one +Restart=always +KillMode=process + +[Install] +WantedBy=multi-user.target diff --git a/ext/installfiles/linux/uninstall.sh b/ext/installfiles/linux/uninstall.sh new file mode 100755 index 000000000..d9495a18f --- /dev/null +++ b/ext/installfiles/linux/uninstall.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin + +if [ "$UID" -ne 0 ]; then + echo "Must be run as root; try: sudo $0" + exit 1 +fi + +# Detect systemd vs. regular init +SYSTEMDUNITDIR= +if [ -e /bin/systemctl -o -e /usr/bin/systemctl -o -e /usr/local/bin/systemctl -o -e /sbin/systemctl -o -e /usr/sbin/systemctl ]; then + if [ -e /usr/bin/pkg-config ]; then + SYSTEMDUNITDIR=`/usr/bin/pkg-config systemd --variable=systemdsystemunitdir` + fi + if [ -z "$SYSTEMDUNITDIR" -o ! -d "$SYSTEMDUNITDIR" ]; then + if [ -d /usr/lib/systemd/system ]; then + SYSTEMDUNITDIR=/usr/lib/systemd/system + fi + if [ -d /etc/systemd/system ]; then + SYSTEMDUNITDIR=/etc/systemd/system + fi + fi +fi + +echo "Killing any running zerotier-one service..." +if [ -n "$SYSTEMDUNITDIR" -a -d "$SYSTEMDUNITDIR" ]; then + systemctl stop zerotier-one.service + systemctl disable zerotier-one.service +else + if [ -f /sbin/service -o -f /usr/sbin/service -o -f /bin/service -o -f /usr/bin/service ]; then + service zerotier-one stop + fi +fi + +sleep 1 +if [ -f /var/lib/zerotier-one/zerotier-one.pid ]; then + kill -TERM `cat /var/lib/zerotier-one/zerotier-one.pid` + sleep 1 +fi +if [ -f /var/lib/zerotier-one/zerotier-one.pid ]; then + kill -KILL `cat /var/lib/zerotier-one/zerotier-one.pid` +fi + +if [ -f /etc/init.d/zerotier-one ]; then + echo "Removing SysV init items..." + if [ -f /sbin/chkconfig -o -f /usr/sbin/chkconfig -o -f /bin/chkconfig -o -f /usr/bin/chkconfig ]; then + chkconfig zerotier-one off + fi + rm -f /etc/init.d/zerotier-one + find /etc/rc*.d -type f -name '???zerotier-one' -print0 | xargs -0 rm -f +fi + +if [ -n "$SYSTEMDUNITDIR" -a -d "$SYSTEMDUNITDIR" -a -f "$SYSTEMDUNITDIR/zerotier-one.service" ]; then + echo "Removing systemd service..." + rm -f "$SYSTEMDUNITDIR/zerotier-one.service" +fi + +echo "Erasing binary and support files..." +if [ -d /var/lib/zerotier-one ]; then + cd /var/lib/zerotier-one + rm -rf zerotier-one *.persist identity.public *.log *.pid *.sh updates.d networks.d iddb.d root-topology ui +fi + +echo "Erasing anything installed into system bin directories..." +rm -f /usr/local/bin/zerotier-cli /usr/bin/zerotier-cli /usr/local/bin/zerotier-idtool /usr/bin/zerotier-idtool + +echo "Done." +echo +echo "Your ZeroTier One identity is still preserved in /var/lib/zerotier-one" +echo "as identity.secret and can be manually deleted if you wish. Save it if" +echo "you wish to re-use the address of this node, as it cannot be regenerated." + +echo + +exit 0 diff --git a/ext/installfiles/linux/zerotier-containerized/Dockerfile b/ext/installfiles/linux/zerotier-containerized/Dockerfile deleted file mode 100644 index 7758faf3a..000000000 --- a/ext/installfiles/linux/zerotier-containerized/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -## NOTE: to retain configuration; mount a Docker volume, or use a bind-mount, on /var/lib/zerotier-one - -FROM debian:buster-slim as builder - -## Supports x86_64, x86, arm, and arm64 - -RUN apt-get update && apt-get install -y curl gnupg -RUN apt-key adv --keyserver pgp.mit.edu --recv-keys 0x1657198823e52a61 && \ - echo "deb http://download.zerotier.com/debian/buster buster main" > /etc/apt/sources.list.d/zerotier.list -RUN apt-get update && apt-get install -y zerotier-one=1.8.6 -COPY ext/installfiles/linux/zerotier-containerized/main.sh /var/lib/zerotier-one/main.sh - -FROM debian:buster-slim -LABEL version="1.8.6" -LABEL description="Containerized ZeroTier One for use on CoreOS or other Docker-only Linux hosts." - -# ZeroTier relies on UDP port 9993 -EXPOSE 9993/udp - -RUN mkdir -p /var/lib/zerotier-one -COPY --from=builder /usr/sbin/zerotier-cli /usr/sbin/zerotier-cli -COPY --from=builder /usr/sbin/zerotier-idtool /usr/sbin/zerotier-idtool -COPY --from=builder /usr/sbin/zerotier-one /usr/sbin/zerotier-one -COPY --from=builder /var/lib/zerotier-one/main.sh /main.sh - -RUN chmod 0755 /main.sh -ENTRYPOINT ["/main.sh"] -CMD ["zerotier-one"] diff --git a/ext/installfiles/linux/zerotier-containerized/main.sh b/ext/installfiles/linux/zerotier-containerized/main.sh deleted file mode 100755 index a33890392..000000000 --- a/ext/installfiles/linux/zerotier-containerized/main.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin - -if [ ! -e /dev/net/tun ]; then - echo 'FATAL: cannot start ZeroTier One in container: /dev/net/tun not present.' - exit 1 -fi - -exec "$@" diff --git a/ext/installfiles/linux/zerotier-one.init.rhel6 b/ext/installfiles/linux/zerotier-one.init.rhel6 deleted file mode 100755 index 3ff2f18e3..000000000 --- a/ext/installfiles/linux/zerotier-one.init.rhel6 +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash -# -# zerotier-one Start the ZeroTier One network virtualization service -# -# chkconfig: 2345 55 25 -# description: ZeroTier One allows systems to join and participate in \ -# ZeroTier virtual networks. See https://www.zerotier.com/ -# -# processname: zerotier-one -# config: /var/lib/zerotier-one/identity.public -# config: /var/lib/zerotier-one/identity.secret -# config: /var/lib/zerotier-one/local.conf -# config: /var/lib/zerotier-one/authtoken.secret -# pidfile: /var/lib/zerotier-one/zerotier-one.pid - -### BEGIN INIT INFO -# Provides: zerotier-one -# Required-Start: $local_fs $network $syslog -# Required-Stop: $local_fs $syslog -# Should-Start: $syslog -# Should-Stop: $network $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Start the ZeroTier One network virtualization service -# Description: ZeroTier One allows systems to join and participate in -# ZeroTier virtual networks. See https://www.zerotier.com/ -### END INIT INFO - -# source function library -. /etc/rc.d/init.d/functions - -# pull in sysconfig settings -[ -f /etc/sysconfig/zerotier-one ] && . /etc/sysconfig/zerotier-one - -RETVAL=0 -prog="zerotier-one" -lockfile=/var/lock/subsys/$prog -ZT="/usr/sbin/zerotier-one" -PID_FILE=/var/lib/zerotier-one/zerotier-one.pid - -runlevel=$(set -- $(runlevel); eval "echo \$$#" ) - -start() -{ - [ -x $ZT ] || exit 5 - echo -n $"Starting $prog: " - $ZT $ZT_OPTIONS -d && success || failure - RETVAL=$? - [ $RETVAL -eq 0 ] && touch $lockfile - echo - return $RETVAL -} - -stop() -{ - echo -n $"Stopping $prog: " - killproc -p $PID_FILE $ZT - RETVAL=$? - if [ "x$runlevel" = x0 -o "x$runlevel" = x6 ] ; then - trap '' TERM - killall $prog 2>/dev/null - trap TERM - fi - [ $RETVAL -eq 0 ] && rm -f $lockfile - echo -} - -reload() -{ - stop - start -} - -restart() { - stop - start -} - -force_reload() { - restart -} - -rh_status() { - status -p $PID_FILE zerotier-one -} - -rh_status_q() { - rh_status >/dev/null 2>&1 -} - -case "$1" in - start) - rh_status_q && exit 0 - start - ;; - stop) - if ! rh_status_q; then - rm -f $lockfile - exit 0 - fi - stop - ;; - restart) - restart - ;; - reload) - rh_status_q || exit 7 - reload - ;; - force-reload) - force_reload - ;; - condrestart|try-restart) - rh_status_q || exit 0 - if [ -f $lockfile ] ; then - do_restart_sanity_check - if [ $RETVAL -eq 0 ] ; then - stop - # avoid race - sleep 3 - start - else - RETVAL=6 - fi - fi - ;; - status) - rh_status - RETVAL=$? - if [ $RETVAL -eq 3 -a -f $lockfile ] ; then - RETVAL=2 - fi - ;; - *) - echo $"Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}" - RETVAL=2 -esac -exit $RETVAL diff --git a/ext/installfiles/linux/zerotier-one.te b/ext/installfiles/linux/zerotier-one.te deleted file mode 100644 index 978df0b10..000000000 --- a/ext/installfiles/linux/zerotier-one.te +++ /dev/null @@ -1,14 +0,0 @@ - -module zerotier-one 1.0; - -require { - type unconfined_t; - type initrc_t; - class memprotect mmap_zero; -} - -#============= initrc_t ============== -allow initrc_t self:memprotect mmap_zero; - -#============= unconfined_t ============== -allow unconfined_t self:memprotect mmap_zero; diff --git a/ext/installfiles/mac-update/updater.tmpl.sh b/ext/installfiles/mac-update/updater.tmpl.sh deleted file mode 100644 index 0b07f6d90..000000000 --- a/ext/installfiles/mac-update/updater.tmpl.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -export PATH=/bin:/usr/bin:/sbin:/usr/sbin -shopt -s expand_aliases - -if [ "$UID" -ne 0 ]; then - echo '*** Auto-updater must be run as root.' - exit 1 -fi - -scriptPath="`dirname "$0"`/`basename "$0"`" -if [ ! -s "$scriptPath" ]; then - scriptPath="$0" - if [ ! -s "$scriptPath" ]; then - echo "*** Auto-updater cannot determine its own path; $scriptPath is not readable." - exit 2 - fi -fi - -endMarkerIndex=`grep -a -b -E '^################' "$scriptPath" | head -c 16 | cut -d : -f 1` -if [ "$endMarkerIndex" -le 100 ]; then - echo 'Internal error: unable to find end of script / start of binary data marker.' - exit 2 -fi -blobStart=`expr $endMarkerIndex + 17` -if [ "$blobStart" -le "$endMarkerIndex" ]; then - echo 'Internal error: unable to find end of script / start of binary data marker.' - exit 2 -fi - -rm -f /tmp/ZeroTierOne-update.pkg -tail -c +$blobStart "$scriptPath" >/tmp/ZeroTierOne-update.pkg -chmod 0600 /tmp/ZeroTierOne-update.pkg - -if [ -s /tmp/ZeroTierOne-update.pkg ]; then - rm -f '/Library/Application Support/ZeroTier/One/latest-update.exe' '/Library/Application Support/ZeroTier/One/latest-update.json' /tmp/ZeroTierOne-update.log - installer -verbose -pkg /tmp/ZeroTierOne-update.pkg -target / >/tmp/ZeroTierOne-update.log 2>&1 - rm -f /tmp/ZeroTierOne-update.pkg - exit 0 -else - echo '*** Error self-unpacking update!' - exit 3 -fi - -# Do not remove the last line or add a carriage return to it! The installer -# looks for an unterminated line beginning with 16 #'s in itself to find -# the binary blob data, which is appended after it. - -################ \ No newline at end of file diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index 70cedf9f9..c917d8243 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -2,715 +2,765 @@ - PACKAGES - - - MUST-CLOSE-APPLICATION-ITEMS - - MUST-CLOSE-APPLICATIONS - - PACKAGE_FILES - - DEFAULT_INSTALL_LOCATION - / - HIERARCHY - - CHILDREN - - - CHILDREN - - - CHILDREN - - GID - 80 - PATH - Utilities - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - BUNDLE_CAN_DOWNGRADE - - BUNDLE_POSTINSTALL_PATH - - PATH_TYPE - 0 - - BUNDLE_PREINSTALL_PATH - - PATH_TYPE - 0 - - CHILDREN - - GID - 80 - PATH - ../../../../DesktopUI/ZeroTier.app - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - GID - 80 - PATH - Applications - PATH_TYPE - 0 - PERMISSIONS - 509 - TYPE - 1 - UID - 0 - - - CHILDREN - - - CHILDREN - - - CHILDREN - - - CHILDREN - - - CHILDREN - - GID - 0 - PATH - get-proxy-settings.sh - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - launch.sh - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - CHILDREN - - GID - 80 - PATH - ../../../MacEthernetTapAgent - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - uninstall.sh - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - ../../../zerotier-one - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - GID - 80 - PATH - One - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 2 - UID - 0 - - - GID - 80 - PATH - ZeroTier - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 2 - UID - 0 - - - GID - 80 - PATH - Application Support - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Automator - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Documentation - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Filesystems - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Frameworks - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Input Methods - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Internet Plug-Ins - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - LaunchAgents - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - - CHILDREN - - GID - 0 - PATH - com.zerotier.one.plist - PATH_TYPE - 1 - PERMISSIONS - 420 - TYPE - 3 - UID - 0 - - - GID - 0 - PATH - LaunchDaemons - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - PreferencePanes - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Preferences - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 80 - PATH - Printers - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - PrivilegedHelperTools - PATH_TYPE - 0 - PERMISSIONS - 1005 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - QuickLook - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - QuickTime - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Screen Savers - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Scripts - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Services - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Widgets - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Extensions - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - GID - 0 - PATH - Library - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - - CHILDREN - - - CHILDREN - - GID - 0 - PATH - Extensions - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - GID - 0 - PATH - Library - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - GID - 0 - PATH - System - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - - CHILDREN - - GID - 0 - PATH - Shared - PATH_TYPE - 0 - PERMISSIONS - 1023 - TYPE - 1 - UID - 0 - - - GID - 80 - PATH - Users - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - GID - 0 - PATH - / - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - PAYLOAD_TYPE - 0 - PRESERVE_EXTENDED_ATTRIBUTES - - SHOW_INVISIBLE - - SPLIT_FORKS - - TREAT_MISSING_FILES_AS_WARNING - - VERSION - 5 - - PACKAGE_SCRIPTS - - POSTINSTALL_PATH - - PATH - postinst.sh - PATH_TYPE - 1 - - PREINSTALL_PATH - - PATH - preinst.sh - PATH_TYPE - 1 - - RESOURCES - - - PACKAGE_SETTINGS - - AUTHENTICATION - 1 - CONCLUSION_ACTION - 0 - FOLLOW_SYMBOLIC_LINKS - - IDENTIFIER - com.zerotier.pkg.ZeroTierOne - LOCATION - 0 - NAME - ZeroTier One - OVERWRITE_PERMISSIONS - - PAYLOAD_SIZE - -1 - REFERENCE_PATH - - RELOCATABLE - - USE_HFS+_COMPRESSION - - VERSION - 1.14.2 - - TYPE - 0 - UUID - 1B6AFC3A-9EA5-4401-83D4-37F06CD13CD6 - - PROJECT + PACKAGE_FILES + + DEFAULT_INSTALL_LOCATION + / + HIERARCHY + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 80 + PATH + Utilities + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + ../../mac-ui-macgap1-wrapper/bin/ZeroTier One.app + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + GID + 80 + PATH + Applications + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + get-proxy-settings.sh + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + launch.sh + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + ../../bin/tap-mac/tap.kext + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + ../../../ui/index.html + PATH_TYPE + 1 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + ../../../ui/main.js + PATH_TYPE + 1 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + ../../../ui/react.min.js + PATH_TYPE + 1 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + ../../../ui/simpleajax.min.js + PATH_TYPE + 1 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + ../../../ui/zerotier.css + PATH_TYPE + 1 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + ../../../ui/ztui.min.js + PATH_TYPE + 1 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + GID + 0 + PATH + ui + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 2 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + uninstall.sh + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + ../../../zerotier-one + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + GID + 80 + PATH + One + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 2 + UID + 0 + + + GID + 80 + PATH + ZeroTier + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 2 + UID + 0 + + + GID + 80 + PATH + Application Support + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Automator + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Documentation + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Filesystems + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Frameworks + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Input Methods + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Internet Plug-Ins + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + LaunchAgents + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + com.zerotier.one.plist + PATH_TYPE + 1 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + GID + 0 + PATH + LaunchDaemons + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + PreferencePanes + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Preferences + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + Printers + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + PrivilegedHelperTools + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + QuickLook + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + QuickTime + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Screen Savers + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Scripts + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Services + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Widgets + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + Library + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + Extensions + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + Library + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + System + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + Shared + PATH_TYPE + 0 + PERMISSIONS + 1023 + TYPE + 1 + UID + 0 + + + GID + 80 + PATH + Users + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + / + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + PAYLOAD_TYPE + 0 + VERSION + 3 + + PACKAGE_SCRIPTS + + POSTINSTALL_PATH + + PATH + postinst.sh + PATH_TYPE + 1 + + PREINSTALL_PATH + + PATH + preinst.sh + PATH_TYPE + 1 + + RESOURCES + + + PACKAGE_SETTINGS + + AUTHENTICATION + 1 + CONCLUSION_ACTION + 0 + IDENTIFIER + com.zerotier.pkg.ZeroTierOne + OVERWRITE_PERMISSIONS + + VERSION + 1.0.3 + PROJECT_COMMENTS NOTES @@ -723,206 +773,30 @@ ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD - b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjE1MDQuNzYiPgo8c3R5bGUg + b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjEzNDcuNTciPgo8c3R5bGUg dHlwZT0idGV4dC9jc3MiPgpwLnAxIHttYXJnaW46IDAuMHB4IDAu - MHB4IDAuMHB4IDAuMHB4OyBsaW5lLWhlaWdodDogMTQuMHB4OyBm - b250OiAxMi4wcHggSGVsdmV0aWNhOyBjb2xvcjogIzAwMDAwMDsg - LXdlYmtpdC10ZXh0LXN0cm9rZTogIzAwMDAwMH0Kc3Bhbi5zMSB7 - Zm9udC1rZXJuaW5nOiBub25lfQo8L3N0eWxlPgo8L2hlYWQ+Cjxi - b2R5Pgo8cCBjbGFzcz0icDEiPjxzcGFuIGNsYXNzPSJzMSI+WmVy - b1RpZXIgT25lIC0gTmV0d29yayBWaXJ0dWFsaXphdGlvbiBFdmVy - eXdoZXJlPC9zcGFuPjwvcD4KPHAgY2xhc3M9InAxIj48c3BhbiBj - bGFzcz0iczEiPihjKTIwMTEtMjAxNyBaZXJvVGllciwgSW5jLjwv - c3Bhbj48L3A+CjxwIGNsYXNzPSJwMSI+PHNwYW4gY2xhc3M9InMx - Ij5jb250YWN0QHplcm90aWVyLmNvbTwvc3Bhbj48L3A+CjxwIGNs - YXNzPSJwMSI+PHNwYW4gY2xhc3M9InMxIj48YnI+Cjwvc3Bhbj48 - L3A+CjxwIGNsYXNzPSJwMSI+PHNwYW4gY2xhc3M9InMxIj5UbyB1 - bmluc3RhbGwgbWFudWFsbHksIHR5cGUgdGhlIGZvbGxvd2luZyBp - biBhIHRlcm1pbmFsIHdpbmRvdzo8L3NwYW4+PC9wPgo8cCBjbGFz - cz0icDEiPjxzcGFuIGNsYXNzPSJzMSI+PGJyPgo8L3NwYW4+PC9w - Pgo8cCBjbGFzcz0icDEiPjxzcGFuIGNsYXNzPSJzMSI+c3VkbyAi - L0xpYnJhcnkvQXBwbGljYXRpb24gU3VwcG9ydC9aZXJvVGllci9P - bmUvdW5pbnN0YWxsLnNoIjwvc3Bhbj48L3A+CjwvYm9keT4KPC9o - dG1sPgo= + MHB4IDAuMHB4IDAuMHB4OyBmb250OiAxMi4wcHggSGVsdmV0aWNh + OyBjb2xvcjogIzAwMDAwMDsgLXdlYmtpdC10ZXh0LXN0cm9rZTog + IzAwMDAwMH0Kc3Bhbi5zMSB7Zm9udC1rZXJuaW5nOiBub25lfQo8 + L3N0eWxlPgo8L2hlYWQ+Cjxib2R5Pgo8cCBjbGFzcz0icDEiPjxz + cGFuIGNsYXNzPSJzMSI+WmVyb1RpZXIgT25lIC0gTmV0d29yayBW + aXJ0dWFsaXphdGlvbiBFdmVyeXdoZXJlPC9zcGFuPjwvcD4KPHAg + Y2xhc3M9InAxIj48c3BhbiBjbGFzcz0iczEiPihjKTIwMTEtMjAx + NSBaZXJvVGllciwgSW5jLjwvc3Bhbj48L3A+CjxwIGNsYXNzPSJw + MSI+PHNwYW4gY2xhc3M9InMxIj5jb250YWN0QHplcm90aWVyLmNv + bTwvc3Bhbj48L3A+CjxwIGNsYXNzPSJwMSI+PHNwYW4gY2xhc3M9 + InMxIj48YnI+Cjwvc3Bhbj48L3A+CjxwIGNsYXNzPSJwMSI+PHNw + YW4gY2xhc3M9InMxIj5UbyB1bmluc3RhbGwgbWFudWFsbHksIHR5 + cGUgdGhlIGZvbGxvd2luZyBpbiBhIHRlcm1pbmFsIHdpbmRvdzo8 + L3NwYW4+PC9wPgo8cCBjbGFzcz0icDEiPjxzcGFuIGNsYXNzPSJz + MSI+PGJyPgo8L3NwYW4+PC9wPgo8cCBjbGFzcz0icDEiPjxzcGFu + IGNsYXNzPSJzMSI+c3VkbyAiL0xpYnJhcnkvQXBwbGljYXRpb24g + U3VwcG9ydC9aZXJvVGllci9PbmUvdW5pbnN0YWxsLnNoIjwvc3Bh + bj48L3A+CjwvYm9keT4KPC9odG1sPgo= - PROJECT_PRESENTATION - - BACKGROUND - - APPAREANCES - - DARK_AQUA - - LIGHT_AQUA - - - SHARED_SETTINGS_FOR_ALL_APPAREANCES - - - INSTALLATION TYPE - - HIERARCHIES - - INSTALLER - - LIST - - - CHILDREN - - DESCRIPTION - - OPTIONS - - HIDDEN - - STATE - 1 - - PACKAGE_UUID - 1B6AFC3A-9EA5-4401-83D4-37F06CD13CD6 - TITLE - - TYPE - 0 - UUID - 0FC7D07B-9BA9-4711-BB08-A05099C9E2B9 - - - REMOVED - - - - MODE - 0 - - INSTALLATION_STEPS - - - ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS - ICPresentationViewIntroductionController - INSTALLER_PLUGIN - Introduction - LIST_TITLE_KEY - InstallerSectionTitle - - - ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS - ICPresentationViewReadMeController - INSTALLER_PLUGIN - ReadMe - LIST_TITLE_KEY - InstallerSectionTitle - - - ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS - ICPresentationViewLicenseController - INSTALLER_PLUGIN - License - LIST_TITLE_KEY - InstallerSectionTitle - - - ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS - ICPresentationViewDestinationSelectController - INSTALLER_PLUGIN - TargetSelect - LIST_TITLE_KEY - InstallerSectionTitle - - - ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS - ICPresentationViewInstallationTypeController - INSTALLER_PLUGIN - PackageSelection - LIST_TITLE_KEY - InstallerSectionTitle - - - ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS - ICPresentationViewInstallationController - INSTALLER_PLUGIN - Install - LIST_TITLE_KEY - InstallerSectionTitle - - - ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS - ICPresentationViewSummaryController - INSTALLER_PLUGIN - Summary - LIST_TITLE_KEY - InstallerSectionTitle - - - INTRODUCTION - - LOCALIZATIONS - - - LICENSE - - LOCALIZATIONS - - MODE - 0 - - README - - LOCALIZATIONS - - - TITLE - - LOCALIZATIONS - - - - PROJECT_REQUIREMENTS - - LIST - - - BEHAVIOR - 3 - DICTIONARY - - IC_REQUIREMENT_OS_DISK_TYPE - 0 - IC_REQUIREMENT_OS_DISTRIBUTION_TYPE - 0 - IC_REQUIREMENT_OS_MINIMUM_VERSION - 101300 - - IC_REQUIREMENT_CHECK_TYPE - 1 - IDENTIFIER - fr.whitebox.Packages.requirement.os - MESSAGE - - NAME - Operating System - STATE - - - - RESOURCES - - ROOT_VOLUME_ONLY - - PROJECT_SETTINGS - ADVANCED_OPTIONS - - installer-script.options:hostArchitectures - - x86_64,arm64 - - - BUILD_FORMAT - 0 BUILD_PATH PATH @@ -1100,19 +974,10 @@
NAME ZeroTier One - PAYLOAD_ONLY - - TREAT_MISSING_PRESENTATION_DOCUMENTS_AS_WARNING - - SHARED_GLOBAL_DATA - - IC_REQUIREMENT_JAVASCRIPT_SHARED_SOURCE_CODE - - TYPE - 0 + 1 VERSION 2 diff --git a/ext/installfiles/mac/launch.sh b/ext/installfiles/mac/launch.sh index ab274cbfb..41c4b9c8c 100755 --- a/ext/installfiles/mac/launch.sh +++ b/ext/installfiles/mac/launch.sh @@ -1,4 +1,7 @@ #!/bin/bash -export PATH="/Library/Application Support/ZeroTier/One:/bin:/usr/bin:/sbin:/usr/sbin" -/usr/bin/killall MacEthernetTapAgent >>/dev/null 2>&1 + +zthome="/Library/Application Support/ZeroTier/One" +export PATH="$zthome:/bin:/usr/bin:/sbin:/usr/sbin" + +# Launch ZeroTier One (not as daemon... launchd monitors it) exec zerotier-one diff --git a/ext/installfiles/mac/postinst.sh b/ext/installfiles/mac/postinst.sh index 707b46701..da15f9c84 100755 --- a/ext/installfiles/mac/postinst.sh +++ b/ext/installfiles/mac/postinst.sh @@ -2,50 +2,45 @@ export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin +OSX_RELEASE=`sw_vers -productVersion | cut -d . -f 1,2` + +launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 +sleep 1 + cd "/Library/Application Support/ZeroTier/One" +if [ "$OSX_RELEASE" = "10.7" ]; then + # OSX 10.7 cannot use the new tap driver since the new way of kext signing + # is not backward compatible. Pull the old one for 10.7 users and replace. + # We use https to fetch and check hash as an extra added measure. + rm -f tap.kext.10_7.tar.gz + curl -s https://download.zerotier.com/tap.kext.10_7.tar.gz >tap.kext.10_7.tar.gz + if [ -s tap.kext.10_7.tar.gz -a "`shasum -a 256 tap.kext.10_7.tar.gz | cut -d ' ' -f 1`" = "e133d4832cef571621d3618f417381b44f51a76ed625089fb4e545e65d3ef2a9" ]; then + rm -rf tap.kext + tar -xzf tap.kext.10_7.tar.gz + fi + rm -f tap.kext.10_7.tar.gz +fi + +rm -rf node.log node.log.old root-topology shutdownIfUnreadable autoupdate.log updates.d +chown -R 0 tap.kext +chgrp -R 0 tap.kext if [ ! -f authtoken.secret ]; then - head -c 1024 /dev/urandom | md5 | head -c 24 >authtoken.secret + head -c 4096 /dev/urandom | md5 | head -c 24 >authtoken.secret chown 0 authtoken.secret chgrp 0 authtoken.secret chmod 0600 authtoken.secret fi - -if [ -f zerotier-one.pid ]; then - kill `cat zerotier-one.pid` - sleep 1 - killall MacEthernetTapAgent - sleep 1 - killall -9 MacEthernetTapAgent - sleep 1 - if [ -f zerotier-one.pid ]; then - kill -9 `cat zerotier-one.pid` - rm -f zerotier-one.pid - fi -fi -launchctl load /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 -sleep 1 - rm -f zerotier-cli zerotier-idtool ln -sf zerotier-one zerotier-cli ln -sf zerotier-one zerotier-idtool -if [ ! -d /usr/local/bin ]; then - mkdir -p /usr/local/bin -fi + +mkdir -p /usr/local/bin cd /usr/local/bin rm -f zerotier-cli zerotier-idtool ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-cli ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-idtool -if [ -f /tmp/zt1-gui-restart.tmp ]; then - for u in `cat /tmp/zt1-gui-restart.tmp`; do - if [ -f '/Applications/ZeroTier One.app/Contents/MacOS/ZeroTier One' ]; then - su $u -c '/usr/bin/open /Applications/ZeroTier\ One.app &' >>/dev/null 2>&1 & - else - su $u -c '/usr/bin/open /Applications/ZeroTier.app &' >>/dev/null 2>&1 & - fi - done -fi -rm -f /tmp/zt1-gui-restart.tmp +launchctl load /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 exit 0 diff --git a/ext/installfiles/mac/preinst.sh b/ext/installfiles/mac/preinst.sh index d2df6a3a8..c2cb494b1 100755 --- a/ext/installfiles/mac/preinst.sh +++ b/ext/installfiles/mac/preinst.sh @@ -2,38 +2,25 @@ export PATH=/bin:/usr/bin:/sbin:/usr/sbin -rm -f /tmp/zt1-gui-restart.tmp -for i in `ps axuwww | tr -s ' ' ',' | grep -F '/Applications/ZeroTier,One.app' | grep -F -v grep | cut -d , -f 1,2 | xargs`; do - u=`echo $i | cut -d , -f 1` - p=`echo $i | cut -d , -f 2` - if [ ! -z "$u" -a "0$p" -gt 0 ]; then - kill $p >>/dev/null 2>&1 - sleep 0.5 - kill -9 $p >>/dev/null 2>&1 - echo "$u" >>/tmp/zt1-gui-restart.tmp +if [ -f /Library/LaunchDaemons/com.zerotier.one.plist ]; then + launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 +fi + +sleep 1 + +if [ -d "/Library/Application Support/ZeroTier/One" ]; then + cd "/Library/Application Support/ZeroTier/One" + if [ -f "zerotier-one.pid" ]; then + ztpid=`cat zerotier-one.pid` + if [ "$ztpid" -gt "0" ]; then + kill `cat zerotier-one.pid` + fi fi -done -for i in `ps axuwww | tr -s ' ' ',' | grep -F '/Applications/ZeroTier.app' | grep -F -v grep | cut -d , -f 1,2 | xargs`; do - u=`echo $i | cut -d , -f 1` - p=`echo $i | cut -d , -f 2` - if [ ! -z "$u" -a "0$p" -gt 0 ]; then - kill $p >>/dev/null 2>&1 - sleep 0.5 - kill -9 $p >>/dev/null 2>&1 - echo "$u" >>/tmp/zt1-gui-restart.tmp - fi -done -chmod 0600 /tmp/zt1-gui-restart.tmp +fi + +sleep 1 cd "/Applications" rm -rf "ZeroTier One.app" -rm -rf "ZeroTier.app" - -if [ -d '/Library/Application Support/ZeroTier/One' ]; then - cd '/Library/Application Support/ZeroTier/One' - # ensure that file locking doesn't cause issues with replacing the binary - rm -f zerotier-one - rm -f MacEthernetTapAgent -fi exit 0 diff --git a/ext/installfiles/mac/uninstall.sh b/ext/installfiles/mac/uninstall.sh index 4b6abe13a..d1effb933 100755 --- a/ext/installfiles/mac/uninstall.sh +++ b/ext/installfiles/mac/uninstall.sh @@ -21,16 +21,20 @@ killall -TERM zerotier-one >>/dev/null 2>&1 sleep 1 killall -KILL zerotier-one >>/dev/null 2>&1 +echo "Making sure kext is unloaded..." +kextunload '/Library/Application Support/ZeroTier/One/tap.kext' >>/dev/null 2>&1 + echo "Removing ZeroTier One files..." rm -rf '/Applications/ZeroTier One.app' -rm -rf '/Applications/ZeroTier.app' -rm -f '/usr/local/bin/zerotier-one' '/usr/local/bin/zerotier-idtool' '/usr/local/bin/zerotier-cli' '/Library/LaunchDaemons/com.zerotier.one.plist' - -cd '/Library/Application Support/ZeroTier/One' -if [ "`pwd`" = '/Library/Application Support/ZeroTier/One' ]; then - rm -rf *.d *.sh *.log *.old *.kext *.conf *.pkg *.dmg *.pid *.port *.save *.bin planet zerotier-* devicemap -fi +rm -f '/usr/bin/zerotier-one' '/usr/bin/zerotier-idtool' '/usr/bin/zerotier-cli' '/Library/LaunchDaemons/com.zerotier.one.plist' +mkdir -p /tmp/ZeroTierOne_uninstall_tmp +cp "/Library/Application Support/ZeroTier/One/*.secret" /tmp/ZeroTierOne_uninstall_tmp +rm -rf '/Library/Application Support/ZeroTier/One' +mkdir -p '/Library/Application Support/ZeroTier/One' +cp "/tmp/ZeroTierOne_uninstall_tmp/*.secret" '/Library/Application Support/ZeroTier/One' +chmod 0600 "/Library/Application Support/ZeroTier/One/*.secret" +rm -rf /tmp/ZeroTierOne_uninstall_tmp echo 'Uninstall complete.' echo diff --git a/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip b/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip index 3c3d6a417..a10cb1e55 100644 --- a/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip +++ b/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip @@ -1,187 +1,156 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip b/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip index 50d5f5575..831516d93 100644 --- a/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip +++ b/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip @@ -1,188 +1,157 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 3066eb788..d8a99c3db 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -1,545 +1,368 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/installfiles/windows/ZeroTier One.back.aip b/ext/installfiles/windows/ZeroTier One.back.aip deleted file mode 100644 index 9ad818277..000000000 --- a/ext/installfiles/windows/ZeroTier One.back.aip +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ext/json-parser/LICENSE b/ext/json-parser/LICENSE new file mode 100644 index 000000000..1aee375e0 --- /dev/null +++ b/ext/json-parser/LICENSE @@ -0,0 +1,26 @@ + + Copyright (C) 2012, 2013 James McLaughlin et al. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + diff --git a/ext/json-parser/json.c b/ext/json-parser/json.c new file mode 100644 index 000000000..166cdcb60 --- /dev/null +++ b/ext/json-parser/json.c @@ -0,0 +1,1012 @@ +/* vim: set et ts=3 sw=3 sts=3 ft=c: + * + * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. + * https://github.com/udp/json-parser + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "json.h" + +#ifdef _MSC_VER + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #pragma warning(disable:4996) +#endif + +const struct _json_value json_value_none; + +#include +#include +#include +#include + +typedef unsigned int json_uchar; + +static unsigned char hex_value (json_char c) +{ + if (isdigit(c)) + return c - '0'; + + switch (c) { + case 'a': case 'A': return 0x0A; + case 'b': case 'B': return 0x0B; + case 'c': case 'C': return 0x0C; + case 'd': case 'D': return 0x0D; + case 'e': case 'E': return 0x0E; + case 'f': case 'F': return 0x0F; + default: return 0xFF; + } +} + +typedef struct +{ + unsigned long used_memory; + + unsigned int uint_max; + unsigned long ulong_max; + + json_settings settings; + int first_pass; + + const json_char * ptr; + unsigned int cur_line, cur_col; + +} json_state; + +static void * default_alloc (size_t size, int zero, void * user_data) +{ + return zero ? calloc (1, size) : malloc (size); +} + +static void default_free (void * ptr, void * user_data) +{ + free (ptr); +} + +static void * json_alloc (json_state * state, unsigned long size, int zero) +{ + if ((state->ulong_max - state->used_memory) < size) + return 0; + + if (state->settings.max_memory + && (state->used_memory += size) > state->settings.max_memory) + { + return 0; + } + + return state->settings.mem_alloc (size, zero, state->settings.user_data); +} + +static int new_value (json_state * state, + json_value ** top, json_value ** root, json_value ** alloc, + json_type type) +{ + json_value * value; + int values_size; + + if (!state->first_pass) + { + value = *top = *alloc; + *alloc = (*alloc)->_reserved.next_alloc; + + if (!*root) + *root = value; + + switch (value->type) + { + case json_array: + + if (value->u.array.length == 0) + break; + + if (! (value->u.array.values = (json_value **) json_alloc + (state, value->u.array.length * sizeof (json_value *), 0)) ) + { + return 0; + } + + value->u.array.length = 0; + break; + + case json_object: + + if (value->u.object.length == 0) + break; + + values_size = sizeof (*value->u.object.values) * value->u.object.length; + + if (! (value->u.object.values = (json_object_entry *) json_alloc + (state, values_size + ((unsigned long) value->u.object.values), 0)) ) + { + return 0; + } + + value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size; + + value->u.object.length = 0; + break; + + case json_string: + + if (! (value->u.string.ptr = (json_char *) json_alloc + (state, (value->u.string.length + 1) * sizeof (json_char), 0)) ) + { + return 0; + } + + value->u.string.length = 0; + break; + + default: + break; + }; + + return 1; + } + + if (! (value = (json_value *) json_alloc + (state, sizeof (json_value) + state->settings.value_extra, 1))) + { + return 0; + } + + if (!*root) + *root = value; + + value->type = type; + value->parent = *top; + + #ifdef JSON_TRACK_SOURCE + value->line = state->cur_line; + value->col = state->cur_col; + #endif + + if (*alloc) + (*alloc)->_reserved.next_alloc = value; + + *alloc = *top = value; + + return 1; +} + +#define whitespace \ + case '\n': ++ state.cur_line; state.cur_col = 0; \ + case ' ': case '\t': case '\r' + +#define string_add(b) \ + do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0); + +#define line_and_col \ + state.cur_line, state.cur_col + +static const long + flag_next = 1 << 0, + flag_reproc = 1 << 1, + flag_need_comma = 1 << 2, + flag_seek_value = 1 << 3, + flag_escaped = 1 << 4, + flag_string = 1 << 5, + flag_need_colon = 1 << 6, + flag_done = 1 << 7, + flag_num_negative = 1 << 8, + flag_num_zero = 1 << 9, + flag_num_e = 1 << 10, + flag_num_e_got_sign = 1 << 11, + flag_num_e_negative = 1 << 12, + flag_line_comment = 1 << 13, + flag_block_comment = 1 << 14; + +json_value * json_parse_ex (json_settings * settings, + const json_char * json, + size_t length, + char * error_buf) +{ + json_char error [json_error_max]; + const json_char * end; + json_value * top, * root, * alloc = 0; + json_state state = { 0 }; + long flags; + long num_digits = 0, num_e = 0; + json_int_t num_fraction = 0; + + /* Skip UTF-8 BOM + */ + if (length >= 3 && ((unsigned char) json [0]) == 0xEF + && ((unsigned char) json [1]) == 0xBB + && ((unsigned char) json [2]) == 0xBF) + { + json += 3; + length -= 3; + } + + error[0] = '\0'; + end = (json + length); + + memcpy (&state.settings, settings, sizeof (json_settings)); + + if (!state.settings.mem_alloc) + state.settings.mem_alloc = default_alloc; + + if (!state.settings.mem_free) + state.settings.mem_free = default_free; + + memset (&state.uint_max, 0xFF, sizeof (state.uint_max)); + memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max)); + + state.uint_max -= 8; /* limit of how much can be added before next check */ + state.ulong_max -= 8; + + for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass) + { + json_uchar uchar; + unsigned char uc_b1, uc_b2, uc_b3, uc_b4; + json_char * string = 0; + unsigned int string_length = 0; + + top = root = 0; + flags = flag_seek_value; + + state.cur_line = 1; + + for (state.ptr = json ;; ++ state.ptr) + { + json_char b = (state.ptr == end ? 0 : *state.ptr); + + if (flags & flag_string) + { + if (!b) + { sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col); + goto e_failed; + } + + if (string_length > state.uint_max) + goto e_overflow; + + if (flags & flag_escaped) + { + flags &= ~ flag_escaped; + + switch (b) + { + case 'b': string_add ('\b'); break; + case 'f': string_add ('\f'); break; + case 'n': string_add ('\n'); break; + case 'r': string_add ('\r'); break; + case 't': string_add ('\t'); break; + case 'u': + + if (end - state.ptr < 4 || + (uc_b1 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b2 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b3 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b4 = hex_value (*++ state.ptr)) == 0xFF) + { + sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col); + goto e_failed; + } + + uc_b1 = (uc_b1 << 4) | uc_b2; + uc_b2 = (uc_b3 << 4) | uc_b4; + uchar = (uc_b1 << 8) | uc_b2; + + if ((uchar & 0xF800) == 0xD800) { + json_uchar uchar2; + + if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' || + (uc_b1 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b2 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b3 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b4 = hex_value (*++ state.ptr)) == 0xFF) + { + sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col); + goto e_failed; + } + + uc_b1 = (uc_b1 << 4) | uc_b2; + uc_b2 = (uc_b3 << 4) | uc_b4; + uchar2 = (uc_b1 << 8) | uc_b2; + + uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF); + } + + if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F)) + { + string_add ((json_char) uchar); + break; + } + + if (uchar <= 0x7FF) + { + if (state.first_pass) + string_length += 2; + else + { string [string_length ++] = 0xC0 | (uchar >> 6); + string [string_length ++] = 0x80 | (uchar & 0x3F); + } + + break; + } + + if (uchar <= 0xFFFF) { + if (state.first_pass) + string_length += 3; + else + { string [string_length ++] = 0xE0 | (uchar >> 12); + string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F); + string [string_length ++] = 0x80 | (uchar & 0x3F); + } + + break; + } + + if (state.first_pass) + string_length += 4; + else + { string [string_length ++] = 0xF0 | (uchar >> 18); + string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F); + string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F); + string [string_length ++] = 0x80 | (uchar & 0x3F); + } + + break; + + default: + string_add (b); + }; + + continue; + } + + if (b == '\\') + { + flags |= flag_escaped; + continue; + } + + if (b == '"') + { + if (!state.first_pass) + string [string_length] = 0; + + flags &= ~ flag_string; + string = 0; + + switch (top->type) + { + case json_string: + + top->u.string.length = string_length; + flags |= flag_next; + + break; + + case json_object: + + if (state.first_pass) + (*(json_char **) &top->u.object.values) += string_length + 1; + else + { + top->u.object.values [top->u.object.length].name + = (json_char *) top->_reserved.object_mem; + + top->u.object.values [top->u.object.length].name_length + = string_length; + + (*(json_char **) &top->_reserved.object_mem) += string_length + 1; + } + + flags |= flag_seek_value | flag_need_colon; + continue; + + default: + break; + }; + } + else + { + string_add (b); + continue; + } + } + + if (state.settings.settings & json_enable_comments) + { + if (flags & (flag_line_comment | flag_block_comment)) + { + if (flags & flag_line_comment) + { + if (b == '\r' || b == '\n' || !b) + { + flags &= ~ flag_line_comment; + -- state.ptr; /* so null can be reproc'd */ + } + + continue; + } + + if (flags & flag_block_comment) + { + if (!b) + { sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col); + goto e_failed; + } + + if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/') + { + flags &= ~ flag_block_comment; + ++ state.ptr; /* skip closing sequence */ + } + + continue; + } + } + else if (b == '/') + { + if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object) + { sprintf (error, "%d:%d: Comment not allowed here", line_and_col); + goto e_failed; + } + + if (++ state.ptr == end) + { sprintf (error, "%d:%d: EOF unexpected", line_and_col); + goto e_failed; + } + + switch (b = *state.ptr) + { + case '/': + flags |= flag_line_comment; + continue; + + case '*': + flags |= flag_block_comment; + continue; + + default: + sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b); + goto e_failed; + }; + } + } + + if (flags & flag_done) + { + if (!b) + break; + + switch (b) + { + whitespace: + continue; + + default: + + sprintf (error, "%d:%d: Trailing garbage: `%c`", + state.cur_line, state.cur_col, b); + + goto e_failed; + }; + } + + if (flags & flag_seek_value) + { + switch (b) + { + whitespace: + continue; + + case ']': + + if (top && top->type == json_array) + flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next; + else + { sprintf (error, "%d:%d: Unexpected ]", line_and_col); + goto e_failed; + } + + break; + + default: + + if (flags & flag_need_comma) + { + if (b == ',') + { flags &= ~ flag_need_comma; + continue; + } + else + { + sprintf (error, "%d:%d: Expected , before %c", + state.cur_line, state.cur_col, b); + + goto e_failed; + } + } + + if (flags & flag_need_colon) + { + if (b == ':') + { flags &= ~ flag_need_colon; + continue; + } + else + { + sprintf (error, "%d:%d: Expected : before %c", + state.cur_line, state.cur_col, b); + + goto e_failed; + } + } + + flags &= ~ flag_seek_value; + + switch (b) + { + case '{': + + if (!new_value (&state, &top, &root, &alloc, json_object)) + goto e_alloc_failure; + + continue; + + case '[': + + if (!new_value (&state, &top, &root, &alloc, json_array)) + goto e_alloc_failure; + + flags |= flag_seek_value; + continue; + + case '"': + + if (!new_value (&state, &top, &root, &alloc, json_string)) + goto e_alloc_failure; + + flags |= flag_string; + + string = top->u.string.ptr; + string_length = 0; + + continue; + + case 't': + + if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' || + *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e') + { + goto e_unknown_value; + } + + if (!new_value (&state, &top, &root, &alloc, json_boolean)) + goto e_alloc_failure; + + top->u.boolean = 1; + + flags |= flag_next; + break; + + case 'f': + + if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' || + *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' || + *(++ state.ptr) != 'e') + { + goto e_unknown_value; + } + + if (!new_value (&state, &top, &root, &alloc, json_boolean)) + goto e_alloc_failure; + + flags |= flag_next; + break; + + case 'n': + + if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' || + *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l') + { + goto e_unknown_value; + } + + if (!new_value (&state, &top, &root, &alloc, json_null)) + goto e_alloc_failure; + + flags |= flag_next; + break; + + default: + + if (isdigit (b) || b == '-') + { + if (!new_value (&state, &top, &root, &alloc, json_integer)) + goto e_alloc_failure; + + if (!state.first_pass) + { + while (isdigit (b) || b == '+' || b == '-' + || b == 'e' || b == 'E' || b == '.') + { + if ( (++ state.ptr) == end) + { + b = 0; + break; + } + + b = *state.ptr; + } + + flags |= flag_next | flag_reproc; + break; + } + + flags &= ~ (flag_num_negative | flag_num_e | + flag_num_e_got_sign | flag_num_e_negative | + flag_num_zero); + + num_digits = 0; + num_fraction = 0; + num_e = 0; + + if (b != '-') + { + flags |= flag_reproc; + break; + } + + flags |= flag_num_negative; + continue; + } + else + { sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b); + goto e_failed; + } + }; + }; + } + else + { + switch (top->type) + { + case json_object: + + switch (b) + { + whitespace: + continue; + + case '"': + + if (flags & flag_need_comma) + { sprintf (error, "%d:%d: Expected , before \"", line_and_col); + goto e_failed; + } + + flags |= flag_string; + + string = (json_char *) top->_reserved.object_mem; + string_length = 0; + + break; + + case '}': + + flags = (flags & ~ flag_need_comma) | flag_next; + break; + + case ',': + + if (flags & flag_need_comma) + { + flags &= ~ flag_need_comma; + break; + } + + default: + sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b); + goto e_failed; + }; + + break; + + case json_integer: + case json_double: + + if (isdigit (b)) + { + ++ num_digits; + + if (top->type == json_integer || flags & flag_num_e) + { + if (! (flags & flag_num_e)) + { + if (flags & flag_num_zero) + { sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b); + goto e_failed; + } + + if (num_digits == 1 && b == '0') + flags |= flag_num_zero; + } + else + { + flags |= flag_num_e_got_sign; + num_e = (num_e * 10) + (b - '0'); + continue; + } + + top->u.integer = (top->u.integer * 10) + (b - '0'); + continue; + } + + num_fraction = (num_fraction * 10) + (b - '0'); + continue; + } + + if (b == '+' || b == '-') + { + if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign)) + { + flags |= flag_num_e_got_sign; + + if (b == '-') + flags |= flag_num_e_negative; + + continue; + } + } + else if (b == '.' && top->type == json_integer) + { + if (!num_digits) + { sprintf (error, "%d:%d: Expected digit before `.`", line_and_col); + goto e_failed; + } + + top->type = json_double; + top->u.dbl = (double) top->u.integer; + + num_digits = 0; + continue; + } + + if (! (flags & flag_num_e)) + { + if (top->type == json_double) + { + if (!num_digits) + { sprintf (error, "%d:%d: Expected digit after `.`", line_and_col); + goto e_failed; + } + + top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits)); + } + + if (b == 'e' || b == 'E') + { + flags |= flag_num_e; + + if (top->type == json_integer) + { + top->type = json_double; + top->u.dbl = (double) top->u.integer; + } + + num_digits = 0; + flags &= ~ flag_num_zero; + + continue; + } + } + else + { + if (!num_digits) + { sprintf (error, "%d:%d: Expected digit after `e`", line_and_col); + goto e_failed; + } + + top->u.dbl *= pow (10.0, (double) + (flags & flag_num_e_negative ? - num_e : num_e)); + } + + if (flags & flag_num_negative) + { + if (top->type == json_integer) + top->u.integer = - top->u.integer; + else + top->u.dbl = - top->u.dbl; + } + + flags |= flag_next | flag_reproc; + break; + + default: + break; + }; + } + + if (flags & flag_reproc) + { + flags &= ~ flag_reproc; + -- state.ptr; + } + + if (flags & flag_next) + { + flags = (flags & ~ flag_next) | flag_need_comma; + + if (!top->parent) + { + /* root value done */ + + flags |= flag_done; + continue; + } + + if (top->parent->type == json_array) + flags |= flag_seek_value; + + if (!state.first_pass) + { + json_value * parent = top->parent; + + switch (parent->type) + { + case json_object: + + parent->u.object.values + [parent->u.object.length].value = top; + + break; + + case json_array: + + parent->u.array.values + [parent->u.array.length] = top; + + break; + + default: + break; + }; + } + + if ( (++ top->parent->u.array.length) > state.uint_max) + goto e_overflow; + + top = top->parent; + + continue; + } + } + + alloc = root; + } + + return root; + +e_unknown_value: + + sprintf (error, "%d:%d: Unknown value", line_and_col); + goto e_failed; + +e_alloc_failure: + + strcpy (error, "Memory allocation failure"); + goto e_failed; + +e_overflow: + + sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col); + goto e_failed; + +e_failed: + + if (error_buf) + { + if (*error) + strcpy (error_buf, error); + else + strcpy (error_buf, "Unknown error"); + } + + if (state.first_pass) + alloc = root; + + while (alloc) + { + top = alloc->_reserved.next_alloc; + state.settings.mem_free (alloc, state.settings.user_data); + alloc = top; + } + + if (!state.first_pass) + json_value_free_ex (&state.settings, root); + + return 0; +} + +json_value * json_parse (const json_char * json, size_t length) +{ + json_settings settings = { 0 }; + return json_parse_ex (&settings, json, length, 0); +} + +void json_value_free_ex (json_settings * settings, json_value * value) +{ + json_value * cur_value; + + if (!value) + return; + + value->parent = 0; + + while (value) + { + switch (value->type) + { + case json_array: + + if (!value->u.array.length) + { + settings->mem_free (value->u.array.values, settings->user_data); + break; + } + + value = value->u.array.values [-- value->u.array.length]; + continue; + + case json_object: + + if (!value->u.object.length) + { + settings->mem_free (value->u.object.values, settings->user_data); + break; + } + + value = value->u.object.values [-- value->u.object.length].value; + continue; + + case json_string: + + settings->mem_free (value->u.string.ptr, settings->user_data); + break; + + default: + break; + }; + + cur_value = value; + value = value->parent; + settings->mem_free (cur_value, settings->user_data); + } +} + +void json_value_free (json_value * value) +{ + json_settings settings = { 0 }; + settings.mem_free = default_free; + json_value_free_ex (&settings, value); +} + diff --git a/ext/json-parser/json.h b/ext/json-parser/json.h new file mode 100644 index 000000000..f6549ec4e --- /dev/null +++ b/ext/json-parser/json.h @@ -0,0 +1,283 @@ + +/* vim: set et ts=3 sw=3 sts=3 ft=c: + * + * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. + * https://github.com/udp/json-parser + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _JSON_H +#define _JSON_H + +#ifndef json_char + #define json_char char +#endif + +#ifndef json_int_t + #ifndef _MSC_VER + #include + #define json_int_t int64_t + #else + #define json_int_t __int64 + #endif +#endif + +#include + +#ifdef __cplusplus + + #include + + extern "C" + { + +#endif + +typedef struct +{ + unsigned long max_memory; + int settings; + + /* Custom allocator support (leave null to use malloc/free) + */ + + void * (* mem_alloc) (size_t, int zero, void * user_data); + void (* mem_free) (void *, void * user_data); + + void * user_data; /* will be passed to mem_alloc and mem_free */ + + size_t value_extra; /* how much extra space to allocate for values? */ + +} json_settings; + +#define json_enable_comments 0x01 + +typedef enum +{ + json_none, + json_object, + json_array, + json_integer, + json_double, + json_string, + json_boolean, + json_null + +} json_type; + +extern const struct _json_value json_value_none; + +typedef struct _json_object_entry +{ + json_char * name; + unsigned int name_length; + + struct _json_value * value; + +} json_object_entry; + +typedef struct _json_value +{ + struct _json_value * parent; + + json_type type; + + union + { + int boolean; + json_int_t integer; + double dbl; + + struct + { + unsigned int length; + json_char * ptr; /* null terminated */ + + } string; + + struct + { + unsigned int length; + + json_object_entry * values; + + #if defined(__cplusplus) && __cplusplus >= 201103L + decltype(values) begin () const + { return values; + } + decltype(values) end () const + { return values + length; + } + #endif + + } object; + + struct + { + unsigned int length; + struct _json_value ** values; + + #if defined(__cplusplus) && __cplusplus >= 201103L + decltype(values) begin () const + { return values; + } + decltype(values) end () const + { return values + length; + } + #endif + + } array; + + } u; + + union + { + struct _json_value * next_alloc; + void * object_mem; + + } _reserved; + + #ifdef JSON_TRACK_SOURCE + + /* Location of the value in the source JSON + */ + unsigned int line, col; + + #endif + + + /* Some C++ operator sugar */ + + #ifdef __cplusplus + + public: + + inline _json_value () + { memset (this, 0, sizeof (_json_value)); + } + + inline const struct _json_value &operator [] (int index) const + { + if (type != json_array || index < 0 + || ((unsigned int) index) >= u.array.length) + { + return json_value_none; + } + + return *u.array.values [index]; + } + + inline const struct _json_value &operator [] (const char * index) const + { + if (type != json_object) + return json_value_none; + + for (unsigned int i = 0; i < u.object.length; ++ i) + if (!strcmp (u.object.values [i].name, index)) + return *u.object.values [i].value; + + return json_value_none; + } + + inline operator const char * () const + { + switch (type) + { + case json_string: + return u.string.ptr; + + default: + return ""; + }; + } + + inline operator json_int_t () const + { + switch (type) + { + case json_integer: + return u.integer; + + case json_double: + return (json_int_t) u.dbl; + + default: + return 0; + }; + } + + inline operator bool () const + { + if (type != json_boolean) + return false; + + return u.boolean != 0; + } + + inline operator double () const + { + switch (type) + { + case json_integer: + return (double) u.integer; + + case json_double: + return u.dbl; + + default: + return 0; + }; + } + + #endif + +} json_value; + +json_value * json_parse (const json_char * json, + size_t length); + +#define json_error_max 128 +json_value * json_parse_ex (json_settings * settings, + const json_char * json, + size_t length, + char * error); + +void json_value_free (json_value *); + + +/* Not usually necessary, unless you used a custom mem_alloc and now want to + * use a custom mem_free. + */ +void json_value_free_ex (json_settings * settings, + json_value *); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif + + diff --git a/ext/libnatpmp/getgateway.c b/ext/libnatpmp/getgateway.c index 0f06e1dc2..dfb9f3e21 100644 --- a/ext/libnatpmp/getgateway.c +++ b/ext/libnatpmp/getgateway.c @@ -53,7 +53,6 @@ POSSIBILITY OF SUCH DAMAGE. #undef USE_PROC_NET_ROUTE #define USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE -#include #endif #ifdef __APPLE__ @@ -97,6 +96,7 @@ POSSIBILITY OF SUCH DAMAGE. #ifdef USE_SYSCTL_NET_ROUTE #include +#include #include #include #endif @@ -271,9 +271,7 @@ int getdefaultgateway(in_addr_t *addr) rtm.rtm_addrs = rtm_addrs; so_dst.sa_family = AF_INET; - so_dst.sa_len = sizeof(struct sockaddr); so_mask.sa_family = AF_INET; - so_mask.sa_len = sizeof(struct sockaddr); NEXTADDR(RTA_DST, so_dst); NEXTADDR(RTA_NETMASK, so_mask); diff --git a/ext/libpqxx-7.7.3/.circleci/config.yml b/ext/libpqxx-7.7.3/.circleci/config.yml deleted file mode 100644 index 038d7adb0..000000000 --- a/ext/libpqxx-7.7.3/.circleci/config.yml +++ /dev/null @@ -1,60 +0,0 @@ -# CircleCI config for automated test builds triggered from Github. -version: 2 -jobs: - build: - docker: - - image: debian:testing -# - image: postgres:latest - environment: - - PGHOST: "/tmp" - steps: - - checkout - - run: - name: Configure apt archives - command: apt update - - run: - name: Install - command: apt install -y lsb-release python3 cmake postgresql libpq-dev postgresql-server-dev-all build-essential autoconf dh-autoreconf autoconf-archive automake cppcheck - - run: - name: Identify - command: lsb_release -a && c++ --version - - run: - name: Prepare postgres - command: | - mkdir /tmp/db && - chown postgres /tmp/db && - su postgres -c '/usr/lib/postgresql/*/bin/initdb --pgdata /tmp/db --auth trust --nosync' - - run: - name: Run postgres - command: (su postgres -c '/usr/lib/postgresql/*/bin/postgres -D /tmp/db -k /tmp' &) && sleep 5 - - run: - name: Create postgres user - command: su postgres -c "createuser -w -d root" - - run: - name: Set up database - command: createdb root - - run: - name: Autogen - command: NOCONFIGURE=1 ./autogen.sh - - run: - name: Configure - command: | - ./configure \ - --disable-documentation \ - --enable-maintainer-mode \ - --enable-audit \ - --enable-shared --disable-static \ - CXXFLAGS=-O3 - - store_artifacts: - path: config.log - - run: - name: Make - command: make -j$(nproc) - - run: - name: Test - command: PGDATA=db/data make check - - run: - name: Analyse - command: ./tools/lint --full >lint.log - - store_artifacts: - path: lint.log diff --git a/ext/libpqxx-7.7.3/.clang-format b/ext/libpqxx-7.7.3/.clang-format deleted file mode 100644 index 97823d8ff..000000000 --- a/ext/libpqxx-7.7.3/.clang-format +++ /dev/null @@ -1,71 +0,0 @@ -Language: Cpp - -AlignAfterOpenBracket: AlwaysBreak -# AllowAllArgumentsOnNextLine: true -# AllowAllConstructorInitializersOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: true -AllowShortCaseLabelsOnASingleLine: true -AllowShortFunctionsOnASingleLine: Inline -# AllowShortIfStatementsOnASingleLine: WithoutElse -# AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: true -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: true -# AlwaysBreakTemplateDeclarations: No -BinPackArguments: true -BinPackParameters: true -BreakBeforeBraces: Custom -BraceWrapping: - # AfterCaseLabel: true - AfterClass: true - AfterControlStatement: true - AfterEnum: true - AfterExternBlock: true - AfterFunction: true - AfterNamespace: true - AfterStruct: true - BeforeCatch: true - BeforeElse: true - IndentBraces: false - SplitEmptyFunction: false - SplitEmptyNamespace: false - SplitEmptyRecord: false -BreakBeforeBinaryOperators: None -BreakBeforeTernaryOperators: false -BreakConstructorInitializers: AfterColon -# BreakInheritanceList: AfterColon -BreakStringLiterals: true -ColumnLimit: 79 -ConstructorInitializerAllOnOneLineOrOnePerLine: true -ConstructorInitializerIndentWidth: 8 -ContinuationIndentWidth: 2 -Cpp11BracedListStyle: true -FixNamespaceComments: true -IncludeBlocks: Preserve -IndentCaseLabels: false -IndentPPDirectives: AfterHash -IndentWidth: 2 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: false -MaxEmptyLinesToKeep: 2 -# NamespaceIndentation: All -SortIncludes: true -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -# SpaceBeforeCpp11BracedList: false -# SpaceBeforeCtorInitializerColon: true -# SpaceBeforeInheritanceColon: true -# SpaceBeforeParents: ControlStatements -# SpaceBeforeRangedBasedForLoopColon: true -SpaceInEmptyParentheses: false -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -UseTab: Never ---- diff --git a/ext/libpqxx-7.7.3/.cmake-format b/ext/libpqxx-7.7.3/.cmake-format deleted file mode 100644 index af00ef936..000000000 --- a/ext/libpqxx-7.7.3/.cmake-format +++ /dev/null @@ -1,184 +0,0 @@ -format: - _help_max_prefix_chars: - - !!python/unicode 'If the statement spelling length (including space and' - - !!python/unicode 'parenthesis) is larger than the tab width by more than this' - - !!python/unicode 'amount, then force reject un-nested layouts.' - max_prefix_chars: 10 - _help_dangle_align: - - !!python/unicode 'If the trailing parenthesis must be ''dangled'' on its own' - - !!python/unicode 'line, then align it to this reference: `prefix`: the start' - - !!python/unicode 'of the statement, `prefix-indent`: the start of the' - - !!python/unicode 'statement, plus one indentation level, `child`: align to' - - !!python/unicode 'the column of the arguments' - dangle_align: !!python/unicode 'prefix' - _help_max_subgroups_hwrap: - - !!python/unicode 'If an argument group contains more than this many sub-groups' - - !!python/unicode '(parg or kwarg groups) then force it to a vertical layout.' - max_subgroups_hwrap: 2 - _help_min_prefix_chars: - - !!python/unicode 'If the statement spelling length (including space and' - - !!python/unicode 'parenthesis) is smaller than this amount, then force reject' - - !!python/unicode 'nested layouts.' - min_prefix_chars: 4 - _help_max_pargs_hwrap: - - !!python/unicode 'If a positional argument group contains more than this many' - - !!python/unicode 'arguments, then force it to a vertical layout.' - max_pargs_hwrap: 6 - _help_max_lines_hwrap: - - !!python/unicode 'If a candidate layout is wrapped horizontally but it exceeds' - - !!python/unicode 'this many lines, then reject the layout.' - max_lines_hwrap: 2 - _help_autosort: - - !!python/unicode 'If true, the parsers may infer whether or not an argument' - - !!python/unicode 'list is sortable (without annotation).' - autosort: false - _help_line_ending: - - !!python/unicode 'What style line endings to use in the output.' - line_ending: !!python/unicode 'unix' - _help_line_width: - - !!python/unicode 'How wide to allow formatted cmake files' - line_width: 80 - _help_dangle_parens: - - !!python/unicode 'If a statement is wrapped to more than one line, then dangle' - - !!python/unicode 'the closing parenthesis on its own line.' - dangle_parens: true - _help_tab_size: - - !!python/unicode 'How many spaces to tab for indent' - tab_size: 4 - _help_always_wrap: - - !!python/unicode 'A list of command names which should always be wrapped' - always_wrap: [] - _help_require_valid_layout: - - !!python/unicode 'By default, if cmake-format cannot successfully fit' - - !!python/unicode 'everything into the desired linewidth it will apply the' - - !!python/unicode 'last, most agressive attempt that it made. If this flag is' - - !!python/unicode 'True, however, cmake-format will print error, exit with non-' - - !!python/unicode 'zero status code, and write-out nothing' - require_valid_layout: true - _help_keyword_case: - - !!python/unicode 'Format keywords consistently as ''lower'' or ''upper'' case' - keyword_case: !!python/unicode 'unchanged' - _help_layout_passes: - - !!python/unicode 'A dictionary mapping layout nodes to a list of wrap' - - !!python/unicode 'decisions. See the documentation for more information.' - layout_passes: {} - _help_enable_sort: - - !!python/unicode 'If true, the argument lists which are known to be sortable' - - !!python/unicode 'will be sorted lexicographically' - enable_sort: true -_help_markup: !!python/unicode 'Options affecting comment reflow and formatting.' -markup: - _help_literal_comment_pattern: - - !!python/unicode 'If comment markup is enabled, don''t reflow any comment block' - - !!python/unicode 'which matches this (regex) pattern. Default is `None`' - - !!python/unicode '(disabled).' - literal_comment_pattern: null - _help_hashruler_min_length: - - !!python/unicode 'If a comment line starts with at least this many consecutive' - - !!python/unicode 'hash characters, then don''t lstrip() them off. This allows' - - !!python/unicode 'for lazy hash rulers where the first hash char is not' - - !!python/unicode 'separated by space' - hashruler_min_length: 10 - _help_fence_pattern: - - !!python/unicode 'Regular expression to match preformat fences in comments' - - !!python/unicode 'default=r''^\s*([`~]{3}[`~]*)(.*)$''' - fence_pattern: !!python/unicode '^\s*([`~]{3}[`~]*)(.*)$' - _help_canonicalize_hashrulers: - - !!python/unicode 'If true, then insert a space between the first hash char and' - - !!python/unicode 'remaining hash chars in a hash ruler, and normalize its' - - !!python/unicode 'length to fill the column' - canonicalize_hashrulers: true - _help_explicit_trailing_pattern: - - !!python/unicode 'If a comment line matches starts with this pattern then it' - - !!python/unicode 'is explicitly a trailing comment for the preceeding' - - !!python/unicode 'argument. Default is ''#<''' - explicit_trailing_pattern: !!python/unicode '#<' - _help_first_comment_is_literal: - - !!python/unicode 'If comment markup is enabled, don''t reflow the first comment' - - !!python/unicode 'block in each listfile. Use this to preserve formatting of' - - !!python/unicode 'your copyright/license statements.' - first_comment_is_literal: false - _help_enable_markup: - - !!python/unicode 'enable comment markup parsing and reflow' - enable_markup: true - _help_ruler_pattern: - - !!python/unicode 'Regular expression to match rulers in comments' - - !!python/unicode 'default=r''^\s*[^\w\s]{3}.*[^\w\s]{3}$''' - ruler_pattern: !!python/unicode '^\s*[^\w\s]{3}.*[^\w\s]{3}$' - _help_enum_char: - - !!python/unicode 'What character to use as punctuation after numerals in an' - - !!python/unicode 'enumerated list' - enum_char: . - _help_bullet_char: - - !!python/unicode 'What character to use for bulleted lists' - bullet_char: '*' -_help_lint: !!python/unicode 'Options affecting the linter' -lint: - _help_function_pattern: - - !!python/unicode 'regular expression pattern describing valid function names' - function_pattern: !!python/unicode '[0-9a-z_]+' - _help_disabled_codes: - - !!python/unicode 'a list of lint codes to disable' - disabled_codes: [] - _help_min_statement_spacing: - - !!python/unicode 'Require at least this many newlines between statements' - min_statement_spacing: 1 - _help_macro_pattern: - - !!python/unicode 'regular expression pattern describing valid macro names' - macro_pattern: !!python/unicode '[0-9A-Z_]+' - _help_public_var_pattern: - - !!python/unicode 'regular expression pattern describing valid names for' - - !!python/unicode 'publicdirectory variables' - public_var_pattern: !!python/unicode '[0-9A-Z][0-9A-Z_]+' - max_statements: 50 - _help_max_conditionals_custom_parser: - - !!python/unicode 'In the heuristic for C0201, how many conditionals to match' - - !!python/unicode 'within a loop in before considering the loop a parser.' - max_conditionals_custom_parser: 2 - _help_global_var_pattern: - - !!python/unicode 'regular expression pattern describing valid names for' - - !!python/unicode 'variables with global scope' - global_var_pattern: !!python/unicode '[0-9A-Z][0-9A-Z_]+' - _help_keyword_pattern: - - !!python/unicode 'regular expression pattern describing valid names for' - - !!python/unicode 'keywords used in functions or macros' - keyword_pattern: !!python/unicode '[0-9A-Z_]+' - max_arguments: 5 - _help_private_var_pattern: - - !!python/unicode 'regular expression pattern describing valid names for' - - !!python/unicode 'privatedirectory variables' - private_var_pattern: !!python/unicode '_[0-9a-z_]+' - max_localvars: 15 - max_branches: 12 - _help_local_var_pattern: - - !!python/unicode 'regular expression pattern describing valid names for' - - !!python/unicode 'variables with local scope' - local_var_pattern: !!python/unicode '[0-9a-z_]+' - _help_max_statement_spacing: - - !!python/unicode 'Require no more than this many newlines between statements' - max_statement_spacing: 1 - _help_internal_var_pattern: - - !!python/unicode 'regular expression pattern describing valid names for' - - !!python/unicode 'variables with global scope (but internal semantic)' - internal_var_pattern: !!python/unicode '_[0-9A-Z][0-9A-Z_]+' - max_returns: 6 -_help_misc: !!python/unicode 'Miscellaneous configurations options.' -misc: - _help_per_command: - - !!python/unicode 'A dictionary containing any per-command configuration' - - !!python/unicode 'overrides. Currently only `command_case` is supported.' - per_command: {} -_help_parse: !!python/unicode 'Options affecting listfile parsing' -parse: - _help_additional_commands: - - !!python/unicode 'Specify structure for custom cmake functions' - additional_commands: - !!python/unicode 'foo': - !!python/unicode 'flags': - - !!python/unicode 'BAR' - - !!python/unicode 'BAZ' - !!python/unicode 'kwargs': - !!python/unicode 'HEADERS': !!python/unicode '*' - !!python/unicode 'DEPENDS': !!python/unicode '*' - !!python/unicode 'SOURCES': !!python/unicode '*' -_help_encode: !!python/unicode 'Options effecting file encoding' diff --git a/ext/libpqxx-7.7.3/.github/workflows/stale.yml b/ext/libpqxx-7.7.3/.github/workflows/stale.yml deleted file mode 100644 index 0983a3e54..000000000 --- a/ext/libpqxx-7.7.3/.github/workflows/stale.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Mark stale issues and pull requests - -on: - schedule: - - cron: "30 1 * * *" - -jobs: - stale: - - runs-on: ubuntu-latest - - steps: - - uses: actions/stale@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-issue-message: 'There has been no activity on this ticket. Consider closing it.' - stale-pr-message: 'There has been no activity on this pull request. Complete it or drop it.' - stale-issue-label: 'no-issue-activity' - stale-pr-label: 'no-pr-activity' diff --git a/ext/libpqxx-7.7.3/.gitignore b/ext/libpqxx-7.7.3/.gitignore deleted file mode 100644 index d798c9dca..000000000 --- a/ext/libpqxx-7.7.3/.gitignore +++ /dev/null @@ -1,49 +0,0 @@ -autom4te.cache -build-*.out -ChangeLog -CMakeFiles/CMakeTmp -confdefs.h -config.log -config.status -conftest -conftest.cpp -conftest.err -doc/_build -doc/Doxyfile -doc/html/Reference/*.css -doc/html/Reference/*.html -doc/html/Reference/*.js -doc/html/Reference/*.png -doc/html/Reference/*.map -doc/html/Reference/*.md5 -doc/reference-stamp -include/pqxx/config-*-*.h -include/pqxx/config.h -include/pqxx/stamp-h1 -libpqxx.pc -libpqxx-*.tar.gz -libtool -pqxx-config -pqxxlo.txt -test/pqxxlo.txt -tools/pqxxthreadsafety -tools/rmlo -README -win32/common -**/Makefile -**/*.la -**/*.lo -**/*.o -**/*.out -**/.*.swp -**/.swp -**/*.tmp -**/.deps -**/.libs -**/*~ -**/lint.log -**/lint.trs -**/runner -**/runner.log -**/runner.trs -**/test-suite.log diff --git a/ext/libpqxx-7.7.3/.lgtm.yml b/ext/libpqxx-7.7.3/.lgtm.yml deleted file mode 100644 index d53664eb4..000000000 --- a/ext/libpqxx-7.7.3/.lgtm.yml +++ /dev/null @@ -1,9 +0,0 @@ -# Config file for lgtm.com static analysis. - -path_classifiers: - test: - - test - generated: - - aclocal.m4 - - configure - - ltmain.sh diff --git a/ext/libpqxx-7.7.3/.lift/ignoreFiles b/ext/libpqxx-7.7.3/.lift/ignoreFiles deleted file mode 100644 index 8c6c7a103..000000000 --- a/ext/libpqxx-7.7.3/.lift/ignoreFiles +++ /dev/null @@ -1,3 +0,0 @@ -# Make Sonatype Lift ignore these generated files. -configure -config/* diff --git a/ext/libpqxx-7.7.3/AUTHORS b/ext/libpqxx-7.7.3/AUTHORS deleted file mode 100644 index 6a922e950..000000000 --- a/ext/libpqxx-7.7.3/AUTHORS +++ /dev/null @@ -1,4 +0,0 @@ -Jeroen T. Vermeulen. Wrote the code. -Ray Dassen. Did most of the autoconf etc. stuff. - -Lots of others helped with various other contributions. diff --git a/ext/libpqxx-7.7.3/BUILDING-cmake.md b/ext/libpqxx-7.7.3/BUILDING-cmake.md deleted file mode 100644 index 48b1e7930..000000000 --- a/ext/libpqxx-7.7.3/BUILDING-cmake.md +++ /dev/null @@ -1,272 +0,0 @@ -Building using CMake -==================== - -The build requires the full PostgreSQL development package. That package must -be installed before you can build libpqxx. - -The instructions will assume that you're working from a command-line shell. -If you prefer to work from an IDE, you'll have to know how your IDE likes to -do things, and you'll want to follow the shell instructions as a guide. - -I'm not too familiar with CMake, and this build relies heavily on contributions -from users. If you see something wrong here, please file a bug and explain, in -simple words, what needs changing and why. - - -Quick start ------------ - -If you just want to get it built and installed quickly, run `cmake` from the -root of the libpqxx source tree. This configures your build. - -Then compile libpqxx by running: - -```shell - cmake --build . -``` - -To install in the default location: - -```shell - cmake --install . -``` - - -Stages ------- - -I'll explain the main build steps in more detail below, but here's a quick -rundown: -1. Configure -2. Compile -3. Test -4. Install -5. Use - -The Test step is optional. - - -Configure ---------- - -Run `cmake` to configure your build. It figures out various parameters, such -as where libpq and its headers are, which C++ features your compiler supports, -and which options your compiler needs. CMake generates configuration for your -build tool: `Makefile`s for `make`, or a Solution (".sln") file for MSVC's -`msbuild`, and so on. - -At this stage you can also override those options yourself. e.g. to instruct -the compiler to look for libpq in a non-standard place, or to use a different -compiler, or pass different compiler flags. Don't try to specify those while -doing the actual compile; set them once when running `cmake`. - -Let's say `$BUILD` is the directory where you want to build libpqxx, and -`$SRC` is where its source code is. So for example, the readme file will be at -`$SRC/README.md`. - -In the simplest case, you just do: - -```shell - cd $BUILD - cmake $SRC -``` - -Add CMake options as needed. There's more about the options below. I'll also -explain the two directories. - - -### Cheat sheet - -Here are some popular `cmake` options for libpqxx: -* `-DSKIP_BUILD_TEST=on` skips compiling libpqxx's tests. -* `-DBUILD_SHARED_LIBS=on` to build a shared library. -* `-DBUILD_SHARED_LIBS=off` to build a static library. -* `-DBUILD_DOC=on` to build documentation. -* `-DINSTALL_TEST=on` to install test executor binary. - -On Windows, I recommend building libpqxx as a shared library and bundling it -with your application. On other platforms I would prefer a static library. - -Building the documentation requires some tools to be installed. It takes at -least Doxygen, but there's no list of requirements. The way to get this set up -is to just try it and see what it's missing. - - -### Generators - -You can also choose your own build tool by telling CMake to use a particular -"generator." For example, here's how to force use of `make`: - -```shell - cmake -G 'Unix Makefiles' -``` - -Or if you prefer to build using `ninja` instead: - -```shell - cmake -G Ninja -``` - -There are many more options. You may prefer yet a different build tool. - - -### Finding libpq - -The CMake step tries to figure out where libpq is, using Cmake's `find_package` -function. If that doesn't work, or if you want a libpq in a different location -from the one it finds, there are two ways to override it. - -The first is to set the individual include and link paths. - -To make the build look for the libpq headers in some directory `$DIR`, add -these options: -* `-DPostgreSQL_TYPE_INCLUDE_DIR=$DIR` -* `-DPostgreSQL_INCLUDE_DIR=$DIR` - -To make the build look for the libpq library binary in a directory `$DIR`, add -this option: -* `-DPostgreSQL_LIBRARY_DIR=$DIR` - -The second, easier way requires CMake 3.12 or better. Here, you specify a path -to a full PostgreSQL build tree. You do this (again for some directory `$DIR`) -by simply passing this cmake option: `-DPostgreSQL_ROOT=$DIR` - - -### Source and Build trees - -Where should you run `cmake`? - -Two directories matter when building libpqxx: the _source tree_ (where the -libpqxx source code is) and the _build tree_ (where you want your build -artefacts). Here I will call them `$SRC` and `$BUILD`, but you can call them -anything you like. - -They can be one and the same, if you like. It's convenient, but less clean, as -source code and build artefacts will exist in the same directory tree. If -you're going to delete the source tree after installing, of course it's fine to -make a mess in there. - - -Compile -------- - -To compile, run: - -```shell - cmake --build $BUILD -``` - -(Where `$BUILD` is again the directory where you wish to do the build.) - -This command will invoke your build tool. Other ways to do the same thing -would be... -* With Unix Makefiles: `make` -* With Ninja: `ninja` -* With Visual Studio: `msbuild libpqxx.sln` -* etc. - -Depending on your build tool, you may want to speed this up by adding an option -like `-j 16`, where `16` is an example of how many processes you might want to -run in parallel. The optimal number depends on your available CPUs and memory. -If you have enough memory, usually the number of CPUs will be a good starting -point for the right number. Don't use this option with Ninja though. It -figures things out for itself. - - -Test ----- - -Of course libpqxx comes with a test suite, to check that the library is -functioning correctly. - -You can run it, but there's one caveat: you need to give it a database where it -can log in, without a password or any other parameters, and try out various -things. - -And when I say you need to "give" it a database, I really mean "give." The -test suite will create and drop tables. Those will all have names prefixed -with "pqxx", so it's probably safe to use a database you already had, but if -any of the items in your database happen to have names starting with `pqxx`, -tough luck. They're fair game. - -Enter this in your shell to build and run the tests: - -```shell - test/runner -``` - - -### Configuring the test database - -But what if you do need a password to log into your test database? Or, what if -it's running on a different system so you need to pass that machine's address? -What if it's not running on the default port? - -You can set these parameters for the test suite, or for any other libpq-based -application, using the following environment variables. (They only set default -values, so they won't override parameters that the application sets in some -other way.) -* `PGHOST` — the IP address where we can contact the database's socket. Or - for a Unix domain socket, its absolute path on the filesystem. -* `PGPORT` — TCP port number on which we can connect to the database. -* `PGDATABASE` — the name of the database to which you wish to connect. -* `PGUSER` — user name under which you wish to log in on the database. -* `PGPASSWORD` — user name's password for accessing the database. - -See the full list at https://www.postgresql.org/docs/current/libpq-envars.html - -**Be careful with passwords,** by the way. Depending on your operating system -and configuration, an attacker with access to your machine could try to read -your password if you set it on the command line: -* Your shell may keep a log of the commands you have entered. -* Environment variables may be visible to other users on the system. - -If at all possible, rely on postgres "peer authentication." Once set up, it is -both more secure and more convenient than passwords. - - -Install -------- - -Once you've built libpqxx, CMake can also help you install the library and -headers on your system. The default installation location will vary from one -operating system to another, but you can set it explicitly. - -Let's say you've got your finished build in `$BUILD`, and you want to install -it to your system's default install location. The command for this is: - -```shell - cmake --install $BUILD -``` - -But you may want to install to some other location. Let's call it `$DEST`. -`$DEST` might be something like `/usr/local` on a Unix-like system, or -something like `D:\Software` on a Windows system. - -To install to `$DEST`, run: - -```shell - cmake --install $BUILD --prefix $DEST -``` - - -Use ---- - -Other projects can include libpqxx in their CMake builds. - -`@abrownsword` uses this configuration: - -```cmake - set(libpqxxdir "libpqxx-${LIBVERSION}") # LIBVERSION set above - set(SKIP_BUILD_TEST on) - set(BUILD_SHARED_LIBS OFF) - - # Used this instead of FindLibrary. - # Setting PostgresSQL_INCLUDE_DIRS externally. - set(PostgreSQL_FOUND true) - set(PostgresSQL_INCLUDE_DIR ${PostgresSQL_INCLUDE_DIRS}) - set(PostgresSQL_TYPE_INCLUDE_DIR ${PostgresSQL_INCLUDE_DIRS}) - - add_subdirectory(${libpqxxdir}) -``` diff --git a/ext/libpqxx-7.7.3/BUILDING-configure.md b/ext/libpqxx-7.7.3/BUILDING-configure.md deleted file mode 100644 index 7c63f5b4c..000000000 --- a/ext/libpqxx-7.7.3/BUILDING-configure.md +++ /dev/null @@ -1,275 +0,0 @@ -Building using `configure` -========================== - -The build requires `libpq`, the C client library for PostgreSQL. This library -must be installed before you can build libpqxx. You'll need the headers as -well as the library binary. - -The instructions will assume that you're working from a command-line shell. -If you prefer to work from an IDE, you'll have to know how your IDE likes to -do things, and you'll want to follow the shell instructions as a guide. - - -Quick start ------------ - -If you just want to get it built and installed quickly, try: - -```shell - ./configure - make - sudo make install -``` - -Want more detail? Read on. - - -Stages ------- - -I'll explain the main build steps in more detail below, but here's a quick -overview: -1. Configure -2. Compile -3. Test -4. Install - -The Test step is optional. - - -Configure ---------- - -The `configure` script configures your build. It figures out various -parameters, such as where libpq and its headers are, which C++ features your -compiler supports, and which options your compiler needs. It generates -Makefiles, which in turn tell the `make` utility how to perform tasks such as -compiling libpqxx, running tests, cleaning up after itself, and installing -libpqxx. - -The `configure` step is also where you can set these options, e.g. to instruct -the compiler to look for libpq in a non-standard place, or to use a different -compiler, or pass different compiler flags. Don't try to specify those while -doing the actual compile; set them once when running `configure`. - -Let's say `$BUILD` is the directory where you want to build libpqxx, and -`$SRC` is where its source code is. So for example, the readme file will be at -`$SRC/README.md`. - -In the simplest case, you just do: - -```shell - cd $BUILD - $SRC/configure -``` - -Add `configure` options as needed. There's more about the options below, or in -the output of `configure --help`. I'll also explain the two directories. - - -### Cheat sheet - -Here are some popular `configure` options: -* `--disable-documentation` skips building of the documentation. -* `CXXFLAGS=-O0` disables optimisation. Slower code, but faster build. -* `CXXFLAGS=-O3` asks for _more_ optimisation. Faster code, slower build. -* `CXX=clang++` compiles with `clang++` as the compiler. -* `--enable-maintainer-mode` makes the compiler more pedantic about the code. -* `--enable-audit` enables expensive run-time checks for debugging. -* `--with-postgres-lib=$DIR` looks for libpq in `$DIR`. -* `--with-postgres-include=$DIR` looks for the libpq headers in `$DIR`. -* `--prefix=$PATH` prepares to install libpqxx in `$PATH`. -* `--enable-shared` enables compilation of libpqxx as a shared library. -* `--disable-shared` disbles compilation of libpqxx as a shared library. -* `--enable-static` enables compilation of libpqxx as a static library. -* `--disable-static` disables compilation of libpqxx as a static library. -* `--help` shows you a lot more of the options. - -So for example, to get a very quick build but produce very inefficient code: - -```shell - ./configure --disable-documentation CXXFLAGS=-O0 -``` - - -Or if you want to pull out all the stops to find problems in the code: - -```shell - ./configure --enable-maintainer-mode --enable-audit CXXFLAGS=-O3 -``` - -(Requesting `-O3` optimisation will make some compilers perform extra analysis -which may, as a side effect, cause them to notice and warn about certain kinds -of mistakes in the code, such as occasionally-unused variables.) - - -### Finding libpq - -One of `configure`'s most important jobs in the libpqxx build is to find the -headers and library for libpq. It has three ways of finding those: -1. Asking a popular tool called `pkg-config`, if installed. -2. Asking postgres' deprecated `pg_config` tool, if installed. -3. Through explicit command-line options to `configure`. - -The explicit command-line options are `--with-postgres-lib` (for the libpq -library binary) and `--with-postgres-include` (for the libpq headers). - -If you want to use a version of libpq that's not installed in a standard -location, e.g. if you're cross-compiling to produce a binary for a different -CPU architecture than your native system's, use the explicit options. - - -### Where does the `configure` script come from? - -I didn't write the `configure` script. It was generated by GNU `autoconf` and -related GNU tools. There's a script to re-generate it, called `autogen.sh`. - -The contents of `configure` are based on a higher-level script called -`configure.ac`. This is where I script checks for specific features in libpq -or the compiler. The `configure` script adds a lot of built-in items that I -don't need to worry about, such as figuring out exactly how your build tools -work. - -Don't try to debug `configure` yourself if you can help it. It's very hard to -read, partly because it's automatically generated, but also because it is -engineered to work with an extremely broad range of shells, compilers, tools, -and operating systems. If you're going to do a "deep dive," try looking at -`configure.ac` instead. - - -### Source and Build trees - -Where should you run `configure`? - -Two directories matter when building libpqxx: the _source tree_ (where the -libpqxx source code is) and the _build tree_ (where you want your build -artefacts). Here I will call them `$SRC` and `$BUILD`, but you can call them -anything you like. - -They can be one and the same, if you like. It's convenient, but less clean, as -source code and build artefacts will exist in the same directory tree. If -you're going to delete the source tree after installing, of course it's fine to -make a mess in there. - - -Compile -------- - -To start the compile, run the `make` tool. It will go through all the steps to -produce a libpqxx library binary. - -Beware though, it only runs _one_ compiler process at a time. That could take -a while. Use the `-j` option to make it run concurrent processes, e.g.: - -```shell - make -j8 -``` - -Very roughly speaking, it's probably fastest if you run one process per CPU -core in your system. If you have the `nproc` utility installed: - -```shell - make -j$(nproc) -``` - -If you want a very fast build and don't mind missing out on efficient code or -documentation, tweak the Configure step above by adding `configure` options -like `CXXFLAGS=-O0` and `--disable-documentation`. - - -Test ----- - -Of course libpqxx comes with a test suite, to check that the library is -functioning correctly. - -You can run it, but there's one caveat: you need to give it a database where it -can log in, without a password or any other parameters, and try out various -things. - -And when I say you need to "give" it a database, I really mean "give." The -test suite will create and drop tables. Those will all have names prefixed -with "pqxx", so it's probably safe to use a database you already had, but if -any of the items in your database happen to have names starting with `pqxx`, -tough luck. They're fair game. - -Enter this in your shell to build and run the tests: - -```shell - make check -``` - -As with compiling, use the `-j` option to make better use of your CPUs. For -example: - -```shell - make check -j$(nproc) -``` - - -### Configuring the test database - -But what if you do need a password to log into your test database? Or, what if -it's running on a different system so you need to pass that machine's address? -What if it's not running on the default port? - -You can set these parameters for the test suite, or for any other libpq-based -application, using the following environment variables. (They only set default -values, so they won't override parameters that the application sets in some -other way.) -* `PGHOST` — the IP address where we can contact the database's socket. Or - for a Unix domain socket, its absolute path on the filesystem. -* `PGPORT` — -* `PGDATABASE` — the name of the database to which you wish to connect. -* `PGUSER` — user name under which you wish to log in on the database. -* `PGPASSWORD` — user name's password for accessing the database. - -See the full list at https://www.postgresql.org/docs/current/libpq-envars.html - -**Be careful with passwords,** by the way. Depending on your operating system -and configuration, an attacker with access to your machine could try to read -your password if you set it on the command line: -* Your shell may keep a log of the commands you have entered. -* Environment variables may be visible to other users on the system. - -If at all possible, rely on postgres "peer authentication." Once set up, it is -both more secure and more convenient than passwords. - - -Install -------- - -Installing libpqxx will install the library and headers in a location chosen at -the time you can the `configure` script. On some systems it defaults to the -`/usr/local/` tree, but it may be different in your environment. Or, use the -`configure` script's `--prefix` option to set an install location. - -(If you want to see exactly what happens, you can run any `make` command line -with the `-n` option, which means: don't actually do this, but print all the -commands you would execute if you did. It's a lot of output though.) - -To install, ensure that you have sufficient privileges to write the files to -their install locations, and run: - -```shell - make install -``` - -Save your build tree somewhere, so that you will be able to undo installation -in the future: - -```shell - make uninstall -``` - -When using the library, make sure the libpqxx headers are in your compiler's -include path. (You will no longer need the libpq headers at that time.) - -Also, building an application which uses libpqxx, make sure the libpqxx library -binary is in your compiler's library search path. And if the library binary is -a shared library, you'll also need it in your loader's search path when running -your application. - -This last part goes for libpq as well: when using libpq, make sure you have -the libpq library binary in your compiler's library search path, and if it's a -shared library, also have it in your loader's search path when running. diff --git a/ext/libpqxx-7.7.3/CMakeLists.txt b/ext/libpqxx-7.7.3/CMakeLists.txt deleted file mode 100644 index 55b3c4d44..000000000 --- a/ext/libpqxx-7.7.3/CMakeLists.txt +++ /dev/null @@ -1,66 +0,0 @@ -cmake_minimum_required(VERSION 3.8) - -file(READ VERSION VER_FILE_CONTENT) -string(STRIP ${VER_FILE_CONTENT} VER_FILE_CONTENT) - -project( - libpqxx - VERSION ${VER_FILE_CONTENT} - LANGUAGES CXX -) - -if(NOT "${CMAKE_CXX_STANDARD}") - set(CMAKE_CXX_STANDARD 17) -endif() -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) - -option(BUILD_DOC "Build documentation" OFF) - -if(NOT SKIP_BUILD_TEST) - option(BUILD_TEST "Build all test cases" ON) -endif() - -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) -include(config) - -add_subdirectory(src) -add_subdirectory(include) -if(BUILD_DOC) - add_subdirectory(doc) -endif() -if(BUILD_TEST) - add_subdirectory(test) -endif() - -# installation -write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config-version.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion -) -install(FILES cmake/libpqxx-config.cmake - "${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config-version.cmake" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libpqxx -) -install( - EXPORT libpqxx-targets - NAMESPACE libpqxx:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libpqxx -) -# Build tree export -export( - EXPORT libpqxx-targets - NAMESPACE libpqxx:: - FILE ${CMAKE_CURRENT_BINARY_DIR}/libpqxx-targets.cmake -) -configure_file( - cmake/libpqxx-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config.cmake - COPYONLY -) -# Package generation -set(CPACK_GENERATOR TGZ) -set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) -include(CPack) diff --git a/ext/libpqxx-7.7.3/COPYING b/ext/libpqxx-7.7.3/COPYING deleted file mode 100644 index 8a566aabe..000000000 --- a/ext/libpqxx-7.7.3/COPYING +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2000-2022 Jeroen T. Vermeulen. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the author, nor the names of other contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/ext/libpqxx-7.7.3/Makefile.am b/ext/libpqxx-7.7.3/Makefile.am deleted file mode 100644 index cd93a57ef..000000000 --- a/ext/libpqxx-7.7.3/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -SUBDIRS = include src test tools config doc -EXTRA_DIST = autogen.sh configitems README.md VERSION requirements.json - -MAINTAINERCLEANFILES = \ - Makefile.in aclocal.m4 config.h.in config.log configure stamp-h.in - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libpqxx.pc - -TESTS = tools/lint - - -# Generate ChangeLog from git history. It goes all the way back through -# the project's git, bzr, svn, and cvs days. -dist-hook: ChangeLog - -ChangeLog: configure.ac - git log --stat --name-only --date=short --abbrev-commit >$@ - - -# We use README.md, but automake expects plain README. -README: README.md - ln -s $< $@ diff --git a/ext/libpqxx-7.7.3/Makefile.in b/ext/libpqxx-7.7.3/Makefile.in deleted file mode 100644 index f6798aa75..000000000 --- a/ext/libpqxx-7.7.3/Makefile.in +++ /dev/null @@ -1,1253 +0,0 @@ -# Makefile.in generated by automake 1.16.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2021 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = . -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ - $(top_srcdir)/config/m4/ltoptions.m4 \ - $(top_srcdir)/config/m4/ltsugar.m4 \ - $(top_srcdir)/config/m4/ltversion.m4 \ - $(top_srcdir)/config/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ - $(am__configure_deps) $(am__DIST_COMMON) -am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ - configure.lineno config.status.lineno -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h -CONFIG_CLEAN_FILES = libpqxx.pc compile_flags -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ - ctags-recursive dvi-recursive html-recursive info-recursive \ - install-data-recursive install-dvi-recursive \ - install-exec-recursive install-html-recursive \ - install-info-recursive install-pdf-recursive \ - install-ps-recursive install-recursive installcheck-recursive \ - installdirs-recursive pdf-recursive ps-recursive \ - tags-recursive uninstall-recursive -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(pkgconfigdir)" -DATA = $(pkgconfig_DATA) -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -am__recursive_targets = \ - $(RECURSIVE_TARGETS) \ - $(RECURSIVE_CLEAN_TARGETS) \ - $(am__extra_recursive_targets) -AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - cscope check recheck distdir distdir-am dist dist-all \ - distcheck -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -am__tty_colors_dummy = \ - mgn= red= grn= lgn= blu= brg= std=; \ - am__color_tests=no -am__tty_colors = { \ - $(am__tty_colors_dummy); \ - if test "X$(AM_COLOR_TESTS)" = Xno; then \ - am__color_tests=no; \ - elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ - am__color_tests=yes; \ - elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ - am__color_tests=yes; \ - fi; \ - if test $$am__color_tests = yes; then \ - red=''; \ - grn=''; \ - lgn=''; \ - blu=''; \ - mgn=''; \ - brg=''; \ - std=''; \ - fi; \ -} -am__recheck_rx = ^[ ]*:recheck:[ ]* -am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* -am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* -# A command that, given a newline-separated list of test names on the -# standard input, print the name of the tests that are to be re-run -# upon "make recheck". -am__list_recheck_tests = $(AWK) '{ \ - recheck = 1; \ - while ((rc = (getline line < ($$0 ".trs"))) != 0) \ - { \ - if (rc < 0) \ - { \ - if ((getline line2 < ($$0 ".log")) < 0) \ - recheck = 0; \ - break; \ - } \ - else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ - { \ - recheck = 0; \ - break; \ - } \ - else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ - { \ - break; \ - } \ - }; \ - if (recheck) \ - print $$0; \ - close ($$0 ".trs"); \ - close ($$0 ".log"); \ -}' -# A command that, given a newline-separated list of test names on the -# standard input, create the global log from their .trs and .log files. -am__create_global_log = $(AWK) ' \ -function fatal(msg) \ -{ \ - print "fatal: making $@: " msg | "cat >&2"; \ - exit 1; \ -} \ -function rst_section(header) \ -{ \ - print header; \ - len = length(header); \ - for (i = 1; i <= len; i = i + 1) \ - printf "="; \ - printf "\n\n"; \ -} \ -{ \ - copy_in_global_log = 1; \ - global_test_result = "RUN"; \ - while ((rc = (getline line < ($$0 ".trs"))) != 0) \ - { \ - if (rc < 0) \ - fatal("failed to read from " $$0 ".trs"); \ - if (line ~ /$(am__global_test_result_rx)/) \ - { \ - sub("$(am__global_test_result_rx)", "", line); \ - sub("[ ]*$$", "", line); \ - global_test_result = line; \ - } \ - else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ - copy_in_global_log = 0; \ - }; \ - if (copy_in_global_log) \ - { \ - rst_section(global_test_result ": " $$0); \ - while ((rc = (getline line < ($$0 ".log"))) != 0) \ - { \ - if (rc < 0) \ - fatal("failed to read from " $$0 ".log"); \ - print line; \ - }; \ - printf "\n"; \ - }; \ - close ($$0 ".trs"); \ - close ($$0 ".log"); \ -}' -# Restructured Text title. -am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } -# Solaris 10 'make', and several other traditional 'make' implementations, -# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it -# by disabling -e (using the XSI extension "set +e") if it's set. -am__sh_e_setup = case $$- in *e*) set +e;; esac -# Default flags passed to test drivers. -am__common_driver_flags = \ - --color-tests "$$am__color_tests" \ - --enable-hard-errors "$$am__enable_hard_errors" \ - --expect-failure "$$am__expect_failure" -# To be inserted before the command running the test. Creates the -# directory for the log if needed. Stores in $dir the directory -# containing $f, in $tst the test, in $log the log. Executes the -# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and -# passes TESTS_ENVIRONMENT. Set up options for the wrapper that -# will run the test scripts (or their associated LOG_COMPILER, if -# thy have one). -am__check_pre = \ -$(am__sh_e_setup); \ -$(am__vpath_adj_setup) $(am__vpath_adj) \ -$(am__tty_colors); \ -srcdir=$(srcdir); export srcdir; \ -case "$@" in \ - */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ - *) am__odir=.;; \ -esac; \ -test "x$$am__odir" = x"." || test -d "$$am__odir" \ - || $(MKDIR_P) "$$am__odir" || exit $$?; \ -if test -f "./$$f"; then dir=./; \ -elif test -f "$$f"; then dir=; \ -else dir="$(srcdir)/"; fi; \ -tst=$$dir$$f; log='$@'; \ -if test -n '$(DISABLE_HARD_ERRORS)'; then \ - am__enable_hard_errors=no; \ -else \ - am__enable_hard_errors=yes; \ -fi; \ -case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ - am__expect_failure=yes;; \ - *) \ - am__expect_failure=no;; \ -esac; \ -$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) -# A shell command to get the names of the tests scripts with any registered -# extension removed (i.e., equivalently, the names of the test logs, with -# the '.log' extension removed). The result is saved in the shell variable -# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, -# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", -# since that might cause problem with VPATH rewrites for suffix-less tests. -# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. -am__set_TESTS_bases = \ - bases='$(TEST_LOGS)'; \ - bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ - bases=`echo $$bases` -AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' -RECHECK_LOGS = $(TEST_LOGS) -TEST_SUITE_LOG = test-suite.log -TEST_EXTENSIONS = @EXEEXT@ .test -LOG_DRIVER = $(SHELL) $(top_srcdir)/config/test-driver -LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) -am__set_b = \ - case '$@' in \ - */*) \ - case '$*' in \ - */*) b='$*';; \ - *) b=`echo '$@' | sed 's/\.log$$//'`; \ - esac;; \ - *) \ - b='$*';; \ - esac -am__test_logs1 = $(TESTS:=.log) -am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) -TEST_LOGS = $(am__test_logs2:.test.log=.log) -TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/config/test-driver -TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ - $(TEST_LOG_FLAGS) -DIST_SUBDIRS = $(SUBDIRS) -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/compile_flags.in \ - $(srcdir)/libpqxx.pc.in $(top_srcdir)/config/compile \ - $(top_srcdir)/config/config.guess \ - $(top_srcdir)/config/config.sub \ - $(top_srcdir)/config/install-sh $(top_srcdir)/config/ltmain.sh \ - $(top_srcdir)/config/missing \ - $(top_srcdir)/config/mkinstalldirs \ - $(top_srcdir)/config/test-driver AUTHORS COPYING ChangeLog \ - INSTALL NEWS README README.md -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -distdir = $(PACKAGE)-$(VERSION) -top_distdir = $(distdir) -am__remove_distdir = \ - if test -d "$(distdir)"; then \ - find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -rf "$(distdir)" \ - || { sleep 5 && rm -rf "$(distdir)"; }; \ - else :; fi -am__post_remove_distdir = $(am__remove_distdir) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -DIST_ARCHIVES = $(distdir).tar.gz -GZIP_ENV = --best -DIST_TARGETS = dist-gzip -# Exists only to be overridden by the user if desired. -AM_DISTCHECK_DVI_TARGET = dvi -distuninstallcheck_listfiles = find . -type f -print -am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ - | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' -distcleancheck_listfiles = find . -type f -print -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSCOPE = @CSCOPE@ -CTAGS = @CTAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ETAGS = @ETAGS@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_DOT = @HAVE_DOT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR = @MKDIR@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PG_CONFIG = @PG_CONFIG@ -PKG_CONFIG = @PKG_CONFIG@ -POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ -PQXXVERSION = @PQXXVERSION@ -PQXX_ABI = @PQXX_ABI@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_postgres_lib = @with_postgres_lib@ -SUBDIRS = include src test tools config doc -EXTRA_DIST = autogen.sh configitems README.md VERSION requirements.json -MAINTAINERCLEANFILES = \ - Makefile.in aclocal.m4 config.h.in config.log configure stamp-h.in - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libpqxx.pc -TESTS = tools/lint -all: all-recursive - -.SUFFIXES: -.SUFFIXES: .log .test .test$(EXEEXT) .trs -am--refresh: Makefile - @: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ - $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - echo ' $(SHELL) ./config.status'; \ - $(SHELL) ./config.status;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - $(SHELL) ./config.status --recheck - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - $(am__cd) $(srcdir) && $(AUTOCONF) -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) -$(am__aclocal_m4_deps): -libpqxx.pc: $(top_builddir)/config.status $(srcdir)/libpqxx.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $@ -compile_flags: $(top_builddir)/config.status $(srcdir)/compile_flags.in - cd $(top_builddir) && $(SHELL) ./config.status $@ - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool config.lt -install-pkgconfigDATA: $(pkgconfig_DATA) - @$(NORMAL_INSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ - done - -uninstall-pkgconfigDATA: - @$(NORMAL_UNINSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) - -# This directory's subdirectories are mostly independent; you can cd -# into them and run 'make' without going through this Makefile. -# To change the values of 'make' variables: instead of editing Makefiles, -# (1) if the variable is set in 'config.status', edit 'config.status' -# (which will cause the Makefiles to be regenerated when you run 'make'); -# (2) otherwise, pass the desired values on the 'make' command line. -$(am__recursive_targets): - @fail=; \ - if $(am__make_keepgoing); then \ - failcom='fail=yes'; \ - else \ - failcom='exit 1'; \ - fi; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-recursive -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-recursive - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscope: cscope.files - test ! -s cscope.files \ - || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) -clean-cscope: - -rm -f cscope.files -cscope.files: clean-cscope cscopelist -cscopelist: cscopelist-recursive - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -rm -f cscope.out cscope.in.out cscope.po.out cscope.files - -# Recover from deleted '.trs' file; this should ensure that -# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create -# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells -# to avoid problems with "make -n". -.log.trs: - rm -f $< $@ - $(MAKE) $(AM_MAKEFLAGS) $< - -# Leading 'am--fnord' is there to ensure the list of targets does not -# expand to empty, as could happen e.g. with make check TESTS=''. -am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) -am--force-recheck: - @: - -$(TEST_SUITE_LOG): $(TEST_LOGS) - @$(am__set_TESTS_bases); \ - am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ - redo_bases=`for i in $$bases; do \ - am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ - done`; \ - if test -n "$$redo_bases"; then \ - redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ - redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ - if $(am__make_dryrun); then :; else \ - rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ - fi; \ - fi; \ - if test -n "$$am__remaking_logs"; then \ - echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ - "recursion detected" >&2; \ - elif test -n "$$redo_logs"; then \ - am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ - fi; \ - if $(am__make_dryrun); then :; else \ - st=0; \ - errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ - for i in $$redo_bases; do \ - test -f $$i.trs && test -r $$i.trs \ - || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ - test -f $$i.log && test -r $$i.log \ - || { echo "$$errmsg $$i.log" >&2; st=1; }; \ - done; \ - test $$st -eq 0 || exit 1; \ - fi - @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ - ws='[ ]'; \ - results=`for b in $$bases; do echo $$b.trs; done`; \ - test -n "$$results" || results=/dev/null; \ - all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ - pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ - fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ - skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ - xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ - xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ - error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ - if test `expr $$fail + $$xpass + $$error` -eq 0; then \ - success=true; \ - else \ - success=false; \ - fi; \ - br='==================='; br=$$br$$br$$br$$br; \ - result_count () \ - { \ - if test x"$$1" = x"--maybe-color"; then \ - maybe_colorize=yes; \ - elif test x"$$1" = x"--no-color"; then \ - maybe_colorize=no; \ - else \ - echo "$@: invalid 'result_count' usage" >&2; exit 4; \ - fi; \ - shift; \ - desc=$$1 count=$$2; \ - if test $$maybe_colorize = yes && test $$count -gt 0; then \ - color_start=$$3 color_end=$$std; \ - else \ - color_start= color_end=; \ - fi; \ - echo "$${color_start}# $$desc $$count$${color_end}"; \ - }; \ - create_testsuite_report () \ - { \ - result_count $$1 "TOTAL:" $$all "$$brg"; \ - result_count $$1 "PASS: " $$pass "$$grn"; \ - result_count $$1 "SKIP: " $$skip "$$blu"; \ - result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ - result_count $$1 "FAIL: " $$fail "$$red"; \ - result_count $$1 "XPASS:" $$xpass "$$red"; \ - result_count $$1 "ERROR:" $$error "$$mgn"; \ - }; \ - { \ - echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ - $(am__rst_title); \ - create_testsuite_report --no-color; \ - echo; \ - echo ".. contents:: :depth: 2"; \ - echo; \ - for b in $$bases; do echo $$b; done \ - | $(am__create_global_log); \ - } >$(TEST_SUITE_LOG).tmp || exit 1; \ - mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ - if $$success; then \ - col="$$grn"; \ - else \ - col="$$red"; \ - test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ - fi; \ - echo "$${col}$$br$${std}"; \ - echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ - echo "$${col}$$br$${std}"; \ - create_testsuite_report --maybe-color; \ - echo "$$col$$br$$std"; \ - if $$success; then :; else \ - echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ - if test -n "$(PACKAGE_BUGREPORT)"; then \ - echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ - fi; \ - echo "$$col$$br$$std"; \ - fi; \ - $$success || exit 1 - -check-TESTS: - @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list - @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list - @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) - @set +e; $(am__set_TESTS_bases); \ - log_list=`for i in $$bases; do echo $$i.log; done`; \ - trs_list=`for i in $$bases; do echo $$i.trs; done`; \ - log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ - $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ - exit $$?; -recheck: all - @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) - @set +e; $(am__set_TESTS_bases); \ - bases=`for i in $$bases; do echo $$i; done \ - | $(am__list_recheck_tests)` || exit 1; \ - log_list=`for i in $$bases; do echo $$i.log; done`; \ - log_list=`echo $$log_list`; \ - $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ - am__force_recheck=am--force-recheck \ - TEST_LOGS="$$log_list"; \ - exit $$? -tools/lint.log: tools/lint - @p='tools/lint'; \ - b='tools/lint'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -.test.log: - @p='$<'; \ - $(am__set_b); \ - $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -@am__EXEEXT_TRUE@.test$(EXEEXT).log: -@am__EXEEXT_TRUE@ @p='$<'; \ -@am__EXEEXT_TRUE@ $(am__set_b); \ -@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ -@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ -@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ -@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - $(am__remove_distdir) - test -d "$(distdir)" || mkdir "$(distdir)" - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-hook - -test -n "$(am__skip_mode_fix)" \ - || find "$(distdir)" -type d ! -perm -755 \ - -exec chmod u+rwx,go+rx {} \; -o \ - ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ - || chmod -R a+r "$(distdir)" -dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz - $(am__post_remove_distdir) - -dist-bzip2: distdir - tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 - $(am__post_remove_distdir) - -dist-lzip: distdir - tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz - $(am__post_remove_distdir) - -dist-xz: distdir - tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz - $(am__post_remove_distdir) - -dist-zstd: distdir - tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst - $(am__post_remove_distdir) - -dist-tarZ: distdir - @echo WARNING: "Support for distribution archives compressed with" \ - "legacy program 'compress' is deprecated." >&2 - @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__post_remove_distdir) - -dist-shar: distdir - @echo WARNING: "Support for shar distribution archives is" \ - "deprecated." >&2 - @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz - $(am__post_remove_distdir) - -dist-zip: distdir - -rm -f $(distdir).zip - zip -rq $(distdir).zip $(distdir) - $(am__post_remove_distdir) - -dist dist-all: - $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' - $(am__post_remove_distdir) - -# This target untars the dist file and tries a VPATH configuration. Then -# it guarantees that the distribution is self-contained by making another -# tarfile. -distcheck: dist - case '$(DIST_ARCHIVES)' in \ - *.tar.gz*) \ - eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ - *.tar.bz2*) \ - bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.lz*) \ - lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ - *.tar.xz*) \ - xz -dc $(distdir).tar.xz | $(am__untar) ;;\ - *.tar.Z*) \ - uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ - *.shar.gz*) \ - eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ - *.zip*) \ - unzip $(distdir).zip ;;\ - *.tar.zst*) \ - zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ - esac - chmod -R a-w $(distdir) - chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst - chmod a-w $(distdir) - test -d $(distdir)/_build || exit 0; \ - dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ - && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ - && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build/sub \ - && ../../configure \ - $(AM_DISTCHECK_CONFIGURE_FLAGS) \ - $(DISTCHECK_CONFIGURE_FLAGS) \ - --srcdir=../.. --prefix="$$dc_install_base" \ - && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ - && $(MAKE) $(AM_MAKEFLAGS) check \ - && $(MAKE) $(AM_MAKEFLAGS) install \ - && $(MAKE) $(AM_MAKEFLAGS) installcheck \ - && $(MAKE) $(AM_MAKEFLAGS) uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ - distuninstallcheck \ - && chmod -R a-w "$$dc_install_base" \ - && ({ \ - (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ - distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ - } || { rm -rf "$$dc_destdir"; exit 1; }) \ - && rm -rf "$$dc_destdir" \ - && $(MAKE) $(AM_MAKEFLAGS) dist \ - && rm -rf $(DIST_ARCHIVES) \ - && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ - && cd "$$am__cwd" \ - || exit 1 - $(am__post_remove_distdir) - @(echo "$(distdir) archives ready for distribution: "; \ - list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' -distuninstallcheck: - @test -n '$(distuninstallcheck_dir)' || { \ - echo 'ERROR: trying to run $@ with an empty' \ - '$$(distuninstallcheck_dir)' >&2; \ - exit 1; \ - }; \ - $(am__cd) '$(distuninstallcheck_dir)' || { \ - echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ - exit 1; \ - }; \ - test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left after uninstall:" ; \ - if test -n "$(DESTDIR)"; then \ - echo " (check DESTDIR support)"; \ - fi ; \ - $(distuninstallcheck_listfiles) ; \ - exit 1; } >&2 -distcleancheck: distclean - @if test '$(srcdir)' = . ; then \ - echo "ERROR: distcleancheck can only run from a VPATH build" ; \ - exit 1 ; \ - fi - @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left in build directory after distclean:" ; \ - $(distcleancheck_listfiles) ; \ - exit 1; } >&2 -check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) check-TESTS -check: check-recursive -all-am: Makefile $(DATA) -installdirs: installdirs-recursive -installdirs-am: - for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) - -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) - -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-recursive - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-recursive - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-libtool \ - distclean-tags - -dvi: dvi-recursive - -dvi-am: - -html: html-recursive - -html-am: - -info: info-recursive - -info-am: - -install-data-am: install-pkgconfigDATA - -install-dvi: install-dvi-recursive - -install-dvi-am: - -install-exec-am: - -install-html: install-html-recursive - -install-html-am: - -install-info: install-info-recursive - -install-info-am: - -install-man: - -install-pdf: install-pdf-recursive - -install-pdf-am: - -install-ps: install-ps-recursive - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf $(top_srcdir)/autom4te.cache - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-recursive - -pdf-am: - -ps: ps-recursive - -ps-am: - -uninstall-am: uninstall-pkgconfigDATA - -.MAKE: $(am__recursive_targets) check-am install-am install-strip - -.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ - am--refresh check check-TESTS check-am clean clean-cscope \ - clean-generic clean-libtool cscope cscopelist-am ctags \ - ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \ - dist-lzip dist-shar dist-tarZ dist-xz dist-zip dist-zstd \ - distcheck distclean distclean-generic distclean-libtool \ - distclean-tags distcleancheck distdir distuninstallcheck dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - installdirs-am maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ - ps ps-am recheck tags tags-am uninstall uninstall-am \ - uninstall-pkgconfigDATA - -.PRECIOUS: Makefile - - -# Generate ChangeLog from git history. It goes all the way back through -# the project's git, bzr, svn, and cvs days. -dist-hook: ChangeLog - -ChangeLog: configure.ac - git log --stat --name-only --date=short --abbrev-commit >$@ - -# We use README.md, but automake expects plain README. -README: README.md - ln -s $< $@ - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ext/libpqxx-7.7.3/NEWS b/ext/libpqxx-7.7.3/NEWS deleted file mode 100644 index 102716c2e..000000000 --- a/ext/libpqxx-7.7.3/NEWS +++ /dev/null @@ -1,1040 +0,0 @@ -7.7.3 - - Fix up more damage done by auto-formatting. - - New `result::for_each()`: simple iteration and conversion of rows. (#528) - - Add some missing headers in ``. (#551) - - More strictness in `header-pre.hxx`/`header-post.hxx` checking. - - Disallow nesting of `ignore-deprecated` blocks. - - Deprecate `exec` functions' `desc` parameter. - - Fix `placeholders` documentation. (#557) - - Strip `const` and references from `value_type`. (#558) - - Get tests running on appveyor. (#560) - - Fix broken nonblocking connection on Windows. (#560) -7.7.2 - - Fix up damage done by auto-formatting. -7.7.1 - - When you build libpqxx, configure the compiler's C++ version yourself! - - Finally fix a long-standing silly warning in autogen. - - Fix `digit_to_number` not being found on some comilers. (#518, #519) - - In audit mode, define `_FORTIFY_SOURCE` to enable some extra checks. - - Make more functions `constexpr`. Nothing particularly useful though. - - Make more functions `noexcept`. - - Move constructor & assignment for `result`. - - Support LGTM.com and Facebook "infer" static analysis. - - Deprecated `set_variable`/`get_variable` on `transaction_base`. - - (Design unearthed warts in SQL variables, which were then fixed.) - - Set/get session variables on `connection`: `set_session_var`/`get_var`. - - Set/get local variables: execute SQL statements. - - When using `select()`, include `` if available. -7.7.0 - - Fix `stream_to` for differing table/client encodings. (#473) - - Use `[[likely]]` & `[[unlikely]]` only in C++20, to silence warnings. - - Fix clang "not a const expression" error in Windows. (#472) - - Fix warnings about `[[likely]]` in `if constexpr`. (#475) - - Clearer error for ambiguous string conversion of `char` type. (#481) - - Pseudo-statement in `prepare()` error was for the wrong statement. (#488) - - New class, `connecting` for nonblocking connection to the database. (#487) - - New class, `range` for SQL range types. (#490) - - Replace `std::isdigit` with a safer alternative. - - Support string conversions for `std::chrono::year_month_day`. (#492) - - Helper for implementing string traits: `generic_to_buf`. - - Support `result::at(row_num, col_num)`. - - Support `result[row_num, col_num]` if the compiler allows it. - - Work around broken `std::filesystem::path` in MinGW. (#498) - - Fix leak when getting client encoding fails. (#500) - - Use `std::cmp_greater` etc. when available. Saves some ugly casts. - - Move `result_iterator.hxx` into `pqxx/include/internal/`. - - Move `compiler-public.hxx` into `pqxx/include/internal/`. - - Add script for updating copyright strings. - - Make `tools/lint` figure out source directory by itself. - - Pass the actual C++ version to `tools/lint`, not the baseline one. - - Re-enable pyflakes testing in `tools/lint`. - - Make more functions `[[nodiscard]]`. - - Qualified some member functions as lvalue or rvalue. - - Don't run clang-tidy by default. Compatibility issues with gcc options. - - Describe version requirements in a JSON file, `requirements.json`. - - Doxygen documentation now uses the (Doxygen-extended) Markdown format. - - Build docs in `doc/html/`, no longer in `doc/html/Reference/`. - - Disable some `std::filesystem` features on Windows. - - Shut up stupid Visual Studio warnings. - - On gcc, mark rarely-used functions as "cold," to be optimised for size. - - Glyph scanning for GB18030 encoding was utterly broken. (#517) -7.6.0 - - Removed bad string conversion to `std::basic_string_view`. (#463) - - Add C++20 concepts: `binary`, `char_string`, `char_strings`. - - Generalise binary strings to any contiguous range of `std::byte`. - - Mark `zview` as a view and as a borrowed range. - - Save a copy step on string fields in `stream_to`. - - New helper: `pqxx::value_type`. - - New helper: `pqxx::binary_cast`. (#450) - - Some escaping functions now have "into my buffer" variants. - - More generic escaping functions, supporting more types of binary. - - In C++20, accept generic columns list for `stream_to`. (#447) - - Renamed `` to ``. - - Deprecated `dynamic_params` in favour of `params`. - - `pqxx::params::append_multi()` now calls `reserve()` if possible. - - `pqxx::params::size()` is now `noexcept` (but sadly, `ssize()` is not). - - Helper for generating parameter placeholders `$1`, `$2`, etc. (#443) - - Now requires support for C++14 `[[deprecated]]` attribute. - - Deprecated `unesc_raw()` with `unesc_bin()` variants. - - Once `unesc_raw()` is gone, we'll support only the hex escape format. - - Work around broken `thread_local` in MinGW gcc < 11.1. - - `pqxx::blob` now supports `std::filesystem::path`. - - Fixed check against header/lib version mismatch: `check_pqxx_version_7_6` - - Deprecated result slicing. Expect `row::slice()` to disappear. - - More complete documentation, of cursors in particular. -7.5.2 - - **Actual serious bug.** `blob::read(std::vector<...>)` was broken. -7.5.1 - - Fixed some Visual Studio warnings. - - Missed a bit in working around MinGW's broken ``. - - Deprecated more obsolete representations of binary data. Use `std::byte`. - - New script `tools/deprecations` lists files that use deprecated code. - - Added automake-generated `config/compile` to revision control. -7.5.0 - - Now requires `std::variant` support! No longer works with gcc7. - - When implementing a string conversion, consider specialising `param_format`. - - Stop "aborting" nontransaction on closing. (#419) - - Silence an overzealous Visual C++ warning. (#418) - - Starting support for C++20 `std::span`. - - New `blob::read()` using `std::span`. (#429) - - New `params` class lets you build parameter lists incrementally. (#387) - - Pass `std::vector` params in binary format. - - Dropped legacy tests 31 and 49 to work around clang C++20 bug. - - Fixed `stream_to` test failure in non-English locales. (#440) - - Clarify `transaction_base::stream` documentation. (#423) - - Avoid `` on MinGW; it's broken there. (#336, #398, #424, #441) -7.4.1 - - Missing includes; broke macOS clang build. (#416) -7.4.0 - - Work around Visual Studio 2017 bug with `[[deprecated]]`. (#405, #406) - - Work around eternal Windows bug with `max` macro yet again. (#101) - - Prepare for C++20 `std::ssize()`. - - Dropped test12, which didn't add much and tried to read null strings. - - Support string conversion for `std::monostate`. (#409) - - Consistent "named constructors" for `stream_to` and `stream_from`. - - New `table_path` type. - - New `connection` methods `quote_table` and `quote_columns`. - - Lots of deprecated stream constructors. - - `pqxx::row::swap()` now finally has the `deprecated` attribute. - - Finally deprecated a bunch of `field`, `row`, and `result` constructors. - - Exposed `transaction_focus` marker class. -7.3.1 - - New, simpler API for large objects: `blob` ("binary large object"). - - `largeobject` and friends are now deprecated. - - Fix visibility issue on gcc/clang, especially on macOS. (#395) - - Use "pure" & "visibility" attributes if they work, regardless of compiler. - - More deprecated items now have the `[[deprecated]]` attribute. - - Document the concept of transaction focus. - - Error messages more often report query description, if given. - - Suppress spurious deprecation messages on Visual Studio. (#402) - - Correct error when prepared/param statement clashes with tx focus. (#401) - - `from_stream` with `from_query` now has a convenient factory function. - - Removed some obsolete scripts from the `tools/` directory. -7.3.0 - - `stream_to` now quotes and escapes its table name. - - Removed `transaction_base::classname()`. Did anyone ever use it? - - Internal reorg of the `transaction` and `transactionfocus` hierarchies. - - Removed the only case of virtual inheritance, related to `namedclass`. - - Internal `concat()` for faster, simpler string concatentation. - - Fix compile omission in string conversions for `nullptr_t`. - - `pqxx::size_buffer()` can now size multiple values at once. - - `multi_to_string()` to convert multiple values into one `std::string`. - - Implicit `zview` constructor from `char const *`. (#389) - - Many `std::string&` parameters are now `zview` or `std::string_view`. - - Now checking statement parameter lengths for overflow. - - `#include ` in connection.cxx. (#394) -7.2.1 - - Fix infinite loop in converting `char *` to string. (#377) - - Deprecated `namedclass`. - - Convert an entire row using `row::as()`. - - Internal rework of `field::to()` and `field::as()` functions. - - Some more warning options in maintainer mode. - - Removed the old, DocBook-based tutorial. - - Fixed wrong `query` and SQLSTATE params to some exceptions. (#378) -7.2.0 - - You can now implicitly convert a `const std::string &` to `zview`. - - Replaced some overloads for C strings and C++ strings with `zview`. - - Deprecating `binarystring`. Use `std::basic_string` instead! - - Array parser did not recognise escaping in unquoted values. - - gcc10 test build fix: a result iterator is not the same thing as a `row`. - - Doc fix: field size does _not_ include terminating zero. (#356) - - Fix error message in `demangle_type_name`: printed result, not raw name. - - Fix compile warning in `demangle_type_name` on GNU systems. - - Document that string conversions assume non-null values. - - Start playing with C++20 _concepts._ - - Sketch out concepts-based `PQconnectdbParams` support. (#343) - - Add missing link to "datatypes" documentation. (#346) - - Supports `to_string`, `stream_to`, etc. for `binarystring`. (#312) - - Fixed infinite recursion when using `std::optional` in `stream_to`. (#364) - - Home-rolled hex-escaping. Saves an allocation. - - Catch floating-point negative overflow in `check_cast`, not underflow. - - Bit more work on CMake build doc. (#318) - - Typo in `datatypes.md`: `nullness`, not `nullness_traits`. (#353) - - Fixed test names map in `tests/runner.cxx`. (#354) - - Integral `from_string` now accept leading whitespace, as in composite types. - - Experimental support basics for composite types. (#355) - - Use `stream_from` without knowing the number of fields. (#357) - - Global `size_buffer` function. - - `quote()` now works for always-null types without conversions defined. - - `std::nullopt` now converts to an SQL null. - - Skip quoting and escaping array/composite fields of "safe" types. - - New type trait: `is_unquoted_safe`. - - Forbid invalid specialisations of `query_value`. - - Fixed `mktemp` invocation that broke on FreeBSD. - - Avoid unneeded encode/decode step on more binary data. - - If `__cxa_demangle` fails, fall back on raw type name. (#361) -7.1.2 - - Document build in `BUILDING-configure.md` / `BUILDING-cmake.md`. - - Work around silly clang warning in `test_errorhandler.cxx`. - - Fix install error with some internal headers. (#322) - - Fix "No object selected" error message in large objects. (#324) - - If error has no SQLSTATE, throw `broken_connection`. (#280) - - Fix argument order in `encrypt_password`. (#333, #334) - - Fix underestimate of buffer size for `to_string` for floats. (#328) -7.1.1 - - Compile fix for Visual Studio. - - Warning fix for clang. - - Also install `transaction_focus.hxx`. (#320) -7.1.0 - - Query tuples straight into `std::tuple` using `transaction::stream()`! - - And, `stream_from` now supports more or less arbitrary queries. - - Instead of a tuple of fields, you can pass `stream_to` a container as well. - - `string_traits::size_buffer()` must now be `noexcept`. - - New `nullness` member: `always_null`. - - There is now `to_buf` support for string literals. - - Streaming data is now more efficient. - - The table name in `stream_from` is now escaped. - - You can now "convert" strings to `std::string_view`. Mind your lifetimes! - - A `std::variant` will now convert to string, if its member types do. - - If a `stream_from` row fails to convert, you can no longer retry it. - - `from_string(field const &)` now handles null values properly. - - Obsolete Windows build docs are gone. - - Added `row::to(std::tuple<...>)`. - - Unified the test suites. We no longer need `test/unit/unit_runner`. - - New helper: `strip_t<...>` to remove a type's constness and reference. - - Replace custom templating with CMake glob in `src/CMakeLists.txt`. - - Replace custom templating with CMake glob in `doc/CMakeLists.txt`. - - Replace custom templating with CMake glob in `test/unit/CMakeLists.txt`. -7.0.8 - - Inline `type_name` in `PQXX_DECLARE_ENUM_CONVERSION`. -7.0.7 - - Fix broken `--with-postgres-lib` option in `configure` script (#311) - - Should now build even if neither `pkg-config` nor `pg_config` is available. - - CMake accepts `PostgreSQL_ROOT`, if it's a sufficiently recent version. -7.0.6 - - Prefer `pg_config` over `pkg-config` for include path (#291). - - Try to plod on if we don't know the PostgreSQL include path. - - Fix error message when starting overlapping transactions and such (#303). - - Fix potential crashes when converting invalid strings to floats (#307, #308). -7.0.5 - - Compile fix for g++ 10: include `` (#292). - - Cleaned up error-checking of PG results. (#280). - - The `esc()` methods now also take `std::string_view` (#295). -7.0.4 - - Fix possible crash in `connection::connection_string` (#290). - - Fix filtering of default values in `connection::connection_string` (#288). - - Deprecate `row::swap` and public inheritance of iterators from `row`. - - More copy/move/default constructors/assignments on result iterators. - - More copy/move/default constructors/assignments on row iterators. -7.0.3 - - Fixed misreporting of broken connection as `sql_error` (#280). - - Replaced non-ASCII test texts with escape codes (#282, #283). - - `ilostream` could truncate at `0xff` byte at buffer boundary (#284, #286). -7.0.2 - - New query function: `query_value`, queries and converts a single value. - - A `stream_from` stream can now be iterated. - - More callable types qualify as transactors, thanks to `std::invoke`. -7.0.1 - - Windows build fixes. - - Documentation for writing your own string conversions. - - `transaction_rollback` and children are now `sql_error`, not just `failure`. -7.0.0 - - Bumped minimum required C++ version to C++17. - - Everything has changed. If you're porting from older versions, be careful! - - There is now only one connection class: `connection`. - - Removed tablereader/tablewriter, replaced by stream_from/stream_to. - - Removed obsolete transactor framework, replaced by post-C++11 one. - - Removed old ways of invoking parameterised and prepared statements. - - Session variables are no longer cached. - - If you do weird stuff with setting/getting variables, it may break. - - Reading a variable written from raw SQL, procedures, etc, will now work. - - Prepared statements are now registered immediately. - - If you do weird stuff with preparing/unpreparing statements, it may break. - - Changed exceptions and errors for many error situations. - - Mishandling prepared statements will now break the connection. - - Many string references and const char pointers are now `std::string_view`. - - New `zview` class wraps `string_view` for string with terminating zero. - - The `stream_base` abstract base class is gone. - - Transactions no longer have an `isolation_tag` nested type. - - The `isolation_traits` type is gone. - - There's no more `pqxx_exception`. Complicated things too much. - - `pqxx::string_traits<>::name()` has been replaced with `pqxx::type_name`. - - `to_string()` can now handle `std::vector` (to produce an SQL array). - - All `from_string()` that took a C string now take a `std::string_view`. - - There are now separate `string_traits` and `null_traits` templates. - - Enums outside classes are now scoped enums. - - `error_verbosity` is no longer nested in connection. - - `connection::get_verbosity` is gone. - - Some enums have changed names: `accesspolicy` to `access_policy`, and so on. - - `dynamic_params` now accepts an accessor. - - Fixed "const" support in arguments to parameterised/prepared statements. - - Connection objects can now be moved. - - `connections::options()` has been replaced by `connection_string()`. - - Replaced pqxx-fulltest with `test_all.py`. - - Some `size_type` have changed to different types, to match current libpq. - - Internal overflows are more consistently caught and reported. - - Deprecated items have been removed. - - Large objects now require backend version 9.3 or better. - - Seeking inside large objects now supports 64-bit sizes. - - Visual Studio project files and sample headers are gone. Use CMake. - - MinGW Makefiles are gone. Use `configure` or CMake. - - Need PostgreSQL 10 to use robusttransaction. - - `robusttransaction` no longer uses a log table. Feel free to drop it. -6.4.4 - - Use pkg-config if pg-config is not available. - - In CMake build, prefer CMake's config headers over any found in source tree. -6.4.3 - - Updated copyright strings. - - Added missing "stream" headers to autotools-based install. - - Added stream headers to pqxx/pqxx header. -6.4.2 - - Fix mistake for Windows in 6.4.1: use PQfreemem, not std::free. - - Easily enable runtime checks in configure: "--enable-audit". - - Enable optimisation in CircleCI build. -6.4.1 - - Fixed more memory leaks. -6.4.0 - - Half fix, half work around nasty notice processor life time bug. - - Fix selective running of tests: "test/unit/runner test_infinities". - - Added some missing `std::` qualifications. -6.3.3 - - Throw more appropriate error when unable to read client encoding. - - CMake build fixes. -6.3.2 - - Conversion errors no longer throw pqxx::failure; always conversion_error! - - Use C++17's built-in numeric string conversions, if available. - - Query numeric precision in a more sensible, standard way. - - Avoid "dead code" warning. - - Replace obsolete autoconf macros. - - Remove all "using namespace std". - - CMake build fixes. -6.3.1 - - Windows compile fix (CALLBACK is a macro there). - - Work around Visual Studio 2017 not supporting ISO 646. -6.3.0 - - New "table stream" classes by Joseph Durel: stream_from/stream_to. - - Support weird characters in more identifiers: cursors, notifcations, etc. - - Connection policies are deprecated. It'll all be one class in 7.0! - - Connection deactivation/reactivation is deprecated. - - Some items that were documented as deprecated are now also declared as such. - - Fix Windows bug where WSAPoll was never used. Thanks dpolunin. - - Fix Windows CMake build to link to socket libraries. Thanks dpolunin. - - Various other changes to the CMake build. - - Fix failure when doing multiple string conversions with Visual C++. - - Fix nested project builds in CMake. Thanks Andrew Brownsword. - - In Visual Studio, build for host architecture, not "x64". - - Fix string conversion link error in Visual Studio. Thanks Ivan Poiakov. - - Fix string conversion to bool for "1". Thanks Amaracs. - - Fix in escaping of strings in arrays. Thanks smirql. - - Faster copying of results of large queries. Thanks Vsevolod Strukchinsky. - - Starting to handle encodings properly! Thanks to Joseph Durel. - - No longer using std::iterator (deprecated in C++17). -6.2.5 - - Removed deprecated pqxx-config. - - Build fix on Visual C++ when not defining NOMINMAX. - - Reduce setup code for string conversions, hopefully improving speed. - - Allow nul bytes in tablereader. - - Support defining string conversions for enum types. - - Fixed const/pure attributes warning in gcc 8. - - Updated build documentation to mention CMake option. - - Fixed a floating-point string conversion failure with Visual Studio 2017. -6.2.4 - - Fix builds in paths containing non-ASCII characters. - - New macro: PQXX_HIDE_EXP_OPTIONAL (to work around a client build error). -6.2.3 - - Build fixes. -6.2.2 - - Variable number of arguments to prepared or parameterised statement (#75). - - Windows build fix (#76). -6.2.1 - - Compile fixes. -6.2.0 - - At last! A check against version mismatch between library and headers. - - Small compile fixes. -6.1.1 - - Small compile fixes. - - A particular error string would always come out empty. -6.1.0 - - Dependencies among headers have changed. You may need extra includes. - - Library headers now include "*.hxx" directly, not the user-level headers. - - Supports parsing of SQL arrays, when using "ASCII-like" encodings. -6.0.0 - - C++11 is now required. Your compiler must have shared_ptr, noexcept, etc. - - Removed configure.ac.in; we now use configure.ac directly. - - Removed pqxx::items. Use the new C++11 initialiser syntax. - - Removed maketemporary. We weren't using it. - - Can now be built outside the source tree. - - New, simpler, lambda-friendly transactor framework. - - New, simpler, prepared statements and parameterised statements. - - Result rows can be passed around independently. - - New exec0(): perform query, expect zero rows of data. - - New exec1(): perform query, expect (and return) a single row of data. - - New exec_n(): perform query, expect exactly n rows of data. - - No longer defines Visual Studio's NOMINMAX in headers. - - Much faster configure script. - - Most configuration items are gone. - - Retired all existing capability flags. - - Uses WSAPoll() on Windows. - - Documentation on readthedocs.org, thanks Tim Sheerman-Chase. -5.1.0 - - Releases after this will require C++11! - - Internal simplification to pqxx::result. - - A row object now keeps its result object alive. - - New exec() variants: "expect & return 1 row," "expect no rows," "expect n." - - ChangeLog is gone. It was a drag on maintenance. -5.0.1 - - Exposed sqlstate in sql_error exception class. -5.0 - - The PGSTD namespace alias is gone. Use the std namespace directly. - - pqxx::tuple is now pqxx::row, to avoid clashes with std::tuple. - - Deprecated escape_binary functions dropped. - - Deprecated notify_listener class dropped. - - Support for many old compilers dropped. - - Support for "long long" and "long double" types is always enabled. - - No longer uses obsolete std::tr1 namespace; use plain std instead. - - Now requires libpq 9.1 or better. - - Requires server version 9.1 or better. - - Support for REPEATABLE READ isolation level added. - - Makefile fixes for Visual Studio 2013. - - Supports C++11 and C++14. - - No longer has obsolete debian & RPM packaging built in. - - Fixed failure to abort uncommitted subtransactions on destruction. - - Fixed failure to detect some integer overflows during conversion. - - Build tooling uses /usr/bin/env python instead of /usr/bin/python. - - New configure options: --with-postgres-include and --with-postgres-lib. - - In g++ or compatible compilers, non-exported items are no longer accessible. - - Many build fixes for various platforms and compilers. -4.0 - - API change: noticers are gone! Use errorhandlers to capture error output. - - API change: tablereaders and tablewriters are gone; they weren't safe. - - API change: prepared statements are now weakly-typed, and much simpler. - - API change: fields and tuples are now stand-alone classes in ::pqxx. - - API change: thread-safety field have_strerror_r is now have_safe_strerror. - - API change: notify_listener has been replaced with notification_receiver. - - notification_receiver takes a payload parameter. - - Easier Visual C++ setup. - - Absolutely requires a libpq version with PQescapeStringConn. - - Absolutely requires libpq 8.0 or better. - - Changes for C++0x. - - Supports clang++. - - Visual C++ makefiles now support new-style unit tests. - - Sample headers for more recent Visual Studio versions. - - Fixes binary-data escaping problems with postgres 9.0. - - Fixes problems with binary-string handling and escaping. - - Fixes compatibility problems between 9.x libpq and 7.x backend. - - quote_name to escape SQL identifiers for use in queries. - - syntax_error reports error's approximate location in the query. - - On Windows, now uses ws2_32 instead of wsock32. - - Various Windows build fixes. - - Updated for gcc 4.6.0. - - configure script supports --enable-documentation/--disable-documentation. - - Streamlined test/release toolchain. -3.1 - - Shared libraries are now versioned by ABI: 3.1 instead of 3.1.0 etc. - - Threading behaviour is now documented, and can be queried. - - Version information available at compile time. - - Supports parameterized statements. - - Result tuples now support slicing. - - Configure with --with-tr1=boost to use BOOST shared_ptr. - - String conversion now has its own header file. - - Supports read-only transactions. - - Fixed breakage with Solaris "make". - - Uses shared_ptr if available. - - binarystring::str() is no longer cached; no longer returns reference. - - Fixed problems in Visual C++ Makefile for test suite. - - Fixed problems with RPM packaging. - - Fixed build problem on RedHat/CentOS 5. - - Lets you check whether a prepared statement has been defined. - - "Varargs" prepared statements. - - Unnamed prepared statements now supported. - - Results have iterator as well as const_iterator. - - Rewrite of robusttransaction logic; may actually do its job now. - - Connections support async query cancel from signal handler or thread. - - More documentation for performance features. -3.0 - - Website is now at http://pqxx.org/ (no redirects) - - Completely replaced cursor classes - - More helpful error messages on failed connections - - More detailed hierarchy of constraint-violation exception classes - - trigger is now called notify_listener, trigger header is now notify-listen - - New mixin base class pqxx_exception distinguishes libpqxx exception types - - Quoting is back! transaction_base::quote() & connection_base::quote() - - Several build & documentation problems with Visual C++ fixed - - Compile fixes for gcc 4.2, 4.3 - - Compile fixes for Sun Studio Express 5.9 - - Uses strlcpy() where available, instead of strncpy() - - Keeps better track of applicable text encodings - - Fixed bug with prepared statement parameters in separate C++ statements - - robusttransaction now works for multiple users - - Pipeline lets you cancel ongoing queries, e.g. because they run for too long - - Fixed broken escaping of binary values in tablewriter - - Floating-point types now represented with full precision - - Proper unit tests for new functionality - - New traits-based system for adding data types - - Floating-point infinities now supported - - Flushing/completing a pipeline now frees up the transaction for other use - - Completely reworked test suite, builds and runs much faster - - tablewriter supports writing of raw lines -2.6.9 - - Removed old 1.x API (that means all identifiers with capital letters!) - - Tested with all current libpq versions and oldest/newest supported backends - - No longer have old OnCommit()/OnAbort()/OnDoubt() callbacks in transactor! - - Fixes failure when closing cursors with upper-case letters in their names - - Fixes bug when adding triggers to connections that aren't open yet - - Fixes bug when removing triggers - - Fixes small memory leak when preparing statements - - Fixes many problems with older backends - - Fixes bug in result::swap(): protocol versions were not swapped - - Some errors went undetected when using certain libpq versions - - Fixes prepared statements on new libpq versions talking to old backends - - Can estimate server version if libpq does not know how to obtain it - - Greatly reduced memory usage while escaping strings - - With Visual C++, creates lib/ directory if not already present - - Useful error messages when preparing statements - - Allows prepared statements to be registered explicitly - - Support for "long long" types; enable with PQXX_ALLOW_LONG_LONG macro - - Compilation errors for older libpq versions fixed - - Some new small utility classes for disabling notice processing etc. - - Result sets remember the queries that yielded them - - New test script, pqxx-fulltest, tests against all current postgres versions - - Connections can simulate failure - - Adds password encryption function -2.6.8 - - Fixes bug: binary parameters to prepared statements truncated at nul bytes - - New, more specific exception types to distinguish errors from server - - Resolved serious problems with generated reference documentation - - Automatically detect Windows socket library with MinGW - - Windows "make" fixed to run from main directory, not win32 - - Fixes "mktemp" problems on some BSD-based platforms - - pqxx-config is deprecated; use pkg-config instead - - On GNU/Linux, uses poll() instead of select() to avoid file descriptor limit - - Will provide server and protocol version information where available - - New cursor class, absolute_cursor -2.6.7 - - New escape functions for binary data: transaction_base::esc_raw() - - Improved detection of socket libraries, especially for MinGW - - Works around bug in some versions of GNU grep 2.5.1 - - Fixes problem with configuration headers - - Fixes PQprepare() detection - - Fixes incomplete Visual C++ Makefile - - Fixes compile error in workaround for older libpq versions - - Removes "rpath" link option -2.6.6 - - New, encoding-safe string-escaping functions - - Upper-case letters now allowed in prepared-statement names - - Fixes crash in test005 - - More Visual C++ improvements - - Removed collaboration diagrams from reference docs - - New templating system for generating Windows Makefiles etc. -2.6.5 - - Visual C++ users: copy win32/common-sample to win32/common before editing it - - Should fix problems finding socket library on MinGW - - Even more work on Visual C++ problems - - Updated documentation for Visual C++ users - - Fixed bug in prepared statements (mostly visible on Visual C++) - - Nested transactions work harder to detect backend support -2.6.4 - - Massively improved compatibility with Windows and Visual C++ - - Fixed late initialization of "direct" connection state - - Fixed problem with initialization of connection capabilities - - Fixed configuration bug for libpq in nonstandard locations - - Sample configuration header for libpq found in PostgreSQL 8.1 -2.6.3 - - Radical rework of prepared statements; INCOMPATIBLE INTERFACE CHANGE! - - Dropped support for g++ 2.95 - - Emulate prepared statements support on old libpq or old backend - - Bug fix: missing tutorial (release script now tests for this) - - Automatically links in socket library on Windows or Solaris, if needed - - Bug fix: check for std namespace didn't work - - Fixes for Cygwin/MSYS/MinGW -2.6.2 - - Bug fix: connection state was not set up properly in some common cases - - Bug fix: headers were installed in "include" instead of "include/pqxx" - - Bug fix: sqlesc(string) broke with multibyte or multiple encodings - - namedclass is now used as a virtual base; affects all subclass constructors - - Initial implementation of subtransactions - - Detect more connection capabilities - - Standard library namespace can be set from configure script's command line - - Completely reworked connection hierarchy, with separate policy objects - - Clients can now define their own connection policies - - Paved the way for client-defined thread synchronization - - Now lives at http://thaiopensource.org/development/libpqxx/ -2.6.1 - - Hugely improved recognition of different strerror_r() versions - - Resolved link problems with gcc 4.0 and shared library -2.6.0 - - New macro PQXX_SHARED defines whether to use/build libpqxx as shared library - - Robusttransaction compatible with PostgreSQL 8.1 - - Infrastructure for querying connection/backend capabilities at runtime - - Greatly improved cursor support - - Connection reactivation can be inhibited explicitly - - Tries even harder to make sense of conflicting strerror_r() definitions - - Detects connection failures that libpq glosses over - - Reference documentation grouped into more coherent sections - - Assumes strerror() is threadsafe on systems that have no strerror_r() - - Now allows connection's socket number to be queried - - New internal_error class for libpqxx-internal errors - - With Visual C++, doesn't redefine NOMINMAX if it is defined already - - Several compatibility improvements for Visual C++ - - Fixes and workarounds for HP-UX and HP aCC compiler - - Phased old cursor interface out of test suite; tests ported to new interface - - Added documentation on thread safety - - New thread safety model - - Large objects have functions to tell current position - - Minor updates to tutorial (somebody pay me and I'll do more :) - - No longer needs libpq-fs.h header - - Meaningful error messages for ambiguous string conversions fixed -2.5.6 - - Support null parameters to prepared statements (use C-style char pointers) -2.5.5 - - Diagnoses connection failure during result transfer - - Fixes invalid -R link option in pqxx-config -2.5.4 - - Fix workaround code for older libpq versions without PQunescapeBytea() - - Work around grep bug in Fedora Core 4 that broke configure in UTF-8 locales - - In Visual C++, assume libpqxx is a DLL when linking to std library as DLL - - Missing documentation in distribution archive is back again - - Export fewer symbols from library binary with gcc 4.0 - - Releases now automatically tested against gcc 4.0 - - Meaningful link errors for additional ambiguous string conversions - - DLL symbol exports now automatically tested before each release -2.5.3 - - Greatly improved builds on MinGW with MSYS - - All known problems with MinGW fixed - - Fix bugs in stream classes that caused failures and crashes with STLport - - Detects and uses STLport automatically -2.5.2 - - Fix memory leaks - - Fix problems with NaN (not-a-number values) on some compilers -2.5.1 - - Fix configure script; broke when very recent libpqxx was already installed - - Fix cursor breakage when "long" is more than 32 bits - - Fix cases where new-style abort/doubt handlers are used - - Fix for division-by-zero error in Visual C++ (changed sample headers) - - Improved checking for strerror_r in configure script - - Fix for problem MinGW has with configure script - - Fix spurious failure of Oid check in configure script -2.5.0 - - Fix race condition in removing triggers - - Fix binary string conversion with older libpq - - Fix some error strings that may previously have come out wrong - - No longer includes any libpq headers while compiling client code - - Improved thread safety: avoid strerror() where possible - - Prepared statements - - Translate more error conditions to std::bad_alloc exception - - Clearer and more specific explanations for configuration failures - - Improved documentation - - Looks for standard library in global namespace as well as std - - Accepts standard C library in std namespace - - Release script automatically tests with a range of compilers, not just one - - Compatible with g++ 2.95 again; this time it's tested automatically -2.4.4 - - Fix problems building shared library in Visual C++ - - Fix autobuild in Debian, which was broken by mistake in BSD grep workaround - - Fix conversion of string to floating-point type NaN - - Remove stray CVS directories from distribution archive - - Workaround for Visual C++ problem when issuing messages from destructors - - Yet more workarounds for Visual C++ bugs - - Fix situation where connection state might not be restored after failure - - Fix configuration problem on SunOS - - Network speedup in connection setup with pending variables and/or triggers -2.4.3 - - Yet more workarounds for bugs in Visual C++ .NET 2003 - - Fixes for SunC++ 5.5 - - On Visual C++, now defines NOMINMAX, fixing large object support - - Workaround for BSD grep - - Improvements for builds from CVS - - Sample config headers for Sun ONE Studio 8 -2.4.2 - - Fix minor problems with Apple's version of g++ 3.3 - - Fix problem with MingW on Windows - - Workarounds and fixes for Visual C++.NET 2003 - - Renewed compatibility with g++ 2.95 - - More sample configuration headers - - Updated reference documentation - - Removed assert code -2.4.1 - - Several bugs in icursor_iterator fixed; incompatible interface changes - - Tightens throw specifications on begin(), end(), size(), capacity() - - Containers define reference and pointer types - - Implements swap() in all container types - - Implements == and != in all container types - - Stabilizes new (but still limited) cursor interface - - icursor_iterator thinks purely in stride granularity - - Introduces />= comparisons for icursor_iterators - - Allows "adopted SQL cursors" in new cursor interface - - Reference-counting in binarystrings, so they can be copied (and efficiently) - - Fixes reference-to-temporary problem with std::reverse_iterator in results - - Result/tuple reverse_iterators no longer require std::reverse_iterator - - Includes some sample config headers (in config/sample-headers) - - Replaces iffy autoconf checks (avoid failures with maintainer mode's -Werror) - - Fixes incompatibility with some implementations of Unix "cut" program (again) -2.4.0 - - Fixes incompatibility with some implementations of Unix "cut" program - - Fixes "ptrdiff_t redefinition" problem in some environments - - More container-like tuples, so fields can be iterated - - All size_type types are now unsigned - - More conservative robusttransaction--thanks Tom Lane - - Stream-like extraction operator for result field conversion - - Warnings about deprecated headers now suppressed while compiling library - - Iterator constructors and copy assignments now have empty throw specs -2.3.0 - - Generates MinGW Makefile automatically - - Documents MinGW build - - Workaround for missing prepared-statement support - - Potential bug fixed in closing of connections - - Fixed incompatibility between new cursor streams and older backends - - Removed pqxxbench -2.2.9 - - Bugfix in removing trigger - - Added "failed connection" to regression test - - Some changes to throw specifications - - Putting libpq in its own namespace is optional -2.2.8 - - Moved libpq into pqxx::internal::pq namespace - - New config system separates compiler-related items from libpq-related ones - - Auto-generates Visual C++ Makefile, should always remain up-to-date now -2.2.7 - - Bugfix: from_string() didn't handle LONG_MIN--thanks Yannick Boivin -2.2.6 - - Complete "pipeline" rewrite, for better exception safety - - New garbage collection scheme for "result;" constructors now exception-free -2.2.5 - - First new cursor classes! - - Fixed strange failure in tablewriter during large insertions - - Updated tutorial -2.2.4 - - New utility class template, items<> for easy container initialization - - New utility function template, separated_list() - - Error handling bugfix in tablewriter - - Fixed tablereader handling of lines ending in empty fields - - tablereader lines no longer end in newline with old libpq versions -2.2.3 - - Trigger names no longer need to be proper identifiers - - Compile fixes for g++ 3.4.0 and other modern compilers - - Tablestreams may specify column lists - - Deprecated Quote() in favour of sqlesc(); improved quoting - - Fixed generation of libpqxx.spec -2.2.2 - - Bugfix in fieldstream w.r.t. reading strings on some systems - - Renamed config.h to internalconfig.h to avoid confusion - - New connection functions allow client to sleep until notification arrives - - Notification functions return number of notifications received - - Even fewer client-visible macros exported by libconfig.h -2.2.1 - - New, 2.x-style string conversions without locale problem - - Documentation improvements - - Implemented result::swap() -2.2.0 - - Installs to /usr/local by default, NOT to /usr/local/pqxx like before! - - Uses Postgres-provided script to find Postgres (thanks Peter Eisentraut) - - Which means no more configure arguments required on Irix (thanks Arjen Baart) - - Fixes long-standing bug in result class! - - New pipeline class for throughput optimization - - New field stream class: read result field as C++ stream - - Separate namespace pqxx::internal for definitions not relevant to the user - - More Windows compilation fixes - - SUN Workshop 6 compile fixes and workarounds (thanks Jon Meinecke) - - Implemented reverse_iterator for result class - - Checks for functional std::reverse_iterator template - - Preliminary Makefile for MinGW compiler (thanks Pasquale Fersini) - - Changed the way unique<> works - - Checks for functional std::count_if() - - Bugs fixed & test programs added -2.1.3 - - Makefile fixes for Visual C++, thanks Paresh Patel - - Library ABI versioning implemented, thanks Roger Leigh - - Uses old SQL isolation level syntax for compatibility, thanks koun@sina.com - - tablestreams can explicitly complete() before destructor - - Bugfix in robusttransaction: forgot to set isolation level - - Fixed off-by-ones in tablewriter escape code - - tablestreams now use \n-style escape sequences - - tablestreams support octal numbers - - Freely definable "null" strings in tablestreams, as originally intended - - Improved Debian packaging, thanks Roger Leigh - - tablestreams use libpq's new-style COPY functions, if available - - Extended automation of build/release procedure - - tablewriter writes in nonblocking mode to help hide communication latency - - Can get backend variables as well as set them - - More configuration macro cleanups - - Workaround for missing clear() in standard string - - Merry Christmas! -2.1.2 - - Compile fix for gcc libstdc++ 2.9, thanks Jaroslaw Staniek - - Moved deprecated functions below current ones - - Cleanups for Debian packaging (thanks Roger Leigh, new Debian maintainer!) - - Updated authors listings - - Bumped ABI version number for the first time (now 2:0:1) -2.1.1 - - More workarounds for gcc 2.95 - - Automated tools keep test makefiles up to date -2.1.0 - - Asynchronous connections - - Fixed configure --includedir option (thanks Ray Dassen!) - - Compile fixes for SUN Workshop 6, and one for gcc on FreeBSD 4.8 -2.0.0 - - New stable release! - - Includes all changes since 1.5 release. - - Workarounds for Microsoft Visual C++ 7 problems. Thanks Costin Musteata! - - No longer need to define PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION - - Integrated Windows configuration into regular configuration - - Only uses #warning if preprocessor supports it - - Works on libpq versions without PQ[un]escapeBytea() -1.9.9 - - Minor documentation changes -1.9.8 - - Workaround for compile problem with postgres 7.3 - - Convenience typedef for transaction<>: "work" -1.9.7 - - binarystring rewritten and moved to its own file - - binarystring::size() does not include terminating null byte! - - Implemented escaping of binary strings - - Fix in workaround for missing numeric_limits on some compilers - - String conversion supported for unsigned char * - - More helpful link errors for unsupported string conversions - - Complete test coverage -1.9.6 - - Fixes in "field table" support - - Improved coexistence with client program's config.h, if any - - Prefixed autoconf macros used in headers with "PQXX_" -1.9.5 - - Header file contents moved to .hxx files for editor filetype recognition - - Fixes wrong timestamp for include/pqxx/result in 1.9.4 distribution -1.9.4 - - Fixes Visual C++ build problem when compiling as library -1.9.3 - - Quick release for various minor changes -1.9.2 - - Renamed most public member functions to all-lower-case names - - (previously is now called -1.9.1 - - tablestream destructor crashed if table didn't exist (thanks Sean [Rogers?]) - - Renamed all header files to remove ".h" suffix - - Tables created by regression test now prefixed with "pqxx" for safety - - Large objects now considered stable - - Migrated tutorial from SGML to DocBook XML (thanks Wichert Akkerman) - - Added tests 57-59 - - Fixed compile error in largeobject - - Updated Windows makefiles -1.9.0 - - EVERYTHING HAS CHANGED. Read the list or run into trouble! - - CURSOR HAS INCOMPATIBLE CHANGES AND MAY BE REPLACED COMPLETELY - - CACHEDRESULT HAS INCOMPATIBLE CHANGES (won't compile without changes) - - REVISE YOUR TRANSACTORS; now templatized on transaction type - - Finally got license file in order - - Incompatible change in setting transactor quality of service - - Cursors require serializable isolation level (checked at link time) - - Renamed Connection_base to connection_base, Connection to connection, - LazyConnection to lazyconnection - - Renamed LargeObject to largeobject, LargeObjectAccess to largeobjectaccess - - Renamed Noticer to noticer - - Renamed Trigger to trigger - - Renamed Result to result, Tuple to tuple, Field to field - - Renamed Unique<> to unique<> - - Renamed CachedResult to cachedresult - - Transformed Transaction Taxonomy (TTT): - - Renamed Transaction_base to transaction_base - - Renamed Transaction to transaction - - Renamed Transactor to transactor<> (now a template) - - Implemented transaction isolation levels as compile-time static properties - - transaction and robusttransaction now templatized on their isolation levels - - cachedresult requires serializable isolation level (checked at link time) - - Now need to include pqxx/transactor.h yourself if you need transactors - - Large objects require real backend transaction at compile time - - New type oid and constant oid_none for row identifiers resp. null oid - - Added some forgotten PQXX_LIBEXPORTs - - Tweaked documentation in many places -1.8.1 - - By popular request: more convenient way to read field values - - Documented locale sensitivity of ToString(), FromString(), Field::to() -1.8.0 - - Compiles on gcc 2.95 again (heavy streambuf workarounds in largeobject.h) - - ConnectionItf renamed to Connection_base, TransactionItf to Transaction_base - - connectionitf.h is now connection_base.h, transactionitf.h connection_base.h -1.7.8 - - BinaryString class for unescaping bytea strings - - PQAlloc template keeps track of libpq-allocated objects - - Removed some consts in Unique<>, ConnectionItf, sorry! - - Can now set session variables on connections, transactions -1.7.7 - - ./configure also looks for postgres in /usr/local/pgsql - - test007 now uses SQL_ASCII as its test encoding - - integrated Greg Hookey's Debian packaging -1.7.6 - - added postgres library (libpq) to dynamic link path -1.7.5 - - added test052 - test055 - - added Result::Tuple::ColumnNumber() - - also test setting of client encodings - - removed superfluous versions of to_file() from large object classes -1.7.4 - - new exception class, sql_error, remembers query text - - moved exception classes to new file include/pqxx/except.h - - test cases report texts of any failed queries - - added tools/rmlo.cxx -1.7.3 - - default constructors for connection classes - - revamped seeking operations on large objects - - better error messages in large objects - - added test050, test051 -1.7.2 - - more workarounds for Sun CC 5.1, thanks Jeroen van Erp! - - preliminary support for "named" queries - - can now Quote() string constants - - included Doxyfile in distribution archive - - helps avoid Windows memory allocation problem in DLLs - - allows setting of client character set encoding -1.7.1 - - regenerated documentation -1.7.0 - - removed all deprecated features - - connection string documentation in README - - separate Connection, LazyConnection classes - - made test001 more concise - - added test049 -1.6.4 - - configure script now respects different std namespace -1.6.3 - - olostream, lostream now flush themselves before closing - - fixed compilation problems when using ToString<>() on a plain char * - - compilation fixes for Sun compiler (thanks Jeroen van Erp!) - - added .pc file for pkgconfig (thanks Ray Dassen!) -1.6.2 - - Debian packaging added to distribution archive - - new ilostream, olostream, lostream classes -1.6.1 - - large object's cunlink() replaced by remove() - - default constructor for LargeObject -1.6.0 - - new large objects interface - - added test048 -1.5.0 - - allow result fields to be written to streams - - removed confusing CachedResult::clear() - - minor documentation updates - - added test046, test047 - - added convenience header -1.4.5 - - fixed crash CachedResult that was less shallow than I thought - - fixed quoting problem with adopted SQL cursors -1.4.4 - - (forgot to save cursor.cxx with new constructor in 1.4.4, sorry) -1.4.3 - - all tests now have three-digit numbers - - Cursor can adopt SQL cursor returned by a function -1.4.2 - - bugfix in CachedResult when accessing empty Results - - minor documentation improvements -1.4.1 - - documents new homepage: http://pqxx.tk/ - - Connection constructor accepts null connect string - - Exec() now also takes queries as C++ strings -1.4.0 - - Connection::IsOpen() renamed to is_open() - - NoticeProcessor replaced by Noticer (with C++ linkage) -1.3.7: - - detects nasty rare problem case with Cursors in unknown positions -1.3.6: - - fixed detection of missing PQescapeString(). Thanks David Wright! -v1.3.5: - - documented Windows build procedure - - fixed problem with upper-case letters in cursor names. Thanks key88! -2003-01-19 16:00, v1.3.4: - - support long double type - - clarified some error messages -2003-01-08 18:45, v1.3.3: - - fix missing include in test13 -2003-01-07 02:30, v1.3.2: - - configure looks for postgres includes/library in more places, thanks Ray! -2003-01-02 23:00, v1.3.1: - - bugfix in Cursor positioning -2003-01-02 20:30, v1.3.0: - - absolute positioning for Cursor - - better documentation on cursors - - reduced, but improved test suite output -2002-12-23 17:30, v1.2.8: - - Cursor::Move() returns number of rows skipped - - new typedef Cursor::size_type -2002-12-14 23:30, v1.2.7: - - test suite now distinguishes expected errors from unexpected ones -2002-12-09 20:00, v1.2.6: - - fixed some Cursor test cases for change in postgres 7.3 - - added important warning to Cursor -2002-12-09 02:00, v1.2.5: - - added important warning to CachedResult -2002-12-08 14:14, v1.2.4: - - fixed compile error on some systems in include/pqxx/util.h -2002-12-04 12:00, v1.2.3: - - workaround for broken on some systems - - fixed Quote() bug -2002-12-03 01:30, v1.2.2: - - fixed serious CachedResult bug - - added test41 -2002-12-02 17:00, v1.2.1: - - hopefully fixed cursor bug with PostgreSQL 7.3 -2002-12-01 22:00, v1.2.0: - - new CachedResult class -2002-11-07 13:15, v1.1.4: - - workaround for missing InvalidOid definition -2002-10-23 16:00, v1.1.3: - - Cursor & TableStream hierarchy now work on any transaction type - - get no. of affected rows & oid of inserted row from Result - - increased test coverage -2002-10-21 01:30, v1.1.2: - - updated build procedure - - Debian packaging improvements -2002-09-25 03:00, v1.1.1: - - supports activating/deactivating of connections - - various Connection getters now activate deferred connection first -2002-09-23 01:00, v1.1.0: - - supports lazy connections (added 19 test cases just for these) - - greatly reduced performance overhead for RobustTransaction - - removed id field from RobustTransaction's transaction log tables -2002-09-14 20:00, v1.0.1: - - now lives on GBorg - - various packaging updates -2002-06-12 17:30, v0.5.1: - - no longer have to destroy one transaction before creating the next -2002-06-07 17:15, v0.5.0: - - "make install" now finally installs headers! - - distribution now includes SGML (DocBook) version of tutorial -2002-06-04 15:00, v0.4.4: - - may now have multiple triggers with same name on single connection -2002-06-02 23:00, v0.4.3: - - fixed TableReader problem with \t and \n -2002-06-01 21:00, v0.4.2: - - hopefully fixes compile problem with broken std::iterator - - configure no longer requires --with-postgres-include=/usr/include/postgresql -2002-05-29 22:00, v0.4.1: - - can now also handle bool, unsigned char, short field types -2002-05-27 22:30, v0.4.0: - - RENAMED Transactor::TRANSACTIONTYPE to argument_type for STL conformance - - RENAMED Result::Field::name() to Name() - - documentation improvements - - minor optimizations -2002-05-18 00:00, v0.3.1: - - removed broken postgres_fe.h dependency (hopefully permanent fix) -2002-05-12 22:45, v0.3.0: - - also looks for postgres_fe.h in postgres' internal/ directory (tmp fix) -2002-05-05 01:30, v0.2.3: - - extensive build instructions in README - - make check now controlled through PG environment variables -2002-05-04 19:30, v0.2.2: - - more STL conformance - - fixed regression test - - test6 now copies "orgevents" to "events" by default -2002-04-28 23:45 Version bumped to 0.2 -2002-04-28 23:45 Self-generated distribution archive -2002-04-27 14:20 Replaced automake symlinks with actual files -2002-04-07 02:30 Released with configure script -2002-03-29 01:15 Not yet released. Still integrating autogen stuff... diff --git a/ext/libpqxx-7.7.3/README.md b/ext/libpqxx-7.7.3/README.md deleted file mode 100644 index 3a1c17ded..000000000 --- a/ext/libpqxx-7.7.3/README.md +++ /dev/null @@ -1,199 +0,0 @@ -libpqxx -======= - -Welcome to libpqxx, the C++ API to the PostgreSQL database management system. - -Home page: http://pqxx.org/development/libpqxx/ - -Find libpqxx on Github: https://github.com/jtv/libpqxx - -Documentation on Read The Docs: https://libpqxx.readthedocs.io - -Compiling this package requires PostgreSQL to be installed -- or at least the C -headers and library for client development. The library builds on top of -PostgreSQL's standard C API, libpq, though your code won't notice. - -If you're getting the code straight from the Git repo, the head of the `master` -branch represents the current _development version._ Releases are tags on -commits in `master`. For example, to get version 7.1.1: - - git checkout 7.1.1 - - -Upgrade notes -------------- - -**The 7.x versions require at least C++17.** Make sure your compiler is up to -date. For libpqxx 8.x you will need at least C++20. - -Also, **7.0 makes some breaking changes in rarely used APIs:** -* There is just a single `connection` class. It connects immediately. -* Custom `connection` classes are no longer supported. -* It's no longer possible to reactivate a connection once it's been closed. -* The API for defining string conversions has changed. - -If you're defining your own type conversions, **7.1 requires one additional -field in your `nullness` traits.** - - -Building libpqxx ----------------- - -There are two different ways of building libpqxx from the command line: -1. Using CMake, on any system which supports it. -2. On Unix-like systems, using a `configure` script. - -"Unix-like" systems include GNU/Linux, Apple macOS and the BSD family, AIX, -HP-UX, Irix, Solaris, etc. Even on Microsoft Windows, a Unix-like environment -such as WSL, Cygwin, or MinGW should work. - -You'll find detailed build and install instructions in `BUILDING-configure.md` -and `BUILDING-cmake.md`, respectively. - -And if you're working with Microsoft Visual Studio, have a look at Gordon -Elliott's -[ - Easy-PQXX Build for Windows Visual Studio -](https://github.com/GordonLElliott/Easy-PQXX-Build-for-Windows-Visual-Studio) -project. - - -Documentation -------------- - -Building the library, if you have the right tools installed, generates HTML -documentation in the `doc/` directory. It is based on the headers in -`include/pqxx/` and text in `include/pqxx/doc/`. This documentation is also -available online at [readthedocs](https://libpqxx.readthedocs.io). - - -Programming with libpqxx ------------------------- - -Your first program will involve the libpqxx classes `connection` (see the -`pqxx/connection.hxx` header), and `work` (a convenience alias for -`transaction<>` which conforms to the interface defined in -`pqxx/transaction_base.hxx`). - -These `*.hxx` headers are not the ones you include in your program. Instead, -include the versions without filename suffix (e.g. `pqxx/connection`). Those -will include the actual .hxx files for you. This was done so that includes are -in standard C++ style (as in `` etc.), but an editor will still -recognize them as files containing C++ code. - -Continuing the list of classes, you will most likely also need the result class -(`pqxx/result.hxx`). In a nutshell, you create a `connection` based on a -Postgres connection string (see below), create a `work` in the context of that -connection, and run one or more queries on the work which return `result` -objects. The results are containers of rows of data, each of which you can -treat as an array of strings: one for each field in the row. It's that simple. - -Here is a simple example program to get you going, with full error handling: - -```c++ - #include - #include - - int main() - { - try - { - // Connect to the database. - pqxx::connection C; - std::cout << "Connected to " << C.dbname() << '\n'; - - // Start a transaction. - pqxx::work W{C}; - - // Perform a query and retrieve all results. - pqxx::result R{W.exec("SELECT name FROM employee")}; - - // Iterate over results. - std::cout << "Found " << R.size() << "employees:\n"; - for (auto row: R) - std::cout << row[0].c_str() << '\n'; - - // Perform a query and check that it returns no result. - std::cout << "Doubling all employees' salaries...\n"; - W.exec0("UPDATE employee SET salary = salary*2"); - - // Commit the transaction. - std::cout << "Making changes definite: "; - W.commit(); - std::cout << "OK.\n"; - } - catch (std::exception const &e) - { - std::cerr << e.what() << '\n'; - return 1; - } - return 0; - } -``` - - -Connection strings ------------------- - -Postgres connection strings state which database server you wish to connect to, -under which username, using which password, and so on. Their format is defined -in the documentation for libpq, the C client interface for PostgreSQL. -Alternatively, these values may be defined by setting certain environment -variables as documented in e.g. the manual for psql, the command line interface -to PostgreSQL. Again the definitions are the same for libpqxx-based programs. - -The connection strings and variables are not fully and definitively documented -here; this document will tell you just enough to get going. Check the -PostgreSQL documentation for authoritative information. - -The connection string consists of attribute=value pairs separated by spaces, -e.g. "user=john password=1x2y3z4". The valid attributes include: -* `host` — - Name of server to connect to, or the full file path (beginning with a - slash) to a Unix-domain socket on the local machine. Defaults to - "/tmp". Equivalent to (but overrides) environment variable PGHOST. -* `hostaddr` — - IP address of a server to connect to; mutually exclusive with "host". -* `port` — - Port number at the server host to connect to, or socket file name - extension for Unix-domain connections. Equivalent to (but overrides) - environment variable PGPORT. -* `dbname` — - Name of the database to connect to. A single server may host multiple - databases. Defaults to the same name as the current user's name. - Equivalent to (but overrides) environment variable PGDATABASE. -* `user` — - User name to connect under. This defaults to the name of the current - user, although PostgreSQL users are not necessarily the same thing as - system users. -* `requiressl` — - If set to 1, demands an encrypted SSL connection (and fails if no SSL - connection can be created). - -Settings in the connection strings override the environment variables, which in -turn override the default, on a variable-by-variable basis. You only need to -define those variables that require non-default values. - - -Linking with libpqxx --------------------- - -To link your final program, make sure you link to both the C-level libpq library -and the actual C++ library, libpqxx. With most Unix-style compilers, you'd do -this using the options - - -lpqxx -lpq - -while linking. Both libraries must be in your link path, so the linker knows -where to find them. Any dynamic libraries you use must also be in a place -where the loader can find them when loading your program at runtime. - -Some users have reported problems using the above syntax, however, particularly -when multiple versions of libpqxx are partially or incorrectly installed on the -system. If you get massive link errors, try removing the "-lpqxx" argument from -the command line and replacing it with the name of the libpqxx library binary -instead. That's typically libpqxx.a, but you'll have to add the path to its -location as well, e.g. /usr/local/pqxx/lib/libpqxx.a. This will ensure that the -linker will use that exact version of the library rather than one found -elsewhere on the system, and eliminate worries about the exact right version of -the library being installed with your program.. diff --git a/ext/libpqxx-7.7.3/VERSION b/ext/libpqxx-7.7.3/VERSION deleted file mode 100644 index d92ba80de..000000000 --- a/ext/libpqxx-7.7.3/VERSION +++ /dev/null @@ -1 +0,0 @@ -7.7.3 diff --git a/ext/libpqxx-7.7.3/aclocal.m4 b/ext/libpqxx-7.7.3/aclocal.m4 deleted file mode 100644 index 2c938cff6..000000000 --- a/ext/libpqxx-7.7.3/aclocal.m4 +++ /dev/null @@ -1,1187 +0,0 @@ -# generated automatically by aclocal 1.16.4 -*- Autoconf -*- - -# Copyright (C) 1996-2021 Free Software Foundation, Inc. - -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, -[m4_warning([this file was generated for autoconf 2.69. -You have another version of autoconf. It may work, but is not guaranteed to. -If you have problems, you may need to regenerate the build system entirely. -To do so, use the procedure documented by the package, typically 'autoreconf'.])]) - -# Copyright (C) 2002-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -# (This private macro should not be called outside this file.) -AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.16' -dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to -dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.16.4], [], - [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl -]) - -# _AM_AUTOCONF_VERSION(VERSION) -# ----------------------------- -# aclocal traces this macro to find the Autoconf version. -# This is a private macro too. Using m4_define simplifies -# the logic in aclocal, which can simply ignore this definition. -m4_define([_AM_AUTOCONF_VERSION], []) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. -# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.16.4])dnl -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) - -# AM_AUX_DIR_EXPAND -*- Autoconf -*- - -# Copyright (C) 2001-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to -# '$srcdir', '$srcdir/..', or '$srcdir/../..'. -# -# Of course, Automake must honor this variable whenever it calls a -# tool from the auxiliary directory. The problem is that $srcdir (and -# therefore $ac_aux_dir as well) can be either absolute or relative, -# depending on how configure is run. This is pretty annoying, since -# it makes $ac_aux_dir quite unusable in subdirectories: in the top -# source directory, any form will work fine, but in subdirectories a -# relative path needs to be adjusted first. -# -# $ac_aux_dir/missing -# fails when called from a subdirectory if $ac_aux_dir is relative -# $top_srcdir/$ac_aux_dir/missing -# fails if $ac_aux_dir is absolute, -# fails when called from a subdirectory in a VPATH build with -# a relative $ac_aux_dir -# -# The reason of the latter failure is that $top_srcdir and $ac_aux_dir -# are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is '.', but things will broke when you -# start a VPATH build or use an absolute $srcdir. -# -# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, -# iff we strip the leading $srcdir from $ac_aux_dir. That would be: -# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` -# and then we would define $MISSING as -# MISSING="\${SHELL} $am_aux_dir/missing" -# This will work as long as MISSING is not called from configure, because -# unfortunately $(top_srcdir) has no meaning in configure. -# However there are other variables, like CC, which are often used in -# configure, and could therefore not use this "fixed" $ac_aux_dir. -# -# Another solution, used here, is to always expand $ac_aux_dir to an -# absolute PATH. The drawback is that using absolute paths prevent a -# configured tree to be moved without reconfiguration. - -AC_DEFUN([AM_AUX_DIR_EXPAND], -[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl -# Expand $ac_aux_dir to an absolute path. -am_aux_dir=`cd "$ac_aux_dir" && pwd` -]) - -# AM_CONDITIONAL -*- Autoconf -*- - -# Copyright (C) 1997-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_CONDITIONAL(NAME, SHELL-CONDITION) -# ------------------------------------- -# Define a conditional. -AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ([2.52])dnl - m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE])dnl -AC_SUBST([$1_FALSE])dnl -_AM_SUBST_NOTMAKE([$1_TRUE])dnl -_AM_SUBST_NOTMAKE([$1_FALSE])dnl -m4_define([_AM_COND_VALUE_$1], [$2])dnl -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi -AC_CONFIG_COMMANDS_PRE( -[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([[conditional "$1" was never defined. -Usually this means the macro was only invoked conditionally.]]) -fi])]) - -# Copyright (C) 1999-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - - -# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - -# _AM_DEPENDENCIES(NAME) -# ---------------------- -# See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". -# We try a few techniques and use that to set a single cache variable. -# -# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was -# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular -# dependency, and given that the user is not expected to run this macro, -# just rely on AC_PROG_CC. -AC_DEFUN([_AM_DEPENDENCIES], -[AC_REQUIRE([AM_SET_DEPDIR])dnl -AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl -AC_REQUIRE([AM_MAKE_INCLUDE])dnl -AC_REQUIRE([AM_DEP_TRACK])dnl - -m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], - [$1], [CXX], [depcc="$CXX" am_compiler_list=], - [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], - [$1], [UPC], [depcc="$UPC" am_compiler_list=], - [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) - -AC_CACHE_CHECK([dependency style of $depcc], - [am_cv_$1_dependencies_compiler_type], -[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_$1_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` - fi - am__universal=false - m4_case([$1], [CC], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac], - [CXX], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac]) - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_$1_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_$1_dependencies_compiler_type=none -fi -]) -AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) -AM_CONDITIONAL([am__fastdep$1], [ - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) -]) - - -# AM_SET_DEPDIR -# ------------- -# Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES. -AC_DEFUN([AM_SET_DEPDIR], -[AC_REQUIRE([AM_SET_LEADING_DOT])dnl -AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl -]) - - -# AM_DEP_TRACK -# ------------ -AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE([dependency-tracking], [dnl -AS_HELP_STRING( - [--enable-dependency-tracking], - [do not reject slow dependency extractors]) -AS_HELP_STRING( - [--disable-dependency-tracking], - [speeds up one-time build])]) -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' - am__nodep='_no' -fi -AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH])dnl -_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl -AC_SUBST([am__nodep])dnl -_AM_SUBST_NOTMAKE([am__nodep])dnl -]) - -# Generate code to set up dependency tracking. -*- Autoconf -*- - -# Copyright (C) 1999-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_OUTPUT_DEPENDENCY_COMMANDS -# ------------------------------ -AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[{ - # Older Autoconf quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - # TODO: see whether this extra hack can be removed once we start - # requiring Autoconf 2.70 or later. - AS_CASE([$CONFIG_FILES], - [*\'*], [eval set x "$CONFIG_FILES"], - [*], [set x $CONFIG_FILES]) - shift - # Used to flag and report bootstrapping failures. - am_rc=0 - for am_mf - do - # Strip MF so we end up with the name of the file. - am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile which includes - # dependency-tracking related rules and includes. - # Grep'ing the whole file directly is not great: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ - || continue - am_dirpart=`AS_DIRNAME(["$am_mf"])` - am_filepart=`AS_BASENAME(["$am_mf"])` - AM_RUN_LOG([cd "$am_dirpart" \ - && sed -e '/# am--include-marker/d' "$am_filepart" \ - | $MAKE -f - am--depfiles]) || am_rc=$? - done - if test $am_rc -ne 0; then - AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments - for automatic dependency tracking. If GNU make was not used, consider - re-running the configure script with MAKE="gmake" (or whatever is - necessary). You can also try re-running configure with the - '--disable-dependency-tracking' option to at least be able to build - the package (albeit without support for automatic dependency tracking).]) - fi - AS_UNSET([am_dirpart]) - AS_UNSET([am_filepart]) - AS_UNSET([am_mf]) - AS_UNSET([am_rc]) - rm -f conftest-deps.mk -} -])# _AM_OUTPUT_DEPENDENCY_COMMANDS - - -# AM_OUTPUT_DEPENDENCY_COMMANDS -# ----------------------------- -# This macro should only be invoked once -- use via AC_REQUIRE. -# -# This code is only required when automatic dependency tracking is enabled. -# This creates each '.Po' and '.Plo' makefile fragment that we'll need in -# order to bootstrap the dependency handling code. -AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], -[AC_CONFIG_COMMANDS([depfiles], - [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) - -# Do all the work for Automake. -*- Autoconf -*- - -# Copyright (C) 1996-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This macro actually does too much. Some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. -m4_define([AC_PROG_CC], -m4_defn([AC_PROG_CC]) -[_AM_PROG_CC_C_O -]) - -# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) -# AM_INIT_AUTOMAKE([OPTIONS]) -# ----------------------------------------------- -# The call with PACKAGE and VERSION arguments is the old style -# call (pre autoconf-2.50), which is being phased out. PACKAGE -# and VERSION should now be passed to AC_INIT and removed from -# the call to AM_INIT_AUTOMAKE. -# We support both call styles for the transition. After -# the next Automake release, Autoconf can make the AC_INIT -# arguments mandatory, and then we can depend on a new Autoconf -# release and drop the old call support. -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.65])dnl -dnl Autoconf wants to disallow AM_ names. We explicitly allow -dnl the ones we care about. -m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl -AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL])dnl -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi -AC_SUBST([CYGPATH_W]) - -# Define the identity of the package. -dnl Distinguish between old-style and new-style calls. -m4_ifval([$2], -[AC_DIAGNOSE([obsolete], - [$0: two- and three-arguments forms are deprecated.]) -m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl - AC_SUBST([PACKAGE], [$1])dnl - AC_SUBST([VERSION], [$2])], -[_AM_SET_OPTIONS([$1])dnl -dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. -m4_if( - m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), - [ok:ok],, - [m4_fatal([AC_INIT should be called with package and version arguments])])dnl - AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl - AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl - -_AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) - AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl - -# Some tools Automake needs. -AC_REQUIRE([AM_SANITY_CHECK])dnl -AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) -AM_MISSING_PROG([AUTOCONF], [autoconf]) -AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) -AM_MISSING_PROG([AUTOHEADER], [autoheader]) -AM_MISSING_PROG([MAKEINFO], [makeinfo]) -AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -# For better backward compatibility. To be removed once Automake 1.9.x -# dies out for good. For more background, see: -# -# -AC_SUBST([mkdir_p], ['$(MKDIR_P)']) -# We need awk for the "check" target (and possibly the TAP driver). The -# system "awk" is bad on some platforms. -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([AC_PROG_MAKE_SET])dnl -AC_REQUIRE([AM_SET_LEADING_DOT])dnl -_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) -_AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES([CC])], - [m4_define([AC_PROG_CC], - m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES([CXX])], - [m4_define([AC_PROG_CXX], - m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES([OBJC])], - [m4_define([AC_PROG_OBJC], - m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], - [_AM_DEPENDENCIES([OBJCXX])], - [m4_define([AC_PROG_OBJCXX], - m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl -]) -# Variables for tags utilities; see am/tags.am -if test -z "$CTAGS"; then - CTAGS=ctags -fi -AC_SUBST([CTAGS]) -if test -z "$ETAGS"; then - ETAGS=etags -fi -AC_SUBST([ETAGS]) -if test -z "$CSCOPE"; then - CSCOPE=cscope -fi -AC_SUBST([CSCOPE]) - -AC_REQUIRE([AM_SILENT_RULES])dnl -dnl The testsuite driver may need to know about EXEEXT, so add the -dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This -dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. -AC_CONFIG_COMMANDS_PRE(dnl -[m4_provide_if([_AM_COMPILER_EXEEXT], - [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl - -# POSIX will say in a future version that running "rm -f" with no argument -# is OK; and we want to be able to make that assumption in our Makefile -# recipes. So use an aggressive probe to check that the usage we want is -# actually supported "in the wild" to an acceptable degree. -# See automake bug#10828. -# To make any issue more visible, cause the running configure to be aborted -# by default if the 'rm' program in use doesn't match our expectations; the -# user can still override this though. -if rm -f && rm -fr && rm -rf; then : OK; else - cat >&2 <<'END' -Oops! - -Your 'rm' program seems unable to run without file operands specified -on the command line, even when the '-f' option is present. This is contrary -to the behaviour of most rm programs out there, and not conforming with -the upcoming POSIX standard: - -Please tell bug-automake@gnu.org about your system, including the value -of your $PATH and any error possibly output before this message. This -can help us improve future automake versions. - -END - if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then - echo 'Configuration will proceed anyway, since you have set the' >&2 - echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 - echo >&2 - else - cat >&2 <<'END' -Aborting the configuration process, to ensure you take notice of the issue. - -You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . - -If you want to complete the configuration process using your problematic -'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM -to "yes", and re-run configure. - -END - AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) - fi -fi -dnl The trailing newline in this macro's definition is deliberate, for -dnl backward compatibility and to allow trailing 'dnl'-style comments -dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. -]) - -dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not -dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further -dnl mangled by Autoconf and run in a shell conditional statement. -m4_define([_AC_COMPILER_EXEEXT], -m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. The stamp files are numbered to have different names. - -# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the -# loop where config.status creates the headers, so we can generate -# our stamp files there. -AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], -[# Compute $1's index in $config_headers. -_am_arg=$1 -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $_am_arg | $_am_arg:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) - -# Copyright (C) 2001-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_SH -# ------------------ -# Define $install_sh. -AC_DEFUN([AM_PROG_INSTALL_SH], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi -AC_SUBST([install_sh])]) - -# Copyright (C) 2003-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- -# From Jim Meyering - -# Copyright (C) 1996-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_MAINTAINER_MODE([DEFAULT-MODE]) -# ---------------------------------- -# Control maintainer-specific portions of Makefiles. -# Default is to disable them, unless 'enable' is passed literally. -# For symmetry, 'disable' may be passed as well. Anyway, the user -# can override the default with the --enable/--disable switch. -AC_DEFUN([AM_MAINTAINER_MODE], -[m4_case(m4_default([$1], [disable]), - [enable], [m4_define([am_maintainer_other], [disable])], - [disable], [m4_define([am_maintainer_other], [enable])], - [m4_define([am_maintainer_other], [enable]) - m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) -AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) - dnl maintainer-mode's default is 'disable' unless 'enable' is passed - AC_ARG_ENABLE([maintainer-mode], - [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], - am_maintainer_other[ make rules and dependencies not useful - (and sometimes confusing) to the casual installer])], - [USE_MAINTAINER_MODE=$enableval], - [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) - AC_MSG_RESULT([$USE_MAINTAINER_MODE]) - AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) - MAINT=$MAINTAINER_MODE_TRUE - AC_SUBST([MAINT])dnl -] -) - -# Check to see how 'make' treats includes. -*- Autoconf -*- - -# Copyright (C) 2001-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_MAKE_INCLUDE() -# ----------------- -# Check whether make has an 'include' directive that can support all -# the idioms we need for our automatic dependency tracking code. -AC_DEFUN([AM_MAKE_INCLUDE], -[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) -cat > confinc.mk << 'END' -am__doit: - @echo this is the am__doit target >confinc.out -.PHONY: am__doit -END -am__include="#" -am__quote= -# BSD make does it like this. -echo '.include "confinc.mk" # ignored' > confmf.BSD -# Other make implementations (GNU, Solaris 10, AIX) do it like this. -echo 'include confinc.mk # ignored' > confmf.GNU -_am_result=no -for s in GNU BSD; do - AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) - AS_CASE([$?:`cat confinc.out 2>/dev/null`], - ['0:this is the am__doit target'], - [AS_CASE([$s], - [BSD], [am__include='.include' am__quote='"'], - [am__include='include' am__quote=''])]) - if test "$am__include" != "#"; then - _am_result="yes ($s style)" - break - fi -done -rm -f confinc.* confmf.* -AC_MSG_RESULT([${_am_result}]) -AC_SUBST([am__include])]) -AC_SUBST([am__quote])]) - -# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- - -# Copyright (C) 1997-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_MISSING_PROG(NAME, PROGRAM) -# ------------------------------ -AC_DEFUN([AM_MISSING_PROG], -[AC_REQUIRE([AM_MISSING_HAS_RUN]) -$1=${$1-"${am_missing_run}$2"} -AC_SUBST($1)]) - -# AM_MISSING_HAS_RUN -# ------------------ -# Define MISSING if not defined so far and test if it is modern enough. -# If it is, set am_missing_run to use it, otherwise, to nothing. -AC_DEFUN([AM_MISSING_HAS_RUN], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([missing])dnl -if test x"${MISSING+set}" != xset; then - MISSING="\${SHELL} '$am_aux_dir/missing'" -fi -# Use eval to expand $SHELL -if eval "$MISSING --is-lightweight"; then - am_missing_run="$MISSING " -else - am_missing_run= - AC_MSG_WARN(['missing' script is too old or missing]) -fi -]) - -# Helper functions for option handling. -*- Autoconf -*- - -# Copyright (C) 2001-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_MANGLE_OPTION(NAME) -# ----------------------- -AC_DEFUN([_AM_MANGLE_OPTION], -[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - -# _AM_SET_OPTION(NAME) -# -------------------- -# Set option NAME. Presently that only means defining a flag for this option. -AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) - -# _AM_SET_OPTIONS(OPTIONS) -# ------------------------ -# OPTIONS is a space-separated list of Automake options. -AC_DEFUN([_AM_SET_OPTIONS], -[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) - -# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) -# ------------------------------------------- -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -AC_DEFUN([_AM_IF_OPTION], -[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) - -# Copyright (C) 1999-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_PROG_CC_C_O -# --------------- -# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC -# to automatically call this. -AC_DEFUN([_AM_PROG_CC_C_O], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([compile])dnl -AC_LANG_PUSH([C])dnl -AC_CACHE_CHECK( - [whether $CC understands -c and -o together], - [am_cv_prog_cc_c_o], - [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) - # Make sure it works both with $CC and with simple cc. - # Following AC_PROG_CC_C_O, we do the test twice because some - # compilers refuse to overwrite an existing .o file with -o, - # though they will create one. - am_cv_prog_cc_c_o=yes - for am_i in 1 2; do - if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ - && test -f conftest2.$ac_objext; then - : OK - else - am_cv_prog_cc_c_o=no - break - fi - done - rm -f core conftest* - unset am_i]) -if test "$am_cv_prog_cc_c_o" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -AC_LANG_POP([C])]) - -# For backward compatibility. -AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) - -# Copyright (C) 2001-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_RUN_LOG(COMMAND) -# ------------------- -# Run COMMAND, save the exit status in ac_status, and log it. -# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) -AC_DEFUN([AM_RUN_LOG], -[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD - ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - (exit $ac_status); }]) - -# Check to make sure that the build environment is sane. -*- Autoconf -*- - -# Copyright (C) 1996-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_SANITY_CHECK -# --------------- -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[[\\\"\#\$\&\'\`$am_lf]]*) - AC_MSG_ERROR([unsafe absolute working directory name]);; -esac -case $srcdir in - *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) - AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; -esac - -# Do 'set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - am_has_slept=no - for am_try in 1 2; do - echo "timestamp, slept: $am_has_slept" > conftest.file - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken - alias in your environment]) - fi - if test "$[2]" = conftest.file || test $am_try -eq 2; then - break - fi - # Just in case. - sleep 1 - am_has_slept=yes - done - test "$[2]" = conftest.file - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -AC_MSG_RESULT([yes]) -# If we didn't sleep, we still need to ensure time stamps of config.status and -# generated files are strictly newer. -am_sleep_pid= -if grep 'slept: no' conftest.file >/dev/null 2>&1; then - ( sleep 1 ) & - am_sleep_pid=$! -fi -AC_CONFIG_COMMANDS_PRE( - [AC_MSG_CHECKING([that generated files are newer than configure]) - if test -n "$am_sleep_pid"; then - # Hide warnings about reused PIDs. - wait $am_sleep_pid 2>/dev/null - fi - AC_MSG_RESULT([done])]) -rm -f conftest.file -]) - -# Copyright (C) 2009-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_SILENT_RULES([DEFAULT]) -# -------------------------- -# Enable less verbose build rules; with the default set to DEFAULT -# ("yes" being less verbose, "no" or empty being verbose). -AC_DEFUN([AM_SILENT_RULES], -[AC_ARG_ENABLE([silent-rules], [dnl -AS_HELP_STRING( - [--enable-silent-rules], - [less verbose build output (undo: "make V=1")]) -AS_HELP_STRING( - [--disable-silent-rules], - [verbose build output (undo: "make V=0")])dnl -]) -case $enable_silent_rules in @%:@ ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; -esac -dnl -dnl A few 'make' implementations (e.g., NonStop OS and NextStep) -dnl do not support nested variable expansions. -dnl See automake bug#9928 and bug#10237. -am_make=${MAKE-make} -AC_CACHE_CHECK([whether $am_make supports nested variables], - [am_cv_make_support_nested_variables], - [if AS_ECHO([['TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi]) -if test $am_cv_make_support_nested_variables = yes; then - dnl Using '$V' instead of '$(V)' breaks IRIX make. - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AC_SUBST([AM_V])dnl -AM_SUBST_NOTMAKE([AM_V])dnl -AC_SUBST([AM_DEFAULT_V])dnl -AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl -AC_SUBST([AM_DEFAULT_VERBOSITY])dnl -AM_BACKSLASH='\' -AC_SUBST([AM_BACKSLASH])dnl -_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl -]) - -# Copyright (C) 2001-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_STRIP -# --------------------- -# One issue with vendor 'install' (even GNU) is that you can't -# specify the program used to strip binaries. This is especially -# annoying in cross-compiling environments, where the build's strip -# is unlikely to handle the host's binaries. -# Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in "make install-strip", and initialize -# STRIPPROG with the value of the STRIP variable (set by the user). -AC_DEFUN([AM_PROG_INSTALL_STRIP], -[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using 'strip' when the user -# run "make install-strip". However 'strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the 'STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. -if test "$cross_compiling" != no; then - AC_CHECK_TOOL([STRIP], [strip], :) -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" -AC_SUBST([INSTALL_STRIP_PROGRAM])]) - -# Copyright (C) 2006-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- -# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. -# This macro is traced by Automake. -AC_DEFUN([_AM_SUBST_NOTMAKE]) - -# AM_SUBST_NOTMAKE(VARIABLE) -# -------------------------- -# Public sister of _AM_SUBST_NOTMAKE. -AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) - -# Check how to create a tarball. -*- Autoconf -*- - -# Copyright (C) 2004-2021 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_PROG_TAR(FORMAT) -# -------------------- -# Check how to create a tarball in format FORMAT. -# FORMAT should be one of 'v7', 'ustar', or 'pax'. -# -# Substitute a variable $(am__tar) that is a command -# writing to stdout a FORMAT-tarball containing the directory -# $tardir. -# tardir=directory && $(am__tar) > result.tar -# -# Substitute a variable $(am__untar) that extract such -# a tarball read from stdin. -# $(am__untar) < result.tar -# -AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. Yes, it's still used -# in the wild :-( We should find a proper way to deprecate it ... -AC_SUBST([AMTAR], ['$${TAR-tar}']) - -# We'll loop over all known methods to create a tar archive until one works. -_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' - -m4_if([$1], [v7], - [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], - - [m4_case([$1], - [ustar], - [# The POSIX 1988 'ustar' format is defined with fixed-size fields. - # There is notably a 21 bits limit for the UID and the GID. In fact, - # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 - # and bug#13588). - am_max_uid=2097151 # 2^21 - 1 - am_max_gid=$am_max_uid - # The $UID and $GID variables are not portable, so we need to resort - # to the POSIX-mandated id(1) utility. Errors in the 'id' calls - # below are definitely unexpected, so allow the users to see them - # (that is, avoid stderr redirection). - am_uid=`id -u || echo unknown` - am_gid=`id -g || echo unknown` - AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) - if test $am_uid -le $am_max_uid; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - _am_tools=none - fi - AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) - if test $am_gid -le $am_max_gid; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - _am_tools=none - fi], - - [pax], - [], - - [m4_fatal([Unknown tar format])]) - - AC_MSG_CHECKING([how to create a $1 tar archive]) - - # Go ahead even if we have the value already cached. We do so because we - # need to set the values for the 'am__tar' and 'am__untar' variables. - _am_tools=${am_cv_prog_tar_$1-$_am_tools} - - for _am_tool in $_am_tools; do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break - - # tar/untar a dummy directory, and stop if the command works. - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) - rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi - done - rm -rf conftest.dir - - AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) - AC_MSG_RESULT([$am_cv_prog_tar_$1])]) - -AC_SUBST([am__tar]) -AC_SUBST([am__untar]) -]) # _AM_PROG_TAR - -m4_include([config/m4/libtool.m4]) -m4_include([config/m4/ltoptions.m4]) -m4_include([config/m4/ltsugar.m4]) -m4_include([config/m4/ltversion.m4]) -m4_include([config/m4/lt~obsolete.m4]) diff --git a/ext/libpqxx-7.7.3/appveyor.yml b/ext/libpqxx-7.7.3/appveyor.yml deleted file mode 100644 index 110bd75ad..000000000 --- a/ext/libpqxx-7.7.3/appveyor.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Configuration for test runs in Appveyor. -version: 1.0.{build} -image: Visual Studio 2022 -services: postgresql13 -# Run CMake to build libpqxx.sln. -before_build: -- cmd: >- - call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - - cmake -DBUILD_SHARED_LIBS=1 -DCMAKE_CXX_STANDARD=23 -configuration: Release -build: - parallel: true - project: libpqxx.sln -test_script: -- ps: >- - $env:Path += ";.\src\Release;C:\Program Files\PostgreSQL\13\bin" - - $env:PGUSER = "postgres" - - $env:PGPASSWORD = "Password12!" - - .\test\Release\runner.exe -notifications: -- provider: Email - subject: 'libpqxx: AppVeyor build failure' - message: The libpqxx AppVeyor build has failed. - on_build_success: false - on_build_failure: true - on_build_status_changed: false diff --git a/ext/libpqxx-7.7.3/autogen.sh b/ext/libpqxx-7.7.3/autogen.sh deleted file mode 100755 index a09cb5ae7..000000000 --- a/ext/libpqxx-7.7.3/autogen.sh +++ /dev/null @@ -1,44 +0,0 @@ -#! /bin/sh -# Run this to generate the configure script etc. - -set -eu - -PQXXVERSION=$(./tools/extract_version) -PQXX_ABI=$(./tools/extract_version --abi) -PQXX_MAJOR=$(./tools/extract_version --major) -PQXX_MINOR=$(./tools/extract_version --minor) -echo "libpqxx version $PQXXVERSION" -echo "libpqxx ABI version $PQXX_ABI" - -substitute() { - sed -e "s/@PQXXVERSION@/$PQXXVERSION/g" \ - -e "s/@PQXX_MAJOR@/$PQXX_MAJOR/g" \ - -e "s/@PQXX_MINOR@/$PQXX_MINOR/g" \ - -e "s/@PQXX_ABI@/$PQXX_ABI/g" \ - "$1" -} - - -# Use templating system to generate various Makefiles. -expand_templates() { - for template in "$@" - do - ./tools/template2mak.py "$template" "${template%.template}" - done -} - - -# We have two kinds of templates. One uses our custom templating tool. And -# a few others simply have some substitutions done. -expand_templates $(find -name \*.template) -substitute include/pqxx/version.hxx.template >include/pqxx/version.hxx -substitute include/pqxx/doc/mainpage.md.template >include/pqxx/doc/mainpage.md - - -autoheader -libtoolize --force --automake --copy -aclocal -I . -I config/m4 -automake --add-missing --copy -autoconf - -echo "Done." diff --git a/ext/libpqxx-7.7.3/cmake/config.cmake b/ext/libpqxx-7.7.3/cmake/config.cmake deleted file mode 100644 index 816ee4474..000000000 --- a/ext/libpqxx-7.7.3/cmake/config.cmake +++ /dev/null @@ -1,157 +0,0 @@ -function(detect_code_compiled code macro msg) - message(STATUS "Detecting ${msg}") - check_cxx_source_compiles("${code}" "${macro}" FAIL_REGEX "warning") - if(${macro}) - message(STATUS "Detecting ${msg} - supported") - else() - message(STATUS "Detecting ${msg} - not supported") - endif() -endfunction(detect_code_compiled) - -include(CheckIncludeFileCXX) -include(CheckFunctionExists) -include(CheckSymbolExists) -include(CMakeDetermineCompileFeatures) -include(CheckCXXSourceCompiles) -include(CMakeFindDependencyMacro) - -if(NOT PostgreSQL_FOUND) - if(POLICY CMP0074) - cmake_policy(PUSH) - # CMP0074 is `OLD` by `cmake_minimum_required(VERSION 3.7)`, - # sets `NEW` to enable support CMake variable `PostgreSQL_ROOT`. - cmake_policy(SET CMP0074 NEW) - endif() - - find_package(PostgreSQL REQUIRED) - - if(POLICY CMP0074) - cmake_policy(POP) - endif() -endif() - -check_function_exists("poll" PQXX_HAVE_POLL) - -set(CMAKE_REQUIRED_LIBRARIES pq) -check_symbol_exists( - PQencryptPasswordConn - "${PostgreSQL_INCLUDE_DIR}/libpq-fe.h" - PQXX_HAVE_PQENCRYPTPASSWORDCONN) -check_symbol_exists( - PQenterPipelineMode - "${PostgreSQL_INCLUDE_DIR}/libpq-fe.h" - PQXX_HAVE_PQ_PIPELINE) - -cmake_determine_compile_features(CXX) -cmake_policy(SET CMP0057 NEW) - -# check_cxx_source_compiles requires CMAKE_REQUIRED_DEFINITIONS to specify -# compiling arguments. -# Wordaround: Push CMAKE_REQUIRED_DEFINITIONS -if(CMAKE_REQUIRED_DEFINITIONS) - set(def "${CMAKE_REQUIRED_DEFINITIONS}") -endif() -set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION}) -set(CMAKE_REQUIRED_QUIET ON) - -try_compile( - PQXX_HAVE_GCC_PURE - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/gcc_pure.cxx) -try_compile( - PQXX_HAVE_GCC_VISIBILITY - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/gcc_visibility.cxx) -try_compile( - PQXX_HAVE_LIKELY - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/likely.cxx) -try_compile( - PQXX_HAVE_CXA_DEMANGLE - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/cxa_demangle.cxx) -try_compile( - PQXX_HAVE_CONCEPTS - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/concepts.cxx) -try_compile( - PQXX_HAVE_SPAN - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/span.cxx) -try_compile( - PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/multidim-subscript.cxx) -try_compile( - PQXX_HAVE_CHARCONV_FLOAT - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/charconv_float.cxx) -try_compile( - PQXX_HAVE_CHARCONV_INT - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/charconv_int.cxx) -try_compile( - PQXX_HAVE_PATH - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/fs.cxx) -try_compile( - PQXX_HAVE_THREAD_LOCAL - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/thread_local.cxx) -try_compile( - PQXX_HAVE_SLEEP_FOR - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/sleep_for.cxx) -try_compile( - PQXX_HAVE_STRERROR_R - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/strerror_r.cxx) -try_compile( - PQXX_HAVE_STRERROR_S - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/strerror_s.cxx) -try_compile( - PQXX_HAVE_YEAR_MONTH_DAY - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/year_month_day.cxx) -try_compile( - PQXX_HAVE_CMP - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/cmp.cxx) - -try_compile( - need_fslib - ${PROJECT_BINARY_DIR} - SOURCES ${PROJECT_SOURCE_DIR}/config-tests/need_fslib.cxx) -if(!need_fslib) - # TODO: This may work for gcc 8, but some clang versions may need -lc++fs. - link_libraries(stdc++fs) -endif() - -# check_cxx_source_compiles requires CMAKE_REQUIRED_DEFINITIONS to specify -# compiling arguments. -# Workaround: Pop CMAKE_REQUIRED_DEFINITIONS -if(def) - set(CMAKE_REQUIRED_DEFINITIONS ${def}) - unset(def CACHE) -else() - unset(CMAKE_REQUIRED_DEFINITIONS CACHE) -endif() -set(CMAKE_REQUIRED_QUIET OFF) - -set(AC_CONFIG_H_IN "${PROJECT_SOURCE_DIR}/include/pqxx/config.h.in") -set(CM_CONFIG_H_IN "${PROJECT_BINARY_DIR}/include/pqxx/config_cmake.h.in") -set(CM_CONFIG_PUB "${PROJECT_BINARY_DIR}/include/pqxx/config-public-compiler.h") -set(CM_CONFIG_INT "${PROJECT_BINARY_DIR}/include/pqxx/config-internal-compiler.h") -set(CM_CONFIG_PQ "${PROJECT_BINARY_DIR}/include/pqxx/config-internal-libpq.h") -message(STATUS "Generating config.h") -file(WRITE "${CM_CONFIG_H_IN}" "") -file(STRINGS "${AC_CONFIG_H_IN}" lines) -foreach(line ${lines}) - string(REGEX REPLACE "^#undef" "#cmakedefine" l "${line}") - file(APPEND "${CM_CONFIG_H_IN}" "${l}\n") -endforeach() -configure_file("${CM_CONFIG_H_IN}" "${CM_CONFIG_INT}" @ONLY) -configure_file("${CM_CONFIG_H_IN}" "${CM_CONFIG_PUB}" @ONLY) -configure_file("${CM_CONFIG_H_IN}" "${CM_CONFIG_PQ}" @ONLY) -message(STATUS "Generating config.h - done") diff --git a/ext/libpqxx-7.7.3/cmake/libpqxx-config.cmake b/ext/libpqxx-7.7.3/cmake/libpqxx-config.cmake deleted file mode 100644 index cb25a05f2..000000000 --- a/ext/libpqxx-7.7.3/cmake/libpqxx-config.cmake +++ /dev/null @@ -1,4 +0,0 @@ -include(CMakeFindDependencyMacro) -find_dependency(PostgreSQL) - -include("${CMAKE_CURRENT_LIST_DIR}/libpqxx-targets.cmake") diff --git a/ext/libpqxx-7.7.3/compile_flags.in b/ext/libpqxx-7.7.3/compile_flags.in deleted file mode 100644 index 1304e8aa8..000000000 --- a/ext/libpqxx-7.7.3/compile_flags.in +++ /dev/null @@ -1 +0,0 @@ -@CPPFLAGS@ @CXXFLAGS@ diff --git a/ext/libpqxx-7.7.3/config-tests/README.md b/ext/libpqxx-7.7.3/config-tests/README.md deleted file mode 100644 index b3865d0f0..000000000 --- a/ext/libpqxx-7.7.3/config-tests/README.md +++ /dev/null @@ -1,22 +0,0 @@ -Configuration tests -=================== - -Libpqxx comes with support for different build systems: the GNU autotools, -CMake, Visual Studio's "nmake", and raw GNU "make" on Windows. - -For several of these build systems, we need to test things like "does this -compiler environment support `std::to_chars` for floating-point types?" - -We test these things by trying to compile a particular snippet of code, and -seeing whether that succeeds. - -To avoid duplicating those snippets for multiple build systems, we put them -here. Both the autotools configuration and the CMake configuration can refer to -them that way. - -It took a bit of nasty magic to read a C++ source file into m4 and treat it as -a string literal, without macro expansion. There is every chance that I missed -something, so be prepared for tests failing for unexpected reasons! Some C++ -syntax may end up having an unforeseen meaning in m4, and screw up the handling -of the code snippet. Re-configure, and read your logs carefully after editing -these snippets. diff --git a/ext/libpqxx-7.7.3/config-tests/charconv_float.cxx b/ext/libpqxx-7.7.3/config-tests/charconv_float.cxx deleted file mode 100644 index bc5d973e3..000000000 --- a/ext/libpqxx-7.7.3/config-tests/charconv_float.cxx +++ /dev/null @@ -1,16 +0,0 @@ -// Test for std::to_string/std::from_string for floating-point types. -#include -#include - -int main() -{ - char z[100]; - auto rt = std::to_chars(std::begin(z), std::end(z), 3.14159L); - if (rt.ec != std::errc{}) - return 1; - long double n; - auto rf = std::from_chars(std::cbegin(z), std::cend(z), n); - if (rf.ec != std::errc{}) - return 2; - return (n > 3 and n < 4) ? 0 : 1; -} diff --git a/ext/libpqxx-7.7.3/config-tests/charconv_int.cxx b/ext/libpqxx-7.7.3/config-tests/charconv_int.cxx deleted file mode 100644 index 076ee0de3..000000000 --- a/ext/libpqxx-7.7.3/config-tests/charconv_int.cxx +++ /dev/null @@ -1,16 +0,0 @@ -// Test for std::to_string/std::from_string for integral types. -#include -#include - -int main() -{ - char z[100]; - auto rt = std::to_chars(std::begin(z), std::end(z), 9ULL); - if (rt.ec != std::errc{}) - return 1; - unsigned long long n; - auto rf = std::from_chars(std::cbegin(z), std::cend(z), n); - if (rf.ec != std::errc{}) - return 2; - return (n == 9ULL) ? 0 : 1; -} diff --git a/ext/libpqxx-7.7.3/config-tests/cmp.cxx b/ext/libpqxx-7.7.3/config-tests/cmp.cxx deleted file mode 100644 index 7f5abaa5d..000000000 --- a/ext/libpqxx-7.7.3/config-tests/cmp.cxx +++ /dev/null @@ -1,8 +0,0 @@ -// Test for C++20 std::cmp_greater etc. support. -#include - - -int main() -{ - return std::cmp_greater(-1, 2u) && std::cmp_less_equal(3, 0); -} diff --git a/ext/libpqxx-7.7.3/config-tests/concepts.cxx b/ext/libpqxx-7.7.3/config-tests/concepts.cxx deleted file mode 100644 index 5589b4e58..000000000 --- a/ext/libpqxx-7.7.3/config-tests/concepts.cxx +++ /dev/null @@ -1,21 +0,0 @@ -// Test for concepts support. Not just the language feature; also headers. -#include -#include -#include - - -template -concept Foo = std::ranges::input_range; - - -template auto foo(F const &r) -{ - return std::distance(std::begin(r), std::end(r)); -} - - -int main() -{ - std::vector const v{1, 2, 3}; - std::cout << foo(v) << '\n'; -} diff --git a/ext/libpqxx-7.7.3/config-tests/cxa_demangle.cxx b/ext/libpqxx-7.7.3/config-tests/cxa_demangle.cxx deleted file mode 100644 index 4d4ee7e6b..000000000 --- a/ext/libpqxx-7.7.3/config-tests/cxa_demangle.cxx +++ /dev/null @@ -1,19 +0,0 @@ -// Test for cross-vendor C++ ABI's __cxa_demangle function. -#include -#include -#include -#include - -#include - -int main() -{ - int status = 0; - char *name = - abi::__cxa_demangle(typeid(10).name(), nullptr, nullptr, &status); - if (status != 0) - throw std::runtime_error("Demangle failed!"); - int result = std::strcmp(name, "int"); - std::free(name); - return result; -} diff --git a/ext/libpqxx-7.7.3/config-tests/fs.cxx b/ext/libpqxx-7.7.3/config-tests/fs.cxx deleted file mode 100644 index d93d37f5d..000000000 --- a/ext/libpqxx-7.7.3/config-tests/fs.cxx +++ /dev/null @@ -1,9 +0,0 @@ -// Check for working std::filesystem support. -#include - - -int main() -{ - // Apparently some versions of MinGW lack this comparison operator. - return std::filesystem::path{} != std::filesystem::path{}; -} diff --git a/ext/libpqxx-7.7.3/config-tests/gcc_pure.cxx b/ext/libpqxx-7.7.3/config-tests/gcc_pure.cxx deleted file mode 100644 index 4edd267c6..000000000 --- a/ext/libpqxx-7.7.3/config-tests/gcc_pure.cxx +++ /dev/null @@ -1,10 +0,0 @@ -// Test for gcc-style "pure" attribute. -int __attribute__((pure)) f() -{ - return 0; -} - -int main() -{ - return f(); -} diff --git a/ext/libpqxx-7.7.3/config-tests/gcc_visibility.cxx b/ext/libpqxx-7.7.3/config-tests/gcc_visibility.cxx deleted file mode 100644 index 23d0111d7..000000000 --- a/ext/libpqxx-7.7.3/config-tests/gcc_visibility.cxx +++ /dev/null @@ -1,12 +0,0 @@ -// Test for gcc-style "visibility" attribute. -struct __attribute__((visibility("hidden"))) D -{ - D() {} - int f() { return 0; } -}; - -int main() -{ - D d; - return d.f(); -} diff --git a/ext/libpqxx-7.7.3/config-tests/likely.cxx b/ext/libpqxx-7.7.3/config-tests/likely.cxx deleted file mode 100644 index 9d0eca8d3..000000000 --- a/ext/libpqxx-7.7.3/config-tests/likely.cxx +++ /dev/null @@ -1,15 +0,0 @@ -// Test for C++20 [[likely]] and [[unlikely]] attributes. - -int main(int argc, char **) -{ -#if __cplusplus < 202002L - deliberately_fail(because, older, C++, standard); -#endif - - int x = 0; - if (argc == 1) [[likely]] - x = 0; - else - x = 1; - return x; -} diff --git a/ext/libpqxx-7.7.3/config-tests/multidim-subscript.cxx b/ext/libpqxx-7.7.3/config-tests/multidim-subscript.cxx deleted file mode 100644 index f75d1aa7a..000000000 --- a/ext/libpqxx-7.7.3/config-tests/multidim-subscript.cxx +++ /dev/null @@ -1,14 +0,0 @@ -// Test for multidimensional subscript operator support. -// Proposed for C++23: P2128R6. -struct table -{ - int width = 100; - - int operator[](int x, int y) const { return x + width * y; } -}; - - -int main() -{ - return table{}[0, 0]; -} diff --git a/ext/libpqxx-7.7.3/config-tests/need_fslib.cxx b/ext/libpqxx-7.7.3/config-tests/need_fslib.cxx deleted file mode 100644 index 041c46b43..000000000 --- a/ext/libpqxx-7.7.3/config-tests/need_fslib.cxx +++ /dev/null @@ -1,21 +0,0 @@ -// Check whether we need to link to the stdc++fs library. -// -// We assume that the presence of the header means that we have -// support for the basics of std::filesystem. This check will succeed if -// either there is no header, or there is one and it works without -// any special options. If the link fails, we assume that -lstdc++fs will fix -// it for us. - -#include - -#if __has_include() -# include -#endif - - -int main() -{ -#if __has_include() - std::cout << std::filesystem::path{"foo.bar"}.c_str() << '\n'; -#endif -} diff --git a/ext/libpqxx-7.7.3/config-tests/poll.cxx b/ext/libpqxx-7.7.3/config-tests/poll.cxx deleted file mode 100644 index d67cef55d..000000000 --- a/ext/libpqxx-7.7.3/config-tests/poll.cxx +++ /dev/null @@ -1,7 +0,0 @@ -// Test for poll(). -#include - -int main() -{ - return poll(nullptr, 0, 0); -} diff --git a/ext/libpqxx-7.7.3/config-tests/sleep_for.cxx b/ext/libpqxx-7.7.3/config-tests/sleep_for.cxx deleted file mode 100644 index f081fe0e5..000000000 --- a/ext/libpqxx-7.7.3/config-tests/sleep_for.cxx +++ /dev/null @@ -1,28 +0,0 @@ -// Test for std::this_thread::sleep_for(). -/* For some reason MinGW's header seems to be broken. - * - * But it gets worse. It looks as if we can include without problems - * in this configuration test. Why does it break when MinGW users try to build - * the library, but succeed when we try it here? - * - * To try and get close to the situation in the library code itself, we try - * including some standard headers that we don't strictly need here. - */ - -#if __has_include() -# include -#endif - -#include -#include -#include -#include -#include - -#include -#include - -int main() -{ - std::this_thread::sleep_for(std::chrono::microseconds{10u}); -} diff --git a/ext/libpqxx-7.7.3/config-tests/span.cxx b/ext/libpqxx-7.7.3/config-tests/span.cxx deleted file mode 100644 index 8c13b97c9..000000000 --- a/ext/libpqxx-7.7.3/config-tests/span.cxx +++ /dev/null @@ -1,8 +0,0 @@ -// Test for std::span. -#include - -int main(int argc, char **argv) -{ - std::span args{argv, static_cast(argc)}; - return static_cast(std::size(args) - 1u); -} diff --git a/ext/libpqxx-7.7.3/config-tests/strerror_r.cxx b/ext/libpqxx-7.7.3/config-tests/strerror_r.cxx deleted file mode 100644 index 604d3b899..000000000 --- a/ext/libpqxx-7.7.3/config-tests/strerror_r.cxx +++ /dev/null @@ -1,14 +0,0 @@ -// Check for strerror_r. -// It can be either the POSIX version (which returns int) or the GNU version -// (which returns char *). - -#include -#include - -int main() -{ - char buffer[200]; - auto res{strerror_r(1, buffer, 200)}; - // Sidestep type differences. We don't really care what the value is. - return not not res; -} diff --git a/ext/libpqxx-7.7.3/config-tests/strerror_s.cxx b/ext/libpqxx-7.7.3/config-tests/strerror_s.cxx deleted file mode 100644 index f6f99a7a5..000000000 --- a/ext/libpqxx-7.7.3/config-tests/strerror_s.cxx +++ /dev/null @@ -1,11 +0,0 @@ -// Test for strerror_s, as defined in Windows and C11. -// Presumably this'll be part of the C++ standard some day. - -#include - -int main() -{ - using namespace std; - char buf[200]; - return strerror_s(buf, 200, 1); -} diff --git a/ext/libpqxx-7.7.3/config-tests/thread_local.cxx b/ext/libpqxx-7.7.3/config-tests/thread_local.cxx deleted file mode 100644 index b5a98b7b8..000000000 --- a/ext/libpqxx-7.7.3/config-tests/thread_local.cxx +++ /dev/null @@ -1,15 +0,0 @@ -// Test for std::to_string/std::from_string for floating-point types. -#include -#include - -int main(int argc, char **) -{ -#if defined(__MINGW32__) && defined(__GNUC__) -# if __GNUC__ < 11 || ((__GNUC__ == 11) && (__GNU_MINOR__ == 0)) -# error "On MinGW before gcc 11.1, thread_local breaks at run time." -# endif -#endif - thread_local std::stringstream s; - s << argc; - std::cout << s.str(); -} diff --git a/ext/libpqxx-7.7.3/config-tests/year_month_day.cxx b/ext/libpqxx-7.7.3/config-tests/year_month_day.cxx deleted file mode 100644 index dbe543b55..000000000 --- a/ext/libpqxx-7.7.3/config-tests/year_month_day.cxx +++ /dev/null @@ -1,7 +0,0 @@ -// Test for std::chrono::year_month_day etc. -#include - -int main() -{ - return int(std::chrono::year{1}); -} diff --git a/ext/libpqxx-7.7.3/config/Makefile.am b/ext/libpqxx-7.7.3/config/Makefile.am deleted file mode 100644 index f34b3107d..000000000 --- a/ext/libpqxx-7.7.3/config/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -EXTRA_DIST=m4/Makefile.am sample-headers -MAINTAINERCLEANFILES=Makefile.in config.guess config.sub install-sh \ - ltmain.sh missing mkinstalldirs - -dist-hook: - find "${distdir}" -type d -name CVS -print0 | xargs -0 rm -rf - find "${distdir}" -type d -name .svn -print0 | xargs -0 rm -rf - diff --git a/ext/libpqxx-7.7.3/config/Makefile.in b/ext/libpqxx-7.7.3/config/Makefile.in deleted file mode 100644 index bf7aa004a..000000000 --- a/ext/libpqxx-7.7.3/config/Makefile.in +++ /dev/null @@ -1,470 +0,0 @@ -# Makefile.in generated by automake 1.16.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2021 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = config -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ - $(top_srcdir)/config/m4/ltoptions.m4 \ - $(top_srcdir)/config/m4/ltsugar.m4 \ - $(top_srcdir)/config/m4/ltversion.m4 \ - $(top_srcdir)/config/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Makefile.in compile config.guess \ - config.sub install-sh ltmain.sh missing mkinstalldirs -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSCOPE = @CSCOPE@ -CTAGS = @CTAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ETAGS = @ETAGS@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_DOT = @HAVE_DOT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR = @MKDIR@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PG_CONFIG = @PG_CONFIG@ -PKG_CONFIG = @PKG_CONFIG@ -POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ -PQXXVERSION = @PQXXVERSION@ -PQXX_ABI = @PQXX_ABI@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_postgres_lib = @with_postgres_lib@ -EXTRA_DIST = m4/Makefile.am sample-headers -MAINTAINERCLEANFILES = Makefile.in config.guess config.sub install-sh \ - ltmain.sh missing mkinstalldirs - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu config/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -tags TAGS: - -ctags CTAGS: - -cscope cscopelist: - -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-hook -check-am: all-am -check: check-am -all-am: Makefile -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - cscopelist-am ctags-am dist-hook distclean distclean-generic \ - distclean-libtool distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags-am uninstall uninstall-am - -.PRECIOUS: Makefile - - -dist-hook: - find "${distdir}" -type d -name CVS -print0 | xargs -0 rm -rf - find "${distdir}" -type d -name .svn -print0 | xargs -0 rm -rf - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ext/libpqxx-7.7.3/config/compile b/ext/libpqxx-7.7.3/config/compile deleted file mode 100755 index df363c8fb..000000000 --- a/ext/libpqxx-7.7.3/config/compile +++ /dev/null @@ -1,348 +0,0 @@ -#! /bin/sh -# Wrapper for compilers which do not understand '-c -o'. - -scriptversion=2018-03-07.03; # UTC - -# Copyright (C) 1999-2021 Free Software Foundation, Inc. -# Written by Tom Tromey . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -nl=' -' - -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent tools from complaining about whitespace usage. -IFS=" "" $nl" - -file_conv= - -# func_file_conv build_file lazy -# Convert a $build file to $host form and store it in $file -# Currently only supports Windows hosts. If the determined conversion -# type is listed in (the comma separated) LAZY, no conversion will -# take place. -func_file_conv () -{ - file=$1 - case $file in - / | /[!/]*) # absolute file, and not a UNC file - if test -z "$file_conv"; then - # lazily determine how to convert abs files - case `uname -s` in - MINGW*) - file_conv=mingw - ;; - CYGWIN* | MSYS*) - file_conv=cygwin - ;; - *) - file_conv=wine - ;; - esac - fi - case $file_conv/,$2, in - *,$file_conv,*) - ;; - mingw/*) - file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` - ;; - cygwin/* | msys/*) - file=`cygpath -m "$file" || echo "$file"` - ;; - wine/*) - file=`winepath -w "$file" || echo "$file"` - ;; - esac - ;; - esac -} - -# func_cl_dashL linkdir -# Make cl look for libraries in LINKDIR -func_cl_dashL () -{ - func_file_conv "$1" - if test -z "$lib_path"; then - lib_path=$file - else - lib_path="$lib_path;$file" - fi - linker_opts="$linker_opts -LIBPATH:$file" -} - -# func_cl_dashl library -# Do a library search-path lookup for cl -func_cl_dashl () -{ - lib=$1 - found=no - save_IFS=$IFS - IFS=';' - for dir in $lib_path $LIB - do - IFS=$save_IFS - if $shared && test -f "$dir/$lib.dll.lib"; then - found=yes - lib=$dir/$lib.dll.lib - break - fi - if test -f "$dir/$lib.lib"; then - found=yes - lib=$dir/$lib.lib - break - fi - if test -f "$dir/lib$lib.a"; then - found=yes - lib=$dir/lib$lib.a - break - fi - done - IFS=$save_IFS - - if test "$found" != yes; then - lib=$lib.lib - fi -} - -# func_cl_wrapper cl arg... -# Adjust compile command to suit cl -func_cl_wrapper () -{ - # Assume a capable shell - lib_path= - shared=: - linker_opts= - for arg - do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - eat=1 - case $2 in - *.o | *.[oO][bB][jJ]) - func_file_conv "$2" - set x "$@" -Fo"$file" - shift - ;; - *) - func_file_conv "$2" - set x "$@" -Fe"$file" - shift - ;; - esac - ;; - -I) - eat=1 - func_file_conv "$2" mingw - set x "$@" -I"$file" - shift - ;; - -I*) - func_file_conv "${1#-I}" mingw - set x "$@" -I"$file" - shift - ;; - -l) - eat=1 - func_cl_dashl "$2" - set x "$@" "$lib" - shift - ;; - -l*) - func_cl_dashl "${1#-l}" - set x "$@" "$lib" - shift - ;; - -L) - eat=1 - func_cl_dashL "$2" - ;; - -L*) - func_cl_dashL "${1#-L}" - ;; - -static) - shared=false - ;; - -Wl,*) - arg=${1#-Wl,} - save_ifs="$IFS"; IFS=',' - for flag in $arg; do - IFS="$save_ifs" - linker_opts="$linker_opts $flag" - done - IFS="$save_ifs" - ;; - -Xlinker) - eat=1 - linker_opts="$linker_opts $2" - ;; - -*) - set x "$@" "$1" - shift - ;; - *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) - func_file_conv "$1" - set x "$@" -Tp"$file" - shift - ;; - *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) - func_file_conv "$1" mingw - set x "$@" "$file" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift - done - if test -n "$linker_opts"; then - linker_opts="-link$linker_opts" - fi - exec "$@" $linker_opts - exit 1 -} - -eat= - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: compile [--help] [--version] PROGRAM [ARGS] - -Wrapper for compilers which do not understand '-c -o'. -Remove '-o dest.o' from ARGS, run PROGRAM with the remaining -arguments, and rename the output as expected. - -If you are trying to build a whole package this is not the -right script to run: please start by reading the file 'INSTALL'. - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "compile $scriptversion" - exit $? - ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ - icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) - func_cl_wrapper "$@" # Doesn't return... - ;; -esac - -ofile= -cfile= - -for arg -do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - # So we strip '-o arg' only if arg is an object. - eat=1 - case $2 in - *.o | *.obj) - ofile=$2 - ;; - *) - set x "$@" -o "$2" - shift - ;; - esac - ;; - *.c) - cfile=$1 - set x "$@" "$1" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift -done - -if test -z "$ofile" || test -z "$cfile"; then - # If no '-o' option was seen then we might have been invoked from a - # pattern rule where we don't need one. That is ok -- this is a - # normal compilation that the losing compiler can handle. If no - # '.c' file was seen then we are probably linking. That is also - # ok. - exec "$@" -fi - -# Name of file we expect compiler to create. -cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` - -# Create the lock directory. -# Note: use '[/\\:.-]' here to ensure that we don't use the same name -# that we are using for the .o file. Also, base the name on the expected -# object file name, since that is what matters with a parallel build. -lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d -while true; do - if mkdir "$lockdir" >/dev/null 2>&1; then - break - fi - sleep 1 -done -# FIXME: race condition here if user kills between mkdir and trap. -trap "rmdir '$lockdir'; exit 1" 1 2 15 - -# Run the compile. -"$@" -ret=$? - -if test -f "$cofile"; then - test "$cofile" = "$ofile" || mv "$cofile" "$ofile" -elif test -f "${cofile}bj"; then - test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" -fi - -rmdir "$lockdir" -exit $ret - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC0" -# time-stamp-end: "; # UTC" -# End: diff --git a/ext/libpqxx-7.7.3/config/config.guess b/ext/libpqxx-7.7.3/config/config.guess deleted file mode 100755 index 2e9ad7fe8..000000000 --- a/ext/libpqxx-7.7.3/config/config.guess +++ /dev/null @@ -1,1462 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2016 Free Software Foundation, Inc. - -timestamp='2016-10-02' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess -# -# Please send patches to . - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2016 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_SYSTEM}" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval $set_cc_for_build - cat <<-EOF > $dummy.c - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - /sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || \ - echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - earmv*) - arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` - machine=${arch}${endian}-unknown - ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently (or will in the future) and ABI. - case "${UNAME_MACHINE_ARCH}" in - earm*) - os=netbsdelf - ;; - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # Determine ABI tags. - case "${UNAME_MACHINE_ARCH}" in - earm*) - expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}${abi}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:Sortix:*:*) - echo ${UNAME_MACHINE}-unknown-sortix - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE=alpha ;; - "EV4.5 (21064)") - UNAME_MACHINE=alpha ;; - "LCA4 (21066/21068)") - UNAME_MACHINE=alpha ;; - "EV5 (21164)") - UNAME_MACHINE=alphaev5 ;; - "EV5.6 (21164A)") - UNAME_MACHINE=alphaev56 ;; - "EV5.6 (21164PC)") - UNAME_MACHINE=alphapca56 ;; - "EV5.7 (21164PC)") - UNAME_MACHINE=alphapca57 ;; - "EV6 (21264)") - UNAME_MACHINE=alphaev6 ;; - "EV6.7 (21264A)") - UNAME_MACHINE=alphaev67 ;; - "EV6.8CB (21264C)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8AL (21264B)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8CX (21264D)") - UNAME_MACHINE=alphaev68 ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE=alphaev69 ;; - "EV7 (21364)") - UNAME_MACHINE=alphaev7 ;; - "EV7.9 (21364A)") - UNAME_MACHINE=alphaev79 ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH=i386 - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH=x86_64 - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 - 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH=hppa2.0n ;; - 64) HP_ARCH=hppa2.0w ;; - '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = hppa2.0w ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH=hppa2.0w - else - HP_ARCH=hppa64 - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - *:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi - else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - e2k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - k1om:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } - ;; - mips64el:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - openrisc*:Linux:*:*) - echo or1k-unknown-linux-${LIBC} - exit ;; - or32:Linux:*:* | or1k*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} - exit ;; - ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} - exit ;; - riscv32:Linux:*:* | riscv64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configure will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - fi - elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 - fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = x86; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = 386; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; - amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; -esac - -cat >&2 </dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/ext/libpqxx-7.7.3/config/config.sub b/ext/libpqxx-7.7.3/config/config.sub deleted file mode 100755 index dd2ca93c6..000000000 --- a/ext/libpqxx-7.7.3/config/config.sub +++ /dev/null @@ -1,1825 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. - -timestamp='2016-11-04' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2016 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | cloudabi*-eabi* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - os=$os"spe" - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* | -cloudabi* | -sortix* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos* | -phoenix* | -fuchsia*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -ios) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - c8051-*) - os=-elf - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/ext/libpqxx-7.7.3/config/depcomp b/ext/libpqxx-7.7.3/config/depcomp deleted file mode 100755 index 715e34311..000000000 --- a/ext/libpqxx-7.7.3/config/depcomp +++ /dev/null @@ -1,791 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2018-03-07.03; # UTC - -# Copyright (C) 1999-2021 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by 'PROGRAMS ARGS'. - object Object file output by 'PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputting dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -# Get the directory component of the given path, and save it in the -# global variables '$dir'. Note that this directory component will -# be either empty or ending with a '/' character. This is deliberate. -set_dir_from () -{ - case $1 in - */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; - *) dir=;; - esac -} - -# Get the suffix-stripped basename of the given path, and save it the -# global variable '$base'. -set_base_from () -{ - base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` -} - -# If no dependency file was actually created by the compiler invocation, -# we still have to create a dummy depfile, to avoid errors with the -# Makefile "include basename.Plo" scheme. -make_dummy_depfile () -{ - echo "#dummy" > "$depfile" -} - -# Factor out some common post-processing of the generated depfile. -# Requires the auxiliary global variable '$tmpdepfile' to be set. -aix_post_process_depfile () -{ - # If the compiler actually managed to produce a dependency file, - # post-process it. - if test -f "$tmpdepfile"; then - # Each line is of the form 'foo.o: dependency.h'. - # Do two passes, one to just change these to - # $object: dependency.h - # and one to simply output - # dependency.h: - # which is needed to avoid the deleted-header problem. - { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" - sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" - } > "$depfile" - rm -f "$tmpdepfile" - else - make_dummy_depfile - fi -} - -# A tabulation character. -tab=' ' -# A newline character. -nl=' -' -# Character ranges might be problematic outside the C locale. -# These definitions help. -upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ -lower=abcdefghijklmnopqrstuvwxyz -digits=0123456789 -alpha=${upper}${lower} - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Avoid interferences from the environment. -gccflag= dashmflag= - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -cygpath_u="cygpath -u -f -" -if test "$depmode" = msvcmsys; then - # This is just like msvisualcpp but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvisualcpp -fi - -if test "$depmode" = msvc7msys; then - # This is just like msvc7 but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvc7 -fi - -if test "$depmode" = xlc; then - # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. - gccflag=-qmakedep=gcc,-MF - depmode=gcc -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. -## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. -## (see the conditional assignment to $gccflag above). -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). Also, it might not be -## supported by the other compilers which use the 'gcc' depmode. -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The second -e expression handles DOS-style file names with drive - # letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the "deleted header file" problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. -## Some versions of gcc put a space before the ':'. On the theory -## that the space means something, we add a space to the output as -## well. hp depmode also adds that space, but also prefixes the VPATH -## to the object. Take care to not repeat it in the output. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like '#:fec' to the end of the - # dependency line. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ - | tr "$nl" ' ' >> "$depfile" - echo >> "$depfile" - # The second pass generates a dummy entry for each header file. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> "$depfile" - else - make_dummy_depfile - fi - rm -f "$tmpdepfile" - ;; - -xlc) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts '$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - set_dir_from "$object" - set_base_from "$object" - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.u - tmpdepfile2=$base.u - tmpdepfile3=$dir.libs/$base.u - "$@" -Wc,-M - else - tmpdepfile1=$dir$base.u - tmpdepfile2=$dir$base.u - tmpdepfile3=$dir$base.u - "$@" -M - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - aix_post_process_depfile - ;; - -tcc) - # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 - # FIXME: That version still under development at the moment of writing. - # Make that this statement remains true also for stable, released - # versions. - # It will wrap lines (doesn't matter whether long or short) with a - # trailing '\', as in: - # - # foo.o : \ - # foo.c \ - # foo.h \ - # - # It will put a trailing '\' even on the last line, and will use leading - # spaces rather than leading tabs (at least since its commit 0394caf7 - # "Emit spaces for -MD"). - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. - # We have to change lines of the first kind to '$object: \'. - sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" - # And for each line of the second kind, we have to emit a 'dep.h:' - # dummy dependency, to avoid the deleted-header problem. - sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" - rm -f "$tmpdepfile" - ;; - -## The order of this option in the case statement is important, since the -## shell code in configure will try each of these formats in the order -## listed in this file. A plain '-MD' option would be understood by many -## compilers, so we must ensure this comes after the gcc and icc options. -pgcc) - # Portland's C compiler understands '-MD'. - # Will always output deps to 'file.d' where file is the root name of the - # source file under compilation, even if file resides in a subdirectory. - # The object file name does not affect the name of the '.d' file. - # pgcc 10.2 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using '\' : - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - set_dir_from "$object" - # Use the source, not the object, to determine the base name, since - # that's sadly what pgcc will do too. - set_base_from "$source" - tmpdepfile=$base.d - - # For projects that build the same source file twice into different object - # files, the pgcc approach of using the *source* file root name can cause - # problems in parallel builds. Use a locking strategy to avoid stomping on - # the same $tmpdepfile. - lockdir=$base.d-lock - trap " - echo '$0: caught signal, cleaning up...' >&2 - rmdir '$lockdir' - exit 1 - " 1 2 13 15 - numtries=100 - i=$numtries - while test $i -gt 0; do - # mkdir is a portable test-and-set. - if mkdir "$lockdir" 2>/dev/null; then - # This process acquired the lock. - "$@" -MD - stat=$? - # Release the lock. - rmdir "$lockdir" - break - else - # If the lock is being held by a different process, wait - # until the winning process is done or we timeout. - while test -d "$lockdir" && test $i -gt 0; do - sleep 1 - i=`expr $i - 1` - done - fi - i=`expr $i - 1` - done - trap - 1 2 13 15 - if test $i -le 0; then - echo "$0: failed to acquire lock after $numtries attempts" >&2 - echo "$0: check lockdir '$lockdir'" >&2 - exit 1 - fi - - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - set_dir_from "$object" - set_base_from "$object" - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" - # Add 'dependent.h:' lines. - sed -ne '2,${ - s/^ *// - s/ \\*$// - s/$/:/ - p - }' "$tmpdepfile" >> "$depfile" - else - make_dummy_depfile - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in 'foo.d' instead, so we check for that too. - # Subdirectories are respected. - set_dir_from "$object" - set_base_from "$object" - - if test "$libtool" = yes; then - # Libtool generates 2 separate objects for the 2 libraries. These - # two compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir$base.o.d # libtool 1.5 - tmpdepfile2=$dir.libs/$base.o.d # Likewise. - tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - # Same post-processing that is required for AIX mode. - aix_post_process_depfile - ;; - -msvc7) - if test "$libtool" = yes; then - showIncludes=-Wc,-showIncludes - else - showIncludes=-showIncludes - fi - "$@" $showIncludes > "$tmpdepfile" - stat=$? - grep -v '^Note: including file: ' "$tmpdepfile" - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The first sed program below extracts the file names and escapes - # backslashes for cygpath. The second sed program outputs the file - # name when reading, but also accumulates all include files in the - # hold buffer in order to output them again at the end. This only - # works with sed implementations that can handle large buffers. - sed < "$tmpdepfile" -n ' -/^Note: including file: *\(.*\)/ { - s//\1/ - s/\\/\\\\/g - p -}' | $cygpath_u | sort -u | sed -n ' -s/ /\\ /g -s/\(.*\)/'"$tab"'\1 \\/p -s/.\(.*\) \\/\1:/ -H -$ { - s/.*/'"$tab"'/ - G - p -}' >> "$depfile" - echo >> "$depfile" # make sure the fragment doesn't end with a backslash - rm -f "$tmpdepfile" - ;; - -msvc7msys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for ':' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. - "$@" $dashmflag | - sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this sed invocation - # correctly. Breaking it into two sed invocations is a workaround. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no eat=no - for arg - do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - if test $eat = yes; then - eat=no - continue - fi - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -arch) - eat=yes ;; - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix=`echo "$object" | sed 's/^.*\././'` - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - # makedepend may prepend the VPATH from the source file name to the object. - # No need to regex-escape $object, excess matching of '.' is harmless. - sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process the last invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed '1,2d' "$tmpdepfile" \ - | tr ' ' "$nl" \ - | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E \ - | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - | sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - IFS=" " - for arg - do - case "$arg" in - -o) - shift - ;; - $object) - shift - ;; - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E 2>/dev/null | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" - echo "$tab" >> "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvcmsys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC0" -# time-stamp-end: "; # UTC" -# End: diff --git a/ext/libpqxx-7.7.3/config/install-sh b/ext/libpqxx-7.7.3/config/install-sh deleted file mode 100755 index 6781b987b..000000000 --- a/ext/libpqxx-7.7.3/config/install-sh +++ /dev/null @@ -1,520 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2009-04-28.21; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# 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 -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - trap '(exit $?); exit' 1 2 13 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dst_arg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writeable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - -*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test -z "$d" && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/ext/libpqxx-7.7.3/config/ltmain.sh b/ext/libpqxx-7.7.3/config/ltmain.sh deleted file mode 100755 index 21e5e0784..000000000 --- a/ext/libpqxx-7.7.3/config/ltmain.sh +++ /dev/null @@ -1,11251 +0,0 @@ -#! /bin/sh -## DO NOT EDIT - This file generated from ./build-aux/ltmain.in -## by inline-source v2014-01-03.01 - -# libtool (GNU libtool) 2.4.6 -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit , 1996 - -# Copyright (C) 1996-2015 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -PROGRAM=libtool -PACKAGE=libtool -VERSION="2.4.6 Debian-2.4.6-15" -package_revision=2.4.6 - - -## ------ ## -## Usage. ## -## ------ ## - -# Run './libtool --help' for help with using this script from the -# command line. - - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# After configure completes, it has a better idea of some of the -# shell tools we need than the defaults used by the functions shared -# with bootstrap, so set those here where they can still be over- -# ridden by the user, but otherwise take precedence. - -: ${AUTOCONF="autoconf"} -: ${AUTOMAKE="automake"} - - -## -------------------------- ## -## Source external libraries. ## -## -------------------------- ## - -# Much of our low-level functionality needs to be sourced from external -# libraries, which are installed to $pkgauxdir. - -# Set a version string for this script. -scriptversion=2015-01-20.17; # UTC - -# General shell script boiler plate, and helper functions. -# Written by Gary V. Vaughan, 2004 - -# Copyright (C) 2004-2015 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. - -# As a special exception to the GNU General Public License, if you distribute -# this file as part of a program or library that is built using GNU Libtool, -# you may include this file under the same distribution terms that you use -# for the rest of that program. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Evaluate this file near the top of your script to gain access to -# the functions and variables defined here: -# -# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh -# -# If you need to override any of the default environment variable -# settings, do that before evaluating this file. - - -## -------------------- ## -## Shell normalisation. ## -## -------------------- ## - -# Some shells need a little help to be as Bourne compatible as possible. -# Before doing anything else, make sure all that help has been provided! - -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac -fi - -# NLS nuisances: We save the old values in case they are required later. -_G_user_locale= -_G_safe_locale= -for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test set = \"\${$_G_var+set}\"; then - save_$_G_var=\$$_G_var - $_G_var=C - export $_G_var - _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" - _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" - fi" -done - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Make sure IFS has a sensible default -sp=' ' -nl=' -' -IFS="$sp $nl" - -# There are apparently some retarded systems that use ';' as a PATH separator! -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - - -## ------------------------- ## -## Locate command utilities. ## -## ------------------------- ## - - -# func_executable_p FILE -# ---------------------- -# Check that FILE is an executable regular file. -func_executable_p () -{ - test -f "$1" && test -x "$1" -} - - -# func_path_progs PROGS_LIST CHECK_FUNC [PATH] -# -------------------------------------------- -# Search for either a program that responds to --version with output -# containing "GNU", or else returned by CHECK_FUNC otherwise, by -# trying all the directories in PATH with each of the elements of -# PROGS_LIST. -# -# CHECK_FUNC should accept the path to a candidate program, and -# set $func_check_prog_result if it truncates its output less than -# $_G_path_prog_max characters. -func_path_progs () -{ - _G_progs_list=$1 - _G_check_func=$2 - _G_PATH=${3-"$PATH"} - - _G_path_prog_max=0 - _G_path_prog_found=false - _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} - for _G_dir in $_G_PATH; do - IFS=$_G_save_IFS - test -z "$_G_dir" && _G_dir=. - for _G_prog_name in $_G_progs_list; do - for _exeext in '' .EXE; do - _G_path_prog=$_G_dir/$_G_prog_name$_exeext - func_executable_p "$_G_path_prog" || continue - case `"$_G_path_prog" --version 2>&1` in - *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; - *) $_G_check_func $_G_path_prog - func_path_progs_result=$func_check_prog_result - ;; - esac - $_G_path_prog_found && break 3 - done - done - done - IFS=$_G_save_IFS - test -z "$func_path_progs_result" && { - echo "no acceptable sed could be found in \$PATH" >&2 - exit 1 - } -} - - -# We want to be able to use the functions in this file before configure -# has figured out where the best binaries are kept, which means we have -# to search for them ourselves - except when the results are already set -# where we skip the searches. - -# Unless the user overrides by setting SED, search the path for either GNU -# sed, or the sed that truncates its output the least. -test -z "$SED" && { - _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for _G_i in 1 2 3 4 5 6 7; do - _G_sed_script=$_G_sed_script$nl$_G_sed_script - done - echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed - _G_sed_script= - - func_check_prog_sed () - { - _G_path_prog=$1 - - _G_count=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo '' >> conftest.nl - "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin - rm -f conftest.sed - SED=$func_path_progs_result -} - - -# Unless the user overrides by setting GREP, search the path for either GNU -# grep, or the grep that truncates its output the least. -test -z "$GREP" && { - func_check_prog_grep () - { - _G_path_prog=$1 - - _G_count=0 - _G_path_prog_max=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo 'GREP' >> conftest.nl - "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin - GREP=$func_path_progs_result -} - - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# All uppercase variable names are used for environment variables. These -# variables can be overridden by the user before calling a script that -# uses them if a suitable command of that name is not already available -# in the command search PATH. - -: ${CP="cp -f"} -: ${ECHO="printf %s\n"} -: ${EGREP="$GREP -E"} -: ${FGREP="$GREP -F"} -: ${LN_S="ln -s"} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} - - -## -------------------- ## -## Useful sed snippets. ## -## -------------------- ## - -sed_dirname='s|/[^/]*$||' -sed_basename='s|^.*/||' - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Same as above, but do not quote variable references. -sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' - -# Sed substitution that converts a w32 file name or path -# that contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-'\' parameter expansions in output of sed_double_quote_subst that -# were '\'-ed in input to the same. If an odd number of '\' preceded a -# '$' in input to sed_double_quote_subst, that '$' was protected from -# expansion. Since each input '\' is now two '\'s, look for any number -# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. -_G_bs='\\' -_G_bs2='\\\\' -_G_bs4='\\\\\\\\' -_G_dollar='\$' -sed_double_backslash="\ - s/$_G_bs4/&\\ -/g - s/^$_G_bs2$_G_dollar/$_G_bs&/ - s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g - s/\n//g" - - -## ----------------- ## -## Global variables. ## -## ----------------- ## - -# Except for the global variables explicitly listed below, the following -# functions in the '^func_' namespace, and the '^require_' namespace -# variables initialised in the 'Resource management' section, sourcing -# this file will not pollute your global namespace with anything -# else. There's no portable way to scope variables in Bourne shell -# though, so actually running these functions will sometimes place -# results into a variable named after the function, and often use -# temporary variables in the '^_G_' namespace. If you are careful to -# avoid using those namespaces casually in your sourcing script, things -# should continue to work as you expect. And, of course, you can freely -# overwrite any of the functions or variables defined here before -# calling anything to customize them. - -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -# Allow overriding, eg assuming that you follow the convention of -# putting '$debug_cmd' at the start of all your functions, you can get -# bash to show function call trace with: -# -# debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name -debug_cmd=${debug_cmd-":"} -exit_cmd=: - -# By convention, finish your script with: -# -# exit $exit_status -# -# so that you can set exit_status to non-zero if you want to indicate -# something went wrong during execution without actually bailing out at -# the point of failure. -exit_status=$EXIT_SUCCESS - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath=$0 - -# The name of this program. -progname=`$ECHO "$progpath" |$SED "$sed_basename"` - -# Make sure we have an absolute progpath for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` - progdir=`cd "$progdir" && pwd` - progpath=$progdir/$progname - ;; - *) - _G_IFS=$IFS - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS=$_G_IFS - test -x "$progdir/$progname" && break - done - IFS=$_G_IFS - test -n "$progdir" || progdir=`pwd` - progpath=$progdir/$progname - ;; -esac - - -## ----------------- ## -## Standard options. ## -## ----------------- ## - -# The following options affect the operation of the functions defined -# below, and should be set appropriately depending on run-time para- -# meters passed on the command line. - -opt_dry_run=false -opt_quiet=false -opt_verbose=false - -# Categories 'all' and 'none' are always available. Append any others -# you will pass as the first argument to func_warning from your own -# code. -warning_categories= - -# By default, display warnings according to 'opt_warning_types'. Set -# 'warning_func' to ':' to elide all warnings, or func_fatal_error to -# treat the next displayed warning as a fatal error. -warning_func=func_warn_and_continue - -# Set to 'all' to display all warnings, 'none' to suppress all -# warnings, or a space delimited list of some subset of -# 'warning_categories' to display only the listed warnings. -opt_warning_types=all - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Call them using their associated -# 'require_*' variable to ensure that they are executed, at most, once. -# -# It's entirely deliberate that calling these functions can set -# variables that don't obey the namespace limitations obeyed by the rest -# of this file, in order that that they be as useful as possible to -# callers. - - -# require_term_colors -# ------------------- -# Allow display of bold text on terminals that support it. -require_term_colors=func_require_term_colors -func_require_term_colors () -{ - $debug_cmd - - test -t 1 && { - # COLORTERM and USE_ANSI_COLORS environment variables take - # precedence, because most terminfo databases neglect to describe - # whether color sequences are supported. - test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} - - if test 1 = "$USE_ANSI_COLORS"; then - # Standard ANSI escape sequences - tc_reset='' - tc_bold=''; tc_standout='' - tc_red=''; tc_green='' - tc_blue=''; tc_cyan='' - else - # Otherwise trust the terminfo database after all. - test -n "`tput sgr0 2>/dev/null`" && { - tc_reset=`tput sgr0` - test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` - tc_standout=$tc_bold - test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` - test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` - test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` - test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` - test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` - } - fi - } - - require_term_colors=: -} - - -## ----------------- ## -## Function library. ## -## ----------------- ## - -# This section contains a variety of useful functions to call in your -# scripts. Take note of the portable wrappers for features provided by -# some modern shells, which will fall back to slower equivalents on -# less featureful shells. - - -# func_append VAR VALUE -# --------------------- -# Append VALUE onto the existing contents of VAR. - - # We should try to minimise forks, especially on Windows where they are - # unreasonably slow, so skip the feature probes when bash or zsh are - # being used: - if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then - : ${_G_HAVE_ARITH_OP="yes"} - : ${_G_HAVE_XSI_OPS="yes"} - # The += operator was introduced in bash 3.1 - case $BASH_VERSION in - [12].* | 3.0 | 3.0*) ;; - *) - : ${_G_HAVE_PLUSEQ_OP="yes"} - ;; - esac - fi - - # _G_HAVE_PLUSEQ_OP - # Can be empty, in which case the shell is probed, "yes" if += is - # useable or anything else if it does not work. - test -z "$_G_HAVE_PLUSEQ_OP" \ - && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ - && _G_HAVE_PLUSEQ_OP=yes - -if test yes = "$_G_HAVE_PLUSEQ_OP" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_append () - { - $debug_cmd - - eval "$1+=\$2" - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_append () - { - $debug_cmd - - eval "$1=\$$1\$2" - } -fi - - -# func_append_quoted VAR VALUE -# ---------------------------- -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -if test yes = "$_G_HAVE_PLUSEQ_OP"; then - eval 'func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1+=\\ \$func_quote_for_eval_result" - }' -else - func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1=\$$1\\ \$func_quote_for_eval_result" - } -fi - - -# func_append_uniq VAR VALUE -# -------------------------- -# Append unique VALUE onto the existing contents of VAR, assuming -# entries are delimited by the first character of VALUE. For example: -# -# func_append_uniq options " --another-option option-argument" -# -# will only append to $options if " --another-option option-argument " -# is not already present somewhere in $options already (note spaces at -# each end implied by leading space in second argument). -func_append_uniq () -{ - $debug_cmd - - eval _G_current_value='`$ECHO $'$1'`' - _G_delim=`expr "$2" : '\(.\)'` - - case $_G_delim$_G_current_value$_G_delim in - *"$2$_G_delim"*) ;; - *) func_append "$@" ;; - esac -} - - -# func_arith TERM... -# ------------------ -# Set func_arith_result to the result of evaluating TERMs. - test -z "$_G_HAVE_ARITH_OP" \ - && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ - && _G_HAVE_ARITH_OP=yes - -if test yes = "$_G_HAVE_ARITH_OP"; then - eval 'func_arith () - { - $debug_cmd - - func_arith_result=$(( $* )) - }' -else - func_arith () - { - $debug_cmd - - func_arith_result=`expr "$@"` - } -fi - - -# func_basename FILE -# ------------------ -# Set func_basename_result to FILE with everything up to and including -# the last / stripped. -if test yes = "$_G_HAVE_XSI_OPS"; then - # If this shell supports suffix pattern removal, then use it to avoid - # forking. Hide the definitions single quotes in case the shell chokes - # on unsupported syntax... - _b='func_basename_result=${1##*/}' - _d='case $1 in - */*) func_dirname_result=${1%/*}$2 ;; - * ) func_dirname_result=$3 ;; - esac' - -else - # ...otherwise fall back to using sed. - _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' - _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` - if test "X$func_dirname_result" = "X$1"; then - func_dirname_result=$3 - else - func_append func_dirname_result "$2" - fi' -fi - -eval 'func_basename () -{ - $debug_cmd - - '"$_b"' -}' - - -# func_dirname FILE APPEND NONDIR_REPLACEMENT -# ------------------------------------------- -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -eval 'func_dirname () -{ - $debug_cmd - - '"$_d"' -}' - - -# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT -# -------------------------------------------------------- -# Perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# For efficiency, we do not delegate to the functions above but instead -# duplicate the functionality here. -eval 'func_dirname_and_basename () -{ - $debug_cmd - - '"$_b"' - '"$_d"' -}' - - -# func_echo ARG... -# ---------------- -# Echo program name prefixed message. -func_echo () -{ - $debug_cmd - - _G_message=$* - - func_echo_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS - $ECHO "$progname: $_G_line" - done - IFS=$func_echo_IFS -} - - -# func_echo_all ARG... -# -------------------- -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - - -# func_echo_infix_1 INFIX ARG... -# ------------------------------ -# Echo program name, followed by INFIX on the first line, with any -# additional lines not showing INFIX. -func_echo_infix_1 () -{ - $debug_cmd - - $require_term_colors - - _G_infix=$1; shift - _G_indent=$_G_infix - _G_prefix="$progname: $_G_infix: " - _G_message=$* - - # Strip color escape sequences before counting printable length - for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" - do - test -n "$_G_tc" && { - _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` - _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` - } - done - _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes - - func_echo_infix_1_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_infix_1_IFS - $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 - _G_prefix=$_G_indent - done - IFS=$func_echo_infix_1_IFS -} - - -# func_error ARG... -# ----------------- -# Echo program name prefixed message to standard error. -func_error () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 -} - - -# func_fatal_error ARG... -# ----------------------- -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - $debug_cmd - - func_error "$*" - exit $EXIT_FAILURE -} - - -# func_grep EXPRESSION FILENAME -# ----------------------------- -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $debug_cmd - - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_len STRING -# --------------- -# Set func_len_result to the length of STRING. STRING may not -# start with a hyphen. - test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_len () - { - $debug_cmd - - func_len_result=${#1} - }' -else - func_len () - { - $debug_cmd - - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` - } -fi - - -# func_mkdir_p DIRECTORY-PATH -# --------------------------- -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - $debug_cmd - - _G_directory_path=$1 - _G_dir_list= - - if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then - - # Protect directory names starting with '-' - case $_G_directory_path in - -*) _G_directory_path=./$_G_directory_path ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$_G_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - _G_dir_list=$_G_directory_path:$_G_dir_list - - # If the last portion added has no slash in it, the list is done - case $_G_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` - done - _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` - - func_mkdir_p_IFS=$IFS; IFS=: - for _G_dir in $_G_dir_list; do - IFS=$func_mkdir_p_IFS - # mkdir can fail with a 'File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$_G_dir" 2>/dev/null || : - done - IFS=$func_mkdir_p_IFS - - # Bail out if we (or some other process) failed to create a directory. - test -d "$_G_directory_path" || \ - func_fatal_error "Failed to create '$1'" - fi -} - - -# func_mktempdir [BASENAME] -# ------------------------- -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, BASENAME is the basename for that directory. -func_mktempdir () -{ - $debug_cmd - - _G_template=${TMPDIR-/tmp}/${1-$progname} - - if test : = "$opt_dry_run"; then - # Return a directory name, but don't create it in dry-run mode - _G_tmpdir=$_G_template-$$ - else - - # If mktemp works, use that first and foremost - _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` - - if test ! -d "$_G_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - _G_tmpdir=$_G_template-${RANDOM-0}$$ - - func_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$_G_tmpdir" - umask $func_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$_G_tmpdir" || \ - func_fatal_error "cannot create temporary directory '$_G_tmpdir'" - fi - - $ECHO "$_G_tmpdir" -} - - -# func_normal_abspath PATH -# ------------------------ -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -func_normal_abspath () -{ - $debug_cmd - - # These SED scripts presuppose an absolute path with a trailing slash. - _G_pathcar='s|^/\([^/]*\).*$|\1|' - _G_pathcdr='s|^/[^/]*||' - _G_removedotparts=':dotsl - s|/\./|/|g - t dotsl - s|/\.$|/|' - _G_collapseslashes='s|/\{1,\}|/|g' - _G_finalslash='s|/*$|/|' - - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` - while :; do - # Processed it all yet? - if test / = "$func_normal_abspath_tpath"; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result"; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - - -# func_notquiet ARG... -# -------------------- -# Echo program name prefixed message only when not in quiet mode. -func_notquiet () -{ - $debug_cmd - - $opt_quiet || func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} - - -# func_relative_path SRCDIR DSTDIR -# -------------------------------- -# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. -func_relative_path () -{ - $debug_cmd - - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=$func_dirname_result - if test -z "$func_relative_path_tlibdir"; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test -n "$func_stripname_result"; then - func_append func_relative_path_result "/$func_stripname_result" - fi - - # Normalisation. If bindir is libdir, return '.' else relative path. - if test -n "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - fi - - test -n "$func_relative_path_result" || func_relative_path_result=. - - : -} - - -# func_quote_for_eval ARG... -# -------------------------- -# Aesthetically quote ARGs to be evaled later. -# This function returns two values: -# i) func_quote_for_eval_result -# double-quoted, suitable for a subsequent eval -# ii) func_quote_for_eval_unquoted_result -# has all characters that are still active within double -# quotes backslashified. -func_quote_for_eval () -{ - $debug_cmd - - func_quote_for_eval_unquoted_result= - func_quote_for_eval_result= - while test 0 -lt $#; do - case $1 in - *[\\\`\"\$]*) - _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; - *) - _G_unquoted_arg=$1 ;; - esac - if test -n "$func_quote_for_eval_unquoted_result"; then - func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" - else - func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" - fi - - case $_G_unquoted_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and variable expansion - # for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_quoted_arg=\"$_G_unquoted_arg\" - ;; - *) - _G_quoted_arg=$_G_unquoted_arg - ;; - esac - - if test -n "$func_quote_for_eval_result"; then - func_append func_quote_for_eval_result " $_G_quoted_arg" - else - func_append func_quote_for_eval_result "$_G_quoted_arg" - fi - shift - done -} - - -# func_quote_for_expand ARG -# ------------------------- -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - $debug_cmd - - case $1 in - *[\\\`\"]*) - _G_arg=`$ECHO "$1" | $SED \ - -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; - *) - _G_arg=$1 ;; - esac - - case $_G_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_arg=\"$_G_arg\" - ;; - esac - - func_quote_for_expand_result=$_G_arg -} - - -# func_stripname PREFIX SUFFIX NAME -# --------------------------------- -# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_stripname () - { - $debug_cmd - - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary variable first. - func_stripname_result=$3 - func_stripname_result=${func_stripname_result#"$1"} - func_stripname_result=${func_stripname_result%"$2"} - }' -else - func_stripname () - { - $debug_cmd - - case $2 in - .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; - *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; - esac - } -fi - - -# func_show_eval CMD [FAIL_EXP] -# ----------------------------- -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - func_quote_for_expand "$_G_cmd" - eval "func_notquiet $func_quote_for_expand_result" - - $opt_dry_run || { - eval "$_G_cmd" - _G_status=$? - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_show_eval_locale CMD [FAIL_EXP] -# ------------------------------------ -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - $opt_quiet || { - func_quote_for_expand "$_G_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - $opt_dry_run || { - eval "$_G_user_locale - $_G_cmd" - _G_status=$? - eval "$_G_safe_locale" - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_tr_sh -# ---------- -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - $debug_cmd - - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_verbose ARG... -# ------------------- -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $debug_cmd - - $opt_verbose && func_echo "$*" - - : -} - - -# func_warn_and_continue ARG... -# ----------------------------- -# Echo program name prefixed warning message to standard error. -func_warn_and_continue () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 -} - - -# func_warning CATEGORY ARG... -# ---------------------------- -# Echo program name prefixed warning message to standard error. Warning -# messages can be filtered according to CATEGORY, where this function -# elides messages where CATEGORY is not listed in the global variable -# 'opt_warning_types'. -func_warning () -{ - $debug_cmd - - # CATEGORY must be in the warning_categories list! - case " $warning_categories " in - *" $1 "*) ;; - *) func_internal_error "invalid warning category '$1'" ;; - esac - - _G_category=$1 - shift - - case " $opt_warning_types " in - *" $_G_category "*) $warning_func ${1+"$@"} ;; - esac -} - - -# func_sort_ver VER1 VER2 -# ----------------------- -# 'sort -V' is not generally available. -# Note this deviates from the version comparison in automake -# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a -# but this should suffice as we won't be specifying old -# version formats or redundant trailing .0 in bootstrap.conf. -# If we did want full compatibility then we should probably -# use m4_version_compare from autoconf. -func_sort_ver () -{ - $debug_cmd - - printf '%s\n%s\n' "$1" "$2" \ - | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n -} - -# func_lt_ver PREV CURR -# --------------------- -# Return true if PREV and CURR are in the correct order according to -# func_sort_ver, otherwise false. Use it like this: -# -# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." -func_lt_ver () -{ - $debug_cmd - - test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: -#! /bin/sh - -# Set a version string for this script. -scriptversion=2015-10-07.11; # UTC - -# A portable, pluggable option parser for Bourne shell. -# Written by Gary V. Vaughan, 2010 - -# Copyright (C) 2010-2015 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# This file is a library for parsing options in your shell scripts along -# with assorted other useful supporting features that you can make use -# of too. -# -# For the simplest scripts you might need only: -# -# #!/bin/sh -# . relative/path/to/funclib.sh -# . relative/path/to/options-parser -# scriptversion=1.0 -# func_options ${1+"$@"} -# eval set dummy "$func_options_result"; shift -# ...rest of your script... -# -# In order for the '--version' option to work, you will need to have a -# suitably formatted comment like the one at the top of this file -# starting with '# Written by ' and ending with '# warranty; '. -# -# For '-h' and '--help' to work, you will also need a one line -# description of your script's purpose in a comment directly above the -# '# Written by ' line, like the one at the top of this file. -# -# The default options also support '--debug', which will turn on shell -# execution tracing (see the comment above debug_cmd below for another -# use), and '--verbose' and the func_verbose function to allow your script -# to display verbose messages only when your user has specified -# '--verbose'. -# -# After sourcing this file, you can plug processing for additional -# options by amending the variables from the 'Configuration' section -# below, and following the instructions in the 'Option parsing' -# section further down. - -## -------------- ## -## Configuration. ## -## -------------- ## - -# You should override these variables in your script after sourcing this -# file so that they reflect the customisations you have added to the -# option parser. - -# The usage line for option parsing errors and the start of '-h' and -# '--help' output messages. You can embed shell variables for delayed -# expansion at the time the message is displayed, but you will need to -# quote other shell meta-characters carefully to prevent them being -# expanded when the contents are evaled. -usage='$progpath [OPTION]...' - -# Short help message in response to '-h' and '--help'. Add to this or -# override it after sourcing this library to reflect the full set of -# options your script accepts. -usage_message="\ - --debug enable verbose shell tracing - -W, --warnings=CATEGORY - report the warnings falling in CATEGORY [all] - -v, --verbose verbosely report processing - --version print version information and exit - -h, --help print short or long help message and exit -" - -# Additional text appended to 'usage_message' in response to '--help'. -long_help_message=" -Warning categories include: - 'all' show all warnings - 'none' turn off all the warnings - 'error' warnings are treated as fatal errors" - -# Help message printed before fatal option parsing errors. -fatal_help="Try '\$progname --help' for more information." - - - -## ------------------------- ## -## Hook function management. ## -## ------------------------- ## - -# This section contains functions for adding, removing, and running hooks -# to the main code. A hook is just a named list of of function, that can -# be run in order later on. - -# func_hookable FUNC_NAME -# ----------------------- -# Declare that FUNC_NAME will run hooks added with -# 'func_add_hook FUNC_NAME ...'. -func_hookable () -{ - $debug_cmd - - func_append hookable_fns " $1" -} - - -# func_add_hook FUNC_NAME HOOK_FUNC -# --------------------------------- -# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must -# first have been declared "hookable" by a call to 'func_hookable'. -func_add_hook () -{ - $debug_cmd - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not accept hook functions." ;; - esac - - eval func_append ${1}_hooks '" $2"' -} - - -# func_remove_hook FUNC_NAME HOOK_FUNC -# ------------------------------------ -# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. -func_remove_hook () -{ - $debug_cmd - - eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' -} - - -# func_run_hooks FUNC_NAME [ARG]... -# --------------------------------- -# Run all hook functions registered to FUNC_NAME. -# It is assumed that the list of hook functions contains nothing more -# than a whitespace-delimited list of legal shell function names, and -# no effort is wasted trying to catch shell meta-characters or preserve -# whitespace. -func_run_hooks () -{ - $debug_cmd - - _G_rc_run_hooks=false - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not support hook funcions.n" ;; - esac - - eval _G_hook_fns=\$$1_hooks; shift - - for _G_hook in $_G_hook_fns; do - if eval $_G_hook '"$@"'; then - # store returned options list back into positional - # parameters for next 'cmd' execution. - eval _G_hook_result=\$${_G_hook}_result - eval set dummy "$_G_hook_result"; shift - _G_rc_run_hooks=: - fi - done - - $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result -} - - - -## --------------- ## -## Option parsing. ## -## --------------- ## - -# In order to add your own option parsing hooks, you must accept the -# full positional parameter list in your hook function, you may remove/edit -# any options that you action, and then pass back the remaining unprocessed -# options in '_result', escaped suitably for -# 'eval'. In this case you also must return $EXIT_SUCCESS to let the -# hook's caller know that it should pay attention to -# '_result'. Returning $EXIT_FAILURE signalizes that -# arguments are left untouched by the hook and therefore caller will ignore the -# result variable. -# -# Like this: -# -# my_options_prep () -# { -# $debug_cmd -# -# # Extend the existing usage message. -# usage_message=$usage_message' -# -s, --silent don'\''t print informational messages -# ' -# # No change in '$@' (ignored completely by this hook). There is -# # no need to do the equivalent (but slower) action: -# # func_quote_for_eval ${1+"$@"} -# # my_options_prep_result=$func_quote_for_eval_result -# false -# } -# func_add_hook func_options_prep my_options_prep -# -# -# my_silent_option () -# { -# $debug_cmd -# -# args_changed=false -# -# # Note that for efficiency, we parse as many options as we can -# # recognise in a loop before passing the remainder back to the -# # caller on the first unrecognised argument we encounter. -# while test $# -gt 0; do -# opt=$1; shift -# case $opt in -# --silent|-s) opt_silent=: -# args_changed=: -# ;; -# # Separate non-argument short options: -# -s*) func_split_short_opt "$_G_opt" -# set dummy "$func_split_short_opt_name" \ -# "-$func_split_short_opt_arg" ${1+"$@"} -# shift -# args_changed=: -# ;; -# *) # Make sure the first unrecognised option "$_G_opt" -# # is added back to "$@", we could need that later -# # if $args_changed is true. -# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; -# esac -# done -# -# if $args_changed; then -# func_quote_for_eval ${1+"$@"} -# my_silent_option_result=$func_quote_for_eval_result -# fi -# -# $args_changed -# } -# func_add_hook func_parse_options my_silent_option -# -# -# my_option_validation () -# { -# $debug_cmd -# -# $opt_silent && $opt_verbose && func_fatal_help "\ -# '--silent' and '--verbose' options are mutually exclusive." -# -# false -# } -# func_add_hook func_validate_options my_option_validation -# -# You'll also need to manually amend $usage_message to reflect the extra -# options you parse. It's preferable to append if you can, so that -# multiple option parsing hooks can be added safely. - - -# func_options_finish [ARG]... -# ---------------------------- -# Finishing the option parse loop (call 'func_options' hooks ATM). -func_options_finish () -{ - $debug_cmd - - _G_func_options_finish_exit=false - if func_run_hooks func_options ${1+"$@"}; then - func_options_finish_result=$func_run_hooks_result - _G_func_options_finish_exit=: - fi - - $_G_func_options_finish_exit -} - - -# func_options [ARG]... -# --------------------- -# All the functions called inside func_options are hookable. See the -# individual implementations for details. -func_hookable func_options -func_options () -{ - $debug_cmd - - _G_rc_options=false - - for my_func in options_prep parse_options validate_options options_finish - do - if eval func_$my_func '${1+"$@"}'; then - eval _G_res_var='$'"func_${my_func}_result" - eval set dummy "$_G_res_var" ; shift - _G_rc_options=: - fi - done - - # Save modified positional parameters for caller. As a top-level - # options-parser function we always need to set the 'func_options_result' - # variable (regardless the $_G_rc_options value). - if $_G_rc_options; then - func_options_result=$_G_res_var - else - func_quote_for_eval ${1+"$@"} - func_options_result=$func_quote_for_eval_result - fi - - $_G_rc_options -} - - -# func_options_prep [ARG]... -# -------------------------- -# All initialisations required before starting the option parse loop. -# Note that when calling hook functions, we pass through the list of -# positional parameters. If a hook function modifies that list, and -# needs to propagate that back to rest of this script, then the complete -# modified list must be put in 'func_run_hooks_result' before -# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). -func_hookable func_options_prep -func_options_prep () -{ - $debug_cmd - - # Option defaults: - opt_verbose=false - opt_warning_types= - - _G_rc_options_prep=false - if func_run_hooks func_options_prep ${1+"$@"}; then - _G_rc_options_prep=: - # save modified positional parameters for caller - func_options_prep_result=$func_run_hooks_result - fi - - $_G_rc_options_prep -} - - -# func_parse_options [ARG]... -# --------------------------- -# The main option parsing loop. -func_hookable func_parse_options -func_parse_options () -{ - $debug_cmd - - func_parse_options_result= - - _G_rc_parse_options=false - # this just eases exit handling - while test $# -gt 0; do - # Defer to hook functions for initial option parsing, so they - # get priority in the event of reusing an option name. - if func_run_hooks func_parse_options ${1+"$@"}; then - eval set dummy "$func_run_hooks_result"; shift - _G_rc_parse_options=: - fi - - # Break out of the loop if we already parsed every option. - test $# -gt 0 || break - - _G_match_parse_options=: - _G_opt=$1 - shift - case $_G_opt in - --debug|-x) debug_cmd='set -x' - func_echo "enabling shell trace mode" - $debug_cmd - ;; - - --no-warnings|--no-warning|--no-warn) - set dummy --warnings none ${1+"$@"} - shift - ;; - - --warnings|--warning|-W) - if test $# = 0 && func_missing_arg $_G_opt; then - _G_rc_parse_options=: - break - fi - case " $warning_categories $1" in - *" $1 "*) - # trailing space prevents matching last $1 above - func_append_uniq opt_warning_types " $1" - ;; - *all) - opt_warning_types=$warning_categories - ;; - *none) - opt_warning_types=none - warning_func=: - ;; - *error) - opt_warning_types=$warning_categories - warning_func=func_fatal_error - ;; - *) - func_fatal_error \ - "unsupported warning category: '$1'" - ;; - esac - shift - ;; - - --verbose|-v) opt_verbose=: ;; - --version) func_version ;; - -\?|-h) func_usage ;; - --help) func_help ;; - - # Separate optargs to long options (plugins may need this): - --*=*) func_split_equals "$_G_opt" - set dummy "$func_split_equals_lhs" \ - "$func_split_equals_rhs" ${1+"$@"} - shift - ;; - - # Separate optargs to short options: - -W*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-v*|-x*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) _G_rc_parse_options=: ; break ;; - -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; - *) set dummy "$_G_opt" ${1+"$@"}; shift - _G_match_parse_options=false - break - ;; - esac - - $_G_match_parse_options && _G_rc_parse_options=: - done - - - if $_G_rc_parse_options; then - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - func_parse_options_result=$func_quote_for_eval_result - fi - - $_G_rc_parse_options -} - - -# func_validate_options [ARG]... -# ------------------------------ -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -func_hookable func_validate_options -func_validate_options () -{ - $debug_cmd - - _G_rc_validate_options=false - - # Display all warnings if -W was not given. - test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" - - if func_run_hooks func_validate_options ${1+"$@"}; then - # save modified positional parameters for caller - func_validate_options_result=$func_run_hooks_result - _G_rc_validate_options=: - fi - - # Bail if the options were screwed! - $exit_cmd $EXIT_FAILURE - - $_G_rc_validate_options -} - - - -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of the -# hookable option parser framework in ascii-betical order. - - -# func_fatal_help ARG... -# ---------------------- -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - $debug_cmd - - eval \$ECHO \""Usage: $usage"\" - eval \$ECHO \""$fatal_help"\" - func_error ${1+"$@"} - exit $EXIT_FAILURE -} - - -# func_help -# --------- -# Echo long help message to standard output and exit. -func_help () -{ - $debug_cmd - - func_usage_message - $ECHO "$long_help_message" - exit 0 -} - - -# func_missing_arg ARGNAME -# ------------------------ -# Echo program name prefixed message to standard error and set global -# exit_cmd. -func_missing_arg () -{ - $debug_cmd - - func_error "Missing argument for '$1'." - exit_cmd=exit -} - - -# func_split_equals STRING -# ------------------------ -# Set func_split_equals_lhs and func_split_equals_rhs shell variables after -# splitting STRING at the '=' sign. -test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=${1%%=*} - func_split_equals_rhs=${1#*=} - test "x$func_split_equals_lhs" = "x$1" \ - && func_split_equals_rhs= - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` - func_split_equals_rhs= - test "x$func_split_equals_lhs" = "x$1" \ - || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` - } -fi #func_split_equals - - -# func_split_short_opt SHORTOPT -# ----------------------------- -# Set func_split_short_opt_name and func_split_short_opt_arg shell -# variables after splitting SHORTOPT after the 2nd character. -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"} - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` - func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` - } -fi #func_split_short_opt - - -# func_usage -# ---------- -# Echo short help message to standard output and exit. -func_usage () -{ - $debug_cmd - - func_usage_message - $ECHO "Run '$progname --help |${PAGER-more}' for full usage" - exit 0 -} - - -# func_usage_message -# ------------------ -# Echo short help message to standard output. -func_usage_message () -{ - $debug_cmd - - eval \$ECHO \""Usage: $usage"\" - echo - $SED -n 's|^# || - /^Written by/{ - x;p;x - } - h - /^Written by/q' < "$progpath" - echo - eval \$ECHO \""$usage_message"\" -} - - -# func_version -# ------------ -# Echo version message to standard output and exit. -func_version () -{ - $debug_cmd - - printf '%s\n' "$progname $scriptversion" - $SED -n ' - /(C)/!b go - :more - /\./!{ - N - s|\n# | | - b more - } - :go - /^# Written by /,/# warranty; / { - s|^# || - s|^# *$|| - s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| - p - } - /^# Written by / { - s|^# || - p - } - /^warranty; /q' < "$progpath" - - exit $? -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: - -# Set a version string. -scriptversion='(GNU libtool) 2.4.6' - - -# func_echo ARG... -# ---------------- -# Libtool also displays the current mode in messages, so override -# funclib.sh func_echo with this custom definition. -func_echo () -{ - $debug_cmd - - _G_message=$* - - func_echo_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS - $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" - done - IFS=$func_echo_IFS -} - - -# func_warning ARG... -# ------------------- -# Libtool warnings are not categorized, so override funclib.sh -# func_warning with this simpler definition. -func_warning () -{ - $debug_cmd - - $warning_func ${1+"$@"} -} - - -## ---------------- ## -## Options parsing. ## -## ---------------- ## - -# Hook in the functions to make sure our own options are parsed during -# the option parsing loop. - -usage='$progpath [OPTION]... [MODE-ARG]...' - -# Short help message in response to '-h'. -usage_message="Options: - --config show all configuration variables - --debug enable verbose shell tracing - -n, --dry-run display commands without modifying any files - --features display basic configuration information and exit - --mode=MODE use operation mode MODE - --no-warnings equivalent to '-Wnone' - --preserve-dup-deps don't remove duplicate dependency libraries - --quiet, --silent don't print informational messages - --tag=TAG use configuration variables from tag TAG - -v, --verbose print more informational messages than default - --version print version information - -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] - -h, --help, --help-all print short, long, or detailed help message -" - -# Additional text appended to 'usage_message' in response to '--help'. -func_help () -{ - $debug_cmd - - func_usage_message - $ECHO "$long_help_message - -MODE must be one of the following: - - clean remove files from the build directory - compile compile a source file into a libtool object - execute automatically set library path, then run a program - finish complete the installation of libtool libraries - install install libraries or executables - link create a library or an executable - uninstall remove libraries from an installed directory - -MODE-ARGS vary depending on the MODE. When passed as first option, -'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. -Try '$progname --help --mode=MODE' for a more detailed description of MODE. - -When reporting a bug, please describe a test case to reproduce it and -include the following information: - - host-triplet: $host - shell: $SHELL - compiler: $LTCC - compiler flags: $LTCFLAGS - linker: $LD (gnu? $with_gnu_ld) - version: $progname $scriptversion Debian-2.4.6-15 - automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` - autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` - -Report bugs to . -GNU libtool home page: . -General help using GNU software: ." - exit 0 -} - - -# func_lo2o OBJECT-NAME -# --------------------- -# Transform OBJECT-NAME from a '.lo' suffix to the platform specific -# object suffix. - -lo2o=s/\\.lo\$/.$objext/ -o2lo=s/\\.$objext\$/.lo/ - -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_lo2o () - { - case $1 in - *.lo) func_lo2o_result=${1%.lo}.$objext ;; - * ) func_lo2o_result=$1 ;; - esac - }' - - # func_xform LIBOBJ-OR-SOURCE - # --------------------------- - # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) - # suffix to a '.lo' libtool-object suffix. - eval 'func_xform () - { - func_xform_result=${1%.*}.lo - }' -else - # ...otherwise fall back to using sed. - func_lo2o () - { - func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` - } - - func_xform () - { - func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` - } -fi - - -# func_fatal_configuration ARG... -# ------------------------------- -# Echo program name prefixed message to standard error, followed by -# a configuration failure hint, and exit. -func_fatal_configuration () -{ - func__fatal_error ${1+"$@"} \ - "See the $PACKAGE documentation for more information." \ - "Fatal configuration error." -} - - -# func_config -# ----------- -# Display the configuration for all the tags in this script. -func_config () -{ - re_begincf='^# ### BEGIN LIBTOOL' - re_endcf='^# ### END LIBTOOL' - - # Default configuration. - $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" - - # Now print the configurations for the tags. - for tagname in $taglist; do - $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" - done - - exit $? -} - - -# func_features -# ------------- -# Display the features supported by this script. -func_features () -{ - echo "host: $host" - if test yes = "$build_libtool_libs"; then - echo "enable shared libraries" - else - echo "disable shared libraries" - fi - if test yes = "$build_old_libs"; then - echo "enable static libraries" - else - echo "disable static libraries" - fi - - exit $? -} - - -# func_enable_tag TAGNAME -# ----------------------- -# Verify that TAGNAME is valid, and either flag an error and exit, or -# enable the TAGNAME tag. We also add TAGNAME to the global $taglist -# variable here. -func_enable_tag () -{ - # Global variable: - tagname=$1 - - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf=/$re_begincf/,/$re_endcf/p - - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac - - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; - *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" - - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac -} - - -# func_check_version_match -# ------------------------ -# Ensure that we are using m4 macros, and libtool script from the same -# release of libtool. -func_check_version_match () -{ - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from an older release. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - fi - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, -$progname: but the definition of this LT_INIT comes from revision $macro_revision. -$progname: You should recreate aclocal.m4 with macros from revision $package_revision -$progname: of $PACKAGE $VERSION and run autoconf again. -_LT_EOF - fi - - exit $EXIT_MISMATCH - fi -} - - -# libtool_options_prep [ARG]... -# ----------------------------- -# Preparation for options parsed by libtool. -libtool_options_prep () -{ - $debug_mode - - # Option defaults: - opt_config=false - opt_dlopen= - opt_dry_run=false - opt_help=false - opt_mode= - opt_preserve_dup_deps=false - opt_quiet=false - - nonopt= - preserve_args= - - _G_rc_lt_options_prep=: - - # Shorthand for --mode=foo, only valid as the first argument - case $1 in - clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; - compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; - execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; - finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; - install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; - link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; - uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; - *) - _G_rc_lt_options_prep=false - ;; - esac - - if $_G_rc_lt_options_prep; then - # Pass back the list of options. - func_quote_for_eval ${1+"$@"} - libtool_options_prep_result=$func_quote_for_eval_result - fi - - $_G_rc_lt_options_prep -} -func_add_hook func_options_prep libtool_options_prep - - -# libtool_parse_options [ARG]... -# --------------------------------- -# Provide handling for libtool specific options. -libtool_parse_options () -{ - $debug_cmd - - _G_rc_lt_parse_options=false - - # Perform our own loop to consume as many options as possible in - # each iteration. - while test $# -gt 0; do - _G_match_lt_parse_options=: - _G_opt=$1 - shift - case $_G_opt in - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - - --config) func_config ;; - - --dlopen|-dlopen) - opt_dlopen="${opt_dlopen+$opt_dlopen -}$1" - shift - ;; - - --preserve-dup-deps) - opt_preserve_dup_deps=: ;; - - --features) func_features ;; - - --finish) set dummy --mode finish ${1+"$@"}; shift ;; - - --help) opt_help=: ;; - - --help-all) opt_help=': help-all' ;; - - --mode) test $# = 0 && func_missing_arg $_G_opt && break - opt_mode=$1 - case $1 in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $_G_opt" - exit_cmd=exit - break - ;; - esac - shift - ;; - - --no-silent|--no-quiet) - opt_quiet=false - func_append preserve_args " $_G_opt" - ;; - - --no-warnings|--no-warning|--no-warn) - opt_warning=false - func_append preserve_args " $_G_opt" - ;; - - --no-verbose) - opt_verbose=false - func_append preserve_args " $_G_opt" - ;; - - --silent|--quiet) - opt_quiet=: - opt_verbose=false - func_append preserve_args " $_G_opt" - ;; - - --tag) test $# = 0 && func_missing_arg $_G_opt && break - opt_tag=$1 - func_append preserve_args " $_G_opt $1" - func_enable_tag "$1" - shift - ;; - - --verbose|-v) opt_quiet=false - opt_verbose=: - func_append preserve_args " $_G_opt" - ;; - - # An option not handled by this hook function: - *) set dummy "$_G_opt" ${1+"$@"} ; shift - _G_match_lt_parse_options=false - break - ;; - esac - $_G_match_lt_parse_options && _G_rc_lt_parse_options=: - done - - if $_G_rc_lt_parse_options; then - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - libtool_parse_options_result=$func_quote_for_eval_result - fi - - $_G_rc_lt_parse_options -} -func_add_hook func_parse_options libtool_parse_options - - - -# libtool_validate_options [ARG]... -# --------------------------------- -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -libtool_validate_options () -{ - # save first non-option argument - if test 0 -lt $#; then - nonopt=$1 - shift - fi - - # preserve --debug - test : = "$debug_cmd" || func_append preserve_args " --debug" - - case $host in - # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 - # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 - *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac - - $opt_help || { - # Sanity checks first: - func_check_version_match - - test yes != "$build_libtool_libs" \ - && test yes != "$build_old_libs" \ - && func_fatal_configuration "not configured to build any kind of library" - - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test execute != "$opt_mode"; then - func_error "unrecognized option '-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help=$help - help="Try '$progname --help --mode=$opt_mode' for more information." - } - - # Pass back the unparsed argument list - func_quote_for_eval ${1+"$@"} - libtool_validate_options_result=$func_quote_for_eval_result -} -func_add_hook func_validate_options libtool_validate_options - - -# Process options as early as possible so that --help and --version -# can return quickly. -func_options ${1+"$@"} -eval set dummy "$func_options_result"; shift - - - -## ----------- ## -## Main. ## -## ----------- ## - -magic='%%%MAGIC variable%%%' -magic_exe='%%%MAGIC EXE variable%%%' - -# Global variables. -extracted_archives= -extracted_serial=0 - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# func_generated_by_libtool -# True iff stdin has been generated by Libtool. This function is only -# a basic sanity check; it will hardly flush out determined imposters. -func_generated_by_libtool_p () -{ - $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 -} - -# func_lalib_p file -# True iff FILE is a libtool '.la' library or '.lo' object file. -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_lalib_p () -{ - test -f "$1" && - $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p -} - -# func_lalib_unsafe_p file -# True iff FILE is a libtool '.la' library or '.lo' object file. -# This function implements the same check as func_lalib_p without -# resorting to external programs. To this end, it redirects stdin and -# closes it afterwards, without saving the original file descriptor. -# As a safety measure, use it only where a negative result would be -# fatal anyway. Works if 'file' does not exist. -func_lalib_unsafe_p () -{ - lalib_p=no - if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then - for lalib_p_l in 1 2 3 4 - do - read lalib_p_line - case $lalib_p_line in - \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; - esac - done - exec 0<&5 5<&- - fi - test yes = "$lalib_p" -} - -# func_ltwrapper_script_p file -# True iff FILE is a libtool wrapper script -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_script_p () -{ - test -f "$1" && - $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p -} - -# func_ltwrapper_executable_p file -# True iff FILE is a libtool wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_executable_p () -{ - func_ltwrapper_exec_suffix= - case $1 in - *.exe) ;; - *) func_ltwrapper_exec_suffix=.exe ;; - esac - $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 -} - -# func_ltwrapper_scriptname file -# Assumes file is an ltwrapper_executable -# uses $file to determine the appropriate filename for a -# temporary ltwrapper_script. -func_ltwrapper_scriptname () -{ - func_dirname_and_basename "$1" "" "." - func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper -} - -# func_ltwrapper_p file -# True iff FILE is a libtool wrapper script or wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_p () -{ - func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" -} - - -# func_execute_cmds commands fail_cmd -# Execute tilde-delimited COMMANDS. -# If FAIL_CMD is given, eval that upon failure. -# FAIL_CMD may read-access the current command in variable CMD! -func_execute_cmds () -{ - $debug_cmd - - save_ifs=$IFS; IFS='~' - for cmd in $1; do - IFS=$sp$nl - eval cmd=\"$cmd\" - IFS=$save_ifs - func_show_eval "$cmd" "${2-:}" - done - IFS=$save_ifs -} - - -# func_source file -# Source FILE, adding directory component if necessary. -# Note that it is not necessary on cygwin/mingw to append a dot to -# FILE even if both FILE and FILE.exe exist: automatic-append-.exe -# behavior happens only for exec(3), not for open(2)! Also, sourcing -# 'FILE.' does not work on cygwin managed mounts. -func_source () -{ - $debug_cmd - - case $1 in - */* | *\\*) . "$1" ;; - *) . "./$1" ;; - esac -} - - -# func_resolve_sysroot PATH -# Replace a leading = in PATH with a sysroot. Store the result into -# func_resolve_sysroot_result -func_resolve_sysroot () -{ - func_resolve_sysroot_result=$1 - case $func_resolve_sysroot_result in - =*) - func_stripname '=' '' "$func_resolve_sysroot_result" - func_resolve_sysroot_result=$lt_sysroot$func_stripname_result - ;; - esac -} - -# func_replace_sysroot PATH -# If PATH begins with the sysroot, replace it with = and -# store the result into func_replace_sysroot_result. -func_replace_sysroot () -{ - case $lt_sysroot:$1 in - ?*:"$lt_sysroot"*) - func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result='='$func_stripname_result - ;; - *) - # Including no sysroot. - func_replace_sysroot_result=$1 - ;; - esac -} - -# func_infer_tag arg -# Infer tagged configuration to use if any are available and -# if one wasn't chosen via the "--tag" command line option. -# Only attempt this if the compiler in the base compile -# command doesn't match the default compiler. -# arg is usually of the form 'gcc ...' -func_infer_tag () -{ - $debug_cmd - - if test -n "$available_tags" && test -z "$tagname"; then - CC_quoted= - for arg in $CC; do - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case $@ in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then - # Evaluate the configuration. - eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" - CC_quoted= - for arg in $CC; do - # Double-quote args containing other shell metacharacters. - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case "$@ " in - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with '--tag'" -# else -# func_verbose "using $tagname tagged configuration" - fi - ;; - esac - fi -} - - - -# func_write_libtool_object output_name pic_name nonpic_name -# Create a libtool object file (analogous to a ".la" file), -# but don't create it if we're doing a dry run. -func_write_libtool_object () -{ - write_libobj=$1 - if test yes = "$build_libtool_libs"; then - write_lobj=\'$2\' - else - write_lobj=none - fi - - if test yes = "$build_old_libs"; then - write_oldobj=\'$3\' - else - write_oldobj=none - fi - - $opt_dry_run || { - cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then - func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$sed_naive_backslashify"` - else - func_convert_core_file_wine_to_w32_result= - fi - fi -} -# end: func_convert_core_file_wine_to_w32 - - -# func_convert_core_path_wine_to_w32 ARG -# Helper function used by path conversion functions when $build is *nix, and -# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly -# configured wine environment available, with the winepath program in $build's -# $PATH. Assumes ARG has no leading or trailing path separator characters. -# -# ARG is path to be converted from $build format to win32. -# Result is available in $func_convert_core_path_wine_to_w32_result. -# Unconvertible file (directory) names in ARG are skipped; if no directory names -# are convertible, then the result may be empty. -func_convert_core_path_wine_to_w32 () -{ - $debug_cmd - - # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result= - if test -n "$1"; then - oldIFS=$IFS - IFS=: - for func_convert_core_path_wine_to_w32_f in $1; do - IFS=$oldIFS - func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result"; then - if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result - else - func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" - fi - fi - done - IFS=$oldIFS - fi -} -# end: func_convert_core_path_wine_to_w32 - - -# func_cygpath ARGS... -# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when -# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) -# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or -# (2), returns the Cygwin file name or path in func_cygpath_result (input -# file name or path is assumed to be in w32 format, as previously converted -# from $build's *nix or MSYS format). In case (3), returns the w32 file name -# or path in func_cygpath_result (input file name or path is assumed to be in -# Cygwin format). Returns an empty string on error. -# -# ARGS are passed to cygpath, with the last one being the file name or path to -# be converted. -# -# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH -# environment variable; do not put it in $PATH. -func_cygpath () -{ - $debug_cmd - - if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then - func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` - if test "$?" -ne 0; then - # on failure, ensure result is empty - func_cygpath_result= - fi - else - func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" - fi -} -#end: func_cygpath - - -# func_convert_core_msys_to_w32 ARG -# Convert file name or path ARG from MSYS format to w32 format. Return -# result in func_convert_core_msys_to_w32_result. -func_convert_core_msys_to_w32 () -{ - $debug_cmd - - # awkward: cmd appends spaces to result - func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` -} -#end: func_convert_core_msys_to_w32 - - -# func_convert_file_check ARG1 ARG2 -# Verify that ARG1 (a file name in $build format) was converted to $host -# format in ARG2. Otherwise, emit an error message, but continue (resetting -# func_to_host_file_result to ARG1). -func_convert_file_check () -{ - $debug_cmd - - if test -z "$2" && test -n "$1"; then - func_error "Could not determine host file name corresponding to" - func_error " '$1'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback: - func_to_host_file_result=$1 - fi -} -# end func_convert_file_check - - -# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH -# Verify that FROM_PATH (a path in $build format) was converted to $host -# format in TO_PATH. Otherwise, emit an error message, but continue, resetting -# func_to_host_file_result to a simplistic fallback value (see below). -func_convert_path_check () -{ - $debug_cmd - - if test -z "$4" && test -n "$3"; then - func_error "Could not determine the host path corresponding to" - func_error " '$3'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback. This is a deliberately simplistic "conversion" and - # should not be "improved". See libtool.info. - if test "x$1" != "x$2"; then - lt_replace_pathsep_chars="s|$1|$2|g" - func_to_host_path_result=`echo "$3" | - $SED -e "$lt_replace_pathsep_chars"` - else - func_to_host_path_result=$3 - fi - fi -} -# end func_convert_path_check - - -# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG -# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT -# and appending REPL if ORIG matches BACKPAT. -func_convert_path_front_back_pathsep () -{ - $debug_cmd - - case $4 in - $1 ) func_to_host_path_result=$3$func_to_host_path_result - ;; - esac - case $4 in - $2 ) func_append func_to_host_path_result "$3" - ;; - esac -} -# end func_convert_path_front_back_pathsep - - -################################################## -# $build to $host FILE NAME CONVERSION FUNCTIONS # -################################################## -# invoked via '$to_host_file_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# Result will be available in $func_to_host_file_result. - - -# func_to_host_file ARG -# Converts the file name ARG from $build format to $host format. Return result -# in func_to_host_file_result. -func_to_host_file () -{ - $debug_cmd - - $to_host_file_cmd "$1" -} -# end func_to_host_file - - -# func_to_tool_file ARG LAZY -# converts the file name ARG from $build format to toolchain format. Return -# result in func_to_tool_file_result. If the conversion in use is listed -# in (the comma separated) LAZY, no conversion takes place. -func_to_tool_file () -{ - $debug_cmd - - case ,$2, in - *,"$to_tool_file_cmd",*) - func_to_tool_file_result=$1 - ;; - *) - $to_tool_file_cmd "$1" - func_to_tool_file_result=$func_to_host_file_result - ;; - esac -} -# end func_to_tool_file - - -# func_convert_file_noop ARG -# Copy ARG to func_to_host_file_result. -func_convert_file_noop () -{ - func_to_host_file_result=$1 -} -# end func_convert_file_noop - - -# func_convert_file_msys_to_w32 ARG -# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_file_result. -func_convert_file_msys_to_w32 () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_to_host_file_result=$func_convert_core_msys_to_w32_result - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_w32 - - -# func_convert_file_cygwin_to_w32 ARG -# Convert file name ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_file_cygwin_to_w32 () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - # because $build is cygwin, we call "the" cygpath in $PATH; no need to use - # LT_CYGPATH in this case. - func_to_host_file_result=`cygpath -m "$1"` - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_cygwin_to_w32 - - -# func_convert_file_nix_to_w32 ARG -# Convert file name ARG from *nix to w32 format. Requires a wine environment -# and a working winepath. Returns result in func_to_host_file_result. -func_convert_file_nix_to_w32 () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result=$func_convert_core_file_wine_to_w32_result - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_w32 - - -# func_convert_file_msys_to_cygwin ARG -# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_file_msys_to_cygwin () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result=$func_cygpath_result - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_cygwin - - -# func_convert_file_nix_to_cygwin ARG -# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed -# in a wine environment, working winepath, and LT_CYGPATH set. Returns result -# in func_to_host_file_result. -func_convert_file_nix_to_cygwin () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. - func_convert_core_file_wine_to_w32 "$1" - func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result=$func_cygpath_result - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_cygwin - - -############################################# -# $build to $host PATH CONVERSION FUNCTIONS # -############################################# -# invoked via '$to_host_path_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# The result will be available in $func_to_host_path_result. -# -# Path separators are also converted from $build format to $host format. If -# ARG begins or ends with a path separator character, it is preserved (but -# converted to $host format) on output. -# -# All path conversion functions are named using the following convention: -# file name conversion function : func_convert_file_X_to_Y () -# path conversion function : func_convert_path_X_to_Y () -# where, for any given $build/$host combination the 'X_to_Y' value is the -# same. If conversion functions are added for new $build/$host combinations, -# the two new functions must follow this pattern, or func_init_to_host_path_cmd -# will break. - - -# func_init_to_host_path_cmd -# Ensures that function "pointer" variable $to_host_path_cmd is set to the -# appropriate value, based on the value of $to_host_file_cmd. -to_host_path_cmd= -func_init_to_host_path_cmd () -{ - $debug_cmd - - if test -z "$to_host_path_cmd"; then - func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd=func_convert_path_$func_stripname_result - fi -} - - -# func_to_host_path ARG -# Converts the path ARG from $build format to $host format. Return result -# in func_to_host_path_result. -func_to_host_path () -{ - $debug_cmd - - func_init_to_host_path_cmd - $to_host_path_cmd "$1" -} -# end func_to_host_path - - -# func_convert_path_noop ARG -# Copy ARG to func_to_host_path_result. -func_convert_path_noop () -{ - func_to_host_path_result=$1 -} -# end func_convert_path_noop - - -# func_convert_path_msys_to_w32 ARG -# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_path_result. -func_convert_path_msys_to_w32 () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # Remove leading and trailing path separator characters from ARG. MSYS - # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; - # and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result=$func_convert_core_msys_to_w32_result - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_msys_to_w32 - - -# func_convert_path_cygwin_to_w32 ARG -# Convert path ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_path_cygwin_to_w32 () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_cygwin_to_w32 - - -# func_convert_path_nix_to_w32 ARG -# Convert path ARG from *nix to w32 format. Requires a wine environment and -# a working winepath. Returns result in func_to_host_file_result. -func_convert_path_nix_to_w32 () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result=$func_convert_core_path_wine_to_w32_result - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_nix_to_w32 - - -# func_convert_path_msys_to_cygwin ARG -# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_path_msys_to_cygwin () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result=$func_cygpath_result - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_msys_to_cygwin - - -# func_convert_path_nix_to_cygwin ARG -# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a -# a wine environment, working winepath, and LT_CYGPATH set. Returns result in -# func_to_host_file_result. -func_convert_path_nix_to_cygwin () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # Remove leading and trailing path separator characters from - # ARG. msys behavior is inconsistent here, cygpath turns them - # into '.;' and ';.', and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result=$func_cygpath_result - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_nix_to_cygwin - - -# func_dll_def_p FILE -# True iff FILE is a Windows DLL '.def' file. -# Keep in sync with _LT_DLL_DEF_P in libtool.m4 -func_dll_def_p () -{ - $debug_cmd - - func_dll_def_p_tmp=`$SED -n \ - -e 's/^[ ]*//' \ - -e '/^\(;.*\)*$/d' \ - -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ - -e q \ - "$1"` - test DEF = "$func_dll_def_p_tmp" -} - - -# func_mode_compile arg... -func_mode_compile () -{ - $debug_cmd - - # Get the compilation command and the source file. - base_compile= - srcfile=$nonopt # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - pie_flag= - - for arg - do - case $arg_mode in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg=$arg - arg_mode=normal - ;; - - target ) - libobj=$arg - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - test -n "$libobj" && \ - func_fatal_error "you cannot specify '-o' more than once" - arg_mode=target - continue - ;; - - -pie | -fpie | -fPIE) - func_append pie_flag " $arg" - continue - ;; - - -shared | -static | -prefer-pic | -prefer-non-pic) - func_append later " $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - lastarg= - save_ifs=$IFS; IFS=, - for arg in $args; do - IFS=$save_ifs - func_append_quoted lastarg "$arg" - done - IFS=$save_ifs - func_stripname ' ' '' "$lastarg" - lastarg=$func_stripname_result - - # Add the arguments to base_compile. - func_append base_compile " $lastarg" - continue - ;; - - *) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg=$srcfile - srcfile=$arg - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - func_append_quoted base_compile "$lastarg" - done # for arg - - case $arg_mode in - arg) - func_fatal_error "you must specify an argument for -Xcompile" - ;; - target) - func_fatal_error "you must specify a target with '-o'" - ;; - *) - # Get the name of the library object. - test -z "$libobj" && { - func_basename "$srcfile" - libobj=$func_basename_result - } - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - case $libobj in - *.[cCFSifmso] | \ - *.ada | *.adb | *.ads | *.asm | \ - *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ - *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) - func_xform "$libobj" - libobj=$func_xform_result - ;; - esac - - case $libobj in - *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; - *) - func_fatal_error "cannot determine name of library object from '$libobj'" - ;; - esac - - func_infer_tag $base_compile - - for arg in $later; do - case $arg in - -shared) - test yes = "$build_libtool_libs" \ - || func_fatal_configuration "cannot build a shared library" - build_old_libs=no - continue - ;; - - -static) - build_libtool_libs=no - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - func_quote_for_eval "$libobj" - test "X$libobj" != "X$func_quote_for_eval_result" \ - && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name '$libobj' may not contain shell special characters." - func_dirname_and_basename "$obj" "/" "" - objname=$func_basename_result - xdir=$func_dirname_result - lobj=$xdir$objdir/$objname - - test -z "$base_compile" && \ - func_fatal_help "you must specify a compilation command" - - # Delete any leftover library objects. - if test yes = "$build_old_libs"; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2* | cegcc*) - pic_mode=default - ;; - esac - if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test no = "$compiler_c_o"; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext - lockfile=$output_obj.lock - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test yes = "$need_locks"; then - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - elif test warn = "$need_locks"; then - if test -f "$lockfile"; then - $ECHO "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - func_append removelist " $output_obj" - $ECHO "$srcfile" > "$lockfile" - fi - - $opt_dry_run || $RM $removelist - func_append removelist " $lockfile" - trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 - - func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 - srcfile=$func_to_tool_file_result - func_quote_for_eval "$srcfile" - qsrcfile=$func_quote_for_eval_result - - # Only build a PIC object if we are building libtool libraries. - if test yes = "$build_libtool_libs"; then - # Without this assignment, base_compile gets emptied. - fbsd_hideous_sh_bug=$base_compile - - if test no != "$pic_mode"; then - command="$base_compile $qsrcfile $pic_flag" - else - # Don't build PIC code - command="$base_compile $qsrcfile" - fi - - func_mkdir_p "$xdir$objdir" - - if test -z "$output_obj"; then - # Place PIC objects in $objdir - func_append command " -o $lobj" - fi - - func_show_eval_locale "$command" \ - 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - - if test warn = "$need_locks" && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - func_show_eval '$MV "$output_obj" "$lobj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - - # Allow error messages only from the first compilation. - if test yes = "$suppress_opt"; then - suppress_output=' >/dev/null 2>&1' - fi - fi - - # Only build a position-dependent object if we build old libraries. - if test yes = "$build_old_libs"; then - if test yes != "$pic_mode"; then - # Don't build PIC code - command="$base_compile $qsrcfile$pie_flag" - else - command="$base_compile $qsrcfile $pic_flag" - fi - if test yes = "$compiler_c_o"; then - func_append command " -o $obj" - fi - - # Suppress compiler output if we already did a PIC compilation. - func_append command "$suppress_output" - func_show_eval_locale "$command" \ - '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - - if test warn = "$need_locks" && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - func_show_eval '$MV "$output_obj" "$obj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - fi - - $opt_dry_run || { - func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" - - # Unlock the critical section if it was locked - if test no != "$need_locks"; then - removelist=$lockfile - $RM "$lockfile" - fi - } - - exit $EXIT_SUCCESS -} - -$opt_help || { - test compile = "$opt_mode" && func_mode_compile ${1+"$@"} -} - -func_mode_help () -{ - # We need to display help for each of the modes. - case $opt_mode in - "") - # Generic help is extracted from the usage comments - # at the start of this file. - func_help - ;; - - clean) - $ECHO \ -"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - - compile) - $ECHO \ -"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -no-suppress do not suppress compiler output for multiple passes - -prefer-pic try to build PIC objects only - -prefer-non-pic try to build non-PIC objects only - -shared do not build a '.o' file suitable for static linking - -static only build a '.o' file suitable for static linking - -Wc,FLAG pass FLAG directly to the compiler - -COMPILE-COMMAND is a command to be used in creating a 'standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix '.c' with the -library object suffix, '.lo'." - ;; - - execute) - $ECHO \ -"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to '-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - - finish) - $ECHO \ -"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the '--dry-run' option if you just want to see what would be executed." - ;; - - install) - $ECHO \ -"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the 'install' or 'cp' program. - -The following components of INSTALL-COMMAND are treated specially: - - -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - - link) - $ECHO \ -"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -bindir BINDIR specify path to binaries directory (for systems where - libraries must be found in the PATH setting at runtime) - -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE use a list of object files found in FILE to specify objects - -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -shared only do dynamic linking of libtool libraries - -shrext SUFFIX override the standard shared library file extension - -static do not do any dynamic linking of uninstalled libtool libraries - -static-libtool-libs - do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -weak LIBNAME declare that the target provides the LIBNAME interface - -Wc,FLAG - -Xcompiler FLAG pass linker-specific FLAG directly to the compiler - -Wl,FLAG - -Xlinker FLAG pass linker-specific FLAG directly to the linker - -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) - -All other options (arguments beginning with '-') are ignored. - -Every other argument is treated as a filename. Files ending in '.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in '.la', then a libtool library is created, -only library objects ('.lo' files) may be specified, and '-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created -using 'ar' and 'ranlib', or on Windows using 'lib'. - -If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file -is created, otherwise an executable program is created." - ;; - - uninstall) - $ECHO \ -"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - - *) - func_fatal_help "invalid operation mode '$opt_mode'" - ;; - esac - - echo - $ECHO "Try '$progname --help' for more information about other modes." -} - -# Now that we've collected a possible --mode arg, show help if necessary -if $opt_help; then - if test : = "$opt_help"; then - func_mode_help - else - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - func_mode_help - done - } | $SED -n '1p; 2,$s/^Usage:/ or: /p' - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - echo - func_mode_help - done - } | - $SED '1d - /^When reporting/,/^Report/{ - H - d - } - $x - /information about other modes/d - /more detailed .*MODE/d - s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' - fi - exit $? -fi - - -# func_mode_execute arg... -func_mode_execute () -{ - $debug_cmd - - # The first argument is the command name. - cmd=$nonopt - test -z "$cmd" && \ - func_fatal_help "you must specify a COMMAND" - - # Handle -dlopen flags immediately. - for file in $opt_dlopen; do - test -f "$file" \ - || func_fatal_help "'$file' is not a file" - - dir= - case $file in - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "'$lib' is not a valid libtool archive" - - # Read the libtool library. - dlname= - library_names= - func_source "$file" - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && \ - func_warning "'$file' was not linked with '-export-dynamic'" - continue - fi - - func_dirname "$file" "" "." - dir=$func_dirname_result - - if test -f "$dir/$objdir/$dlname"; then - func_append dir "/$objdir" - else - if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" - fi - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - func_dirname "$file" "" "." - dir=$func_dirname_result - ;; - - *) - func_warning "'-dlopen' is ignored for non-libtool libraries and objects" - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir=$absdir - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic=$magic - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -* | *.la | *.lo ) ;; - *) - # Do a test to see if this is really a libtool program. - if func_ltwrapper_script_p "$file"; then - func_source "$file" - # Transform arg to wrapped name. - file=$progdir/$program - elif func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - func_source "$func_ltwrapper_scriptname_result" - # Transform arg to wrapped name. - file=$progdir/$program - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - func_append_quoted args "$file" - done - - if $opt_dry_run; then - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS - else - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES - do - eval "if test \"\${save_$lt_var+set}\" = set; then - $lt_var=\$save_$lt_var; export $lt_var - else - $lt_unset $lt_var - fi" - done - - # Now prepare to actually exec the command. - exec_cmd=\$cmd$args - fi -} - -test execute = "$opt_mode" && func_mode_execute ${1+"$@"} - - -# func_mode_finish arg... -func_mode_finish () -{ - $debug_cmd - - libs= - libdirs= - admincmds= - - for opt in "$nonopt" ${1+"$@"} - do - if test -d "$opt"; then - func_append libdirs " $opt" - - elif test -f "$opt"; then - if func_lalib_unsafe_p "$opt"; then - func_append libs " $opt" - else - func_warning "'$opt' is not a valid libtool archive" - fi - - else - func_fatal_error "invalid argument '$opt'" - fi - done - - if test -n "$libs"; then - if test -n "$lt_sysroot"; then - sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` - sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" - else - sysroot_cmd= - fi - - # Remove sysroot references - if $opt_dry_run; then - for lib in $libs; do - echo "removing references to $lt_sysroot and '=' prefixes from $lib" - done - else - tmpdir=`func_mktempdir` - for lib in $libs; do - $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ - > $tmpdir/tmp-la - mv -f $tmpdir/tmp-la $lib - done - ${RM}r "$tmpdir" - fi - fi - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - func_execute_cmds "$finish_cmds" 'admincmds="$admincmds -'"$cmd"'"' - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $opt_dry_run || eval "$cmds" || func_append admincmds " - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - $opt_quiet && exit $EXIT_SUCCESS - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - echo "----------------------------------------------------------------------" - echo "Libraries have been installed in:" - for libdir in $libdirs; do - $ECHO " $libdir" - done - echo - echo "If you ever happen to want to link against installed libraries" - echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the '-LLIBDIR'" - echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the '$shlibpath_var' environment variable" - echo " during execution" - fi - if test -n "$runpath_var"; then - echo " - add LIBDIR to the '$runpath_var' environment variable" - echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $ECHO " - use the '$flag' linker flag" - fi - if test -n "$admincmds"; then - $ECHO " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" - fi - echo - - echo "See any operating system documentation about shared libraries for" - case $host in - solaris2.[6789]|solaris2.1[0-9]) - echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" - echo "pages." - ;; - *) - echo "more information, such as the ld(1) and ld.so(8) manual pages." - ;; - esac - echo "----------------------------------------------------------------------" - fi - exit $EXIT_SUCCESS -} - -test finish = "$opt_mode" && func_mode_finish ${1+"$@"} - - -# func_mode_install arg... -func_mode_install () -{ - $debug_cmd - - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || - # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac - then - # Aesthetically quote it. - func_quote_for_eval "$nonopt" - install_prog="$func_quote_for_eval_result " - arg=$1 - shift - else - install_prog= - arg=$nonopt - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - func_quote_for_eval "$arg" - func_append install_prog "$func_quote_for_eval_result" - install_shared_prog=$install_prog - case " $install_prog " in - *[\\\ /]cp\ *) install_cp=: ;; - *) install_cp=false ;; - esac - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=false - stripme= - no_mode=: - for arg - do - arg2= - if test -n "$dest"; then - func_append files " $dest" - dest=$arg - continue - fi - - case $arg in - -d) isdir=: ;; - -f) - if $install_cp; then :; else - prev=$arg - fi - ;; - -g | -m | -o) - prev=$arg - ;; - -s) - stripme=" -s" - continue - ;; - -*) - ;; - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - if test X-m = "X$prev" && test -n "$install_override_mode"; then - arg2=$install_override_mode - no_mode=false - fi - prev= - else - dest=$arg - continue - fi - ;; - esac - - # Aesthetically quote the argument. - func_quote_for_eval "$arg" - func_append install_prog " $func_quote_for_eval_result" - if test -n "$arg2"; then - func_quote_for_eval "$arg2" - fi - func_append install_shared_prog " $func_quote_for_eval_result" - done - - test -z "$install_prog" && \ - func_fatal_help "you must specify an install program" - - test -n "$prev" && \ - func_fatal_help "the '$prev' option requires an argument" - - if test -n "$install_override_mode" && $no_mode; then - if $install_cp; then :; else - func_quote_for_eval "$install_override_mode" - func_append install_shared_prog " -m $func_quote_for_eval_result" - fi - fi - - if test -z "$files"; then - if test -z "$dest"; then - func_fatal_help "no file or destination specified" - else - func_fatal_help "you must specify a destination" - fi - fi - - # Strip any trailing slash from the destination. - func_stripname '' '/' "$dest" - dest=$func_stripname_result - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=: - if $isdir; then - destdir=$dest - destname= - else - func_dirname_and_basename "$dest" "" "." - destdir=$func_dirname_result - destname=$func_basename_result - - # Not a directory, so check to see that there is only one file specified. - set dummy $files; shift - test "$#" -gt 1 && \ - func_fatal_help "'$dest' is not a directory" - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - func_fatal_help "'$destdir' must be an absolute directory name" - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic=$magic - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - func_append staticlibs " $file" - ;; - - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "'$file' is not a valid libtool archive" - - library_names= - old_library= - relink_command= - func_source "$file" - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) func_append current_libdirs " $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) func_append future_libdirs " $libdir" ;; - esac - fi - - func_dirname "$file" "/" "" - dir=$func_dirname_result - func_append dir "$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` - else - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` - fi - - func_warning "relinking '$file'" - func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' - fi - - # See the names of the shared library. - set dummy $library_names; shift - if test -n "$1"; then - realname=$1 - shift - - srcname=$realname - test -n "$relink_command" && srcname=${realname}T - - # Install the shared library and build the symlinks. - func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ - 'exit $?' - tstripme=$stripme - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - case $realname in - *.dll.a) - tstripme= - ;; - esac - ;; - os2*) - case $realname in - *_dll.a) - tstripme= - ;; - esac - ;; - esac - if test -n "$tstripme" && test -n "$striplib"; then - func_show_eval "$striplib $destdir/$realname" 'exit $?' - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - # Try 'ln -sf' first, because the 'ln' binary might depend on - # the symlink we replace! Solaris /bin/ln does not understand -f, - # so we also need to try rm && ln -s. - for linkname - do - test "$linkname" != "$realname" \ - && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" - done - fi - - # Do each command in the postinstall commands. - lib=$destdir/$realname - func_execute_cmds "$postinstall_cmds" 'exit $?' - fi - - # Install the pseudo-library for information purposes. - func_basename "$file" - name=$func_basename_result - instname=$dir/${name}i - func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' - - # Maybe install the static library, too. - test -n "$old_library" && func_append staticlibs " $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile=$destdir/$destname - else - func_basename "$file" - destfile=$func_basename_result - destfile=$destdir/$destfile - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - func_lo2o "$destfile" - staticdest=$func_lo2o_result - ;; - *.$objext) - staticdest=$destfile - destfile= - ;; - *) - func_fatal_help "cannot copy a libtool object to '$destfile'" - ;; - esac - - # Install the libtool object if requested. - test -n "$destfile" && \ - func_show_eval "$install_prog $file $destfile" 'exit $?' - - # Install the old object if enabled. - if test yes = "$build_old_libs"; then - # Deduce the name of the old-style object file. - func_lo2o "$file" - staticobj=$func_lo2o_result - func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' - fi - exit $EXIT_SUCCESS - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile=$destdir/$destname - else - func_basename "$file" - destfile=$func_basename_result - destfile=$destdir/$destfile - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext= - case $file in - *.exe) - if test ! -f "$file"; then - func_stripname '' '.exe' "$file" - file=$func_stripname_result - stripped_ext=.exe - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin* | *mingw*) - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - wrapper=$func_ltwrapper_scriptname_result - else - func_stripname '' '.exe' "$file" - wrapper=$func_stripname_result - fi - ;; - *) - wrapper=$file - ;; - esac - if func_ltwrapper_script_p "$wrapper"; then - notinst_deplibs= - relink_command= - - func_source "$wrapper" - - # Check the variables that should have been set. - test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script '$wrapper'" - - finalize=: - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - func_source "$lib" - fi - libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` - if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "'$lib' has not been installed in '$libdir'" - finalize=false - fi - done - - relink_command= - func_source "$wrapper" - - outputname= - if test no = "$fast_install" && test -n "$relink_command"; then - $opt_dry_run || { - if $finalize; then - tmpdir=`func_mktempdir` - func_basename "$file$stripped_ext" - file=$func_basename_result - outputname=$tmpdir/$file - # Replace the output file specification. - relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - - $opt_quiet || { - func_quote_for_expand "$relink_command" - eval "func_echo $func_quote_for_expand_result" - } - if eval "$relink_command"; then : - else - func_error "error: relink '$file' with the above command before installing it" - $opt_dry_run || ${RM}r "$tmpdir" - continue - fi - file=$outputname - else - func_warning "cannot relink '$file'" - fi - } - else - # Install the binary that we compiled earlier. - file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyway - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - func_stripname '' '.exe' "$destfile" - destfile=$func_stripname_result - ;; - esac - ;; - esac - func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' - $opt_dry_run || if test -n "$outputname"; then - ${RM}r "$tmpdir" - fi - ;; - esac - done - - for file in $staticlibs; do - func_basename "$file" - name=$func_basename_result - - # Set up the ranlib parameters. - oldlib=$destdir/$name - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - - func_show_eval "$install_prog \$file \$oldlib" 'exit $?' - - if test -n "$stripme" && test -n "$old_striplib"; then - func_show_eval "$old_striplib $tool_oldlib" 'exit $?' - fi - - # Do each command in the postinstall commands. - func_execute_cmds "$old_postinstall_cmds" 'exit $?' - done - - test -n "$future_libdirs" && \ - func_warning "remember to run '$progname --finish$future_libdirs'" - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' - else - exit $EXIT_SUCCESS - fi -} - -test install = "$opt_mode" && func_mode_install ${1+"$@"} - - -# func_generate_dlsyms outputname originator pic_p -# Extract symbols from dlprefiles and create ${outputname}S.o with -# a dlpreopen symbol table. -func_generate_dlsyms () -{ - $debug_cmd - - my_outputname=$1 - my_originator=$2 - my_pic_p=${3-false} - my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` - my_dlsyms= - - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms=${my_outputname}S.c - else - func_error "not configured to extract global symbols from dlpreopened files" - fi - fi - - if test -n "$my_dlsyms"; then - case $my_dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist=$output_objdir/$my_outputname.nm - - func_show_eval "$RM $nlist ${nlist}S ${nlist}T" - - # Parse the name list into a source file. - func_verbose "creating $output_objdir/$my_dlsyms" - - $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) -#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" -#endif - -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined __osf__ -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - -#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) - -/* External symbol declarations for the compiler. */\ -" - - if test yes = "$dlself"; then - func_verbose "generating symbol list for '$output'" - - $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` - for progfile in $progfiles; do - func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from '$func_to_tool_file_result'" - $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $opt_dry_run || { - eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - if test -n "$export_symbols_regex"; then - $opt_dry_run || { - eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols=$output_objdir/$outputname.exp - $opt_dry_run || { - $RM $export_symbols - eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' - ;; - esac - } - else - $opt_dry_run || { - eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' - eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' - ;; - esac - } - fi - fi - - for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from '$dlprefile'" - func_basename "$dlprefile" - name=$func_basename_result - case $host in - *cygwin* | *mingw* | *cegcc* ) - # if an import library, we need to obtain dlname - if func_win32_import_lib_p "$dlprefile"; then - func_tr_sh "$dlprefile" - eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename= - if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then - # Use subshell, to avoid clobbering current variable values - dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname"; then - func_basename "$dlprefile_dlname" - dlprefile_dlbasename=$func_basename_result - else - # no lafile. user explicitly requested -dlpreopen . - $sharedlib_from_linklib_cmd "$dlprefile" - dlprefile_dlbasename=$sharedlib_from_linklib_result - fi - fi - $opt_dry_run || { - if test -n "$dlprefile_dlbasename"; then - eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' - else - func_warning "Could not compute DLL name from $name" - eval '$ECHO ": $name " >> "$nlist"' - fi - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | - $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" - } - else # not an import lib - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - fi - ;; - *) - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - ;; - esac - done - - $opt_dry_run || { - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $MV "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if $GREP -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - $GREP -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' - else - echo '/* NONE */' >> "$output_objdir/$my_dlsyms" - fi - - func_show_eval '$RM "${nlist}I"' - if test -n "$global_symbol_to_import"; then - eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' - fi - - echo >> "$output_objdir/$my_dlsyms" "\ - -/* The mapping between symbol names and symbols. */ -typedef struct { - const char *name; - void *address; -} lt_dlsymlist; -extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[];\ -" - - if test -s "$nlist"I; then - echo >> "$output_objdir/$my_dlsyms" "\ -static void lt_syminit(void) -{ - LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; - for (; symbol->name; ++symbol) - {" - $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" - echo >> "$output_objdir/$my_dlsyms" "\ - } -}" - fi - echo >> "$output_objdir/$my_dlsyms" "\ -LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[] = -{ {\"$my_originator\", (void *) 0}," - - if test -s "$nlist"I; then - echo >> "$output_objdir/$my_dlsyms" "\ - {\"@INIT@\", (void *) <_syminit}," - fi - - case $need_lib_prefix in - no) - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - *) - eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - esac - echo >> "$output_objdir/$my_dlsyms" "\ - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_${my_prefix}_LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - } # !$opt_dry_run - - pic_flag_for_symtable= - case "$compile_command " in - *" -static "*) ;; - *) - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; - *-*-hpux*) - pic_flag_for_symtable=" $pic_flag" ;; - *) - $my_pic_p && pic_flag_for_symtable=" $pic_flag" - ;; - esac - ;; - esac - symtab_cflags= - for arg in $LTCFLAGS; do - case $arg in - -pie | -fpie | -fPIE) ;; - *) func_append symtab_cflags " $arg" ;; - esac - done - - # Now compile the dynamic symbol file. - func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' - - # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' - - # Transform the symbol file into the correct name. - symfileobj=$output_objdir/${my_outputname}S.$objext - case $host in - *cygwin* | *mingw* | *cegcc* ) - if test -f "$output_objdir/$my_outputname.def"; then - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - else - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - fi - ;; - *) - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - ;; - esac - ;; - *) - func_fatal_error "unknown suffix for '$my_dlsyms'" - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` - fi -} - -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $debug_cmd - - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $debug_cmd - - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - -# func_win32_libid arg -# return the library type of file 'arg' -# -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -# Despite the name, also deal with 64 bit binaries. -func_win32_libid () -{ - $debug_cmd - - win32_libid_type=unknown - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - case $nm_interface in - "MS dumpbin") - if func_cygming_ms_implib_p "$1" || - func_cygming_gnu_implib_p "$1" - then - win32_nmres=import - else - win32_nmres= - fi - ;; - *) - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' - 1,100{ - / I /{ - s|.*|import| - p - q - } - }'` - ;; - esac - case $win32_nmres in - import*) win32_libid_type="x86 archive import";; - *) win32_libid_type="x86 archive static";; - esac - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $ECHO "$win32_libid_type" -} - -# func_cygming_dll_for_implib ARG -# -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib () -{ - $debug_cmd - - sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` -} - -# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs -# -# The is the core of a fallback implementation of a -# platform-specific function to extract the name of the -# DLL associated with the specified import library LIBNAME. -# -# SECTION_NAME is either .idata$6 or .idata$7, depending -# on the platform and compiler that created the implib. -# -# Echos the name of the DLL associated with the -# specified import library. -func_cygming_dll_for_implib_fallback_core () -{ - $debug_cmd - - match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` - $OBJDUMP -s --section "$1" "$2" 2>/dev/null | - $SED '/^Contents of section '"$match_literal"':/{ - # Place marker at beginning of archive member dllname section - s/.*/====MARK====/ - p - d - } - # These lines can sometimes be longer than 43 characters, but - # are always uninteresting - /:[ ]*file format pe[i]\{,1\}-/d - /^In archive [^:]*:/d - # Ensure marker is printed - /^====MARK====/p - # Remove all lines with less than 43 characters - /^.\{43\}/!d - # From remaining lines, remove first 43 characters - s/^.\{43\}//' | - $SED -n ' - # Join marker and all lines until next marker into a single line - /^====MARK====/ b para - H - $ b para - b - :para - x - s/\n//g - # Remove the marker - s/^====MARK====// - # Remove trailing dots and whitespace - s/[\. \t]*$// - # Print - /./p' | - # we now have a list, one entry per line, of the stringified - # contents of the appropriate section of all members of the - # archive that possess that section. Heuristic: eliminate - # all those that have a first or second character that is - # a '.' (that is, objdump's representation of an unprintable - # character.) This should work for all archives with less than - # 0x302f exports -- but will fail for DLLs whose name actually - # begins with a literal '.' or a single character followed by - # a '.'. - # - # Of those that remain, print the first one. - $SED -e '/^\./d;/^.\./d;q' -} - -# func_cygming_dll_for_implib_fallback ARG -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# -# This fallback implementation is for use when $DLLTOOL -# does not support the --identify-strict option. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib_fallback () -{ - $debug_cmd - - if func_cygming_gnu_implib_p "$1"; then - # binutils import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1"; then - # ms-generated import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` - else - # unknown - sharedlib_from_linklib_result= - fi -} - - -# func_extract_an_archive dir oldlib -func_extract_an_archive () -{ - $debug_cmd - - f_ex_an_ar_dir=$1; shift - f_ex_an_ar_oldlib=$1 - if test yes = "$lock_old_archive_extraction"; then - lockfile=$f_ex_an_ar_oldlib.lock - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - fi - func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ - 'stat=$?; rm -f "$lockfile"; exit $stat' - if test yes = "$lock_old_archive_extraction"; then - $opt_dry_run || rm -f "$lockfile" - fi - if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then - : - else - func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" - fi -} - - -# func_extract_archives gentop oldlib ... -func_extract_archives () -{ - $debug_cmd - - my_gentop=$1; shift - my_oldlibs=${1+"$@"} - my_oldobjs= - my_xlib= - my_xabs= - my_xdir= - - for my_xlib in $my_oldlibs; do - # Extract the objects. - case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; - *) my_xabs=`pwd`"/$my_xlib" ;; - esac - func_basename "$my_xlib" - my_xlib=$func_basename_result - my_xlib_u=$my_xlib - while :; do - case " $extracted_archives " in - *" $my_xlib_u "*) - func_arith $extracted_serial + 1 - extracted_serial=$func_arith_result - my_xlib_u=lt$extracted_serial-$my_xlib ;; - *) break ;; - esac - done - extracted_archives="$extracted_archives $my_xlib_u" - my_xdir=$my_gentop/$my_xlib_u - - func_mkdir_p "$my_xdir" - - case $host in - *-darwin*) - func_verbose "Extracting $my_xabs" - # Do not bother doing anything if just a dry run - $opt_dry_run || { - darwin_orig_dir=`pwd` - cd $my_xdir || exit $? - darwin_archive=$my_xabs - darwin_curdir=`pwd` - func_basename "$darwin_archive" - darwin_base_archive=$func_basename_result - darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` - if test -n "$darwin_arches"; then - darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` - darwin_arch= - func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches; do - func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" - $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" - cd "unfat-$$/$darwin_base_archive-$darwin_arch" - func_extract_an_archive "`pwd`" "$darwin_base_archive" - cd "$darwin_curdir" - $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" - done # $darwin_arches - ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` - darwin_file= - darwin_files= - for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` - $LIPO -create -output "$darwin_file" $darwin_files - done # $darwin_filelist - $RM -rf unfat-$$ - cd "$darwin_orig_dir" - else - cd $darwin_orig_dir - func_extract_an_archive "$my_xdir" "$my_xabs" - fi # $darwin_arches - } # !$opt_dry_run - ;; - *) - func_extract_an_archive "$my_xdir" "$my_xabs" - ;; - esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` - done - - func_extract_archives_result=$my_oldobjs -} - - -# func_emit_wrapper [arg=no] -# -# Emit a libtool wrapper script on stdout. -# Don't directly open a file because we may want to -# incorporate the script contents within a cygwin/mingw -# wrapper executable. Must ONLY be called from within -# func_mode_link because it depends on a number of variables -# set therein. -# -# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR -# variable will take. If 'yes', then the emitted script -# will assume that the directory where it is stored is -# the $objdir directory. This is a cygwin/mingw-specific -# behavior. -func_emit_wrapper () -{ - func_emit_wrapper_arg1=${1-no} - - $ECHO "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE) $VERSION -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='$sed_quote_subst' - -# Be Bourne compatible -if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variables: - generated_by_libtool_version='$macro_version' - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$ECHO are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - file=\"\$0\"" - - qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` - $ECHO "\ - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - ECHO=\"$qECHO\" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on -# windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options that match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's $0 value, followed by "$@". -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=\$0 - shift - for lt_opt - do - case \"\$lt_opt\" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` - test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. - lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` - cat \"\$lt_dump_D/\$lt_dump_F\" - exit 0 - ;; - --lt-*) - \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n \"\$lt_option_debug\"; then - echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" - lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2* | *-cegcc*) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $ECHO "\ - \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from \$@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case \" \$* \" in - *\\ --lt-*) - for lt_wr_arg - do - case \$lt_wr_arg in - --lt-*) ;; - *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; - esac - shift - done ;; - esac - func_exec_program_core \${1+\"\$@\"} -} - - # Parse options - func_parse_lt_options \"\$0\" \${1+\"\$@\"} - - # Find the directory that this script lives in. - thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 - if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then - # special case for '.' - if test \"\$thisdir\" = \".\"; then - thisdir=\`pwd\` - fi - # remove .libs from thisdir - case \"\$thisdir\" in - *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; - $objdir ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test yes = "$fast_install"; then - $ECHO "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $MKDIR \"\$progdir\" - else - $RM \"\$progdir/\$file\" - fi" - - $ECHO "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - \$ECHO \"\$relink_command_output\" >&2 - $RM \"\$progdir/\$file\" - exit 1 - fi - fi - - $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $RM \"\$progdir/\$program\"; - $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $RM \"\$progdir/\$file\" - fi" - else - $ECHO "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $ECHO "\ - - if test -f \"\$progdir/\$program\"; then" - - # fixup the dll searchpath if we need to. - # - # Fix the DLL searchpath if we need to. Do this before prepending - # to shlibpath, because on Windows, both are PATH and uninstalled - # libraries must come first. - if test -n "$dllsearchpath"; then - $ECHO "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - # Export our shlibpath_var if we have one. - if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $ECHO "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` - - export $shlibpath_var -" - fi - - $ECHO "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. - func_exec_program \${1+\"\$@\"} - fi - else - # The program doesn't exist. - \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 - \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 - \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" -} - - -# func_emit_cwrapperexe_src -# emit the source code for a wrapper executable on stdout -# Must ONLY be called from within func_mode_link because -# it depends on a number of variable set therein. -func_emit_cwrapperexe_src () -{ - cat < -#include -#ifdef _MSC_VER -# include -# include -# include -#else -# include -# include -# ifdef __CYGWIN__ -# include -# endif -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) - -/* declarations of non-ANSI functions */ -#if defined __MINGW32__ -# ifdef __STRICT_ANSI__ -int _putenv (const char *); -# endif -#elif defined __CYGWIN__ -# ifdef __STRICT_ANSI__ -char *realpath (const char *, char *); -int putenv (char *); -int setenv (const char *, const char *, int); -# endif -/* #elif defined other_platform || defined ... */ -#endif - -/* portability defines, excluding path handling macros */ -#if defined _MSC_VER -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -# define S_IXUSR _S_IEXEC -#elif defined __MINGW32__ -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -#elif defined __CYGWIN__ -# define HAVE_SETENV -# define FOPEN_WB "wb" -/* #elif defined other platforms ... */ -#endif - -#if defined PATH_MAX -# define LT_PATHMAX PATH_MAX -#elif defined MAXPATHLEN -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef S_IXOTH -# define S_IXOTH 0 -#endif -#ifndef S_IXGRP -# define S_IXGRP 0 -#endif - -/* path handling portability macros */ -#ifndef DIR_SEPARATOR -# define DIR_SEPARATOR '/' -# define PATH_SEPARATOR ':' -#endif - -#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ - defined __OS2__ -# define HAVE_DOS_BASED_FILE_SYSTEM -# define FOPEN_WB "wb" -# ifndef DIR_SEPARATOR_2 -# define DIR_SEPARATOR_2 '\\' -# endif -# ifndef PATH_SEPARATOR_2 -# define PATH_SEPARATOR_2 ';' -# endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#ifndef PATH_SEPARATOR_2 -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) -#else /* PATH_SEPARATOR_2 */ -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) -#endif /* PATH_SEPARATOR_2 */ - -#ifndef FOPEN_WB -# define FOPEN_WB "w" -#endif -#ifndef _O_BINARY -# define _O_BINARY 0 -#endif - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free (stale); stale = 0; } \ -} while (0) - -#if defined LT_DEBUGWRAPPER -static int lt_debug = 1; -#else -static int lt_debug = 0; -#endif - -const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ - -void *xmalloc (size_t num); -char *xstrdup (const char *string); -const char *base_name (const char *name); -char *find_executable (const char *wrapper); -char *chase_symlinks (const char *pathspec); -int make_executable (const char *path); -int check_executable (const char *path); -char *strendzap (char *str, const char *pat); -void lt_debugprintf (const char *file, int line, const char *fmt, ...); -void lt_fatal (const char *file, int line, const char *message, ...); -static const char *nonnull (const char *s); -static const char *nonempty (const char *s); -void lt_setenv (const char *name, const char *value); -char *lt_extend_str (const char *orig_value, const char *add, int to_end); -void lt_update_exe_path (const char *name, const char *value); -void lt_update_lib_path (const char *name, const char *value); -char **prepare_spawn (char **argv); -void lt_dump_script (FILE *f); -EOF - - cat <= 0) - && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - return 1; - else - return 0; -} - -int -make_executable (const char *path) -{ - int rval = 0; - struct stat st; - - lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", - nonempty (path)); - if ((!path) || (!*path)) - return 0; - - if (stat (path, &st) >= 0) - { - rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); - } - return rval; -} - -/* Searches for the full path of the wrapper. Returns - newly allocated full path name if found, NULL otherwise - Does not chase symlinks, even on platforms that support them. -*/ -char * -find_executable (const char *wrapper) -{ - int has_slash = 0; - const char *p; - const char *p_next; - /* static buffer for getcwd */ - char tmp[LT_PATHMAX + 1]; - size_t tmp_len; - char *concat_name; - - lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", - nonempty (wrapper)); - - if ((wrapper == NULL) || (*wrapper == '\0')) - return NULL; - - /* Absolute path? */ -#if defined HAVE_DOS_BASED_FILE_SYSTEM - if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - else - { -#endif - if (IS_DIR_SEPARATOR (wrapper[0])) - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } -#if defined HAVE_DOS_BASED_FILE_SYSTEM - } -#endif - - for (p = wrapper; *p; p++) - if (*p == '/') - { - has_slash = 1; - break; - } - if (!has_slash) - { - /* no slashes; search PATH */ - const char *path = getenv ("PATH"); - if (path != NULL) - { - for (p = path; *p; p = p_next) - { - const char *q; - size_t p_len; - for (q = p; *q; q++) - if (IS_PATH_SEPARATOR (*q)) - break; - p_len = (size_t) (q - p); - p_next = (*q == '\0' ? q : q + 1); - if (p_len == 0) - { - /* empty path: current directory */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = - XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - } - else - { - concat_name = - XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, p, p_len); - concat_name[p_len] = '/'; - strcpy (concat_name + p_len + 1, wrapper); - } - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - } - /* not found in PATH; assume curdir */ - } - /* Relative path | not found in path: prepend cwd */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - return NULL; -} - -char * -chase_symlinks (const char *pathspec) -{ -#ifndef S_ISLNK - return xstrdup (pathspec); -#else - char buf[LT_PATHMAX]; - struct stat s; - char *tmp_pathspec = xstrdup (pathspec); - char *p; - int has_symlinks = 0; - while (strlen (tmp_pathspec) && !has_symlinks) - { - lt_debugprintf (__FILE__, __LINE__, - "checking path component for symlinks: %s\n", - tmp_pathspec); - if (lstat (tmp_pathspec, &s) == 0) - { - if (S_ISLNK (s.st_mode) != 0) - { - has_symlinks = 1; - break; - } - - /* search backwards for last DIR_SEPARATOR */ - p = tmp_pathspec + strlen (tmp_pathspec) - 1; - while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - p--; - if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - { - /* no more DIR_SEPARATORS left */ - break; - } - *p = '\0'; - } - else - { - lt_fatal (__FILE__, __LINE__, - "error accessing file \"%s\": %s", - tmp_pathspec, nonnull (strerror (errno))); - } - } - XFREE (tmp_pathspec); - - if (!has_symlinks) - { - return xstrdup (pathspec); - } - - tmp_pathspec = realpath (pathspec, buf); - if (tmp_pathspec == 0) - { - lt_fatal (__FILE__, __LINE__, - "could not follow symlinks for %s", pathspec); - } - return xstrdup (tmp_pathspec); -#endif -} - -char * -strendzap (char *str, const char *pat) -{ - size_t len, patlen; - - assert (str != NULL); - assert (pat != NULL); - - len = strlen (str); - patlen = strlen (pat); - - if (patlen <= len) - { - str += len - patlen; - if (STREQ (str, pat)) - *str = '\0'; - } - return str; -} - -void -lt_debugprintf (const char *file, int line, const char *fmt, ...) -{ - va_list args; - if (lt_debug) - { - (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); - } -} - -static void -lt_error_core (int exit_status, const char *file, - int line, const char *mode, - const char *message, va_list ap) -{ - fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *file, int line, const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); - va_end (ap); -} - -static const char * -nonnull (const char *s) -{ - return s ? s : "(null)"; -} - -static const char * -nonempty (const char *s) -{ - return (s && !*s) ? "(empty)" : nonnull (s); -} - -void -lt_setenv (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_setenv) setting '%s' to '%s'\n", - nonnull (name), nonnull (value)); - { -#ifdef HAVE_SETENV - /* always make a copy, for consistency with !HAVE_SETENV */ - char *str = xstrdup (value); - setenv (name, str, 1); -#else - size_t len = strlen (name) + 1 + strlen (value) + 1; - char *str = XMALLOC (char, len); - sprintf (str, "%s=%s", name, value); - if (putenv (str) != EXIT_SUCCESS) - { - XFREE (str); - } -#endif - } -} - -char * -lt_extend_str (const char *orig_value, const char *add, int to_end) -{ - char *new_value; - if (orig_value && *orig_value) - { - size_t orig_value_len = strlen (orig_value); - size_t add_len = strlen (add); - new_value = XMALLOC (char, add_len + orig_value_len + 1); - if (to_end) - { - strcpy (new_value, orig_value); - strcpy (new_value + orig_value_len, add); - } - else - { - strcpy (new_value, add); - strcpy (new_value + add_len, orig_value); - } - } - else - { - new_value = xstrdup (add); - } - return new_value; -} - -void -lt_update_exe_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - /* some systems can't cope with a ':'-terminated path #' */ - size_t len = strlen (new_value); - while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) - { - new_value[--len] = '\0'; - } - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -void -lt_update_lib_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -EOF - case $host_os in - mingw*) - cat <<"EOF" - -/* Prepares an argument vector before calling spawn(). - Note that spawn() does not by itself call the command interpreter - (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : - ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&v); - v.dwPlatformId == VER_PLATFORM_WIN32_NT; - }) ? "cmd.exe" : "command.com"). - Instead it simply concatenates the arguments, separated by ' ', and calls - CreateProcess(). We must quote the arguments since Win32 CreateProcess() - interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a - special way: - - Space and tab are interpreted as delimiters. They are not treated as - delimiters if they are surrounded by double quotes: "...". - - Unescaped double quotes are removed from the input. Their only effect is - that within double quotes, space and tab are treated like normal - characters. - - Backslashes not followed by double quotes are not special. - - But 2*n+1 backslashes followed by a double quote become - n backslashes followed by a double quote (n >= 0): - \" -> " - \\\" -> \" - \\\\\" -> \\" - */ -#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -char ** -prepare_spawn (char **argv) -{ - size_t argc; - char **new_argv; - size_t i; - - /* Count number of arguments. */ - for (argc = 0; argv[argc] != NULL; argc++) - ; - - /* Allocate new argument vector. */ - new_argv = XMALLOC (char *, argc + 1); - - /* Put quoted arguments into the new argument vector. */ - for (i = 0; i < argc; i++) - { - const char *string = argv[i]; - - if (string[0] == '\0') - new_argv[i] = xstrdup ("\"\""); - else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) - { - int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); - size_t length; - unsigned int backslashes; - const char *s; - char *quoted_string; - char *p; - - length = 0; - backslashes = 0; - if (quote_around) - length++; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - length += backslashes + 1; - length++; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - - quoted_string = XMALLOC (char, length + 1); - - p = quoted_string; - backslashes = 0; - if (quote_around) - *p++ = '"'; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - { - unsigned int j; - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - *p++ = c; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - unsigned int j; - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - - new_argv[i] = quoted_string; - } - else - new_argv[i] = (char *) string; - } - new_argv[argc] = NULL; - - return new_argv; -} -EOF - ;; - esac - - cat <<"EOF" -void lt_dump_script (FILE* f) -{ -EOF - func_emit_wrapper yes | - $SED -n -e ' -s/^\(.\{79\}\)\(..*\)/\1\ -\2/ -h -s/\([\\"]\)/\\\1/g -s/$/\\n/ -s/\([^\n]*\).*/ fputs ("\1", f);/p -g -D' - cat <<"EOF" -} -EOF -} -# end: func_emit_cwrapperexe_src - -# func_win32_import_lib_p ARG -# True if ARG is an import lib, as indicated by $file_magic_cmd -func_win32_import_lib_p () -{ - $debug_cmd - - case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in - *import*) : ;; - *) false ;; - esac -} - -# func_suncc_cstd_abi -# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! -# Several compiler flags select an ABI that is incompatible with the -# Cstd library. Avoid specifying it if any are in CXXFLAGS. -func_suncc_cstd_abi () -{ - $debug_cmd - - case " $compile_command " in - *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) - suncc_use_cstd_abi=no - ;; - *) - suncc_use_cstd_abi=yes - ;; - esac -} - -# func_mode_link arg... -func_mode_link () -{ - $debug_cmd - - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - # It is impossible to link a dll without this setting, and - # we shouldn't force the makefile maintainer to figure out - # what system we are compiling for in order to pass an extra - # flag for every libtool invocation. - # allow_undefined=no - - # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll that has undefined symbols, in which case not - # even a static library is built. For now, we need to specify - # -no-undefined on the libtool link line when we can be certain - # that all symbols are satisfied, otherwise we get a static library. - allow_undefined=yes - ;; - *) - allow_undefined=yes - ;; - esac - libtool_args=$nonopt - base_compile="$nonopt $@" - compile_command=$nonopt - finalize_command=$nonopt - - compile_rpath= - finalize_rpath= - compile_shlibpath= - finalize_shlibpath= - convenience= - old_convenience= - deplibs= - old_deplibs= - compiler_flags= - linker_flags= - dllsearchpath= - lib_search_path=`pwd` - inst_prefix_dir= - new_inherited_linker_flags= - - avoid_version=no - bindir= - dlfiles= - dlprefiles= - dlself=no - export_dynamic=no - export_symbols= - export_symbols_regex= - generated= - libobjs= - ltlibs= - module=no - no_install=no - objs= - os2dllname= - non_pic_objects= - precious_files_regex= - prefer_static_libs=no - preload=false - prev= - prevarg= - release= - rpath= - xrpath= - perm_rpath= - temp_rpath= - thread_safe=no - vinfo= - vinfo_number=no - weak_libs= - single_module=$wl-single_module - func_infer_tag $base_compile - - # We need to know -static, to get the right output filenames. - for arg - do - case $arg in - -shared) - test yes != "$build_libtool_libs" \ - && func_fatal_configuration "cannot build a shared library" - build_old_libs=no - break - ;; - -all-static | -static | -static-libtool-libs) - case $arg in - -all-static) - if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then - func_warning "complete static linking is impossible in this configuration" - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - -static) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=built - ;; - -static-libtool-libs) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - esac - build_libtool_libs=no - build_old_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg=$1 - shift - func_quote_for_eval "$arg" - qarg=$func_quote_for_eval_unquoted_result - func_append libtool_args " $func_quote_for_eval_result" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - func_append compile_command " @OUTPUT@" - func_append finalize_command " @OUTPUT@" - ;; - esac - - case $prev in - bindir) - bindir=$arg - prev= - continue - ;; - dlfiles|dlprefiles) - $preload || { - # Add the symbol object into the linking commands. - func_append compile_command " @SYMFILE@" - func_append finalize_command " @SYMFILE@" - preload=: - } - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test no = "$dlself"; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test dlprefiles = "$prev"; then - dlself=yes - elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test dlfiles = "$prev"; then - func_append dlfiles " $arg" - else - func_append dlprefiles " $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols=$arg - test -f "$arg" \ - || func_fatal_error "symbol file '$arg' does not exist" - prev= - continue - ;; - expsyms_regex) - export_symbols_regex=$arg - prev= - continue - ;; - framework) - case $host in - *-*-darwin*) - case "$deplibs " in - *" $qarg.ltframework "*) ;; - *) func_append deplibs " $qarg.ltframework" # this is fixed later - ;; - esac - ;; - esac - prev= - continue - ;; - inst_prefix) - inst_prefix_dir=$arg - prev= - continue - ;; - mllvm) - # Clang does not use LLVM to link, so we can simply discard any - # '-mllvm $arg' options when doing the link step. - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat "$save_arg"` - do -# func_append moreargs " $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test none = "$pic_object" && - test none = "$non_pic_object"; then - func_fatal_error "cannot find name of object for '$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir=$func_dirname_result - - if test none != "$pic_object"; then - # Prepend the subdirectory the object is found in. - pic_object=$xdir$pic_object - - if test dlfiles = "$prev"; then - if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test dlprefiles = "$prev"; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg=$pic_object - fi - - # Non-PIC object. - if test none != "$non_pic_object"; then - # Prepend the subdirectory the object is found in. - non_pic_object=$xdir$non_pic_object - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test none = "$pic_object"; then - arg=$non_pic_object - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object=$pic_object - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir=$func_dirname_result - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "'$arg' is not a valid libtool object" - fi - fi - done - else - func_fatal_error "link input file '$arg' does not exist" - fi - arg=$save_arg - prev= - continue - ;; - os2dllname) - os2dllname=$arg - prev= - continue - ;; - precious_regex) - precious_files_regex=$arg - prev= - continue - ;; - release) - release=-$arg - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - if test rpath = "$prev"; then - case "$rpath " in - *" $arg "*) ;; - *) func_append rpath " $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) func_append xrpath " $arg" ;; - esac - fi - prev= - continue - ;; - shrext) - shrext_cmds=$arg - prev= - continue - ;; - weak) - func_append weak_libs " $arg" - prev= - continue - ;; - xcclinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xcompiler) - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xlinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $wl$qarg" - prev= - func_append compile_command " $wl$qarg" - func_append finalize_command " $wl$qarg" - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg=$arg - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - # See comment for -static flag below, for more details. - func_append compile_command " $link_static_flag" - func_append finalize_command " $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - func_fatal_error "'-allow-undefined' must not be used because it is the default" - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -bindir) - prev=bindir - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - func_fatal_error "more than one -exported-symbols argument is not allowed" - fi - if test X-export-symbols = "X$arg"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -framework) - prev=framework - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - func_append compile_command " $arg" - func_append finalize_command " $arg" - ;; - esac - continue - ;; - - -L*) - func_stripname "-L" '' "$arg" - if test -z "$func_stripname_result"; then - if test "$#" -gt 0; then - func_fatal_error "require no space between '-L' and '$1'" - else - func_fatal_error "need path for '-L' option" - fi - fi - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of '$dir'" - dir=$absdir - ;; - esac - case "$deplibs " in - *" -L$dir "* | *" $arg "*) - # Will only happen for absolute or sysroot arguments - ;; - *) - # Preserve sysroot, but never include relative directories - case $dir in - [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; - *) func_append deplibs " -L$dir" ;; - esac - func_append lib_search_path " $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$dir:"*) ;; - ::) dllsearchpath=$dir;; - *) func_append dllsearchpath ":$dir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - continue - ;; - - -l*) - if test X-lc = "X$arg" || test X-lm = "X$arg"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-os2*) - # These systems don't actually have a C library (as such) - test X-lc = "X$arg" && continue - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) - # Do not include libc due to us having libc/libc_r. - test X-lc = "X$arg" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - func_append deplibs " System.ltframework" - continue - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - test X-lc = "X$arg" && continue - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - test X-lc = "X$arg" && continue - ;; - esac - elif test X-lc_r = "X$arg"; then - case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - func_append deplibs " $arg" - continue - ;; - - -mllvm) - prev=mllvm - continue - ;; - - -module) - module=yes - continue - ;; - - # Tru64 UNIX uses -model [arg] to determine the layout of C++ - # classes, name mangling, and exception handling. - # Darwin uses the -arch flag to determine output architecture. - -model|-arch|-isysroot|--sysroot) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - prev=xcompiler - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case "$new_inherited_linker_flags " in - *" $arg "*) ;; - * ) func_append new_inherited_linker_flags " $arg" ;; - esac - continue - ;; - - -multi_module) - single_module=$wl-multi_module - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) - # The PATH hackery in wrapper scripts is required on Windows - # and Darwin in order for the loader to find any dlls it needs. - func_warning "'-no-install' is ignored for $host" - func_warning "assuming '-no-fast-install' instead" - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -os2dllname) - prev=os2dllname - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - func_stripname '-R' '' "$arg" - dir=$func_stripname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - =*) - func_stripname '=' '' "$dir" - dir=$lt_sysroot$func_stripname_result - ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - continue - ;; - - -shared) - # The effects of -shared are defined in a previous loop. - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -static | -static-libtool-libs) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -weak) - prev=weak - continue - ;; - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs=$IFS; IFS=, - for flag in $args; do - IFS=$save_ifs - func_quote_for_eval "$flag" - func_append arg " $func_quote_for_eval_result" - func_append compiler_flags " $func_quote_for_eval_result" - done - IFS=$save_ifs - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Wl,*) - func_stripname '-Wl,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs=$IFS; IFS=, - for flag in $args; do - IFS=$save_ifs - func_quote_for_eval "$flag" - func_append arg " $wl$func_quote_for_eval_result" - func_append compiler_flags " $wl$func_quote_for_eval_result" - func_append linker_flags " $func_quote_for_eval_result" - done - IFS=$save_ifs - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # -msg_* for osf cc - -msg_*) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - ;; - - # Flags to be passed through unchanged, with rationale: - # -64, -mips[0-9] enable 64-bit mode for the SGI compiler - # -r[0-9][0-9]* specify processor for the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler - # +DA*, +DD* enable 64-bit mode for the HP compiler - # -q* compiler args for the IBM compiler - # -m*, -t[45]*, -txscale* architecture-specific flags for GCC - # -F/path path to uninstalled frameworks, gcc on darwin - # -p, -pg, --coverage, -fprofile-* profiling flags for GCC - # -fstack-protector* stack protector flags for GCC - # @file GCC response files - # -tp=* Portland pgcc target processor selection - # --sysroot=* for sysroot support - # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization - # -specs=* GCC specs files - # -stdlib=* select c++ std lib with clang - # -fsanitize=* Clang/GCC memory and address sanitizer - # -fuse-ld=* Linker select flags for GCC - # -static-* direct GCC to link specific libraries statically - # -fcilkplus Cilk Plus language extension features for C/C++ - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ - -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - func_append compile_command " $arg" - func_append finalize_command " $arg" - func_append compiler_flags " $arg" - continue - ;; - - -Z*) - if test os2 = "`expr $host : '.*\(os2\)'`"; then - # OS/2 uses -Zxxx to specify OS/2-specific options - compiler_flags="$compiler_flags $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case $arg in - -Zlinker | -Zstack) - prev=xcompiler - ;; - esac - continue - else - # Otherwise treat like 'Some other compiler flag' below - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - fi - ;; - - # Some other compiler flag. - -* | +*) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - ;; - - *.$objext) - # A standard object. - func_append objs " $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test none = "$pic_object" && - test none = "$non_pic_object"; then - func_fatal_error "cannot find name of object for '$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir=$func_dirname_result - - test none = "$pic_object" || { - # Prepend the subdirectory the object is found in. - pic_object=$xdir$pic_object - - if test dlfiles = "$prev"; then - if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test dlprefiles = "$prev"; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg=$pic_object - } - - # Non-PIC object. - if test none != "$non_pic_object"; then - # Prepend the subdirectory the object is found in. - non_pic_object=$xdir$non_pic_object - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test none = "$pic_object"; then - arg=$non_pic_object - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object=$pic_object - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir=$func_dirname_result - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "'$arg' is not a valid libtool object" - fi - fi - ;; - - *.$libext) - # An archive. - func_append deplibs " $arg" - func_append old_deplibs " $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - func_resolve_sysroot "$arg" - if test dlfiles = "$prev"; then - # This library was specified with -dlopen. - func_append dlfiles " $func_resolve_sysroot_result" - prev= - elif test dlprefiles = "$prev"; then - # The library was specified with -dlpreopen. - func_append dlprefiles " $func_resolve_sysroot_result" - prev= - else - func_append deplibs " $func_resolve_sysroot_result" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - done # argument parsing loop - - test -n "$prev" && \ - func_fatal_help "the '$prevarg' option requires an argument" - - if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - func_basename "$output" - outputname=$func_basename_result - libobjs_save=$libobjs - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - # Definition is injected by LT_CONFIG during libtool generation. - func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" - - func_dirname "$output" "/" "" - output_objdir=$func_dirname_result$objdir - func_to_tool_file "$output_objdir/" - tool_output_objdir=$func_to_tool_file_result - # Create the object directory. - func_mkdir_p "$output_objdir" - - # Determine the type of output - case $output in - "") - func_fatal_help "you must specify an output file" - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if $opt_preserve_dup_deps; then - case "$libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append libs " $deplib" - done - - if test lib = "$linkmode"; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if $opt_duplicate_compiler_generated_deps; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; - esac - func_append pre_post_deps " $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - notinst_path= # paths that contain not-installed libtool libraries - - case $linkmode in - lib) - passes="conv dlpreopen link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=false - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - - for pass in $passes; do - # The preopen pass in lib mode reverses $deplibs; put it back here - # so that -L comes before libs that need it for instance... - if test lib,link = "$linkmode,$pass"; then - ## FIXME: Find the place where the list is rebuilt in the wrong - ## order, and fix it there properly - tmp_deplibs= - for deplib in $deplibs; do - tmp_deplibs="$deplib $tmp_deplibs" - done - deplibs=$tmp_deplibs - fi - - if test lib,link = "$linkmode,$pass" || - test prog,scan = "$linkmode,$pass"; then - libs=$deplibs - deplibs= - fi - if test prog = "$linkmode"; then - case $pass in - dlopen) libs=$dlfiles ;; - dlpreopen) libs=$dlprefiles ;; - link) - libs="$deplibs %DEPLIBS%" - test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" - ;; - esac - fi - if test lib,dlpreopen = "$linkmode,$pass"; then - # Collect and forward deplibs of preopened libtool libs - for lib in $dlprefiles; do - # Ignore non-libtool-libs - dependency_libs= - func_resolve_sysroot "$lib" - case $lib in - *.la) func_source "$func_resolve_sysroot_result" ;; - esac - - # Collect preopened libtool deplibs, except any this library - # has declared as weak libs - for deplib in $dependency_libs; do - func_basename "$deplib" - deplib_base=$func_basename_result - case " $weak_libs " in - *" $deplib_base "*) ;; - *) func_append deplibs " $deplib" ;; - esac - done - done - libs=$dlprefiles - fi - if test dlopen = "$pass"; then - # Collect dlpreopened libraries - save_deplibs=$deplibs - deplibs= - fi - - for deplib in $libs; do - lib= - found=false - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append compiler_flags " $deplib" - if test lib = "$linkmode"; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -l*) - if test lib != "$linkmode" && test prog != "$linkmode"; then - func_warning "'-l' is ignored for archives/objects" - continue - fi - func_stripname '-l' '' "$deplib" - name=$func_stripname_result - if test lib = "$linkmode"; then - searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" - else - searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" - fi - for searchdir in $searchdirs; do - for search_ext in .la $std_shrext .so .a; do - # Search the libtool library - lib=$searchdir/lib$name$search_ext - if test -f "$lib"; then - if test .la = "$search_ext"; then - found=: - else - found=false - fi - break 2 - fi - done - done - if $found; then - # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test yes = "$allow_libtool_libs_with_static_runtimes"; then - case " $predeps $postdeps " in - *" $deplib "*) - if func_lalib_p "$lib"; then - library_names= - old_library= - func_source "$lib" - for l in $old_library $library_names; do - ll=$l - done - if test "X$ll" = "X$old_library"; then # only static version available - found=false - func_dirname "$lib" "" "." - ladir=$func_dirname_result - lib=$ladir/$old_library - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - else - # deplib doesn't seem to be a libtool library - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - ;; # -l - *.ltframework) - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - if test lib = "$linkmode"; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test conv = "$pass" && continue - newdependency_libs="$deplib $newdependency_libs" - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - prog) - if test conv = "$pass"; then - deplibs="$deplib $deplibs" - continue - fi - if test scan = "$pass"; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - *) - func_warning "'-L' is ignored for archives/objects" - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test link = "$pass"; then - func_stripname '-R' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) - func_resolve_sysroot "$deplib" - lib=$func_resolve_sysroot_result - ;; - *.$libext) - if test conv = "$pass"; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - # Linking convenience modules into shared libraries is allowed, - # but linking other static libraries is non-portable. - case " $dlpreconveniencelibs " in - *" $deplib "*) ;; - *) - valid_a_lib=false - case $deplibs_check_method in - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=: - fi - ;; - pass_all) - valid_a_lib=: - ;; - esac - if $valid_a_lib; then - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - else - echo - $ECHO "*** Warning: Trying to link with static lib archive $deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because the file extensions .$libext of this argument makes me believe" - echo "*** that it is just a static archive that I should not use here." - fi - ;; - esac - continue - ;; - prog) - if test link != "$pass"; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test conv = "$pass"; then - deplibs="$deplib $deplibs" - elif test prog = "$linkmode"; then - if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - func_append newdlprefiles " $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append newdlfiles " $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=: - continue - ;; - esac # case $deplib - - $found || test -f "$lib" \ - || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$lib" \ - || func_fatal_error "'$lib' is not a valid libtool archive" - - func_dirname "$lib" "" "." - ladir=$func_dirname_result - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - inherited_linker_flags= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - avoidtemprpath= - - - # Read the .la file - func_source "$lib" - - # Convert "-framework foo" to "foo.ltframework" - if test -n "$inherited_linker_flags"; then - tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` - for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do - case " $new_inherited_linker_flags " in - *" $tmp_inherited_linker_flag "*) ;; - *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; - esac - done - fi - dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test lib,link = "$linkmode,$pass" || - test prog,scan = "$linkmode,$pass" || - { test prog != "$linkmode" && test lib != "$linkmode"; }; then - test -n "$dlopen" && func_append dlfiles " $dlopen" - test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" - fi - - if test conv = "$pass"; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for '$lib'" - fi - # It is a libtool convenience library, so add in its objects. - func_append convenience " $ladir/$objdir/$old_library" - func_append old_convenience " $ladir/$objdir/$old_library" - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done - elif test prog != "$linkmode" && test lib != "$linkmode"; then - func_fatal_error "'$lib' is not a convenience library" - fi - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - if test -n "$old_library" && - { test yes = "$prefer_static_libs" || - test built,no = "$prefer_static_libs,$installed"; }; then - linklib=$old_library - else - for l in $old_library $library_names; do - linklib=$l - done - fi - if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for '$lib'" - fi - - # This library was specified with -dlopen. - if test dlopen = "$pass"; then - test -z "$libdir" \ - && func_fatal_error "cannot -dlopen a convenience library: '$lib'" - if test -z "$dlname" || - test yes != "$dlopen_support" || - test no = "$build_libtool_libs" - then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - func_append dlprefiles " $lib $dependency_libs" - else - func_append newdlfiles " $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of '$ladir'" - func_warning "passing it literally to the linker, although it might fail" - abs_ladir=$ladir - fi - ;; - esac - func_basename "$lib" - laname=$func_basename_result - - # Find the relevant object directory and library name. - if test yes = "$installed"; then - if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library '$lib' was moved." - dir=$ladir - absdir=$abs_ladir - libdir=$abs_ladir - else - dir=$lt_sysroot$libdir - absdir=$lt_sysroot$libdir - fi - test yes = "$hardcode_automatic" && avoidtemprpath=yes - else - if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir=$ladir - absdir=$abs_ladir - # Remove this search path later - func_append notinst_path " $abs_ladir" - else - dir=$ladir/$objdir - absdir=$abs_ladir/$objdir - # Remove this search path later - func_append notinst_path " $abs_ladir" - fi - fi # $installed = yes - func_stripname 'lib' '.la' "$laname" - name=$func_stripname_result - - # This library was specified with -dlpreopen. - if test dlpreopen = "$pass"; then - if test -z "$libdir" && test prog = "$linkmode"; then - func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" - fi - case $host in - # special handling for platforms with PE-DLLs. - *cygwin* | *mingw* | *cegcc* ) - # Linker will automatically link against shared library if both - # static and shared are present. Therefore, ensure we extract - # symbols from the import library if a shared library is present - # (otherwise, the dlopen module name will be incorrect). We do - # this by putting the import library name into $newdlprefiles. - # We recover the dlopen module name by 'saving' the la file - # name in a special purpose variable, and (later) extracting the - # dlname from the la file. - if test -n "$dlname"; then - func_tr_sh "$dir/$linklib" - eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" - func_append newdlprefiles " $dir/$linklib" - else - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - fi - ;; - * ) - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - func_append newdlprefiles " $dir/$dlname" - else - func_append newdlprefiles " $dir/$linklib" - fi - ;; - esac - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test lib = "$linkmode"; then - deplibs="$dir/$old_library $deplibs" - elif test prog,link = "$linkmode,$pass"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test prog = "$linkmode" && test link != "$pass"; then - func_append newlib_search_path " $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=false - if test no != "$link_all_deplibs" || test -z "$library_names" || - test no = "$build_libtool_libs"; then - linkalldeplibs=: - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - esac - # Need to link against all dependency_libs? - if $linkalldeplibs; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test prog,link = "$linkmode,$pass"; then - if test -n "$library_names" && - { { test no = "$prefer_static_libs" || - test built,yes = "$prefer_static_libs,$installed"; } || - test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then - # Make sure the rpath contains only unique directories. - case $temp_rpath: in - *"$absdir:"*) ;; - *) func_append temp_rpath "$absdir:" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if $alldeplibs && - { test pass_all = "$deplibs_check_method" || - { test yes = "$build_libtool_libs" && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - use_static_libs=$prefer_static_libs - if test built = "$use_static_libs" && test yes = "$installed"; then - use_static_libs=no - fi - if test -n "$library_names" && - { test no = "$use_static_libs" || test -z "$old_library"; }; then - case $host in - *cygwin* | *mingw* | *cegcc* | *os2*) - # No point in relinking DLLs because paths are not encoded - func_append notinst_deplibs " $lib" - need_relink=no - ;; - *) - if test no = "$installed"; then - func_append notinst_deplibs " $lib" - need_relink=yes - fi - ;; - esac - # This is a shared library - - # Warn about portability, can't link against -module's on some - # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule= - for dlpremoduletest in $dlprefiles; do - if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule=$dlpremoduletest - break - fi - done - if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then - echo - if test prog = "$linkmode"; then - $ECHO "*** Warning: Linking the executable $output against the loadable module" - else - $ECHO "*** Warning: Linking the shared library $output against the loadable module" - fi - $ECHO "*** $linklib is not portable!" - fi - if test lib = "$linkmode" && - test yes = "$hardcode_into_libs"; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - shift - realname=$1 - shift - libname=`eval "\\$ECHO \"$libname_spec\""` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname=$dlname - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw* | *cegcc* | *os2*) - func_arith $current - $age - major=$func_arith_result - versuffix=-$major - ;; - esac - eval soname=\"$soname_spec\" - else - soname=$realname - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot=$soname - func_basename "$soroot" - soname=$func_basename_result - func_stripname 'lib' '.dll' "$soname" - newlib=libimp-$func_stripname_result.a - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - func_verbose "extracting exported symbol list from '$soname'" - func_execute_cmds "$extract_expsyms_cmds" 'exit $?' - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for '$soname'" - func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test prog = "$linkmode" || test relink != "$opt_mode"; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test no = "$hardcode_direct"; then - add=$dir/$linklib - case $host in - *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; - *-*-sysv4*uw2*) add_dir=-L$dir ;; - *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir=-L$dir ;; - *-*-darwin* ) - # if the lib is a (non-dlopened) module then we cannot - # link against it, someone is ignoring the earlier warnings - if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null; then - if test "X$dlopenmodule" != "X$lib"; then - $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library"; then - echo - echo "*** And there doesn't seem to be a static archive available" - echo "*** The link will probably fail, sorry" - else - add=$dir/$old_library - fi - elif test -n "$old_library"; then - add=$dir/$old_library - fi - fi - esac - elif test no = "$hardcode_minus_L"; then - case $host in - *-*-sunos*) add_shlibpath=$dir ;; - esac - add_dir=-L$dir - add=-l$name - elif test no = "$hardcode_shlibpath_var"; then - add_shlibpath=$dir - add=-l$name - else - lib_linked=no - fi - ;; - relink) - if test yes = "$hardcode_direct" && - test no = "$hardcode_direct_absolute"; then - add=$dir/$linklib - elif test yes = "$hardcode_minus_L"; then - add_dir=-L$absdir - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add=-l$name - elif test yes = "$hardcode_shlibpath_var"; then - add_shlibpath=$dir - add=-l$name - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test yes != "$lib_linked"; then - func_fatal_configuration "unsupported hardcode properties" - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) func_append compile_shlibpath "$add_shlibpath:" ;; - esac - fi - if test prog = "$linkmode"; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test yes != "$hardcode_direct" && - test yes != "$hardcode_minus_L" && - test yes = "$hardcode_shlibpath_var"; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - fi - fi - fi - - if test prog = "$linkmode" || test relink = "$opt_mode"; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test yes = "$hardcode_direct" && - test no = "$hardcode_direct_absolute"; then - add=$libdir/$linklib - elif test yes = "$hardcode_minus_L"; then - add_dir=-L$libdir - add=-l$name - elif test yes = "$hardcode_shlibpath_var"; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - add=-l$name - elif test yes = "$hardcode_automatic"; then - if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib"; then - add=$inst_prefix_dir$libdir/$linklib - else - add=$libdir/$linklib - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir=-L$libdir - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add=-l$name - fi - - if test prog = "$linkmode"; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test prog = "$linkmode"; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test unsupported != "$hardcode_direct"; then - test -n "$old_library" && linklib=$old_library - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test yes = "$build_libtool_libs"; then - # Not a shared library - if test pass_all != "$deplibs_check_method"; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - echo - $ECHO "*** Warning: This system cannot link to static lib archive $lib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have." - if test yes = "$module"; then - echo "*** But as you try to build a module library, libtool will still create " - echo "*** a static module, that should work as long as the dlopening application" - echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using 'nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** 'nm' from GNU binutils and a full rebuild may help." - fi - if test no = "$build_old_libs"; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test lib = "$linkmode"; then - if test -n "$dependency_libs" && - { test yes != "$hardcode_into_libs" || - test yes = "$build_old_libs" || - test yes = "$link_static"; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) func_stripname '-R' '' "$libdir" - temp_xrpath=$func_stripname_result - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) func_append xrpath " $temp_xrpath";; - esac;; - *) func_append temp_deplibs " $libdir";; - esac - done - dependency_libs=$temp_deplibs - fi - - func_append newlib_search_path " $absdir" - # Link against this library - test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result";; - *) func_resolve_sysroot "$deplib" ;; - esac - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $func_resolve_sysroot_result "*) - func_append specialdeplibs " $func_resolve_sysroot_result" ;; - esac - fi - func_append tmp_libs " $func_resolve_sysroot_result" - done - - if test no != "$link_all_deplibs"; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - path= - case $deplib in - -L*) path=$deplib ;; - *.la) - func_resolve_sysroot "$deplib" - deplib=$func_resolve_sysroot_result - func_dirname "$deplib" "" "." - dir=$func_dirname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of '$dir'" - absdir=$dir - fi - ;; - esac - if $GREP "^installed=no" $deplib > /dev/null; then - case $host in - *-*-darwin*) - depdepl= - eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names"; then - for tmp in $deplibrary_names; do - depdepl=$tmp - done - if test -f "$absdir/$objdir/$depdepl"; then - depdepl=$absdir/$objdir/$depdepl - darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - if test -z "$darwin_install_name"; then - darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - fi - func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" - func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" - path= - fi - fi - ;; - *) - path=-L$absdir/$objdir - ;; - esac - else - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - test -z "$libdir" && \ - func_fatal_error "'$deplib' is not a valid libtool archive" - test "$absdir" != "$libdir" && \ - func_warning "'$deplib' seems to be moved" - - path=-L$absdir - fi - ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$path $deplibs" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - if test link = "$pass"; then - if test prog = "$linkmode"; then - compile_deplibs="$new_inherited_linker_flags $compile_deplibs" - finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" - else - compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - fi - fi - dependency_libs=$newdependency_libs - if test dlpreopen = "$pass"; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test dlopen != "$pass"; then - test conv = "$pass" || { - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) func_append lib_search_path " $dir" ;; - esac - done - newlib_search_path= - } - - if test prog,link = "$linkmode,$pass"; then - vars="compile_deplibs finalize_deplibs" - else - vars=deplibs - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) func_append tmp_libs " $deplib" ;; - esac - ;; - *) func_append tmp_libs " $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - - # Add Sun CC postdeps if required: - test CXX = "$tagname" && { - case $host_os in - linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C++ 5.9 - func_suncc_cstd_abi - - if test no != "$suncc_use_cstd_abi"; then - func_append postdeps ' -library=Cstd -library=Crun' - fi - ;; - esac - ;; - - solaris*) - func_cc_basename "$CC" - case $func_cc_basename_result in - CC* | sunCC*) - func_suncc_cstd_abi - - if test no != "$suncc_use_cstd_abi"; then - func_append postdeps ' -library=Cstd -library=Crun' - fi - ;; - esac - ;; - esac - } - - # Last step: remove runtime libs from dependency_libs - # (they stay in deplibs) - tmp_libs= - for i in $dependency_libs; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i= - ;; - esac - if test -n "$i"; then - func_append tmp_libs " $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test prog = "$linkmode"; then - dlfiles=$newdlfiles - fi - if test prog = "$linkmode" || test lib = "$linkmode"; then - dlprefiles=$newdlprefiles - fi - - case $linkmode in - oldlib) - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then - func_warning "'-dlopen' is ignored for archives" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "'-l' and '-L' are ignored for archives" ;; - esac - - test -n "$rpath" && \ - func_warning "'-rpath' is ignored for archives" - - test -n "$xrpath" && \ - func_warning "'-R' is ignored for archives" - - test -n "$vinfo" && \ - func_warning "'-version-info/-version-number' is ignored for archives" - - test -n "$release" && \ - func_warning "'-release' is ignored for archives" - - test -n "$export_symbols$export_symbols_regex" && \ - func_warning "'-export-symbols' is ignored for archives" - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs=$output - func_append objs "$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form 'libNAME.la'. - case $outputname in - lib*) - func_stripname 'lib' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - ;; - *) - test no = "$module" \ - && func_fatal_help "libtool library '$output' must begin with 'lib'" - - if test no != "$need_lib_prefix"; then - # Add the "lib" prefix for modules if required - func_stripname '' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - else - func_stripname '' '.la' "$outputname" - libname=$func_stripname_result - fi - ;; - esac - - if test -n "$objs"; then - if test pass_all != "$deplibs_check_method"; then - func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" - else - echo - $ECHO "*** Warning: Linking the shared library $output against the non-libtool" - $ECHO "*** objects $objs is not portable!" - func_append libobjs " $objs" - fi - fi - - test no = "$dlself" \ - || func_warning "'-dlopen self' is ignored for libtool libraries" - - set dummy $rpath - shift - test 1 -lt "$#" \ - && func_warning "ignoring multiple '-rpath's for a libtool library" - - install_libdir=$1 - - oldlibs= - if test -z "$rpath"; then - if test yes = "$build_libtool_libs"; then - # Building a libtool convenience library. - # Some compilers have problems with a '.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - test -n "$vinfo" && \ - func_warning "'-version-info/-version-number' is ignored for convenience libraries" - - test -n "$release" && \ - func_warning "'-release' is ignored for convenience libraries" - else - - # Parse the version information argument. - save_ifs=$IFS; IFS=: - set dummy $vinfo 0 0 0 - shift - IFS=$save_ifs - - test -n "$7" && \ - func_fatal_help "too many parameters to '-version-info'" - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major=$1 - number_minor=$2 - number_revision=$3 - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # that has an extra 1 added just for fun - # - case $version_type in - # correct linux to gnu/linux during the next big refactor - darwin|freebsd-elf|linux|osf|windows|none) - func_arith $number_major + $number_minor - current=$func_arith_result - age=$number_minor - revision=$number_revision - ;; - freebsd-aout|qnx|sunos) - current=$number_major - revision=$number_minor - age=0 - ;; - irix|nonstopux) - func_arith $number_major + $number_minor - current=$func_arith_result - age=$number_minor - revision=$number_minor - lt_irix_increment=no - ;; - *) - func_fatal_configuration "$modename: unknown library version type '$version_type'" - ;; - esac - ;; - no) - current=$1 - revision=$2 - age=$3 - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "CURRENT '$current' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" - ;; - esac - - case $revision in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "REVISION '$revision' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" - ;; - esac - - case $age in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "AGE '$age' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" - ;; - esac - - if test "$age" -gt "$current"; then - func_error "AGE '$age' is greater than the current interface number '$current'" - func_fatal_error "'$vinfo' is not valid version information" - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - func_arith $current - $age - major=.$func_arith_result - versuffix=$major.$age.$revision - # Darwin ld doesn't like 0 for these options... - func_arith $current + 1 - minor_current=$func_arith_result - xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - # On Darwin other compilers - case $CC in - nagfor*) - verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" - ;; - *) - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - esac - ;; - - freebsd-aout) - major=.$current - versuffix=.$current.$revision - ;; - - freebsd-elf) - func_arith $current - $age - major=.$func_arith_result - versuffix=$major.$age.$revision - ;; - - irix | nonstopux) - if test no = "$lt_irix_increment"; then - func_arith $current - $age - else - func_arith $current - $age + 1 - fi - major=$func_arith_result - - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring=$verstring_prefix$major.$revision - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test 0 -ne "$loop"; do - func_arith $revision - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring=$verstring_prefix$major.$iface:$verstring - done - - # Before this point, $major must not contain '.'. - major=.$major - versuffix=$major.$revision - ;; - - linux) # correct to gnu/linux during the next big refactor - func_arith $current - $age - major=.$func_arith_result - versuffix=$major.$age.$revision - ;; - - osf) - func_arith $current - $age - major=.$func_arith_result - versuffix=.$current.$age.$revision - verstring=$current.$age.$revision - - # Add in all the interfaces that we are compatible with. - loop=$age - while test 0 -ne "$loop"; do - func_arith $current - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring=$verstring:$iface.0 - done - - # Make executables depend on our current version. - func_append verstring ":$current.0" - ;; - - qnx) - major=.$current - versuffix=.$current - ;; - - sco) - major=.$current - versuffix=.$current - ;; - - sunos) - major=.$current - versuffix=.$current.$revision - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 file systems. - func_arith $current - $age - major=$func_arith_result - versuffix=-$major - ;; - - *) - func_fatal_configuration "unknown library version type '$version_type'" - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring=0.0 - ;; - esac - if test no = "$need_version"; then - versuffix= - else - versuffix=.0.0 - fi - fi - - # Remove version info from name if versioning should be avoided - if test yes,no = "$avoid_version,$need_version"; then - major= - versuffix= - verstring= - fi - - # Check to see if the archive will have undefined symbols. - if test yes = "$allow_undefined"; then - if test unsupported = "$allow_undefined_flag"; then - if test yes = "$build_old_libs"; then - func_warning "undefined symbols not allowed in $host shared libraries; building static only" - build_libtool_libs=no - else - func_fatal_error "can't build $host shared library unless -no-undefined is specified" - fi - fi - else - # Don't allow undefined symbols. - allow_undefined_flag=$no_undefined_flag - fi - - fi - - func_generate_dlsyms "$libname" "$libname" : - func_append libobjs " $symfileobj" - test " " = "$libobjs" && libobjs= - - if test relink != "$opt_mode"; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$ECHO "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext | *.gcno) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) - if test -n "$precious_files_regex"; then - if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - fi - func_append removelist " $p" - ;; - *) ;; - esac - done - test -n "$removelist" && \ - func_show_eval "${RM}r \$removelist" - fi - - # Now set the variables for building old libraries. - if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then - func_append oldlibs " $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - #for path in $notinst_path; do - # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` - # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` - # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` - #done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - func_replace_sysroot "$libdir" - func_append temp_xrpath " -R$func_replace_sysroot_result" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles=$dlfiles - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) func_append dlfiles " $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles=$dlprefiles - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) func_append dlprefiles " $lib" ;; - esac - done - - if test yes = "$build_libtool_libs"; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - func_append deplibs " System.ltframework" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test yes = "$build_libtool_need_lc"; then - func_append deplibs " -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release= - versuffix= - major= - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $opt_dry_run || $RM conftest.c - cat > conftest.c </dev/null` - $nocaseglob - else - potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` - fi - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null | - $GREP " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib=$potent_lib - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | $SED 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; - *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | - $SED -e 10q | - $EGREP "$file_magic_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib= - break 2 - fi - done - done - fi - if test -n "$a_deplib"; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib"; then - $ECHO "*** with $libname but no candidates were found. (...for file magic test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a file magic. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - for a_deplib in $deplibs; do - case $a_deplib in - -l*) - func_stripname -l '' "$a_deplib" - name=$func_stripname_result - if test yes = "$allow_libtool_libs_with_static_runtimes"; then - case " $predeps $postdeps " in - *" $a_deplib "*) - func_append newdeplibs " $a_deplib" - a_deplib= - ;; - esac - fi - if test -n "$a_deplib"; then - libname=`eval "\\$ECHO \"$libname_spec\""` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib=$potent_lib # see symlink-check above in file_magic test - if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ - $EGREP "$match_pattern_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib= - break 2 - fi - done - done - fi - if test -n "$a_deplib"; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib"; then - $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a regex pattern. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs= - tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test yes = "$allow_libtool_libs_with_static_runtimes"; then - for i in $predeps $postdeps; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` - done - fi - case $tmp_deplibs in - *[!\ \ ]*) - echo - if test none = "$deplibs_check_method"; then - echo "*** Warning: inter-library dependencies are not supported in this platform." - else - echo "*** Warning: inter-library dependencies are not known to be supported." - fi - echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - ;; - esac - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library with the System framework - newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - if test yes = "$droppeddeps"; then - if test yes = "$module"; then - echo - echo "*** Warning: libtool could not satisfy all declared inter-library" - $ECHO "*** dependencies of module $libname. Therefore, libtool will create" - echo "*** a static module, that should work as long as the dlopening" - echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using 'nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** 'nm' from GNU binutils and a full rebuild may help." - fi - if test no = "$build_old_libs"; then - oldlibs=$output_objdir/$libname.$libext - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - echo "*** The inter-library dependencies that have been dropped here will be" - echo "*** automatically added whenever a program is linked with this library" - echo "*** or is declared to -dlopen it." - - if test no = "$allow_undefined"; then - echo - echo "*** Since this library must not contain undefined symbols," - echo "*** because either the platform does not support them or" - echo "*** it was explicitly requested with -no-undefined," - echo "*** libtool will only create a static version of it." - if test no = "$build_old_libs"; then - oldlibs=$output_objdir/$libname.$libext - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - case $host in - *-*-darwin*) - newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - deplibs=$new_libs - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test yes = "$build_libtool_libs"; then - # Remove $wl instances when linking with ld. - # FIXME: should test the right _cmds variable. - case $archive_cmds in - *\$LD\ *) wl= ;; - esac - if test yes = "$hardcode_into_libs"; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath=$finalize_rpath - test relink = "$opt_mode" || rpath=$compile_rpath$rpath - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - func_replace_sysroot "$libdir" - libdir=$func_replace_sysroot_result - if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append dep_rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs - eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath=$finalize_shlibpath - test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext_cmds\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - shift - realname=$1 - shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname=$realname - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib=$output_objdir/$realname - linknames= - for link - do - func_append linknames " $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` - test "X$libobjs" = "X " && libobjs= - - delfiles= - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols=$output_objdir/$libname.uexp - func_append delfiles " $export_symbols" - fi - - orig_export_symbols= - case $host_os in - cygwin* | mingw* | cegcc*) - if test -n "$export_symbols" && test -z "$export_symbols_regex"; then - # exporting using user supplied symfile - func_dll_def_p "$export_symbols" || { - # and it's NOT already a .def file. Must figure out - # which of the given symbols are data symbols and tag - # them as such. So, trigger use of export_symbols_cmds. - # export_symbols gets reassigned inside the "prepare - # the list of exported symbols" if statement, so the - # include_expsyms logic still works. - orig_export_symbols=$export_symbols - export_symbols= - always_export_symbols=yes - } - fi - ;; - esac - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for '$libname.la'" - export_symbols=$output_objdir/$libname.exp - $opt_dry_run || $RM $export_symbols - cmds=$export_symbols_cmds - save_ifs=$IFS; IFS='~' - for cmd1 in $cmds; do - IFS=$save_ifs - # Take the normal branch if the nm_file_list_spec branch - # doesn't work or if tool conversion is not needed. - case $nm_file_list_spec~$to_tool_file_cmd in - *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) - try_normal_branch=yes - eval cmd=\"$cmd1\" - func_len " $cmd" - len=$func_len_result - ;; - *) - try_normal_branch=no - ;; - esac - if test yes = "$try_normal_branch" \ - && { test "$len" -lt "$max_cmd_len" \ - || test "$max_cmd_len" -le -1; } - then - func_show_eval "$cmd" 'exit $?' - skipped_export=false - elif test -n "$nm_file_list_spec"; then - func_basename "$output" - output_la=$func_basename_result - save_libobjs=$libobjs - save_output=$output - output=$output_objdir/$output_la.nm - func_to_tool_file "$output" - libobjs=$nm_file_list_spec$func_to_tool_file_result - func_append delfiles " $output" - func_verbose "creating $NM input file list: $output" - for obj in $save_libobjs; do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > "$output" - eval cmd=\"$cmd1\" - func_show_eval "$cmd" 'exit $?' - output=$save_output - libobjs=$save_libobjs - skipped_export=false - else - # The command line is too long to execute in one step. - func_verbose "using reloadable object file for export list..." - skipped_export=: - # Break out early, otherwise skipped_export may be - # set to false by a later but shorter cmd. - break - fi - done - IFS=$save_ifs - if test -n "$export_symbols_regex" && test : != "$skipped_export"; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols=$export_symbols - test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test : != "$skipped_export" && test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for '$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands, which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - func_append tmp_deplibs " $test_deplib" - ;; - esac - done - deplibs=$tmp_deplibs - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec" && - test yes = "$compiler_needs_object" && - test -z "$libobjs"; then - # extract the archives, so we have objects to list. - # TODO: could optimize this to just extract one archive. - whole_archive_flag_spec= - fi - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - else - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - fi - - if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - func_append linker_flags " $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test relink = "$opt_mode"; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test yes = "$module" && test -n "$module_cmds"; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test : != "$skipped_export" && - func_len " $test_cmds" && - len=$func_len_result && - test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise - # or, if using GNU ld and skipped_export is not :, use a linker - # script. - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - func_basename "$output" - output_la=$func_basename_result - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - last_robj= - k=1 - - if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then - output=$output_objdir/$output_la.lnkscript - func_verbose "creating GNU ld script: $output" - echo 'INPUT (' > $output - for obj in $save_libobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - echo ')' >> $output - func_append delfiles " $output" - func_to_tool_file "$output" - output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then - output=$output_objdir/$output_la.lnk - func_verbose "creating linker input file list: $output" - : > $output - set x $save_libobjs - shift - firstobj= - if test yes = "$compiler_needs_object"; then - firstobj="$1 " - shift - fi - for obj - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - func_append delfiles " $output" - func_to_tool_file "$output" - output=$firstobj\"$file_list_spec$func_to_tool_file_result\" - else - if test -n "$save_libobjs"; then - func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-$k.$objext - eval test_cmds=\"$reload_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - if test -z "$objlist" || - test "$len" -lt "$max_cmd_len"; then - func_append objlist " $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test 1 -eq "$k"; then - # The first file doesn't have a previous command to add. - reload_objs=$objlist - eval concat_cmds=\"$reload_cmds\" - else - # All subsequent reloadable object files will link in - # the last one created. - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" - fi - last_robj=$output_objdir/$output_la-$k.$objext - func_arith $k + 1 - k=$func_arith_result - output=$output_objdir/$output_la-$k.$objext - objlist=" $obj" - func_len " $last_robj" - func_arith $len0 + $func_len_result - len=$func_arith_result - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds$reload_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" - fi - func_append delfiles " $output" - - else - output= - fi - - ${skipped_export-false} && { - func_verbose "generating symbol list for '$libname.la'" - export_symbols=$output_objdir/$libname.exp - $opt_dry_run || $RM $export_symbols - libobjs=$output - # Append the command to create the export file. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" - fi - } - - test -n "$save_libobjs" && - func_verbose "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs=$IFS; IFS='~' - for cmd in $concat_cmds; do - IFS=$save_ifs - $opt_quiet || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS=$save_ifs - - if test -n "$export_symbols_regex" && ${skipped_export-false}; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - - ${skipped_export-false} && { - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols=$export_symbols - test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for '$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands, which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - } - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test yes = "$module" && test -n "$module_cmds"; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - fi - - if test -n "$delfiles"; then - # Append the command to remove temporary files to $cmds. - eval cmds=\"\$cmds~\$RM $delfiles\" - fi - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - - save_ifs=$IFS; IFS='~' - for cmd in $cmds; do - IFS=$sp$nl - eval cmd=\"$cmd\" - IFS=$save_ifs - $opt_quiet || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS=$save_ifs - - # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? - - if test -n "$convenience"; then - if test -z "$whole_archive_flag_spec"; then - func_show_eval '${RM}r "$gentop"' - fi - fi - - exit $EXIT_SUCCESS - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test yes = "$module" || test yes = "$export_dynamic"; then - # On all known operating systems, these are identical. - dlname=$soname - fi - fi - ;; - - obj) - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then - func_warning "'-dlopen' is ignored for objects" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "'-l' and '-L' are ignored for objects" ;; - esac - - test -n "$rpath" && \ - func_warning "'-rpath' is ignored for objects" - - test -n "$xrpath" && \ - func_warning "'-R' is ignored for objects" - - test -n "$vinfo" && \ - func_warning "'-version-info' is ignored for objects" - - test -n "$release" && \ - func_warning "'-release' is ignored for objects" - - case $output in - *.lo) - test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object '$output' from non-libtool objects" - - libobj=$output - func_lo2o "$libobj" - obj=$func_lo2o_result - ;; - *) - libobj= - obj=$output - ;; - esac - - # Delete the old objects. - $opt_dry_run || $RM $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # if reload_cmds runs $LD directly, get rid of -Wl from - # whole_archive_flag_spec and hope we can get by with turning comma - # into space. - case $reload_cmds in - *\$LD[\ \$]*) wl= ;; - esac - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` - reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags - else - gentop=$output_objdir/${obj}x - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - reload_conv_objs="$reload_objs $func_extract_archives_result" - fi - fi - - # If we're not building shared, we need to use non_pic_objs - test yes = "$build_libtool_libs" || libobjs=$non_pic_objects - - # Create the old-style object. - reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs - - output=$obj - func_execute_cmds "$reload_cmds" 'exit $?' - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - fi - - test yes = "$build_libtool_libs" || { - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? - exit $EXIT_SUCCESS - } - - if test -n "$pic_flag" || test default != "$pic_mode"; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output=$libobj - func_execute_cmds "$reload_cmds" 'exit $?' - fi - - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - ;; - - prog) - case $host in - *cygwin*) func_stripname '' '.exe' "$output" - output=$func_stripname_result.exe;; - esac - test -n "$vinfo" && \ - func_warning "'-version-info' is ignored for programs" - - test -n "$release" && \ - func_warning "'-release' is ignored for programs" - - $preload \ - && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ - && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - case $host in - *-*-darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - # But is supposedly fixed on 10.4 or later (yay!). - if test CXX = "$tagname"; then - case ${MACOSX_DEPLOYMENT_TARGET-10.0} in - 10.[0123]) - func_append compile_command " $wl-bind_at_load" - func_append finalize_command " $wl-bind_at_load" - ;; - esac - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $compile_deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $compile_deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - compile_deplibs=$new_libs - - - func_append compile_command " $compile_deplibs" - func_append finalize_command " $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$libdir:"*) ;; - ::) dllsearchpath=$libdir;; - *) func_append dllsearchpath ":$libdir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath=$rpath - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) func_append finalize_perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath=$rpath - - if test -n "$libobjs" && test yes = "$build_old_libs"; then - # Transform all the library objects into standard objects. - compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - fi - - func_generate_dlsyms "$outputname" "@PROGRAM@" false - - # template prelinking step - if test -n "$prelink_cmds"; then - func_execute_cmds "$prelink_cmds" 'exit $?' - fi - - wrappers_required=: - case $host in - *cegcc* | *mingw32ce*) - # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=false - ;; - *cygwin* | *mingw* ) - test yes = "$build_libtool_libs" || wrappers_required=false - ;; - *) - if test no = "$need_relink" || test yes != "$build_libtool_libs"; then - wrappers_required=false - fi - ;; - esac - $wrappers_required || { - # Replace the output file specification. - compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command=$compile_command$compile_rpath - - # We have no uninstalled library dependencies, so finalize right now. - exit_status=0 - func_show_eval "$link_command" 'exit_status=$?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Delete the generated files. - if test -f "$output_objdir/${outputname}S.$objext"; then - func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' - fi - - exit $exit_status - } - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - func_append rpath "$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test yes = "$no_install"; then - # We don't need to create a wrapper script. - link_command=$compile_var$compile_command$compile_rpath - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $opt_dry_run || $RM $output - # Link the executable and exit - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - exit $EXIT_SUCCESS - fi - - case $hardcode_action,$fast_install in - relink,*) - # Fast installation is not supported - link_command=$compile_var$compile_command$compile_rpath - relink_command=$finalize_var$finalize_command$finalize_rpath - - func_warning "this platform does not like uninstalled shared libraries" - func_warning "'$output' will be relinked during installation" - ;; - *,yes) - link_command=$finalize_var$compile_command$finalize_rpath - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - ;; - *,no) - link_command=$compile_var$compile_command$compile_rpath - relink_command=$finalize_var$finalize_command$finalize_rpath - ;; - *,needless) - link_command=$finalize_var$compile_command$finalize_rpath - relink_command= - ;; - esac - - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname - - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output_objdir/$outputname" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Now create the wrapper script. - func_verbose "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - fi - - # Only actually do things if not in dry run mode. - $opt_dry_run || { - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) func_stripname '' '.exe' "$output" - output=$func_stripname_result ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - func_stripname '' '.exe' "$outputname" - outputname=$func_stripname_result ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - func_dirname_and_basename "$output" "" "." - output_name=$func_basename_result - output_path=$func_dirname_result - cwrappersource=$output_path/$objdir/lt-$output_name.c - cwrapper=$output_path/$output_name.exe - $RM $cwrappersource $cwrapper - trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 - - func_emit_cwrapperexe_src > $cwrappersource - - # The wrapper executable is built using the $host compiler, - # because it contains $host paths and files. If cross- - # compiling, it, like the target executable, must be - # executed on the $host or under an emulation environment. - $opt_dry_run || { - $LTCC $LTCFLAGS -o $cwrapper $cwrappersource - $STRIP $cwrapper - } - - # Now, create the wrapper script for func_source use: - func_ltwrapper_scriptname $cwrapper - $RM $func_ltwrapper_scriptname_result - trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 - $opt_dry_run || { - # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host"; then - $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result - else - func_emit_wrapper no > $func_ltwrapper_scriptname_result - fi - } - ;; - * ) - $RM $output - trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 - - func_emit_wrapper no > $output - chmod +x $output - ;; - esac - } - exit $EXIT_SUCCESS - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - case $build_libtool_libs in - convenience) - oldobjs="$libobjs_save $symfileobj" - addlibs=$convenience - build_libtool_libs=no - ;; - module) - oldobjs=$libobjs_save - addlibs=$old_convenience - build_libtool_libs=no - ;; - *) - oldobjs="$old_deplibs $non_pic_objects" - $preload && test -f "$symfileobj" \ - && func_append oldobjs " $symfileobj" - addlibs=$old_convenience - ;; - esac - - if test -n "$addlibs"; then - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - - func_extract_archives $gentop $addlibs - func_append oldobjs " $func_extract_archives_result" - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then - cmds=$old_archive_from_new_cmds - else - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append oldobjs " $func_extract_archives_result" - fi - - # POSIX demands no paths to be encoded in archives. We have - # to avoid creating archives with duplicate basenames if we - # might have to extract them afterwards, e.g., when creating a - # static archive out of a convenience library, or when linking - # the entirety of a libtool archive into another (currently - # not supported by libtool). - if (for obj in $oldobjs - do - func_basename "$obj" - $ECHO "$func_basename_result" - done | sort | sort -uc >/dev/null 2>&1); then - : - else - echo "copying selected object files to avoid basename conflicts..." - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - func_mkdir_p "$gentop" - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs - do - func_basename "$obj" - objbase=$func_basename_result - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[\ /]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - func_arith $counter + 1 - counter=$func_arith_result - case " $oldobjs " in - *[\ /]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - func_append oldobjs " $gentop/$newobj" - ;; - *) func_append oldobjs " $obj" ;; - esac - done - fi - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - eval cmds=\"$old_archive_cmds\" - - func_len " $cmds" - len=$func_len_result - if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - elif test -n "$archiver_list_spec"; then - func_verbose "using command file archive linking..." - for obj in $oldobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > $output_objdir/$libname.libcmd - func_to_tool_file "$output_objdir/$libname.libcmd" - oldobjs=" $archiver_list_spec$func_to_tool_file_result" - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - func_verbose "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - oldobjs= - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - eval test_cmds=\"$old_archive_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - for obj in $save_oldobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - func_append objlist " $obj" - if test "$len" -lt "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj"; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" - objlist= - len=$len0 - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test -z "$oldobjs"; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - func_execute_cmds "$cmds" 'exit $?' - done - - test -n "$generated" && \ - func_show_eval "${RM}r$generated" - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test yes = "$build_old_libs" && old_library=$libname.$libext - func_verbose "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test yes = "$hardcode_automatic"; then - relink_command= - fi - - # Only create the output if not a dry run. - $opt_dry_run || { - for installed in no yes; do - if test yes = "$installed"; then - if test -z "$install_libdir"; then - break - fi - output=$output_objdir/${outputname}i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - func_basename "$deplib" - name=$func_basename_result - func_resolve_sysroot "$deplib" - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` - test -z "$libdir" && \ - func_fatal_error "'$deplib' is not a valid libtool archive" - func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" - ;; - -L*) - func_stripname -L '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -L$func_replace_sysroot_result" - ;; - -R*) - func_stripname -R '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -R$func_replace_sysroot_result" - ;; - *) func_append newdependency_libs " $deplib" ;; - esac - done - dependency_libs=$newdependency_libs - newdlfiles= - - for lib in $dlfiles; do - case $lib in - *.la) - func_basename "$lib" - name=$func_basename_result - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "'$lib' is not a valid libtool archive" - func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" - ;; - *) func_append newdlfiles " $lib" ;; - esac - done - dlfiles=$newdlfiles - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - *.la) - # Only pass preopened files to the pseudo-archive (for - # eventual linking with the app. that links it) if we - # didn't already link the preopened objects directly into - # the library: - func_basename "$lib" - name=$func_basename_result - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "'$lib' is not a valid libtool archive" - func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" - ;; - esac - done - dlprefiles=$newdlprefiles - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlfiles " $abs" - done - dlfiles=$newdlfiles - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlprefiles " $abs" - done - dlprefiles=$newdlprefiles - fi - $RM $output - # place dlname in correct position for cygwin - # In fact, it would be nice if we could use this code for all target - # systems that can't hard-code library paths into their executables - # and that have no shared library path variable independent of PATH, - # but it turns out we can't easily determine that from inspecting - # libtool variables, so we have to hard-code the OSs to which it - # applies here; at the moment, that means platforms that use the PE - # object format with DLL files. See the long comment at the top of - # tests/bindir.at for full details. - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) - # If a -bindir argument was supplied, place the dll there. - if test -n "$bindir"; then - func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result/$dlname - else - # Otherwise fall back on heuristic. - tdlname=../bin/$dlname - fi - ;; - esac - $ECHO > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE) $VERSION -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Linker flags that cannot go in dependency_libs. -inherited_linker_flags='$new_inherited_linker_flags' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Names of additional weak libraries provided by this library -weak_library_names='$weak_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test no,yes = "$installed,$need_relink"; then - $ECHO >> $output "\ -relink_command=\"$relink_command\"" - fi - done - } - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' - ;; - esac - exit $EXIT_SUCCESS -} - -if test link = "$opt_mode" || test relink = "$opt_mode"; then - func_mode_link ${1+"$@"} -fi - - -# func_mode_uninstall arg... -func_mode_uninstall () -{ - $debug_cmd - - RM=$nonopt - files= - rmforce=false - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic=$magic - - for arg - do - case $arg in - -f) func_append RM " $arg"; rmforce=: ;; - -*) func_append RM " $arg" ;; - *) func_append files " $arg" ;; - esac - done - - test -z "$RM" && \ - func_fatal_help "you must specify an RM program" - - rmdirs= - - for file in $files; do - func_dirname "$file" "" "." - dir=$func_dirname_result - if test . = "$dir"; then - odir=$objdir - else - odir=$dir/$objdir - fi - func_basename "$file" - name=$func_basename_result - test uninstall = "$opt_mode" && odir=$dir - - # Remember odir for removal later, being careful to avoid duplicates - if test clean = "$opt_mode"; then - case " $rmdirs " in - *" $odir "*) ;; - *) func_append rmdirs " $odir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if { test -L "$file"; } >/dev/null 2>&1 || - { test -h "$file"; } >/dev/null 2>&1 || - test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif $rmforce; then - continue - fi - - rmfiles=$file - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if func_lalib_p "$file"; then - func_source $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - func_append rmfiles " $odir/$n" - done - test -n "$old_library" && func_append rmfiles " $odir/$old_library" - - case $opt_mode in - clean) - case " $library_names " in - *" $dlname "*) ;; - *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; - esac - test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" - ;; - uninstall) - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' - fi - # FIXME: should reinstall the best remaining shared library. - ;; - esac - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if func_lalib_p "$file"; then - - # Read the .lo file - func_source $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" && test none != "$pic_object"; then - func_append rmfiles " $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && test none != "$non_pic_object"; then - func_append rmfiles " $dir/$non_pic_object" - fi - fi - ;; - - *) - if test clean = "$opt_mode"; then - noexename=$name - case $file in - *.exe) - func_stripname '' '.exe' "$file" - file=$func_stripname_result - func_stripname '' '.exe' "$name" - noexename=$func_stripname_result - # $file with .exe has already been added to rmfiles, - # add $file without .exe - func_append rmfiles " $file" - ;; - esac - # Do a test to see if this is a libtool program. - if func_ltwrapper_p "$file"; then - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - relink_command= - func_source $func_ltwrapper_scriptname_result - func_append rmfiles " $func_ltwrapper_scriptname_result" - else - relink_command= - func_source $dir/$noexename - fi - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.$objext" - if test yes = "$fast_install" && test -n "$relink_command"; then - func_append rmfiles " $odir/lt-$name" - fi - if test "X$noexename" != "X$name"; then - func_append rmfiles " $odir/lt-$noexename.c" - fi - fi - fi - ;; - esac - func_show_eval "$RM $rmfiles" 'exit_status=1' - done - - # Try to remove the $objdir's in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - func_show_eval "rmdir $dir >/dev/null 2>&1" - fi - done - - exit $exit_status -} - -if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then - func_mode_uninstall ${1+"$@"} -fi - -test -z "$opt_mode" && { - help=$generic_help - func_fatal_help "you must specify a MODE" -} - -test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode '$opt_mode'" - -if test -n "$exec_cmd"; then - eval exec "$exec_cmd" - exit $EXIT_FAILURE -fi - -exit $exit_status - - -# The TAGs below are defined such that we never get into a situation -# where we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -build_libtool_libs=no -build_old_libs=yes -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/ext/libpqxx-7.7.3/config/m4/Makefile.am b/ext/libpqxx-7.7.3/config/m4/Makefile.am deleted file mode 100644 index c5dd1572f..000000000 --- a/ext/libpqxx-7.7.3/config/m4/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES=Makefile.in config.guess config.sub install-sh \ - ltmain.sh missing mkinstalldirs - diff --git a/ext/libpqxx-7.7.3/config/m4/libtool.m4 b/ext/libpqxx-7.7.3/config/m4/libtool.m4 deleted file mode 100644 index c4c02946d..000000000 --- a/ext/libpqxx-7.7.3/config/m4/libtool.m4 +++ /dev/null @@ -1,8394 +0,0 @@ -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -# -# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -m4_define([_LT_COPYING], [dnl -# Copyright (C) 2014 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program or library that is built -# using GNU Libtool, you may include this file under the same -# distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -]) - -# serial 58 LT_INIT - - -# LT_PREREQ(VERSION) -# ------------------ -# Complain and exit if this libtool version is less that VERSION. -m4_defun([LT_PREREQ], -[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, - [m4_default([$3], - [m4_fatal([Libtool version $1 or higher is required], - 63)])], - [$2])]) - - -# _LT_CHECK_BUILDDIR -# ------------------ -# Complain if the absolute build directory name contains unusual characters -m4_defun([_LT_CHECK_BUILDDIR], -[case `pwd` in - *\ * | *\ *) - AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; -esac -]) - - -# LT_INIT([OPTIONS]) -# ------------------ -AC_DEFUN([LT_INIT], -[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK -AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl -AC_BEFORE([$0], [LT_LANG])dnl -AC_BEFORE([$0], [LT_OUTPUT])dnl -AC_BEFORE([$0], [LTDL_INIT])dnl -m4_require([_LT_CHECK_BUILDDIR])dnl - -dnl Autoconf doesn't catch unexpanded LT_ macros by default: -m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl -m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl -dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 -dnl unless we require an AC_DEFUNed macro: -AC_REQUIRE([LTOPTIONS_VERSION])dnl -AC_REQUIRE([LTSUGAR_VERSION])dnl -AC_REQUIRE([LTVERSION_VERSION])dnl -AC_REQUIRE([LTOBSOLETE_VERSION])dnl -m4_require([_LT_PROG_LTMAIN])dnl - -_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) - -dnl Parse OPTIONS -_LT_SET_OPTIONS([$0], [$1]) - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS=$ltmain - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -_LT_SETUP - -# Only expand once: -m4_define([LT_INIT]) -])# LT_INIT - -# Old names: -AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) -AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PROG_LIBTOOL], []) -dnl AC_DEFUN([AM_PROG_LIBTOOL], []) - - -# _LT_PREPARE_CC_BASENAME -# ----------------------- -m4_defun([_LT_PREPARE_CC_BASENAME], [ -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in @S|@*""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} -])# _LT_PREPARE_CC_BASENAME - - -# _LT_CC_BASENAME(CC) -# ------------------- -# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, -# but that macro is also expanded into generated libtool script, which -# arranges for $SED and $ECHO to be set by different means. -m4_defun([_LT_CC_BASENAME], -[m4_require([_LT_PREPARE_CC_BASENAME])dnl -AC_REQUIRE([_LT_DECL_SED])dnl -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl -func_cc_basename $1 -cc_basename=$func_cc_basename_result -]) - - -# _LT_FILEUTILS_DEFAULTS -# ---------------------- -# It is okay to use these file commands and assume they have been set -# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. -m4_defun([_LT_FILEUTILS_DEFAULTS], -[: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} -])# _LT_FILEUTILS_DEFAULTS - - -# _LT_SETUP -# --------- -m4_defun([_LT_SETUP], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl - -_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl -dnl -_LT_DECL([], [host_alias], [0], [The host system])dnl -_LT_DECL([], [host], [0])dnl -_LT_DECL([], [host_os], [0])dnl -dnl -_LT_DECL([], [build_alias], [0], [The build system])dnl -_LT_DECL([], [build], [0])dnl -_LT_DECL([], [build_os], [0])dnl -dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -dnl -AC_REQUIRE([AC_PROG_LN_S])dnl -test -z "$LN_S" && LN_S="ln -s" -_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl -dnl -AC_REQUIRE([LT_CMD_MAX_LEN])dnl -_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl -_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl -dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_CHECK_SHELL_FEATURES])dnl -m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl -m4_require([_LT_CMD_RELOAD])dnl -m4_require([_LT_CHECK_MAGIC_METHOD])dnl -m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl -m4_require([_LT_CMD_OLD_ARCHIVE])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -m4_require([_LT_WITH_SYSROOT])dnl -m4_require([_LT_CMD_TRUNCATE])dnl - -_LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options that allow our -# commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST -fi -]) -if test -n "${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST -fi - -_LT_CHECK_OBJDIR - -m4_require([_LT_TAG_COMPILER])dnl - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test set != "${COLLECT_NAMES+set}"; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a '.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld=$lt_cv_prog_gnu_ld - -old_CC=$CC -old_CFLAGS=$CFLAGS - -# Set sane defaults for various variables -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$LD" && LD=ld -test -z "$ac_objext" && ac_objext=o - -_LT_CC_BASENAME([$compiler]) - -# Only perform the check for file, if the check method requires it -test -z "$MAGIC_CMD" && MAGIC_CMD=file -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - _LT_PATH_MAGIC - fi - ;; -esac - -# Use C for the default configuration in the libtool script -LT_SUPPORTED_TAG([CC]) -_LT_LANG_C_CONFIG -_LT_LANG_DEFAULT_CONFIG -_LT_CONFIG_COMMANDS -])# _LT_SETUP - - -# _LT_PREPARE_SED_QUOTE_VARS -# -------------------------- -# Define a few sed substitution that help us do robust quoting. -m4_defun([_LT_PREPARE_SED_QUOTE_VARS], -[# Backslashify metacharacters that are still active within -# double-quoted strings. -sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([["`\\]]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' -]) - -# _LT_PROG_LTMAIN -# --------------- -# Note that this code is called both from 'configure', and 'config.status' -# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# 'config.status' has no value for ac_aux_dir unless we are using Automake, -# so we pass a copy along to make sure it has a sensible value anyway. -m4_defun([_LT_PROG_LTMAIN], -[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl -_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain=$ac_aux_dir/ltmain.sh -])# _LT_PROG_LTMAIN - - -## ------------------------------------- ## -## Accumulate code for creating libtool. ## -## ------------------------------------- ## - -# So that we can recreate a full libtool script including additional -# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the 'libtool' -# label. - - -# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) -# ---------------------------------------- -# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL_INIT], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_INIT], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_INIT]) - - -# _LT_CONFIG_LIBTOOL([COMMANDS]) -# ------------------------------ -# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) - - -# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) -# ----------------------------------------------------- -m4_defun([_LT_CONFIG_SAVE_COMMANDS], -[_LT_CONFIG_LIBTOOL([$1]) -_LT_CONFIG_LIBTOOL_INIT([$2]) -]) - - -# _LT_FORMAT_COMMENT([COMMENT]) -# ----------------------------- -# Add leading comment marks to the start of each line, and a trailing -# full-stop to the whole comment if one is not present already. -m4_define([_LT_FORMAT_COMMENT], -[m4_ifval([$1], [ -m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], - [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) -)]) - - - -## ------------------------ ## -## FIXME: Eliminate VARNAME ## -## ------------------------ ## - - -# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) -# ------------------------------------------------------------------- -# CONFIGNAME is the name given to the value in the libtool script. -# VARNAME is the (base) name used in the configure script. -# VALUE may be 0, 1 or 2 for a computed quote escaped value based on -# VARNAME. Any other value will be used directly. -m4_define([_LT_DECL], -[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], - [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], - [m4_ifval([$1], [$1], [$2])]) - lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) - m4_ifval([$4], - [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) - lt_dict_add_subkey([lt_decl_dict], [$2], - [tagged?], [m4_ifval([$5], [yes], [no])])]) -]) - - -# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) -# -------------------------------------------------------- -m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) - - -# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_tag_varnames], -[_lt_decl_filter([tagged?], [yes], $@)]) - - -# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) -# --------------------------------------------------------- -m4_define([_lt_decl_filter], -[m4_case([$#], - [0], [m4_fatal([$0: too few arguments: $#])], - [1], [m4_fatal([$0: too few arguments: $#: $1])], - [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], - [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], - [lt_dict_filter([lt_decl_dict], $@)])[]dnl -]) - - -# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) -# -------------------------------------------------- -m4_define([lt_decl_quote_varnames], -[_lt_decl_filter([value], [1], $@)]) - - -# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_dquote_varnames], -[_lt_decl_filter([value], [2], $@)]) - - -# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_varnames_tagged], -[m4_assert([$# <= 2])dnl -_$0(m4_quote(m4_default([$1], [[, ]])), - m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), - m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) -m4_define([_lt_decl_varnames_tagged], -[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) - - -# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_all_varnames], -[_$0(m4_quote(m4_default([$1], [[, ]])), - m4_if([$2], [], - m4_quote(lt_decl_varnames), - m4_quote(m4_shift($@))))[]dnl -]) -m4_define([_lt_decl_all_varnames], -[lt_join($@, lt_decl_varnames_tagged([$1], - lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl -]) - - -# _LT_CONFIG_STATUS_DECLARE([VARNAME]) -# ------------------------------------ -# Quote a variable value, and forward it to 'config.status' so that its -# declaration there will have the same value as in 'configure'. VARNAME -# must have a single quote delimited value for this to work. -m4_define([_LT_CONFIG_STATUS_DECLARE], -[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) - - -# _LT_CONFIG_STATUS_DECLARATIONS -# ------------------------------ -# We delimit libtool config variables with single quotes, so when -# we write them to config.status, we have to be sure to quote all -# embedded single quotes properly. In configure, this macro expands -# each variable declared with _LT_DECL (and _LT_TAGDECL) into: -# -# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' -m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], -[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), - [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAGS -# ---------------- -# Output comment and list of tags supported by the script -m4_defun([_LT_LIBTOOL_TAGS], -[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags='_LT_TAGS'dnl -]) - - -# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) -# ----------------------------------- -# Extract the dictionary values for VARNAME (optionally with TAG) and -# expand to a commented shell variable setting: -# -# # Some comment about what VAR is for. -# visible_name=$lt_internal_name -m4_define([_LT_LIBTOOL_DECLARE], -[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], - [description])))[]dnl -m4_pushdef([_libtool_name], - m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl -m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), - [0], [_libtool_name=[$]$1], - [1], [_libtool_name=$lt_[]$1], - [2], [_libtool_name=$lt_[]$1], - [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl -m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl -]) - - -# _LT_LIBTOOL_CONFIG_VARS -# ----------------------- -# Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' -# script. Tagged libtool config variables (even for the LIBTOOL CONFIG -# section) are produced by _LT_LIBTOOL_TAG_VARS. -m4_defun([_LT_LIBTOOL_CONFIG_VARS], -[m4_foreach([_lt_var], - m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAG_VARS(TAG) -# ------------------------- -m4_define([_LT_LIBTOOL_TAG_VARS], -[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) - - -# _LT_TAGVAR(VARNAME, [TAGNAME]) -# ------------------------------ -m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) - - -# _LT_CONFIG_COMMANDS -# ------------------- -# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of -# variables for single and double quote escaping we saved from calls -# to _LT_DECL, we can put quote escaped variables declarations -# into 'config.status', and then the shell code to quote escape them in -# for loops in 'config.status'. Finally, any additional code accumulated -# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. -m4_defun([_LT_CONFIG_COMMANDS], -[AC_PROVIDE_IFELSE([LT_OUTPUT], - dnl If the libtool generation code has been placed in $CONFIG_LT, - dnl instead of duplicating it all over again into config.status, - dnl then we will have config.status run $CONFIG_LT later, so it - dnl needs to know what name is stored there: - [AC_CONFIG_COMMANDS([libtool], - [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], - dnl If the libtool generation code is destined for config.status, - dnl expand the accumulated commands and init code now: - [AC_CONFIG_COMMANDS([libtool], - [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) -])#_LT_CONFIG_COMMANDS - - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], -[ - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='$sed_quote_subst' -double_quote_subst='$double_quote_subst' -delay_variable_subst='$delay_variable_subst' -_LT_CONFIG_STATUS_DECLARATIONS -LTCC='$LTCC' -LTCFLAGS='$LTCFLAGS' -compiler='$compiler_DEFAULT' - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$[]1 -_LTECHO_EOF' -} - -# Quote evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_quote_varnames); do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_dquote_varnames); do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -_LT_OUTPUT_LIBTOOL_INIT -]) - -# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) -# ------------------------------------ -# Generate a child script FILE with all initialization necessary to -# reuse the environment learned by the parent script, and make the -# file executable. If COMMENT is supplied, it is inserted after the -# '#!' sequence but before initialization text begins. After this -# macro, additional text can be appended to FILE to form the body of -# the child script. The macro ends with non-zero status if the -# file could not be fully written (such as if the disk is full). -m4_ifdef([AS_INIT_GENERATED], -[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], -[m4_defun([_LT_GENERATED_FILE_INIT], -[m4_require([AS_PREPARE])]dnl -[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl -[lt_write_fail=0 -cat >$1 <<_ASEOF || lt_write_fail=1 -#! $SHELL -# Generated by $as_me. -$2 -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$1 <<\_ASEOF || lt_write_fail=1 -AS_SHELL_SANITIZE -_AS_PREPARE -exec AS_MESSAGE_FD>&1 -_ASEOF -test 0 = "$lt_write_fail" && chmod +x $1[]dnl -m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT - -# LT_OUTPUT -# --------- -# This macro allows early generation of the libtool script (before -# AC_OUTPUT is called), incase it is used in configure for compilation -# tests. -AC_DEFUN([LT_OUTPUT], -[: ${CONFIG_LT=./config.lt} -AC_MSG_NOTICE([creating $CONFIG_LT]) -_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], -[# Run this file to recreate a libtool stub with the current configuration.]) - -cat >>"$CONFIG_LT" <<\_LTEOF -lt_cl_silent=false -exec AS_MESSAGE_LOG_FD>>config.log -{ - echo - AS_BOX([Running $as_me.]) -} >&AS_MESSAGE_LOG_FD - -lt_cl_help="\ -'$as_me' creates a local libtool stub from the current configuration, -for use in further configure time tests before the real libtool is -generated. - -Usage: $[0] [[OPTIONS]] - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - -Report bugs to ." - -lt_cl_version="\ -m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl -m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) -configured by $[0], generated by m4_PACKAGE_STRING. - -Copyright (C) 2011 Free Software Foundation, Inc. -This config.lt script is free software; the Free Software Foundation -gives unlimited permision to copy, distribute and modify it." - -while test 0 != $[#] -do - case $[1] in - --version | --v* | -V ) - echo "$lt_cl_version"; exit 0 ;; - --help | --h* | -h ) - echo "$lt_cl_help"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --quiet | --q* | --silent | --s* | -q ) - lt_cl_silent=: ;; - - -*) AC_MSG_ERROR([unrecognized option: $[1] -Try '$[0] --help' for more information.]) ;; - - *) AC_MSG_ERROR([unrecognized argument: $[1] -Try '$[0] --help' for more information.]) ;; - esac - shift -done - -if $lt_cl_silent; then - exec AS_MESSAGE_FD>/dev/null -fi -_LTEOF - -cat >>"$CONFIG_LT" <<_LTEOF -_LT_OUTPUT_LIBTOOL_COMMANDS_INIT -_LTEOF - -cat >>"$CONFIG_LT" <<\_LTEOF -AC_MSG_NOTICE([creating $ofile]) -_LT_OUTPUT_LIBTOOL_COMMANDS -AS_EXIT(0) -_LTEOF -chmod +x "$CONFIG_LT" - -# configure is writing to config.log, but config.lt does its own redirection, -# appending to config.log, which fails on DOS, as config.log is still kept -# open by configure. Here we exec the FD to /dev/null, effectively closing -# config.log, so it can be properly (re)opened and appended to by config.lt. -lt_cl_success=: -test yes = "$silent" && - lt_config_lt_args="$lt_config_lt_args --quiet" -exec AS_MESSAGE_LOG_FD>/dev/null -$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false -exec AS_MESSAGE_LOG_FD>>config.log -$lt_cl_success || AS_EXIT(1) -])# LT_OUTPUT - - -# _LT_CONFIG(TAG) -# --------------- -# If TAG is the built-in tag, create an initial libtool script with a -# default configuration from the untagged config vars. Otherwise add code -# to config.status for appending the configuration named by TAG from the -# matching tagged config vars. -m4_defun([_LT_CONFIG], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_CONFIG_SAVE_COMMANDS([ - m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl - m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options that allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST - fi - - cfgfile=${ofile}T - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL -# Generated automatically by $as_me ($PACKAGE) $VERSION -# NOTE: Changes made to this file will be lost: look at ltmain.sh. - -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit, 1996 - -_LT_COPYING -_LT_LIBTOOL_TAGS - -# Configured defaults for sys_lib_dlsearch_path munging. -: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} - -# ### BEGIN LIBTOOL CONFIG -_LT_LIBTOOL_CONFIG_VARS -_LT_LIBTOOL_TAG_VARS -# ### END LIBTOOL CONFIG - -_LT_EOF - - cat <<'_LT_EOF' >> "$cfgfile" - -# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE - -_LT_PREPARE_MUNGE_PATH_LIST -_LT_PREPARE_CC_BASENAME - -# ### END FUNCTIONS SHARED WITH CONFIGURE - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test set != "${COLLECT_NAMES+set}"; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - _LT_PROG_LTMAIN - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" -], -[cat <<_LT_EOF >> "$ofile" - -dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded -dnl in a comment (ie after a #). -# ### BEGIN LIBTOOL TAG CONFIG: $1 -_LT_LIBTOOL_TAG_VARS(_LT_TAG) -# ### END LIBTOOL TAG CONFIG: $1 -_LT_EOF -])dnl /m4_if -], -[m4_if([$1], [], [ - PACKAGE='$PACKAGE' - VERSION='$VERSION' - RM='$RM' - ofile='$ofile'], []) -])dnl /_LT_CONFIG_SAVE_COMMANDS -])# _LT_CONFIG - - -# LT_SUPPORTED_TAG(TAG) -# --------------------- -# Trace this macro to discover what tags are supported by the libtool -# --tag option, using: -# autoconf --trace 'LT_SUPPORTED_TAG:$1' -AC_DEFUN([LT_SUPPORTED_TAG], []) - - -# C support is built-in for now -m4_define([_LT_LANG_C_enabled], []) -m4_define([_LT_TAGS], []) - - -# LT_LANG(LANG) -# ------------- -# Enable libtool support for the given language if not already enabled. -AC_DEFUN([LT_LANG], -[AC_BEFORE([$0], [LT_OUTPUT])dnl -m4_case([$1], - [C], [_LT_LANG(C)], - [C++], [_LT_LANG(CXX)], - [Go], [_LT_LANG(GO)], - [Java], [_LT_LANG(GCJ)], - [Fortran 77], [_LT_LANG(F77)], - [Fortran], [_LT_LANG(FC)], - [Windows Resource], [_LT_LANG(RC)], - [m4_ifdef([_LT_LANG_]$1[_CONFIG], - [_LT_LANG($1)], - [m4_fatal([$0: unsupported language: "$1"])])])dnl -])# LT_LANG - - -# _LT_LANG(LANGNAME) -# ------------------ -m4_defun([_LT_LANG], -[m4_ifdef([_LT_LANG_]$1[_enabled], [], - [LT_SUPPORTED_TAG([$1])dnl - m4_append([_LT_TAGS], [$1 ])dnl - m4_define([_LT_LANG_]$1[_enabled], [])dnl - _LT_LANG_$1_CONFIG($1)])dnl -])# _LT_LANG - - -m4_ifndef([AC_PROG_GO], [ -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_GO. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ -m4_defun([AC_PROG_GO], -[AC_LANG_PUSH(Go)dnl -AC_ARG_VAR([GOC], [Go compiler command])dnl -AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl -_AC_ARG_VAR_LDFLAGS()dnl -AC_CHECK_TOOL(GOC, gccgo) -if test -z "$GOC"; then - if test -n "$ac_tool_prefix"; then - AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) - fi -fi -if test -z "$GOC"; then - AC_CHECK_PROG(GOC, gccgo, gccgo, false) -fi -])#m4_defun -])#m4_ifndef - - -# _LT_LANG_DEFAULT_CONFIG -# ----------------------- -m4_defun([_LT_LANG_DEFAULT_CONFIG], -[AC_PROVIDE_IFELSE([AC_PROG_CXX], - [LT_LANG(CXX)], - [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) - -AC_PROVIDE_IFELSE([AC_PROG_F77], - [LT_LANG(F77)], - [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) - -AC_PROVIDE_IFELSE([AC_PROG_FC], - [LT_LANG(FC)], - [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) - -dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal -dnl pulling things in needlessly. -AC_PROVIDE_IFELSE([AC_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([LT_PROG_GCJ], - [LT_LANG(GCJ)], - [m4_ifdef([AC_PROG_GCJ], - [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([A][M_PROG_GCJ], - [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([LT_PROG_GCJ], - [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) - -AC_PROVIDE_IFELSE([AC_PROG_GO], - [LT_LANG(GO)], - [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) - -AC_PROVIDE_IFELSE([LT_PROG_RC], - [LT_LANG(RC)], - [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) -])# _LT_LANG_DEFAULT_CONFIG - -# Obsolete macros: -AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) -AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) -AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) -AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) -AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_CXX], []) -dnl AC_DEFUN([AC_LIBTOOL_F77], []) -dnl AC_DEFUN([AC_LIBTOOL_FC], []) -dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) -dnl AC_DEFUN([AC_LIBTOOL_RC], []) - - -# _LT_TAG_COMPILER -# ---------------- -m4_defun([_LT_TAG_COMPILER], -[AC_REQUIRE([AC_PROG_CC])dnl - -_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl -_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl -_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl -_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC -])# _LT_TAG_COMPILER - - -# _LT_COMPILER_BOILERPLATE -# ------------------------ -# Check for compiler boilerplate output or warnings with -# the simple compiler test code. -m4_defun([_LT_COMPILER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* -])# _LT_COMPILER_BOILERPLATE - - -# _LT_LINKER_BOILERPLATE -# ---------------------- -# Check for linker boilerplate output or warnings with -# the simple link test code. -m4_defun([_LT_LINKER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* -])# _LT_LINKER_BOILERPLATE - -# _LT_REQUIRED_DARWIN_CHECKS -# ------------------------- -m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ - case $host_os in - rhapsody* | darwin*) - AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) - AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) - AC_CHECK_TOOL([LIPO], [lipo], [:]) - AC_CHECK_TOOL([OTOOL], [otool], [:]) - AC_CHECK_TOOL([OTOOL64], [otool64], [:]) - _LT_DECL([], [DSYMUTIL], [1], - [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) - _LT_DECL([], [NMEDIT], [1], - [Tool to change global to local symbols on Mac OS X]) - _LT_DECL([], [LIPO], [1], - [Tool to manipulate fat objects and archives on Mac OS X]) - _LT_DECL([], [OTOOL], [1], - [ldd/readelf like tool for Mach-O binaries on Mac OS X]) - _LT_DECL([], [OTOOL64], [1], - [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) - - AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], - [lt_cv_apple_cc_single_mod=no - if test -z "$LT_MULTI_MODULE"; then - # By default we will add the -single_module flag. You can override - # by either setting the environment variable LT_MULTI_MODULE - # non-empty at configure time, or by adding -multi_module to the - # link flags. - rm -rf libconftest.dylib* - echo "int foo(void){return 1;}" > conftest.c - echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ --dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ - -dynamiclib -Wl,-single_module conftest.c 2>conftest.err - _lt_result=$? - # If there is a non-empty error log, and "single_module" - # appears in it, assume the flag caused a linker warning - if test -s conftest.err && $GREP single_module conftest.err; then - cat conftest.err >&AS_MESSAGE_LOG_FD - # Otherwise, if the output was created with a 0 exit code from - # the compiler, it worked. - elif test -f libconftest.dylib && test 0 = "$_lt_result"; then - lt_cv_apple_cc_single_mod=yes - else - cat conftest.err >&AS_MESSAGE_LOG_FD - fi - rm -rf libconftest.dylib* - rm -f conftest.* - fi]) - - AC_CACHE_CHECK([for -exported_symbols_list linker flag], - [lt_cv_ld_exported_symbols_list], - [lt_cv_ld_exported_symbols_list=no - save_LDFLAGS=$LDFLAGS - echo "_main" > conftest.sym - LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [lt_cv_ld_exported_symbols_list=yes], - [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS=$save_LDFLAGS - ]) - - AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], - [lt_cv_ld_force_load=no - cat > conftest.c << _LT_EOF -int forced_loaded() { return 2;} -_LT_EOF - echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD - echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD - $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD - echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD - $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD - cat > conftest.c << _LT_EOF -int main() { return 0;} -_LT_EOF - echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err - _lt_result=$? - if test -s conftest.err && $GREP force_load conftest.err; then - cat conftest.err >&AS_MESSAGE_LOG_FD - elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then - lt_cv_ld_force_load=yes - else - cat conftest.err >&AS_MESSAGE_LOG_FD - fi - rm -f conftest.err libconftest.a conftest conftest.c - rm -rf conftest.dSYM - ]) - case $host_os in - rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[[912]]*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - 10.[[012]][[,.]]*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - 10.*|11.*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test yes = "$lt_cv_apple_cc_single_mod"; then - _lt_dar_single_mod='$single_module' - fi - if test yes = "$lt_cv_ld_exported_symbols_list"; then - _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' - fi - if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac -]) - - -# _LT_DARWIN_LINKER_FEATURES([TAG]) -# --------------------------------- -# Checks for linker and compiler features on darwin -m4_defun([_LT_DARWIN_LINKER_FEATURES], -[ - m4_require([_LT_REQUIRED_DARWIN_CHECKS]) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_automatic, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - if test yes = "$lt_cv_ld_force_load"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], - [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) - else - _LT_TAGVAR(whole_archive_flag_spec, $1)='' - fi - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined - case $cc_basename in - ifort*|nagfor*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test yes = "$_lt_dar_can_shared"; then - output_verbose_link_cmd=func_echo_all - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" - m4_if([$1], [CXX], -[ if test yes != "$lt_cv_apple_cc_single_mod"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" - fi -],[]) - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi -]) - -# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) -# ---------------------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -# Store the results from the different compilers for each TAGNAME. -# Allow to override them for all tags through lt_cv_aix_libpath. -m4_defun([_LT_SYS_MODULE_PATH_AIX], -[m4_require([_LT_DECL_SED])dnl -if test set = "${lt_cv_aix_libpath+set}"; then - aix_libpath=$lt_cv_aix_libpath -else - AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], - [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ - lt_aix_libpath_sed='[ - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }]' - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi],[]) - if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib - fi - ]) - aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) -fi -])# _LT_SYS_MODULE_PATH_AIX - - -# _LT_SHELL_INIT(ARG) -# ------------------- -m4_define([_LT_SHELL_INIT], -[m4_divert_text([M4SH-INIT], [$1 -])])# _LT_SHELL_INIT - - - -# _LT_PROG_ECHO_BACKSLASH -# ----------------------- -# Find how we can fake an echo command that does not interpret backslash. -# In particular, with Autoconf 2.60 or later we add some code to the start -# of the generated configure script that will find a shell with a builtin -# printf (that we can use as an echo command). -m4_defun([_LT_PROG_ECHO_BACKSLASH], -[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - -AC_MSG_CHECKING([how to print strings]) -# Test print first, because it will be a builtin if present. -if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ - test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='print -r --' -elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='printf %s\n' -else - # Use this function as a fallback that always works. - func_fallback_echo () - { - eval 'cat <<_LTECHO_EOF -$[]1 -_LTECHO_EOF' - } - ECHO='func_fallback_echo' -fi - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - -case $ECHO in - printf*) AC_MSG_RESULT([printf]) ;; - print*) AC_MSG_RESULT([print -r]) ;; - *) AC_MSG_RESULT([cat]) ;; -esac - -m4_ifdef([_AS_DETECT_SUGGESTED], -[_AS_DETECT_SUGGESTED([ - test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( - ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' - ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO - ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - PATH=/empty FPATH=/empty; export PATH FPATH - test "X`printf %s $ECHO`" = "X$ECHO" \ - || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) - -_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) -_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) -])# _LT_PROG_ECHO_BACKSLASH - - -# _LT_WITH_SYSROOT -# ---------------- -AC_DEFUN([_LT_WITH_SYSROOT], -[AC_MSG_CHECKING([for sysroot]) -AC_ARG_WITH([sysroot], -[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], - [Search for dependent libraries within DIR (or the compiler's sysroot - if not specified).])], -[], [with_sysroot=no]) - -dnl lt_sysroot will always be passed unquoted. We quote it here -dnl in case the user passed a directory name. -lt_sysroot= -case $with_sysroot in #( - yes) - if test yes = "$GCC"; then - lt_sysroot=`$CC --print-sysroot 2>/dev/null` - fi - ;; #( - /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` - ;; #( - no|'') - ;; #( - *) - AC_MSG_RESULT([$with_sysroot]) - AC_MSG_ERROR([The sysroot must be an absolute path.]) - ;; -esac - - AC_MSG_RESULT([${lt_sysroot:-no}]) -_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl -[dependent libraries, and where our libraries should be installed.])]) - -# _LT_ENABLE_LOCK -# --------------- -m4_defun([_LT_ENABLE_LOCK], -[AC_ARG_ENABLE([libtool-lock], - [AS_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test no = "$enable_libtool_lock" || enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out what ABI is being produced by ac_compile, and set mode - # options accordingly. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE=32 - ;; - *ELF-64*) - HPUX_IA64_MODE=64 - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - if test yes = "$lt_cv_prog_gnu_ld"; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -mips64*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - emul=elf - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - emul="${emul}32" - ;; - *64-bit*) - emul="${emul}64" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *MSB*) - emul="${emul}btsmip" - ;; - *LSB*) - emul="${emul}ltsmip" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *N32*) - emul="${emul}n32" - ;; - esac - LD="${LD-ld} -m $emul" - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ -s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. Note that the listed cases only cover the - # situations where additional linker options are needed (such as when - # doing 32-bit compilation for a host where ld defaults to 64-bit, or - # vice versa); the common cases where no linker options are needed do - # not appear in the list. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - case `/usr/bin/file conftest.o` in - *x86-64*) - LD="${LD-ld} -m elf32_x86_64" - ;; - *) - LD="${LD-ld} -m elf_i386" - ;; - esac - ;; - powerpc64le-*linux*) - LD="${LD-ld} -m elf32lppclinux" - ;; - powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - powerpcle-*linux*) - LD="${LD-ld} -m elf64lppc" - ;; - powerpc-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*|s390*-*tpf*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_LANG_PUSH(C) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) - AC_LANG_POP]) - if test yes != "$lt_cv_cc_needs_belf"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS=$SAVE_CFLAGS - fi - ;; -*-*solaris*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) - case $host in - i?86-*-solaris*|x86_64-*-solaris*) - LD="${LD-ld} -m elf_x86_64" - ;; - sparc*-*-solaris*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - # GNU ld 2.21 introduced _sol2 emulations. Use them if available. - if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD=${LD-ld}_sol2 - fi - ;; - *) - if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then - LD="${LD-ld} -64" - fi - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; -esac - -need_locks=$enable_libtool_lock -])# _LT_ENABLE_LOCK - - -# _LT_PROG_AR -# ----------- -m4_defun([_LT_PROG_AR], -[AC_CHECK_TOOLS(AR, [ar], false) -: ${AR=ar} -: ${AR_FLAGS=cr} -_LT_DECL([], [AR], [1], [The archiver]) -_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) - -AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], - [lt_cv_ar_at_file=no - AC_COMPILE_IFELSE([AC_LANG_PROGRAM], - [echo conftest.$ac_objext > conftest.lst - lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' - AC_TRY_EVAL([lt_ar_try]) - if test 0 -eq "$ac_status"; then - # Ensure the archiver fails upon bogus file names. - rm -f conftest.$ac_objext libconftest.a - AC_TRY_EVAL([lt_ar_try]) - if test 0 -ne "$ac_status"; then - lt_cv_ar_at_file=@ - fi - fi - rm -f conftest.* libconftest.a - ]) - ]) - -if test no = "$lt_cv_ar_at_file"; then - archiver_list_spec= -else - archiver_list_spec=$lt_cv_ar_at_file -fi -_LT_DECL([], [archiver_list_spec], [1], - [How to feed a file listing to the archiver]) -])# _LT_PROG_AR - - -# _LT_CMD_OLD_ARCHIVE -# ------------------- -m4_defun([_LT_CMD_OLD_ARCHIVE], -[_LT_PROG_AR - -AC_CHECK_TOOL(STRIP, strip, :) -test -z "$STRIP" && STRIP=: -_LT_DECL([], [STRIP], [1], [A symbol stripping program]) - -AC_CHECK_TOOL(RANLIB, ranlib, :) -test -z "$RANLIB" && RANLIB=: -_LT_DECL([], [RANLIB], [1], - [Commands used to install an old-style archive]) - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - bitrig* | openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" -fi - -case $host_os in - darwin*) - lock_old_archive_extraction=yes ;; - *) - lock_old_archive_extraction=no ;; -esac -_LT_DECL([], [old_postinstall_cmds], [2]) -_LT_DECL([], [old_postuninstall_cmds], [2]) -_LT_TAGDECL([], [old_archive_cmds], [2], - [Commands used to build an old-style archive]) -_LT_DECL([], [lock_old_archive_extraction], [0], - [Whether to use a lock for old archive extraction]) -])# _LT_CMD_OLD_ARCHIVE - - -# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -AC_DEFUN([_LT_COMPILER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - fi - $RM conftest* -]) - -if test yes = "[$]$2"; then - m4_if([$5], , :, [$5]) -else - m4_if([$6], , :, [$6]) -fi -])# _LT_COMPILER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) - - -# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------- -# Check whether the given linker option works -AC_DEFUN([_LT_LINKER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS $3" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&AS_MESSAGE_LOG_FD - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - else - $2=yes - fi - fi - $RM -r conftest* - LDFLAGS=$save_LDFLAGS -]) - -if test yes = "[$]$2"; then - m4_if([$4], , :, [$4]) -else - m4_if([$5], , :, [$5]) -fi -])# _LT_LINKER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) - - -# LT_CMD_MAX_LEN -#--------------- -AC_DEFUN([LT_CMD_MAX_LEN], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -# find the maximum length of command line arguments -AC_MSG_CHECKING([the maximum length of command line arguments]) -AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl - i=0 - teststring=ABCD - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - mint*) - # On MiNT this can take a long time and run out of memory. - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - os2*) - # The test takes a long time on OS/2. - lt_cv_sys_max_cmd_len=8192 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len" && \ - test undefined != "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test X`env echo "$teststring$teststring" 2>/dev/null` \ - = "X$teststring$teststring"; } >/dev/null 2>&1 && - test 17 != "$i" # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac -]) -if test -n "$lt_cv_sys_max_cmd_len"; then - AC_MSG_RESULT($lt_cv_sys_max_cmd_len) -else - AC_MSG_RESULT(none) -fi -max_cmd_len=$lt_cv_sys_max_cmd_len -_LT_DECL([], [max_cmd_len], [0], - [What is the maximum length of a command?]) -])# LT_CMD_MAX_LEN - -# Old name: -AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) - - -# _LT_HEADER_DLFCN -# ---------------- -m4_defun([_LT_HEADER_DLFCN], -[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl -])# _LT_HEADER_DLFCN - - -# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# ---------------------------------------------------------------- -m4_defun([_LT_TRY_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test yes = "$cross_compiling"; then : - [$4] -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -[#line $LINENO "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -/* When -fvisibility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -}] -_LT_EOF - if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then - (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) $1 ;; - x$lt_dlneed_uscore) $2 ;; - x$lt_dlunknown|x*) $3 ;; - esac - else : - # compilation failed - $3 - fi -fi -rm -fr conftest* -])# _LT_TRY_DLOPEN_SELF - - -# LT_SYS_DLOPEN_SELF -# ------------------ -AC_DEFUN([LT_SYS_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test yes != "$enable_dlopen"; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen=load_add_on - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen=LoadLibrary - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ - lt_cv_dlopen=dyld - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - tpf*) - # Don't try to run any link tests for TPF. We know it's impossible - # because TPF is a cross-compiler, and we know how we open DSOs. - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - lt_cv_dlopen_self=no - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen=shl_load], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen=dlopen], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - - if test no = "$lt_cv_dlopen"; then - enable_dlopen=no - else - enable_dlopen=yes - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS=$CPPFLAGS - test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS=$LDFLAGS - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS=$LIBS - LIBS="$lt_cv_dlopen_libs $LIBS" - - AC_CACHE_CHECK([whether a program can dlopen itself], - lt_cv_dlopen_self, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, - lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) - ]) - - if test yes = "$lt_cv_dlopen_self"; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - AC_CACHE_CHECK([whether a statically linked program can dlopen itself], - lt_cv_dlopen_self_static, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, - lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) - ]) - fi - - CPPFLAGS=$save_CPPFLAGS - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi -_LT_DECL([dlopen_support], [enable_dlopen], [0], - [Whether dlopen is supported]) -_LT_DECL([dlopen_self], [enable_dlopen_self], [0], - [Whether dlopen of programs is supported]) -_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], - [Whether dlopen of statically linked programs is supported]) -])# LT_SYS_DLOPEN_SELF - -# Old name: -AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) - - -# _LT_COMPILER_C_O([TAGNAME]) -# --------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler. -# This macro does not hard code the compiler like AC_PROG_CC_C_O. -m4_defun([_LT_COMPILER_C_O], -[m4_require([_LT_DECL_SED])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - fi - fi - chmod u+w . 2>&AS_MESSAGE_LOG_FD - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* -]) -_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], - [Does compiler simultaneously support -c and -o options?]) -])# _LT_COMPILER_C_O - - -# _LT_COMPILER_FILE_LOCKS([TAGNAME]) -# ---------------------------------- -# Check to see if we can do hard links to lock some files if needed -m4_defun([_LT_COMPILER_FILE_LOCKS], -[m4_require([_LT_ENABLE_LOCK])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_COMPILER_C_O([$1]) - -hard_links=nottested -if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then - # do not overwrite the value of need_locks provided by the user - AC_MSG_CHECKING([if we can lock with hard links]) - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - AC_MSG_RESULT([$hard_links]) - if test no = "$hard_links"; then - AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) - need_locks=warn - fi -else - need_locks=no -fi -_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) -])# _LT_COMPILER_FILE_LOCKS - - -# _LT_CHECK_OBJDIR -# ---------------- -m4_defun([_LT_CHECK_OBJDIR], -[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], -[rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null]) -objdir=$lt_cv_objdir -_LT_DECL([], [objdir], [0], - [The name of the directory that contains temporary libtool files])dnl -m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", - [Define to the sub-directory where libtool stores uninstalled libraries.]) -])# _LT_CHECK_OBJDIR - - -# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) -# -------------------------------------- -# Check hardcoding attributes. -m4_defun([_LT_LINKER_HARDCODE_LIBPATH], -[AC_MSG_CHECKING([how to hardcode library paths into programs]) -_LT_TAGVAR(hardcode_action, $1)= -if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || - test -n "$_LT_TAGVAR(runpath_var, $1)" || - test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then - - # We can hardcode non-existent directories. - if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && - test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then - # Linking always hardcodes the temporary library directory. - _LT_TAGVAR(hardcode_action, $1)=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - _LT_TAGVAR(hardcode_action, $1)=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - _LT_TAGVAR(hardcode_action, $1)=unsupported -fi -AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) - -if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || - test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then - # Fast installation is not supported - enable_fast_install=no -elif test yes = "$shlibpath_overrides_runpath" || - test no = "$enable_shared"; then - # Fast installation is not necessary - enable_fast_install=needless -fi -_LT_TAGDECL([], [hardcode_action], [0], - [How to hardcode a shared library path into an executable]) -])# _LT_LINKER_HARDCODE_LIBPATH - - -# _LT_CMD_STRIPLIB -# ---------------- -m4_defun([_LT_CMD_STRIPLIB], -[m4_require([_LT_DECL_EGREP]) -striplib= -old_striplib= -AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP"; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac -fi -_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) -_LT_DECL([], [striplib], [1]) -])# _LT_CMD_STRIPLIB - - -# _LT_PREPARE_MUNGE_PATH_LIST -# --------------------------- -# Make sure func_munge_path_list() is defined correctly. -m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], -[[# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x@S|@2 in - x) - ;; - *:) - eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" - ;; - x:*) - eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" - ;; - *) - eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" - ;; - esac -} -]])# _LT_PREPARE_PATH_LIST - - -# _LT_SYS_DYNAMIC_LINKER([TAG]) -# ----------------------------- -# PORTME Fill in your ld.so characteristics -m4_defun([_LT_SYS_DYNAMIC_LINKER], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_OBJDUMP])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_CHECK_SHELL_FEATURES])dnl -m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl -AC_MSG_CHECKING([dynamic linker characteristics]) -m4_if([$1], - [], [ -if test yes = "$GCC"; then - case $host_os in - darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; - *) lt_awk_arg='/^libraries:/' ;; - esac - case $host_os in - mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; - *) lt_sed_strip_eq='s|=/|/|g' ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` - case $lt_search_path_spec in - *\;*) - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` - ;; - *) - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` - ;; - esac - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary... - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - # ...but if some path component already ends with the multilib dir we assume - # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). - case "$lt_multi_os_dir; $lt_search_path_spec " in - "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) - lt_multi_os_dir= - ;; - esac - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" - elif test -n "$lt_multi_os_dir"; then - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS = " "; FS = "/|\n";} { - lt_foo = ""; - lt_count = 0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo = "/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[[lt_foo]]++; } - if (lt_freq[[lt_foo]] == 1) { print lt_foo; } -}'` - # AWK program above erroneously prepends '/' to C:/dos/paths - # for these hosts. - case $host_os in - mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; - esac - sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi]) -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=.so -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -AC_ARG_VAR([LT_SYS_LIBRARY_PATH], -[User-defined run-time library search path.]) - -case $host_os in -aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='$libname$release$shared_ext$major' - ;; - -aix[[4-9]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test ia64 = "$host_cpu"; then - # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line '#! .'. This would cause the generated library to - # depend on '.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[[01]] | aix4.[[01]].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # Using Import Files as archive members, it is possible to support - # filename-based versioning of shared library archives on AIX. While - # this would work for both with and without runtime linking, it will - # prevent static linking of such archives. So we do filename-based - # shared library versioning with .so extension only, which is used - # when both runtime linking and shared linking is enabled. - # Unfortunately, runtime linking may impact performance, so we do - # not want this to be the default eventually. Also, we use the - # versioned .so libs for executables only if there is the -brtl - # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. - # To allow for filename-based versioning support, we need to create - # libNAME.so.V as an archive file, containing: - # *) an Import File, referring to the versioned filename of the - # archive as well as the shared archive member, telling the - # bitwidth (32 or 64) of that shared object, and providing the - # list of exported symbols of that shared object, eventually - # decorated with the 'weak' keyword - # *) the shared object with the F_LOADONLY flag set, to really avoid - # it being seen by the linker. - # At run time we better use the real file rather than another symlink, - # but for link time we create the symlink libNAME.so -> libNAME.so.V - - case $with_aix_soname,$aix_use_runtimelinking in - # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - aix,yes) # traditional libtool - dynamic_linker='AIX unversionable lib.so' - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - aix,no) # traditional AIX only - dynamic_linker='AIX lib.a[(]lib.so.V[)]' - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - ;; - svr4,*) # full svr4 only - dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,yes) # both, prefer svr4 - dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # unpreferred sharedlib libNAME.a needs extra handling - postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' - postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,no) # both, prefer aix - dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling - postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' - postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' - ;; - esac - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='$libname$shared_ext' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[[45]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=.dll - need_version=no - need_lib_prefix=no - - case $GCC,$cc_basename in - yes,*) - # gcc - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' -m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' - ;; - esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' - library_names_spec='$libname.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec=$LIB - if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' - ;; - - *) - # Assume MSVC wrapper - library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' - dynamic_linker='Win32 ld.exe' - ;; - esac - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' - soname_spec='$libname$release$major$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' -m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[[23]].*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2.*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[[01]]* | freebsdelf3.[[01]]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ - freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - if test 32 = "$HPUX_IA64_MODE"; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - sys_lib_dlsearch_path_spec=/usr/lib/hpux32 - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - sys_lib_dlsearch_path_spec=/usr/lib/hpux64 - fi - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... - postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 - ;; - -interix[[3-9]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test yes = "$lt_cv_prog_gnu_ld"; then - version_type=linux # correct to gnu/linux during the next big refactor - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -linux*android*) - version_type=none # Android doesn't support versioned libraries. - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext' - soname_spec='$libname$release$shared_ext' - finish_cmds= - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - - # Some binutils ld are patched to set DT_RUNPATH - AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], - [lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ - LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], - [lt_cv_shlibpath_overrides_runpath=yes])]) - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - ]) - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Ideally, we could use ldconfig to report *all* directores which are - # searched for libraries, however this is still not possible. Aside from not - # being certain /sbin/ldconfig is available, command - # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, - # even though it is searched at run-time. Try to do the best guess by - # appending ld.so.conf contents (and includes) to the search path. - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd* | bitrig*) - version_type=sunos - sys_lib_dlsearch_path_spec=/usr/lib - need_lib_prefix=no - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - need_version=no - else - need_version=yes - fi - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -os2*) - libname_spec='$name' - version_type=windows - shrext_cmds=.dll - need_version=no - need_lib_prefix=no - # OS/2 can only load a DLL with a base name of 8 characters or less. - soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; - v=$($ECHO $release$versuffix | tr -d .-); - n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); - $ECHO $n$v`$shared_ext' - library_names_spec='${libname}_dll.$libext' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=BEGINLIBPATH - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test yes = "$with_gnu_ld"; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec; then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' - soname_spec='$libname$shared_ext.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=sco - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test yes = "$with_gnu_ld"; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -AC_MSG_RESULT([$dynamic_linker]) -test no = "$dynamic_linker" && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test yes = "$GCC"; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then - sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec -fi - -if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then - sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec -fi - -# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... -configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec - -# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code -func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" - -# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool -configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH - -_LT_DECL([], [variables_saved_for_relink], [1], - [Variables whose values should be saved in libtool wrapper scripts and - restored at link time]) -_LT_DECL([], [need_lib_prefix], [0], - [Do we need the "lib" prefix for modules?]) -_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) -_LT_DECL([], [version_type], [0], [Library versioning type]) -_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) -_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) -_LT_DECL([], [shlibpath_overrides_runpath], [0], - [Is shlibpath searched before the hard-coded library search path?]) -_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) -_LT_DECL([], [library_names_spec], [1], - [[List of archive names. First name is the real one, the rest are links. - The last name is the one that the linker finds with -lNAME]]) -_LT_DECL([], [soname_spec], [1], - [[The coded name of the library, if different from the real name]]) -_LT_DECL([], [install_override_mode], [1], - [Permission mode override for installation of shared libraries]) -_LT_DECL([], [postinstall_cmds], [2], - [Command to use after installation of a shared archive]) -_LT_DECL([], [postuninstall_cmds], [2], - [Command to use after uninstallation of a shared archive]) -_LT_DECL([], [finish_cmds], [2], - [Commands used to finish a libtool library installation in a directory]) -_LT_DECL([], [finish_eval], [1], - [[As "finish_cmds", except a single script fragment to be evaled but - not shown]]) -_LT_DECL([], [hardcode_into_libs], [0], - [Whether we should hardcode library paths into libraries]) -_LT_DECL([], [sys_lib_search_path_spec], [2], - [Compile-time system search path for libraries]) -_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], - [Detected run-time system search path for libraries]) -_LT_DECL([], [configure_time_lt_sys_library_path], [2], - [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) -])# _LT_SYS_DYNAMIC_LINKER - - -# _LT_PATH_TOOL_PREFIX(TOOL) -# -------------------------- -# find a file program that can recognize shared library -AC_DEFUN([_LT_PATH_TOOL_PREFIX], -[m4_require([_LT_DECL_EGREP])dnl -AC_MSG_CHECKING([for $1]) -AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, -[case $MAGIC_CMD in -[[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR -dnl $ac_dummy forces splitting on constant user-supplied paths. -dnl POSIX.2 word splitting is done only on the output of word expansions, -dnl not every word. This closes a longstanding sh security hole. - ac_dummy="m4_if([$2], , $PATH, [$2])" - for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$1"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"$1" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD - ;; -esac]) -MAGIC_CMD=$lt_cv_path_MAGIC_CMD -if test -n "$MAGIC_CMD"; then - AC_MSG_RESULT($MAGIC_CMD) -else - AC_MSG_RESULT(no) -fi -_LT_DECL([], [MAGIC_CMD], [0], - [Used to examine libraries when file_magic_cmd begins with "file"])dnl -])# _LT_PATH_TOOL_PREFIX - -# Old name: -AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) - - -# _LT_PATH_MAGIC -# -------------- -# find a file program that can recognize a shared library -m4_defun([_LT_PATH_MAGIC], -[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) - else - MAGIC_CMD=: - fi -fi -])# _LT_PATH_MAGIC - - -# LT_PATH_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -AC_DEFUN([LT_PATH_LD], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_PROG_ECHO_BACKSLASH])dnl - -AC_ARG_WITH([gnu-ld], - [AS_HELP_STRING([--with-gnu-ld], - [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test no = "$withval" || with_gnu_ld=yes], - [with_gnu_ld=no])dnl - -ac_prog=ld -if test yes = "$GCC"; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by $CC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return, which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]]* | ?:[[\\/]]*) - re_direlt='/[[^/]][[^/]]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD=$ac_prog - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test yes = "$with_gnu_ld"; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(lt_cv_path_LD, -[if test -z "$LD"; then - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD=$ac_dir/$ac_prog - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i -cat conftest.i conftest.i >conftest2.i -: ${lt_DD:=$DD} -AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], -[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: -fi]) -rm -f conftest.i conftest2.i conftest.out]) -])# _LT_PATH_DD - - -# _LT_CMD_TRUNCATE -# ---------------- -# find command to truncate a binary pipe -m4_defun([_LT_CMD_TRUNCATE], -[m4_require([_LT_PATH_DD]) -AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], -[printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -lt_cv_truncate_bin= -if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" -fi -rm -f conftest.i conftest2.i conftest.out -test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) -_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], - [Command to truncate a binary pipe]) -])# _LT_CMD_TRUNCATE - - -# _LT_CHECK_MAGIC_METHOD -# ---------------------- -# how to check for library dependencies -# -- PORTME fill in with the dynamic library characteristics -m4_defun([_LT_CHECK_MAGIC_METHOD], -[m4_require([_LT_DECL_EGREP]) -m4_require([_LT_DECL_OBJDUMP]) -AC_CACHE_CHECK([how to recognize dependent libraries], -lt_cv_deplibs_check_method, -[lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# 'unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# that responds to the $file_magic_cmd with a given extended regex. -# If you have 'file' or equivalent on your system and you're not sure -# whether 'pass_all' will *always* work, you probably want this one. - -case $host_os in -aix[[4-9]]*) - lt_cv_deplibs_check_method=pass_all - ;; - -beos*) - lt_cv_deplibs_check_method=pass_all - ;; - -bsdi[[45]]*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # func_win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump', - # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc*) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -haiku*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[[3-9]]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd* | bitrig*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -os2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac -]) - -file_magic_glob= -want_nocaseglob=no -if test "$build" = "$host"; then - case $host_os in - mingw* | pw32*) - if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then - want_nocaseglob=yes - else - file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` - fi - ;; - esac -fi - -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - -_LT_DECL([], [deplibs_check_method], [1], - [Method to check whether dependent libraries are shared objects]) -_LT_DECL([], [file_magic_cmd], [1], - [Command to use when deplibs_check_method = "file_magic"]) -_LT_DECL([], [file_magic_glob], [1], - [How to find potential files when deplibs_check_method = "file_magic"]) -_LT_DECL([], [want_nocaseglob], [1], - [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) -])# _LT_CHECK_MAGIC_METHOD - - -# LT_PATH_NM -# ---------- -# find the pathname to a BSD- or MS-compatible name lister -AC_DEFUN([LT_PATH_NM], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM=$NM -else - lt_nm_to_check=${ac_tool_prefix}nm - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - tmp_nm=$ac_dir/$lt_tmp_nm - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the 'sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty - case $build_os in - mingw*) lt_bad_file=conftest.nm/nofile ;; - *) lt_bad_file=/dev/null ;; - esac - case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in - *$lt_bad_file* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break 2 - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break 2 - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS=$lt_save_ifs - done - : ${lt_cv_path_NM=no} -fi]) -if test no != "$lt_cv_path_NM"; then - NM=$lt_cv_path_NM -else - # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$DUMPBIN"; then : - # Let the user override the test. - else - AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) - case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in - *COFF*) - DUMPBIN="$DUMPBIN -symbols -headers" - ;; - *) - DUMPBIN=: - ;; - esac - fi - AC_SUBST([DUMPBIN]) - if test : != "$DUMPBIN"; then - NM=$DUMPBIN - fi -fi -test -z "$NM" && NM=nm -AC_SUBST([NM]) -_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl - -AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], - [lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) - cat conftest.out >&AS_MESSAGE_LOG_FD - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest*]) -])# LT_PATH_NM - -# Old names: -AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) -AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_PROG_NM], []) -dnl AC_DEFUN([AC_PROG_NM], []) - -# _LT_CHECK_SHAREDLIB_FROM_LINKLIB -# -------------------------------- -# how to determine the name of the shared library -# associated with a specific link library. -# -- PORTME fill in with the dynamic library characteristics -m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], -[m4_require([_LT_DECL_EGREP]) -m4_require([_LT_DECL_OBJDUMP]) -m4_require([_LT_DECL_DLLTOOL]) -AC_CACHE_CHECK([how to associate runtime and link libraries], -lt_cv_sharedlib_from_linklib_cmd, -[lt_cv_sharedlib_from_linklib_cmd='unknown' - -case $host_os in -cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh; - # decide which one to use based on capabilities of $DLLTOOL - case `$DLLTOOL --help 2>&1` in - *--identify-strict*) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib - ;; - *) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback - ;; - esac - ;; -*) - # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd=$ECHO - ;; -esac -]) -sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd -test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO - -_LT_DECL([], [sharedlib_from_linklib_cmd], [1], - [Command to associate shared and link libraries]) -])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB - - -# _LT_PATH_MANIFEST_TOOL -# ---------------------- -# locate the manifest tool -m4_defun([_LT_PATH_MANIFEST_TOOL], -[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) -test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt -AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], - [lt_cv_path_mainfest_tool=no - echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD - $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out - cat conftest.err >&AS_MESSAGE_LOG_FD - if $GREP 'Manifest Tool' conftest.out > /dev/null; then - lt_cv_path_mainfest_tool=yes - fi - rm -f conftest*]) -if test yes != "$lt_cv_path_mainfest_tool"; then - MANIFEST_TOOL=: -fi -_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl -])# _LT_PATH_MANIFEST_TOOL - - -# _LT_DLL_DEF_P([FILE]) -# --------------------- -# True iff FILE is a Windows DLL '.def' file. -# Keep in sync with func_dll_def_p in the libtool script -AC_DEFUN([_LT_DLL_DEF_P], -[dnl - test DEF = "`$SED -n dnl - -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace - -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments - -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl - -e q dnl Only consider the first "real" line - $1`" dnl -])# _LT_DLL_DEF_P - - -# LT_LIB_M -# -------- -# check for math library -AC_DEFUN([LT_LIB_M], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case $host in -*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) - # These system don't have libm, or don't need it - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) - AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, cos, LIBM=-lm) - ;; -esac -AC_SUBST([LIBM]) -])# LT_LIB_M - -# Old name: -AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_CHECK_LIBM], []) - - -# _LT_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------- -m4_defun([_LT_COMPILER_NO_RTTI], -[m4_require([_LT_TAG_COMPILER])dnl - -_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - -if test yes = "$GCC"; then - case $cc_basename in - nvcc*) - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; - *) - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; - esac - - _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], - lt_cv_prog_compiler_rtti_exceptions, - [-fno-rtti -fno-exceptions], [], - [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) -fi -_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], - [Compiler flag to turn off builtin functions]) -])# _LT_COMPILER_NO_RTTI - - -# _LT_CMD_GLOBAL_SYMBOLS -# ---------------------- -m4_defun([_LT_CMD_GLOBAL_SYMBOLS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([LT_PATH_NM])dnl -AC_REQUIRE([LT_PATH_LD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_TAG_COMPILER])dnl - -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output from $compiler object]) -AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], -[ -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[[BCDEGRST]]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[[BCDT]]' - ;; -cygwin* | mingw* | pw32* | cegcc*) - symcode='[[ABCDGISTW]]' - ;; -hpux*) - if test ia64 = "$host_cpu"; then - symcode='[[ABCDEGRST]]' - fi - ;; -irix* | nonstopux*) - symcode='[[BCDEGRST]]' - ;; -osf*) - symcode='[[BCDEGQRST]]' - ;; -solaris*) - symcode='[[BDRT]]' - ;; -sco3.2v5*) - symcode='[[DT]]' - ;; -sysv4.2uw2*) - symcode='[[DT]]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[[ABDT]]' - ;; -sysv4) - symcode='[[DFNSTU]]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[[ABCDGIRSTW]]' ;; -esac - -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Gets list of data symbols to import. - lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" - # Adjust the below global symbol transforms to fixup imported variables. - lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" - lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" - lt_c_name_lib_hook="\ - -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ - -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" -else - # Disable hooks by default. - lt_cv_sys_global_symbol_to_import= - lt_cdecl_hook= - lt_c_name_hook= - lt_c_name_lib_hook= -fi - -# Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, -# so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n"\ -$lt_cdecl_hook\ -" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ -$lt_c_name_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" - -# Transform an extracted symbol line into symbol name with lib prefix and -# symbol address. -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ -$lt_c_name_lib_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# Try without a prefix underscore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function, - # D for any global variable and I for any imported variable. - # Also find C++ and __fastcall symbols from MSVC++, - # which start with @ or ?. - lt_cv_sys_global_symbol_pipe="$AWK ['"\ -" {last_section=section; section=\$ 3};"\ -" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ -" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ -" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ -" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ -" \$ 0!~/External *\|/{next};"\ -" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ -" {if(hide[section]) next};"\ -" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ -" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ -" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ -" ' prfx=^$ac_symprfx]" - else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <<_LT_EOF -#ifdef __cplusplus -extern "C" { -#endif -char nm_test_var; -void nm_test_func(void); -void nm_test_func(void){} -#ifdef __cplusplus -} -#endif -int main(){nm_test_var='a';nm_test_func();return(0);} -_LT_EOF - - if AC_TRY_EVAL(ac_compile); then - # Now try to grab the symbols. - nlist=conftest.nm - $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD - if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if $GREP ' nm_test_var$' "$nlist" >/dev/null; then - if $GREP ' nm_test_func$' "$nlist" >/dev/null; then - cat <<_LT_EOF > conftest.$ac_ext -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT@&t@_DLSYM_CONST -#elif defined __osf__ -/* This system does not cope well with relocations in const data. */ -# define LT@&t@_DLSYM_CONST -#else -# define LT@&t@_DLSYM_CONST const -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -_LT_EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' - - cat <<_LT_EOF >> conftest.$ac_ext - -/* The mapping between symbol names and symbols. */ -LT@&t@_DLSYM_CONST struct { - const char *name; - void *address; -} -lt__PROGRAM__LTX_preloaded_symbols[[]] = -{ - { "@PROGRAM@", (void *) 0 }, -_LT_EOF - $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext - cat <<\_LT_EOF >> conftest.$ac_ext - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt__PROGRAM__LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif -_LT_EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_globsym_save_LIBS=$LIBS - lt_globsym_save_CFLAGS=$CFLAGS - LIBS=conftstm.$ac_objext - CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then - pipe_works=yes - fi - LIBS=$lt_globsym_save_LIBS - CFLAGS=$lt_globsym_save_CFLAGS - else - echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.$ac_ext >&5 - fi - rm -rf conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test yes = "$pipe_works"; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done -]) -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - AC_MSG_RESULT(failed) -else - AC_MSG_RESULT(ok) -fi - -# Response file support. -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - nm_file_list_spec='@' -elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then - nm_file_list_spec='@' -fi - -_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], - [Take the output of nm and produce a listing of raw symbols and C names]) -_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], - [Transform the output of nm in a proper C declaration]) -_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], - [Transform the output of nm into a list of symbols to manually relocate]) -_LT_DECL([global_symbol_to_c_name_address], - [lt_cv_sys_global_symbol_to_c_name_address], [1], - [Transform the output of nm in a C name address pair]) -_LT_DECL([global_symbol_to_c_name_address_lib_prefix], - [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], - [Transform the output of nm in a C name address pair when lib prefix is needed]) -_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], - [The name lister interface]) -_LT_DECL([], [nm_file_list_spec], [1], - [Specify filename containing input files for $NM]) -]) # _LT_CMD_GLOBAL_SYMBOLS - - -# _LT_COMPILER_PIC([TAGNAME]) -# --------------------------- -m4_defun([_LT_COMPILER_PIC], -[m4_require([_LT_TAG_COMPILER])dnl -_LT_TAGVAR(lt_prog_compiler_wl, $1)= -_LT_TAGVAR(lt_prog_compiler_pic, $1)= -_LT_TAGVAR(lt_prog_compiler_static, $1)= - -m4_if([$1], [CXX], [ - # C++ specific cases for pic, static, wl, etc. - if test yes = "$GXX"; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - _LT_TAGVAR(lt_prog_compiler_static, $1)= - ;; - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - case $host_os in - aix[[4-9]]*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - dgux*) - case $cc_basename in - ec++*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' - if test ia64 != "$host_cpu"; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - fi - ;; - aCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - KCC*) - # KAI C++ Compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - ecpc* ) - # old Intel C++ for x86_64, which still supported -KPIC. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - icpc* ) - # Intel C++, used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) - # IBM XL 8.0, 9.0 on PPC and BlueGene - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - cxx*) - # Digital/Compaq C++ - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - lcc*) - # Lucid - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - *) - ;; - esac - ;; - vxworks*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -], -[ - if test yes = "$GCC"; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - _LT_TAGVAR(lt_prog_compiler_static, $1)= - ;; - - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - enable_shared=no - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - - case $cc_basename in - nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' - if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" - fi - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - case $cc_basename in - nagfor*) - # NAG Fortran compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac - ;; - - hpux9* | hpux10* | hpux11*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC (with -KPIC) is the default. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - # old Intel for x86_64, which still supported -KPIC. - ecc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # flang / f18. f95 an alias for gfortran or flang on Debian - flang* | f18* | f95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # icc used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - icc* | ifort*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # Lahey Fortran 8.1. - lf95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' - _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' - ;; - nagfor*) - # NAG Fortran compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - ccc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All Alpha code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xl* | bgxl* | bgf* | mpixl*) - # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='' - ;; - *Sun\ F* | *Sun*Fortran*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - *Sun\ C*) - # Sun C 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - ;; - *Intel*\ [[CF]]*Compiler*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - *Portland\ Group*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - esac - ;; - - newsos6) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - osf3* | osf4* | osf5*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All OSF/1 code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - rdos*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - solaris*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - case $cc_basename in - f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; - *) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; - esac - ;; - - sunos4*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - unicos*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - - uts4*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -]) -case $host_os in - # For platforms that do not support PIC, -DPIC is meaningless: - *djgpp*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" - ;; -esac - -AC_CACHE_CHECK([for $compiler option to produce PIC], - [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], - [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) -_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then - _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], - [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], - [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], - [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in - "" | " "*) ;; - *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; - esac], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) -fi -_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], - [Additional compiler flags for building library objects]) - -_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], - [How to pass a linker flag through the compiler]) -# -# Check to make sure the static flag actually works. -# -wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" -_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], - _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), - $lt_tmp_static_flag, - [], - [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) -_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], - [Compiler flag to prevent dynamic linking]) -])# _LT_COMPILER_PIC - - -# _LT_LINKER_SHLIBS([TAGNAME]) -# ---------------------------- -# See if the linker supports building shared libraries. -m4_defun([_LT_LINKER_SHLIBS], -[AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -m4_require([_LT_PATH_MANIFEST_TOOL])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -m4_if([$1], [CXX], [ - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] - case $host_os in - aix[[4-9]]*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds - ;; - cygwin* | mingw* | cegcc*) - case $cc_basename in - cl*) - _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - ;; - *) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] - ;; - esac - ;; - linux* | k*bsd*-gnu | gnu*) - _LT_TAGVAR(link_all_deplibs, $1)=no - ;; - *) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac -], [ - runpath_var= - _LT_TAGVAR(allow_undefined_flag, $1)= - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(archive_cmds, $1)= - _LT_TAGVAR(archive_expsym_cmds, $1)= - _LT_TAGVAR(compiler_needs_object, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(hardcode_automatic, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_separator, $1)= - _LT_TAGVAR(hardcode_minus_L, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(inherit_rpath, $1)=no - _LT_TAGVAR(link_all_deplibs, $1)=unknown - _LT_TAGVAR(module_cmds, $1)= - _LT_TAGVAR(module_expsym_cmds, $1)= - _LT_TAGVAR(old_archive_from_new_cmds, $1)= - _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= - _LT_TAGVAR(thread_safe_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - _LT_TAGVAR(include_expsyms, $1)= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ' (' and ')$', so one must not match beginning or - # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', - # as well as any symbol that contains 'd'. - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - # Exclude shared library initialization/finalization symbols. -dnl Note also adjust exclude_expsyms for C++ above. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test yes != "$GCC"; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd* | bitrig*) - with_gnu_ld=no - ;; - linux* | k*bsd*-gnu | gnu*) - _LT_TAGVAR(link_all_deplibs, $1)=no - ;; - esac - - _LT_TAGVAR(ld_shlibs, $1)=yes - - # On some targets, GNU ld is compatible enough with the native linker - # that we're better off using the native interface for both. - lt_use_gnu_ld_interface=no - if test yes = "$with_gnu_ld"; then - case $host_os in - aix*) - # The AIX port of GNU ld has always aspired to compatibility - # with the native linker. However, as the warning in the GNU ld - # block says, versions before 2.19.5* couldn't really create working - # shared libraries, regardless of the interface used. - case `$LD -v 2>&1` in - *\ \(GNU\ Binutils\)\ 2.19.5*) ;; - *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; - *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - fi - - if test yes = "$lt_use_gnu_ld_interface"; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='$wl' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - supports_anon_versioning=no - case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in - *GNU\ gold*) supports_anon_versioning=yes ;; - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix[[3-9]]*) - # On AIX/PPC, the GNU linker is very broken - if test ia64 != "$host_cpu"; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: the GNU linker, at least up to release 2.19, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to install binutils -*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. -*** You will then need to restart the configuration process. - -_LT_EOF - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) - tmp_diet=no - if test linux-dietlibc = "$host_os"; then - case $cc_basename in - diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) - esac - fi - if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test no = "$tmp_diet" - then - tmp_addflag=' $pic_flag' - tmp_sharedflag='-shared' - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - lf95*) # Lahey Fortran 8.1 - _LT_TAGVAR(whole_archive_flag_spec, $1)= - tmp_sharedflag='--shared' ;; - nagfor*) # NAGFOR 5.3 - tmp_sharedflag='-Wl,-shared' ;; - xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) - tmp_sharedflag='-qmkshrobj' - tmp_addflag= ;; - nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - - if test yes = "$supports_anon_versioning"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' - fi - - case $cc_basename in - tcc*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' - ;; - xlf* | bgf* | bgxlf* | mpixlf*) - # IBM XL Fortran 10.1 on PPC cannot create shared libs itself - _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test yes = "$supports_anon_versioning"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' - fi - ;; - esac - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - sunos4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - - if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then - runpath_var= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - _LT_TAGVAR(hardcode_direct, $1)=unsupported - fi - ;; - - aix[[4-9]]*) - if test ia64 = "$host_cpu"; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag= - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then - aix_use_runtimelinking=yes - break - fi - done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # traditional, no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - ;; - esac - - if test yes = "$GCC"; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - ;; - esac - shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag="$shared_flag "'$wl-G' - fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' - else - # not using gcc - if test ia64 = "$host_cpu"; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' - else - shared_flag='$wl-bM:SRE' - fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag - else - if test ia64 = "$host_cpu"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' - if test yes = "$with_gnu_ld"; then - # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' - fi - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - bsdi[[45]]*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - case $cc_basename in - cl*) - # Native MSVC - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' - # Don't use ranlib - _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' - _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # Assume MSVC wrapper - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - esac - ;; - - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - dgux*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2.*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - hpux9*) - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - ;; - - hpux10*) - if test yes,no = "$GCC,$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - fi - ;; - - hpux11*) - if test yes,no = "$GCC,$with_gnu_ld"; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - m4_if($1, [], [ - # Older versions of the 11.00 compiler do not understand -b yet - # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) - _LT_LINKER_OPTION([if $CC understands -b], - _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], - [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) - ;; - esac - fi - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - # Try to use the -exported_symbol ld option, if it does not - # work, assume that -exports_file does not work either and - # implicitly export all symbols. - # This should be the same for all languages, so no per-tag cache variable. - AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], - [lt_cv_irix_exported_symbol], - [save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" - AC_LINK_IFELSE( - [AC_LANG_SOURCE( - [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], - [C++], [[int foo (void) { return 0; }]], - [Fortran 77], [[ - subroutine foo - end]], - [Fortran], [[ - subroutine foo - end]])])], - [lt_cv_irix_exported_symbol=yes], - [lt_cv_irix_exported_symbol=no]) - LDFLAGS=$save_LDFLAGS]) - if test yes = "$lt_cv_irix_exported_symbol"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' - fi - _LT_TAGVAR(link_all_deplibs, $1)=no - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - linux*) - case $cc_basename in - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - _LT_TAGVAR(ld_shlibs, $1)=yes - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - newsos6) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *nto* | *qnx*) - ;; - - openbsd* | bitrig*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - fi - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - osf3*) - if test yes = "$GCC"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test yes = "$GCC"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' - - # Both c and cxx compiler support -rpath directly - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - solaris*) - _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test yes = "$GCC"; then - wlarc='$wl' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - else - case `$CC -V 2>&1` in - *"Compilers 5.0"*) - wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' - ;; - *) - wlarc='$wl' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - ;; - esac - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. GCC discards it without '$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test yes = "$GCC"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - fi - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - sunos4*) - if test sequent = "$host_vendor"; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4) - case $host_vendor in - sni) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' - _LT_TAGVAR(hardcode_direct, $1)=no - ;; - motorola) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4.3*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - _LT_TAGVAR(ld_shlibs, $1)=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' - runpath_var='LD_RUN_PATH' - - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - if test sni = "$host_vendor"; then - case $host in - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' - ;; - esac - fi - fi -]) -AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no - -_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld - -_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl -_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl -_LT_DECL([], [extract_expsyms_cmds], [2], - [The commands to extract the exported symbol list from a shared archive]) - -# -# Do we need to explicitly link libc? -# -case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in -x|xyes) - # Assume -lc should be added - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - - if test yes,yes = "$GCC,$enable_shared"; then - case $_LT_TAGVAR(archive_cmds, $1) in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - AC_CACHE_CHECK([whether -lc should be explicitly linked in], - [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), - [$RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) - pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) - _LT_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) - then - lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no - else - lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - ]) - _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) - ;; - esac - fi - ;; -esac - -_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], - [Whether or not to add -lc for building shared libraries]) -_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], - [enable_shared_with_static_runtimes], [0], - [Whether or not to disallow shared libs when runtime libs are static]) -_LT_TAGDECL([], [export_dynamic_flag_spec], [1], - [Compiler flag to allow reflexive dlopens]) -_LT_TAGDECL([], [whole_archive_flag_spec], [1], - [Compiler flag to generate shared objects directly from archives]) -_LT_TAGDECL([], [compiler_needs_object], [1], - [Whether the compiler copes with passing no objects directly]) -_LT_TAGDECL([], [old_archive_from_new_cmds], [2], - [Create an old-style archive from a shared archive]) -_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], - [Create a temporary old-style archive to link instead of a shared archive]) -_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) -_LT_TAGDECL([], [archive_expsym_cmds], [2]) -_LT_TAGDECL([], [module_cmds], [2], - [Commands used to build a loadable module if different from building - a shared archive.]) -_LT_TAGDECL([], [module_expsym_cmds], [2]) -_LT_TAGDECL([], [with_gnu_ld], [1], - [Whether we are building with GNU ld or not]) -_LT_TAGDECL([], [allow_undefined_flag], [1], - [Flag that allows shared libraries with undefined symbols to be built]) -_LT_TAGDECL([], [no_undefined_flag], [1], - [Flag that enforces no undefined symbols]) -_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], - [Flag to hardcode $libdir into a binary during linking. - This must work even if $libdir does not exist]) -_LT_TAGDECL([], [hardcode_libdir_separator], [1], - [Whether we need a single "-rpath" flag with a separated argument]) -_LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes - DIR into the resulting binary]) -_LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes - DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting $shlibpath_var if the - library is relocated]) -_LT_TAGDECL([], [hardcode_minus_L], [0], - [Set to "yes" if using the -LDIR flag during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_shlibpath_var], [0], - [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_automatic], [0], - [Set to "yes" if building a shared library automatically hardcodes DIR - into the library and all subsequent libraries and executables linked - against it]) -_LT_TAGDECL([], [inherit_rpath], [0], - [Set to yes if linker adds runtime paths of dependent libraries - to runtime path list]) -_LT_TAGDECL([], [link_all_deplibs], [0], - [Whether libtool must link a program against all its dependency libraries]) -_LT_TAGDECL([], [always_export_symbols], [0], - [Set to "yes" if exported symbols are required]) -_LT_TAGDECL([], [export_symbols_cmds], [2], - [The commands to list exported symbols]) -_LT_TAGDECL([], [exclude_expsyms], [1], - [Symbols that should not be listed in the preloaded symbols]) -_LT_TAGDECL([], [include_expsyms], [1], - [Symbols that must always be exported]) -_LT_TAGDECL([], [prelink_cmds], [2], - [Commands necessary for linking programs (against libraries) with templates]) -_LT_TAGDECL([], [postlink_cmds], [2], - [Commands necessary for finishing linking programs]) -_LT_TAGDECL([], [file_list_spec], [1], - [Specify filename containing input files]) -dnl FIXME: Not yet implemented -dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], -dnl [Compiler flag to generate thread safe objects]) -])# _LT_LINKER_SHLIBS - - -# _LT_LANG_C_CONFIG([TAG]) -# ------------------------ -# Ensure that the configuration variables for a C compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_C_CONFIG], -[m4_require([_LT_DECL_EGREP])dnl -lt_save_CC=$CC -AC_LANG_PUSH(C) - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - -_LT_TAG_COMPILER -# Save the default compiler, since it gets overwritten when the other -# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. -compiler_DEFAULT=$CC - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - LT_SYS_DLOPEN_SELF - _LT_CMD_STRIPLIB - - # Report what library types will actually be built - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test yes = "$enable_shared" && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - - aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_CONFIG($1) -fi -AC_LANG_POP -CC=$lt_save_CC -])# _LT_LANG_C_CONFIG - - -# _LT_LANG_CXX_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a C++ compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_CXX_CONFIG], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_PATH_MANIFEST_TOOL])dnl -if test -n "$CXX" && ( test no != "$CXX" && - ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || - (test g++ != "$CXX"))); then - AC_PROG_CXXCPP -else - _lt_caught_CXX_error=yes -fi - -AC_LANG_PUSH(C++) -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(compiler_needs_object, $1)=no -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the CXX compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_caught_CXX_error"; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="int some_variable = 0;" - - # Code to be used in simple link tests - lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_CFLAGS=$CFLAGS - lt_save_LD=$LD - lt_save_GCC=$GCC - GCC=$GXX - lt_save_with_gnu_ld=$with_gnu_ld - lt_save_path_LD=$lt_cv_path_LD - if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx - else - $as_unset lt_cv_prog_gnu_ld - fi - if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX - else - $as_unset lt_cv_path_LD - fi - test -z "${LDCXX+set}" || LD=$LDCXX - CC=${CXX-"c++"} - CFLAGS=$CXXFLAGS - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - # We don't want -fno-exception when compiling C++ code, so set the - # no_builtin_flag separately - if test yes = "$GXX"; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - else - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - fi - - if test yes = "$GXX"; then - # Set up default GNU C++ configuration - - LT_PATH_LD - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test yes = "$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='$wl' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | - $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' - - else - GXX=no - with_gnu_ld=no - wlarc= - fi - - # PORTME: fill in a description of your system's C++ link characteristics - AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) - _LT_TAGVAR(ld_shlibs, $1)=yes - case $host_os in - aix3*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aix[[4-9]]*) - if test ia64 = "$host_cpu"; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag= - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - ;; - esac - - if test yes = "$GXX"; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag=$shared_flag' $wl-G' - fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' - else - # not using gcc - if test ia64 = "$host_cpu"; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' - else - shared_flag='$wl-bM:SRE' - fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to - # export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - # The "-G" linker flag allows undefined symbols. - _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' - # Determine the default libpath from the value encoded in an empty - # executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag - else - if test ia64 = "$host_cpu"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' - if test yes = "$with_gnu_ld"; then - # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared - # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - cygwin* | mingw* | pw32* | cegcc*) - case $GXX,$cc_basename in - ,cl* | no,cl*) - # Native MSVC - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - # Don't use ranlib - _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' - _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # g++ - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - freebsd2.*) - # C++ shared libraries reported to be fairly broken before - # switch to ELF - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - freebsd-elf*) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes = "$GXX"; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - hpux10*|hpux11*) - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' - fi - fi - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc* | ecpc* ) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - case `$CC -V` in - *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) - _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' - _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' - _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 6 and above use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - ;; - cxx*) - # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' - ;; - xl* | mpixl* | bgxl*) - # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test yes = "$supports_anon_versioning"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' - fi - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - - lynxos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - m88k*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - - *nto* | *qnx*) - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - openbsd* | bitrig*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - fi - output_verbose_link_cmd=func_echo_all - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - case $host in - osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; - *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; - esac - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - cxx*) - case $host in - osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - ;; - *) - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ - $RM $lib.exp' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes,no = "$GXX,$with_gnu_ld"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - case $host in - osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' - - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - psos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(archive_cmds_need_lc,$1)=yes - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test yes,no = "$GXX,$with_gnu_ld"; then - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' - if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' - else - # g++ 2.7 appears to require '-G' NOT '-shared' on this - # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' - fi - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ - '"$_LT_TAGVAR(old_archive_cmds, $1)" - _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ - '"$_LT_TAGVAR(reload_cmds, $1)" - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - vxworks*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no - - _LT_TAGVAR(GCC, $1)=$GXX - _LT_TAGVAR(LD, $1)=$LD - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS - LDCXX=$LD - LD=$lt_save_LD - GCC=$lt_save_GCC - with_gnu_ld=$lt_save_with_gnu_ld - lt_cv_path_LDCXX=$lt_cv_path_LD - lt_cv_path_LD=$lt_save_path_LD - lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld - lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test yes != "$_lt_caught_CXX_error" - -AC_LANG_POP -])# _LT_LANG_CXX_CONFIG - - -# _LT_FUNC_STRIPNAME_CNF -# ---------------------- -# func_stripname_cnf prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# -# This function is identical to the (non-XSI) version of func_stripname, -# except this one can be used by m4 code that may be executed by configure, -# rather than the libtool script. -m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl -AC_REQUIRE([_LT_DECL_SED]) -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) -func_stripname_cnf () -{ - case @S|@2 in - .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; - *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; - esac -} # func_stripname_cnf -])# _LT_FUNC_STRIPNAME_CNF - - -# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) -# --------------------------------- -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -m4_defun([_LT_SYS_HIDDEN_LIBDEPS], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl -# Dependencies to place before and after the object being linked: -_LT_TAGVAR(predep_objects, $1)= -_LT_TAGVAR(postdep_objects, $1)= -_LT_TAGVAR(predeps, $1)= -_LT_TAGVAR(postdeps, $1)= -_LT_TAGVAR(compiler_lib_search_path, $1)= - -dnl we can't use the lt_simple_compile_test_code here, -dnl because it contains code intended for an executable, -dnl not a library. It's possible we should let each -dnl tag define a new lt_????_link_test_code variable, -dnl but it's only used here... -m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF -int a; -void foo (void) { a = 0; } -_LT_EOF -], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF -class Foo -{ -public: - Foo (void) { a = 0; } -private: - int a; -}; -_LT_EOF -], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer*4 a - a=0 - return - end -_LT_EOF -], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer a - a=0 - return - end -_LT_EOF -], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF -public class foo { - private int a; - public void bar (void) { - a = 0; - } -}; -_LT_EOF -], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF -package foo -func foo() { -} -_LT_EOF -]) - -_lt_libdeps_save_CFLAGS=$CFLAGS -case "$CC $CFLAGS " in #( -*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; -*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; -*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; -esac - -dnl Parse the compiler output and extract the necessary -dnl objects, libraries and library flags. -if AC_TRY_EVAL(ac_compile); then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - for p in `eval "$output_verbose_link_cmd"`; do - case $prev$p in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test x-L = "$p" || - test x-R = "$p"; then - prev=$p - continue - fi - - # Expand the sysroot to ease extracting the directories later. - if test -z "$prev"; then - case $p in - -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; - -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; - -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; - esac - fi - case $p in - =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; - esac - if test no = "$pre_test_object_deps_done"; then - case $prev in - -L | -R) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p - else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)=$prev$p - else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" - fi - fi - prev= - ;; - - *.lto.$objext) ;; # Ignore GCC LTO objects - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test no = "$pre_test_object_deps_done"; then - if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)=$p - else - _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" - fi - else - if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)=$p - else - _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling $1 test program" -fi - -$RM -f confest.$objext -CFLAGS=$_lt_libdeps_save_CFLAGS - -# PORTME: override above test on systems where it is broken -m4_if([$1], [CXX], -[case $host_os in -interix[[3-9]]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - _LT_TAGVAR(predep_objects,$1)= - _LT_TAGVAR(postdep_objects,$1)= - _LT_TAGVAR(postdeps,$1)= - ;; -esac -]) - -case " $_LT_TAGVAR(postdeps, $1) " in -*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; -esac - _LT_TAGVAR(compiler_lib_search_dirs, $1)= -if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` -fi -_LT_TAGDECL([], [compiler_lib_search_dirs], [1], - [The directories searched by this compiler when creating a shared library]) -_LT_TAGDECL([], [predep_objects], [1], - [Dependencies to place before and after the objects being linked to - create a shared library]) -_LT_TAGDECL([], [postdep_objects], [1]) -_LT_TAGDECL([], [predeps], [1]) -_LT_TAGDECL([], [postdeps], [1]) -_LT_TAGDECL([], [compiler_lib_search_path], [1], - [The library search path used internally by the compiler when linking - a shared library]) -])# _LT_SYS_HIDDEN_LIBDEPS - - -# _LT_LANG_F77_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a Fortran 77 compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_F77_CONFIG], -[AC_LANG_PUSH(Fortran 77) -if test -z "$F77" || test no = "$F77"; then - _lt_disable_F77=yes -fi - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the F77 compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_disable_F77"; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_GCC=$GCC - lt_save_CFLAGS=$CFLAGS - CC=${F77-"f77"} - CFLAGS=$FFLAGS - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - GCC=$G77 - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test yes = "$enable_shared" && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)=$G77 - _LT_TAGVAR(LD, $1)=$LD - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS -fi # test yes != "$_lt_disable_F77" - -AC_LANG_POP -])# _LT_LANG_F77_CONFIG - - -# _LT_LANG_FC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for a Fortran compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_FC_CONFIG], -[AC_LANG_PUSH(Fortran) - -if test -z "$FC" || test no = "$FC"; then - _lt_disable_FC=yes -fi - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for fc test sources. -ac_ext=${ac_fc_srcext-f} - -# Object file extension for compiled fc test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the FC compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_disable_FC"; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_GCC=$GCC - lt_save_CFLAGS=$CFLAGS - CC=${FC-"f95"} - CFLAGS=$FCFLAGS - compiler=$CC - GCC=$ac_cv_fc_compiler_gnu - - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test yes = "$enable_shared" && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu - _LT_TAGVAR(LD, $1)=$LD - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS -fi # test yes != "$_lt_disable_FC" - -AC_LANG_POP -])# _LT_LANG_FC_CONFIG - - -# _LT_LANG_GCJ_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for the GNU Java Compiler compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_GCJ_CONFIG], -[AC_REQUIRE([LT_PROG_GCJ])dnl -AC_LANG_SAVE - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC=yes -CC=${GCJ-"gcj"} -CFLAGS=$GCJFLAGS -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)=$LD -_LT_CC_BASENAME([$compiler]) - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -_LT_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) -fi - -AC_LANG_RESTORE - -GCC=$lt_save_GCC -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_GCJ_CONFIG - - -# _LT_LANG_GO_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for the GNU Go compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_GO_CONFIG], -[AC_REQUIRE([LT_PROG_GO])dnl -AC_LANG_SAVE - -# Source file extension for Go test sources. -ac_ext=go - -# Object file extension for compiled Go test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="package main; func main() { }" - -# Code to be used in simple link tests -lt_simple_link_test_code='package main; func main() { }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC=yes -CC=${GOC-"gccgo"} -CFLAGS=$GOFLAGS -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)=$LD -_LT_CC_BASENAME([$compiler]) - -# Go did not exist at the time GCC didn't implicitly link libc in. -_LT_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) -fi - -AC_LANG_RESTORE - -GCC=$lt_save_GCC -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_GO_CONFIG - - -# _LT_LANG_RC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for the Windows resource compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_RC_CONFIG], -[AC_REQUIRE([LT_PROG_RC])dnl -AC_LANG_SAVE - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' - -# Code to be used in simple link tests -lt_simple_link_test_code=$lt_simple_compile_test_code - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC= -CC=${RC-"windres"} -CFLAGS= -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) -_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - -if test -n "$compiler"; then - : - _LT_CONFIG($1) -fi - -GCC=$lt_save_GCC -AC_LANG_RESTORE -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_RC_CONFIG - - -# LT_PROG_GCJ -# ----------- -AC_DEFUN([LT_PROG_GCJ], -[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], - [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], - [AC_CHECK_TOOL(GCJ, gcj,) - test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" - AC_SUBST(GCJFLAGS)])])[]dnl -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_GCJ], []) - - -# LT_PROG_GO -# ---------- -AC_DEFUN([LT_PROG_GO], -[AC_CHECK_TOOL(GOC, gccgo,) -]) - - -# LT_PROG_RC -# ---------- -AC_DEFUN([LT_PROG_RC], -[AC_CHECK_TOOL(RC, windres,) -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_RC], []) - - -# _LT_DECL_EGREP -# -------------- -# If we don't have a new enough Autoconf to choose the best grep -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_EGREP], -[AC_REQUIRE([AC_PROG_EGREP])dnl -AC_REQUIRE([AC_PROG_FGREP])dnl -test -z "$GREP" && GREP=grep -_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) -_LT_DECL([], [EGREP], [1], [An ERE matcher]) -_LT_DECL([], [FGREP], [1], [A literal string matcher]) -dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too -AC_SUBST([GREP]) -]) - - -# _LT_DECL_OBJDUMP -# -------------- -# If we don't have a new enough Autoconf to choose the best objdump -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_OBJDUMP], -[AC_CHECK_TOOL(OBJDUMP, objdump, false) -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) -AC_SUBST([OBJDUMP]) -]) - -# _LT_DECL_DLLTOOL -# ---------------- -# Ensure DLLTOOL variable is set. -m4_defun([_LT_DECL_DLLTOOL], -[AC_CHECK_TOOL(DLLTOOL, dlltool, false) -test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) -AC_SUBST([DLLTOOL]) -]) - -# _LT_DECL_SED -# ------------ -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. -m4_defun([_LT_DECL_SED], -[AC_PROG_SED -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" -_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) -_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], - [Sed that helps us avoid accidentally triggering echo(1) options like -n]) -])# _LT_DECL_SED - -m4_ifndef([AC_PROG_SED], [ -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ - -m4_defun([AC_PROG_SED], -[AC_MSG_CHECKING([for a sed that does not truncate output]) -AC_CACHE_VAL(lt_cv_path_SED, -[# Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -IFS=$as_save_IFS -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f "$lt_ac_sed" && continue - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test 10 -lt "$lt_ac_count" && break - lt_ac_count=`expr $lt_ac_count + 1` - if test "$lt_ac_count" -gt "$lt_ac_max"; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -]) -SED=$lt_cv_path_SED -AC_SUBST([SED]) -AC_MSG_RESULT([$SED]) -])#AC_PROG_SED -])#m4_ifndef - -# Old name: -AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_SED], []) - - -# _LT_CHECK_SHELL_FEATURES -# ------------------------ -# Find out whether the shell is Bourne or XSI compatible, -# or has some other useful features. -m4_defun([_LT_CHECK_SHELL_FEATURES], -[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi -_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl - -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' - ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' - ;; -esac -_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl -_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl -])# _LT_CHECK_SHELL_FEATURES - - -# _LT_PATH_CONVERSION_FUNCTIONS -# ----------------------------- -# Determine what file name conversion functions should be used by -# func_to_host_file (and, implicitly, by func_to_host_path). These are needed -# for certain cross-compile configurations and native mingw. -m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_MSG_CHECKING([how to convert $build file names to $host format]) -AC_CACHE_VAL(lt_cv_to_host_file_cmd, -[case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 - ;; - esac - ;; - *-*-cygwin* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin - ;; - esac - ;; - * ) # unhandled hosts (and "normal" native builds) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; -esac -]) -to_host_file_cmd=$lt_cv_to_host_file_cmd -AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) -_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], - [0], [convert $build file names to $host format])dnl - -AC_MSG_CHECKING([how to convert $build file names to toolchain format]) -AC_CACHE_VAL(lt_cv_to_tool_file_cmd, -[#assume ordinary cross tools, or native build. -lt_cv_to_tool_file_cmd=func_convert_file_noop -case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 - ;; - esac - ;; -esac -]) -to_tool_file_cmd=$lt_cv_to_tool_file_cmd -AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) -_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], - [0], [convert $build files to toolchain format])dnl -])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/ext/libpqxx-7.7.3/config/m4/ltoptions.m4 b/ext/libpqxx-7.7.3/config/m4/ltoptions.m4 deleted file mode 100644 index 94b082976..000000000 --- a/ext/libpqxx-7.7.3/config/m4/ltoptions.m4 +++ /dev/null @@ -1,437 +0,0 @@ -# Helper functions for option handling. -*- Autoconf -*- -# -# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software -# Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 8 ltoptions.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) - - -# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) -# ------------------------------------------ -m4_define([_LT_MANGLE_OPTION], -[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) - - -# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) -# --------------------------------------- -# Set option OPTION-NAME for macro MACRO-NAME, and if there is a -# matching handler defined, dispatch to it. Other OPTION-NAMEs are -# saved as a flag. -m4_define([_LT_SET_OPTION], -[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl -m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), - _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option '$2'])])[]dnl -]) - - -# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) -# ------------------------------------------------------------ -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -m4_define([_LT_IF_OPTION], -[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) - - -# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) -# ------------------------------------------------------- -# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME -# are set. -m4_define([_LT_UNLESS_OPTIONS], -[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), - [m4_define([$0_found])])])[]dnl -m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 -])[]dnl -]) - - -# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) -# ---------------------------------------- -# OPTION-LIST is a space-separated list of Libtool options associated -# with MACRO-NAME. If any OPTION has a matching handler declared with -# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about -# the unknown option and exit. -m4_defun([_LT_SET_OPTIONS], -[# Set options -m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [_LT_SET_OPTION([$1], _LT_Option)]) - -m4_if([$1],[LT_INIT],[ - dnl - dnl Simply set some default values (i.e off) if boolean options were not - dnl specified: - _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no - ]) - _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no - ]) - dnl - dnl If no reference was made to various pairs of opposing options, then - dnl we run the default mode handler for the pair. For example, if neither - dnl 'shared' nor 'disable-shared' was passed, we enable building of shared - dnl archives by default: - _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) - _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) - _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], - [_LT_WITH_AIX_SONAME([aix])]) - ]) -])# _LT_SET_OPTIONS - - -## --------------------------------- ## -## Macros to handle LT_INIT options. ## -## --------------------------------- ## - -# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) -# ----------------------------------------- -m4_define([_LT_MANGLE_DEFUN], -[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) - - -# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) -# ----------------------------------------------- -m4_define([LT_OPTION_DEFINE], -[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl -])# LT_OPTION_DEFINE - - -# dlopen -# ------ -LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes -]) - -AU_DEFUN([AC_LIBTOOL_DLOPEN], -[_LT_SET_OPTION([LT_INIT], [dlopen]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'dlopen' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) - - -# win32-dll -# --------- -# Declare package support for building win32 dll's. -LT_OPTION_DEFINE([LT_INIT], [win32-dll], -[enable_win32_dll=yes - -case $host in -*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; -esac - -test -z "$AS" && AS=as -_LT_DECL([], [AS], [1], [Assembler program])dnl - -test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl - -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl -])# win32-dll - -AU_DEFUN([AC_LIBTOOL_WIN32_DLL], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -_LT_SET_OPTION([LT_INIT], [win32-dll]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'win32-dll' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) - - -# _LT_ENABLE_SHARED([DEFAULT]) -# ---------------------------- -# implement the --enable-shared flag, and supports the 'shared' and -# 'disable-shared' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. -m4_define([_LT_ENABLE_SHARED], -[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([shared], - [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], - [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS=$lt_save_ifs - ;; - esac], - [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) - - _LT_DECL([build_libtool_libs], [enable_shared], [0], - [Whether or not to build shared libraries]) -])# _LT_ENABLE_SHARED - -LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) -]) - -AC_DEFUN([AC_DISABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], [disable-shared]) -]) - -AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) -AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_SHARED], []) -dnl AC_DEFUN([AM_DISABLE_SHARED], []) - - - -# _LT_ENABLE_STATIC([DEFAULT]) -# ---------------------------- -# implement the --enable-static flag, and support the 'static' and -# 'disable-static' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. -m4_define([_LT_ENABLE_STATIC], -[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([static], - [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], - [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS=$lt_save_ifs - ;; - esac], - [enable_static=]_LT_ENABLE_STATIC_DEFAULT) - - _LT_DECL([build_old_libs], [enable_static], [0], - [Whether or not to build static libraries]) -])# _LT_ENABLE_STATIC - -LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) -]) - -AC_DEFUN([AC_DISABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], [disable-static]) -]) - -AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) -AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_STATIC], []) -dnl AC_DEFUN([AM_DISABLE_STATIC], []) - - - -# _LT_ENABLE_FAST_INSTALL([DEFAULT]) -# ---------------------------------- -# implement the --enable-fast-install flag, and support the 'fast-install' -# and 'disable-fast-install' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. -m4_define([_LT_ENABLE_FAST_INSTALL], -[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([fast-install], - [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], - [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS=$lt_save_ifs - ;; - esac], - [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) - -_LT_DECL([fast_install], [enable_fast_install], [0], - [Whether or not to optimize for fast installation])dnl -])# _LT_ENABLE_FAST_INSTALL - -LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) - -# Old names: -AU_DEFUN([AC_ENABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the 'fast-install' option into LT_INIT's first parameter.]) -]) - -AU_DEFUN([AC_DISABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the 'disable-fast-install' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) -dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) - - -# _LT_WITH_AIX_SONAME([DEFAULT]) -# ---------------------------------- -# implement the --with-aix-soname flag, and support the `aix-soname=aix' -# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT -# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. -m4_define([_LT_WITH_AIX_SONAME], -[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl -shared_archive_member_spec= -case $host,$enable_shared in -power*-*-aix[[5-9]]*,yes) - AC_MSG_CHECKING([which variant of shared library versioning to provide]) - AC_ARG_WITH([aix-soname], - [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], - [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], - [case $withval in - aix|svr4|both) - ;; - *) - AC_MSG_ERROR([Unknown argument to --with-aix-soname]) - ;; - esac - lt_cv_with_aix_soname=$with_aix_soname], - [AC_CACHE_VAL([lt_cv_with_aix_soname], - [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) - with_aix_soname=$lt_cv_with_aix_soname]) - AC_MSG_RESULT([$with_aix_soname]) - if test aix != "$with_aix_soname"; then - # For the AIX way of multilib, we name the shared archive member - # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', - # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. - # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, - # the AIX toolchain works better with OBJECT_MODE set (default 32). - if test 64 = "${OBJECT_MODE-32}"; then - shared_archive_member_spec=shr_64 - else - shared_archive_member_spec=shr - fi - fi - ;; -*) - with_aix_soname=aix - ;; -esac - -_LT_DECL([], [shared_archive_member_spec], [0], - [Shared archive member basename, for filename based shared library versioning on AIX])dnl -])# _LT_WITH_AIX_SONAME - -LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) -LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) -LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) - - -# _LT_WITH_PIC([MODE]) -# -------------------- -# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' -# LT_INIT options. -# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. -m4_define([_LT_WITH_PIC], -[AC_ARG_WITH([pic], - [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], - [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [lt_p=${PACKAGE-default} - case $withval in - yes|no) pic_mode=$withval ;; - *) - pic_mode=default - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for lt_pkg in $withval; do - IFS=$lt_save_ifs - if test "X$lt_pkg" = "X$lt_p"; then - pic_mode=yes - fi - done - IFS=$lt_save_ifs - ;; - esac], - [pic_mode=m4_default([$1], [default])]) - -_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl -])# _LT_WITH_PIC - -LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) - -# Old name: -AU_DEFUN([AC_LIBTOOL_PICMODE], -[_LT_SET_OPTION([LT_INIT], [pic-only]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'pic-only' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) - -## ----------------- ## -## LTDL_INIT Options ## -## ----------------- ## - -m4_define([_LTDL_MODE], []) -LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], - [m4_define([_LTDL_MODE], [nonrecursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [recursive], - [m4_define([_LTDL_MODE], [recursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [subproject], - [m4_define([_LTDL_MODE], [subproject])]) - -m4_define([_LTDL_TYPE], []) -LT_OPTION_DEFINE([LTDL_INIT], [installable], - [m4_define([_LTDL_TYPE], [installable])]) -LT_OPTION_DEFINE([LTDL_INIT], [convenience], - [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/ext/libpqxx-7.7.3/config/m4/ltsugar.m4 b/ext/libpqxx-7.7.3/config/m4/ltsugar.m4 deleted file mode 100644 index 48bc9344a..000000000 --- a/ext/libpqxx-7.7.3/config/m4/ltsugar.m4 +++ /dev/null @@ -1,124 +0,0 @@ -# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- -# -# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software -# Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 6 ltsugar.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) - - -# lt_join(SEP, ARG1, [ARG2...]) -# ----------------------------- -# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their -# associated separator. -# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier -# versions in m4sugar had bugs. -m4_define([lt_join], -[m4_if([$#], [1], [], - [$#], [2], [[$2]], - [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) -m4_define([_lt_join], -[m4_if([$#$2], [2], [], - [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) - - -# lt_car(LIST) -# lt_cdr(LIST) -# ------------ -# Manipulate m4 lists. -# These macros are necessary as long as will still need to support -# Autoconf-2.59, which quotes differently. -m4_define([lt_car], [[$1]]) -m4_define([lt_cdr], -[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], - [$#], 1, [], - [m4_dquote(m4_shift($@))])]) -m4_define([lt_unquote], $1) - - -# lt_append(MACRO-NAME, STRING, [SEPARATOR]) -# ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. -# Note that neither SEPARATOR nor STRING are expanded; they are appended -# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). -# No SEPARATOR is output if MACRO-NAME was previously undefined (different -# than defined and empty). -# -# This macro is needed until we can rely on Autoconf 2.62, since earlier -# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. -m4_define([lt_append], -[m4_define([$1], - m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) - - - -# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) -# ---------------------------------------------------------- -# Produce a SEP delimited list of all paired combinations of elements of -# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list -# has the form PREFIXmINFIXSUFFIXn. -# Needed until we can rely on m4_combine added in Autoconf 2.62. -m4_define([lt_combine], -[m4_if(m4_eval([$# > 3]), [1], - [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl -[[m4_foreach([_Lt_prefix], [$2], - [m4_foreach([_Lt_suffix], - ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, - [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) - - -# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) -# ----------------------------------------------------------------------- -# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited -# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. -m4_define([lt_if_append_uniq], -[m4_ifdef([$1], - [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], - [lt_append([$1], [$2], [$3])$4], - [$5])], - [lt_append([$1], [$2], [$3])$4])]) - - -# lt_dict_add(DICT, KEY, VALUE) -# ----------------------------- -m4_define([lt_dict_add], -[m4_define([$1($2)], [$3])]) - - -# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) -# -------------------------------------------- -m4_define([lt_dict_add_subkey], -[m4_define([$1($2:$3)], [$4])]) - - -# lt_dict_fetch(DICT, KEY, [SUBKEY]) -# ---------------------------------- -m4_define([lt_dict_fetch], -[m4_ifval([$3], - m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), - m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) - - -# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) -# ----------------------------------------------------------------- -m4_define([lt_if_dict_fetch], -[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], - [$5], - [$6])]) - - -# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) -# -------------------------------------------------------------- -m4_define([lt_dict_filter], -[m4_if([$5], [], [], - [lt_join(m4_quote(m4_default([$4], [[, ]])), - lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), - [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl -]) diff --git a/ext/libpqxx-7.7.3/config/m4/ltversion.m4 b/ext/libpqxx-7.7.3/config/m4/ltversion.m4 deleted file mode 100644 index fa04b52a3..000000000 --- a/ext/libpqxx-7.7.3/config/m4/ltversion.m4 +++ /dev/null @@ -1,23 +0,0 @@ -# ltversion.m4 -- version numbers -*- Autoconf -*- -# -# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# @configure_input@ - -# serial 4179 ltversion.m4 -# This file is part of GNU Libtool - -m4_define([LT_PACKAGE_VERSION], [2.4.6]) -m4_define([LT_PACKAGE_REVISION], [2.4.6]) - -AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.6' -macro_revision='2.4.6' -_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) -_LT_DECL(, macro_revision, 0) -]) diff --git a/ext/libpqxx-7.7.3/config/m4/lt~obsolete.m4 b/ext/libpqxx-7.7.3/config/m4/lt~obsolete.m4 deleted file mode 100644 index c6b26f88f..000000000 --- a/ext/libpqxx-7.7.3/config/m4/lt~obsolete.m4 +++ /dev/null @@ -1,99 +0,0 @@ -# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- -# -# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software -# Foundation, Inc. -# Written by Scott James Remnant, 2004. -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 5 lt~obsolete.m4 - -# These exist entirely to fool aclocal when bootstrapping libtool. -# -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), -# which have later been changed to m4_define as they aren't part of the -# exported API, or moved to Autoconf or Automake where they belong. -# -# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN -# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us -# using a macro with the same name in our local m4/libtool.m4 it'll -# pull the old libtool.m4 in (it doesn't see our shiny new m4_define -# and doesn't know about Autoconf macros at all.) -# -# So we provide this file, which has a silly filename so it's always -# included after everything else. This provides aclocal with the -# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything -# because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. -# -# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. -# Yes, that means every name once taken will need to remain here until -# we give up compatibility with versions before 1.7, at which point -# we need to keep only those names which we still refer to. - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) - -m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) -m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) -m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) -m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) -m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) -m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) -m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) -m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) -m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) -m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) -m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) -m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) -m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) -m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) -m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) -m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) -m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) -m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) -m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) -m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) -m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) -m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) -m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) -m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) -m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) -m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) -m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) -m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) -m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) -m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) -m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) -m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) -m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) -m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) -m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) -m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) -m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) -m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) -m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) -m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) -m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) -m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) -m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) -m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) -m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) -m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) -m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) -m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) -m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/ext/libpqxx-7.7.3/config/missing b/ext/libpqxx-7.7.3/config/missing deleted file mode 100755 index 1fe1611f1..000000000 --- a/ext/libpqxx-7.7.3/config/missing +++ /dev/null @@ -1,215 +0,0 @@ -#! /bin/sh -# Common wrapper for a few potentially missing GNU programs. - -scriptversion=2018-03-07.03; # UTC - -# Copyright (C) 1996-2021 Free Software Foundation, Inc. -# Originally written by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try '$0 --help' for more information" - exit 1 -fi - -case $1 in - - --is-lightweight) - # Used by our autoconf macros to check whether the available missing - # script is modern enough. - exit 0 - ;; - - --run) - # Back-compat with the calling convention used by older automake. - shift - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due -to PROGRAM being missing or too old. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - -Supported PROGRAM values: - aclocal autoconf autoheader autom4te automake makeinfo - bison yacc flex lex help2man - -Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and -'g' are ignored when checking the name. - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: unknown '$1' option" - echo 1>&2 "Try '$0 --help' for more information" - exit 1 - ;; - -esac - -# Run the given program, remember its exit status. -"$@"; st=$? - -# If it succeeded, we are done. -test $st -eq 0 && exit 0 - -# Also exit now if we it failed (or wasn't found), and '--version' was -# passed; such an option is passed most likely to detect whether the -# program is present and works. -case $2 in --version|--help) exit $st;; esac - -# Exit code 63 means version mismatch. This often happens when the user -# tries to use an ancient version of a tool on a file that requires a -# minimum version. -if test $st -eq 63; then - msg="probably too old" -elif test $st -eq 127; then - # Program was missing. - msg="missing on your system" -else - # Program was found and executed, but failed. Give up. - exit $st -fi - -perl_URL=https://www.perl.org/ -flex_URL=https://github.com/westes/flex -gnu_software_URL=https://www.gnu.org/software - -program_details () -{ - case $1 in - aclocal|automake) - echo "The '$1' program is part of the GNU Automake package:" - echo "<$gnu_software_URL/automake>" - echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/autoconf>" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - autoconf|autom4te|autoheader) - echo "The '$1' program is part of the GNU Autoconf package:" - echo "<$gnu_software_URL/autoconf/>" - echo "It also requires GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - esac -} - -give_advice () -{ - # Normalize program name to check for. - normalized_program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - - printf '%s\n' "'$1' is $msg." - - configure_deps="'configure.ac' or m4 files included by 'configure.ac'" - case $normalized_program in - autoconf*) - echo "You should only need it if you modified 'configure.ac'," - echo "or m4 files included by it." - program_details 'autoconf' - ;; - autoheader*) - echo "You should only need it if you modified 'acconfig.h' or" - echo "$configure_deps." - program_details 'autoheader' - ;; - automake*) - echo "You should only need it if you modified 'Makefile.am' or" - echo "$configure_deps." - program_details 'automake' - ;; - aclocal*) - echo "You should only need it if you modified 'acinclude.m4' or" - echo "$configure_deps." - program_details 'aclocal' - ;; - autom4te*) - echo "You might have modified some maintainer files that require" - echo "the 'autom4te' program to be rebuilt." - program_details 'autom4te' - ;; - bison*|yacc*) - echo "You should only need it if you modified a '.y' file." - echo "You may want to install the GNU Bison package:" - echo "<$gnu_software_URL/bison/>" - ;; - lex*|flex*) - echo "You should only need it if you modified a '.l' file." - echo "You may want to install the Fast Lexical Analyzer package:" - echo "<$flex_URL>" - ;; - help2man*) - echo "You should only need it if you modified a dependency" \ - "of a man page." - echo "You may want to install the GNU Help2man package:" - echo "<$gnu_software_URL/help2man/>" - ;; - makeinfo*) - echo "You should only need it if you modified a '.texi' file, or" - echo "any other file indirectly affecting the aspect of the manual." - echo "You might want to install the Texinfo package:" - echo "<$gnu_software_URL/texinfo/>" - echo "The spurious makeinfo call might also be the consequence of" - echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" - echo "want to install GNU make:" - echo "<$gnu_software_URL/make/>" - ;; - *) - echo "You might have modified some files without having the proper" - echo "tools for further handling them. Check the 'README' file, it" - echo "often tells you about the needed prerequisites for installing" - echo "this package. You may also peek at any GNU archive site, in" - echo "case some other package contains this missing '$1' program." - ;; - esac -} - -give_advice "$1" | sed -e '1s/^/WARNING: /' \ - -e '2,$s/^/ /' >&2 - -# Propagate the correct exit status (expected to be 127 for a program -# not found, 63 for a program that failed due to version mismatch). -exit $st - -# Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC0" -# time-stamp-end: "; # UTC" -# End: diff --git a/ext/libpqxx-7.7.3/config/mkinstalldirs b/ext/libpqxx-7.7.3/config/mkinstalldirs deleted file mode 100755 index 6b3b5fc5d..000000000 --- a/ext/libpqxx-7.7.3/config/mkinstalldirs +++ /dev/null @@ -1,40 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -# $Id$ - -errstatus=0 - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# mkinstalldirs ends here diff --git a/ext/libpqxx-7.7.3/config/test-driver b/ext/libpqxx-7.7.3/config/test-driver deleted file mode 100755 index 8e575b017..000000000 --- a/ext/libpqxx-7.7.3/config/test-driver +++ /dev/null @@ -1,148 +0,0 @@ -#! /bin/sh -# test-driver - basic testsuite driver script. - -scriptversion=2013-07-13.22; # UTC - -# Copyright (C) 2011-2014 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -# Make unconditional expansion of undefined variables an error. This -# helps a lot in preventing typo-related bugs. -set -u - -usage_error () -{ - echo "$0: $*" >&2 - print_usage >&2 - exit 2 -} - -print_usage () -{ - cat <$log_file 2>&1 -estatus=$? - -if test $enable_hard_errors = no && test $estatus -eq 99; then - tweaked_estatus=1 -else - tweaked_estatus=$estatus -fi - -case $tweaked_estatus:$expect_failure in - 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; - 0:*) col=$grn res=PASS recheck=no gcopy=no;; - 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; - 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; - *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; - *:*) col=$red res=FAIL recheck=yes gcopy=yes;; -esac - -# Report the test outcome and exit status in the logs, so that one can -# know whether the test passed or failed simply by looking at the '.log' -# file, without the need of also peaking into the corresponding '.trs' -# file (automake bug#11814). -echo "$res $test_name (exit status: $estatus)" >>$log_file - -# Report outcome to console. -echo "${col}${res}${std}: $test_name" - -# Register the test result, and other relevant metadata. -echo ":test-result: $res" > $trs_file -echo ":global-test-result: $res" >> $trs_file -echo ":recheck: $recheck" >> $trs_file -echo ":copy-in-global-log: $gcopy" >> $trs_file - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/ext/libpqxx-7.7.3/configitems b/ext/libpqxx-7.7.3/configitems deleted file mode 100644 index e6f3925ef..000000000 --- a/ext/libpqxx-7.7.3/configitems +++ /dev/null @@ -1,26 +0,0 @@ -PACKAGE internal autotools -PACKAGE_BUGREPORT internal autotools -PACKAGE_NAME internal autotools -PACKAGE_STRING internal autotools -PACKAGE_TARNAME internal autotools -PACKAGE_VERSION internal autotools -PQXX_HAVE_CHARCONV_INT internal compiler -PQXX_HAVE_CHARCONV_FLOAT internal compiler -PQXX_HAVE_CMP public compiler -PQXX_HAVE_CONCEPTS public compiler -PQXX_HAVE_CXA_DEMANGLE internal compiler -PQXX_HAVE_GCC_PURE public compiler -PQXX_HAVE_GCC_VISIBILITY public compiler -PQXX_HAVE_LIKELY public compiler -PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT public compiler -PQXX_HAVE_PATH public compiler -PQXX_HAVE_POLL internal compiler -PQXX_HAVE_PQENCRYPTPASSWORDCONN internal libpq -PQXX_HAVE_PQ_PIPELINE internal libpq -PQXX_HAVE_SLEEP_FOR internal compiler -PQXX_HAVE_SPAN public compiler -PQXX_HAVE_STRERROR_R internal compiler -PQXX_HAVE_STRERROR_S internal compiler -PQXX_HAVE_THREAD_LOCAL internal compiler -PQXX_HAVE_YEAR_MONTH_DAY public compiler -VERSION internal autotools diff --git a/ext/libpqxx-7.7.3/configure b/ext/libpqxx-7.7.3/configure deleted file mode 100755 index 4c58f19c2..000000000 --- a/ext/libpqxx-7.7.3/configure +++ /dev/null @@ -1,20443 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libpqxx 7.7.3. -# -# Report bugs to . -# -# -# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Use a proper internal environment variable to ensure we don't fall - # into an infinite loop, continuously re-executing ourselves. - if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then - _as_can_reexec=no; export _as_can_reexec; - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -as_fn_exit 255 - fi - # We don't want this to propagate to other subprocesses. - { _as_can_reexec=; unset _as_can_reexec;} -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : - -else - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || exit 1 -test -x / || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 - - test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( - ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' - ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO - ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO - PATH=/empty FPATH=/empty; export PATH FPATH - test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ - || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes -else - as_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - if test "x$CONFIG_SHELL" != x; then : - export CONFIG_SHELL - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org and Jeroen T. -$0: Vermeulen about your system, including any error -$0: possibly output before this message. Then install a -$0: modern shell, or manually run the script under such a -$0: shell if you do have one." - fi - exit 1 -fi -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # If we had to re-execute with $CONFIG_SHELL, we're ensured to have - # already done that, so ensure we don't try to do so again and fall - # in an infinite loop. This has already happened in practice. - _as_can_reexec=no; export _as_can_reexec - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - -SHELL=${CONFIG_SHELL-/bin/sh} - - -test -n "$DJDIR" || exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME='libpqxx' -PACKAGE_TARNAME='libpqxx' -PACKAGE_VERSION='7.7.3' -PACKAGE_STRING='libpqxx 7.7.3' -PACKAGE_BUGREPORT='Jeroen T. Vermeulen' -PACKAGE_URL='' - -ac_unique_file="src/connection.cxx" -ac_default_prefix=/usr/local -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='am__EXEEXT_FALSE -am__EXEEXT_TRUE -LTLIBOBJS -LIBOBJS -with_postgres_lib -POSTGRES_INCLUDE -PG_CONFIG -PKG_CONFIG -MAINT -MAINTAINER_MODE_FALSE -MAINTAINER_MODE_TRUE -BUILD_REFERENCE_FALSE -BUILD_REFERENCE_TRUE -HAVE_DOT -DOXYGEN -MKDIR -CXXCPP -CPP -LT_SYS_LIBRARY_PATH -OTOOL64 -OTOOL -LIPO -NMEDIT -DSYMUTIL -MANIFEST_TOOL -RANLIB -ac_ct_AR -AR -DLLTOOL -OBJDUMP -LN_S -NM -ac_ct_DUMPBIN -DUMPBIN -LD -FGREP -EGREP -GREP -SED -am__fastdepCC_FALSE -am__fastdepCC_TRUE -CCDEPMODE -ac_ct_CC -CFLAGS -CC -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build -LIBTOOL -am__fastdepCXX_FALSE -am__fastdepCXX_TRUE -CXXDEPMODE -am__nodep -AMDEPBACKSLASH -AMDEP_FALSE -AMDEP_TRUE -am__include -DEPDIR -OBJEXT -EXEEXT -ac_ct_CXX -CPPFLAGS -LDFLAGS -CXXFLAGS -CXX -PQXX_ABI -PQXXVERSION -AM_BACKSLASH -AM_DEFAULT_VERBOSITY -AM_DEFAULT_V -AM_V -CSCOPE -ETAGS -CTAGS -am__untar -am__tar -AMTAR -am__leading_dot -SET_MAKE -AWK -mkdir_p -MKDIR_P -INSTALL_STRIP_PROGRAM -STRIP -install_sh -MAKEINFO -AUTOHEADER -AUTOMAKE -AUTOCONF -ACLOCAL -VERSION -PACKAGE -CYGPATH_W -am__isrc -INSTALL_DATA -INSTALL_SCRIPT -INSTALL_PROGRAM -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -runstatedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL -am__quote' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -enable_silent_rules -enable_dependency_tracking -enable_shared -enable_static -with_pic -enable_fast_install -with_aix_soname -with_gnu_ld -with_sysroot -enable_libtool_lock -enable_documentation -enable_maintainer_mode -enable_audit -enable_suggest -with_postgres_include -with_postgres_lib -' - ac_precious_vars='build_alias -host_alias -target_alias -CXX -CXXFLAGS -LDFLAGS -LIBS -CPPFLAGS -CCC -CC -CFLAGS -LT_SYS_LIBRARY_PATH -CPP -CXXCPP -DOXYGEN -HAVE_DOT' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures libpqxx 7.7.3 to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/libpqxx] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -Program names: - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM run sed PROGRAM on installed program names - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of libpqxx 7.7.3:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-silent-rules less verbose build output (undo: "make V=1") - --disable-silent-rules verbose build output (undo: "make V=0") - --enable-dependency-tracking - do not reject slow dependency extractors - --disable-dependency-tracking - speeds up one-time build - --enable-shared[=PKGS] build shared libraries [default=no] - --enable-static[=PKGS] build static libraries [default=yes] - --enable-fast-install[=PKGS] - optimize for fast installation [default=yes] - --disable-libtool-lock avoid locking (might break parallel builds) - --enable-documentation Generate documentation - --enable-maintainer-mode - enable make rules and dependencies not useful (and - sometimes confusing) to the casual installer - - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use - both] - --with-aix-soname=aix|svr4|both - shared library versioning (aka "SONAME") variant to - provide on AIX, [default=aix]. - --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-sysroot[=DIR] Search for dependent libraries within DIR (or the - compiler's sysroot if not specified). - --with-postgres-include=DIR - Use PostgreSQL includes from DIR. Defaults to - querying pg_config or pkg-config, whichever is - available. - --with-postgres-lib=DIR Use PostgreSQL libraries from DIR. Defaults to - querying pg_config. - -Some influential environment variables: - CXX C++ compiler command - CXXFLAGS C++ compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - CC C compiler command - CFLAGS C compiler flags - LT_SYS_LIBRARY_PATH - User-defined run-time library search path. - CPP C preprocessor - CXXCPP C++ preprocessor - DOXYGEN Path to doxygen needed to build reference documentation - HAVE_DOT Variable used by doxygen to declare availibility of dot - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to . -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -libpqxx configure 7.7.3 -generated by GNU Autoconf 2.69 - -Copyright (C) 2012 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## - -# ac_fn_cxx_try_compile LINENO -# ---------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_compile - -# ac_fn_c_try_compile LINENO -# -------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_compile - -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link - -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_compile - -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - -# ac_fn_c_try_run LINENO -# ---------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_c_try_run () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=$ac_status -fi - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_run - -# ac_fn_c_check_func LINENO FUNC VAR -# ---------------------------------- -# Tests whether FUNC exists, setting the cache variable VAR accordingly -ac_fn_c_check_func () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Define $2 to an innocuous variant, in case declares $2. - For example, HP-UX 11i declares gettimeofday. */ -#define $2 innocuous_$2 - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $2 (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $2 - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $2 (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$2 || defined __stub___$2 -choke me -#endif - -int -main () -{ -return $2 (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_func - -# ac_fn_cxx_try_cpp LINENO -# ------------------------ -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_cpp - -# ac_fn_cxx_try_link LINENO -# ------------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_link - -# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES -# --------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_cxx_check_header_mongrel () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval \${$3+:} false; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## ---------------------------------- ## -## Report this to Jeroen T. Vermeulen ## -## ---------------------------------- ##" - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_cxx_check_header_mongrel -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by libpqxx $as_me 7.7.3, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - $as_echo "## ---------------- ## -## Cache variables. ## -## ---------------- ##" - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - $as_echo "## ----------------- ## -## Output variables. ## -## ----------------- ##" - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## -## File substitutions. ## -## ------------------- ##" - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - $as_echo "## ----------- ## -## confdefs.h. ## -## ----------- ##" - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5; } - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - -ac_aux_dir= -for ac_dir in config "$srcdir"/config; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - - -am__api_version='1.16' - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } -if test -z "$INSTALL"; then -if ${ac_cv_path_install+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - fi - done - done - ;; -esac - - done -IFS=$as_save_IFS - -rm -rf conftest.one conftest.two conftest.dir - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -$as_echo_n "checking whether build environment is sane... " >&6; } -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[\\\"\#\$\&\'\`$am_lf]*) - as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; -esac -case $srcdir in - *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; -esac - -# Do 'set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - am_has_slept=no - for am_try in 1 2; do - echo "timestamp, slept: $am_has_slept" > conftest.file - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - as_fn_error $? "ls -t appears to fail. Make sure there is not a broken - alias in your environment" "$LINENO" 5 - fi - if test "$2" = conftest.file || test $am_try -eq 2; then - break - fi - # Just in case. - sleep 1 - am_has_slept=yes - done - test "$2" = conftest.file - ) -then - # Ok. - : -else - as_fn_error $? "newly created file is older than distributed files! -Check your system clock" "$LINENO" 5 -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -# If we didn't sleep, we still need to ensure time stamps of config.status and -# generated files are strictly newer. -am_sleep_pid= -if grep 'slept: no' conftest.file >/dev/null 2>&1; then - ( sleep 1 ) & - am_sleep_pid=$! -fi - -rm -f conftest.file - -test "$program_prefix" != NONE && - program_transform_name="s&^&$program_prefix&;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s&\$&$program_suffix&;$program_transform_name" -# Double any \ or $. -# By default was `s,x,x', remove it if useless. -ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' -program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` - -# Expand $ac_aux_dir to an absolute path. -am_aux_dir=`cd "$ac_aux_dir" && pwd` - -if test x"${MISSING+set}" != xset; then - MISSING="\${SHELL} '$am_aux_dir/missing'" -fi -# Use eval to expand $SHELL -if eval "$MISSING --is-lightweight"; then - am_missing_run="$MISSING " -else - am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} -fi - -if test x"${install_sh+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi - -# Installed binaries are usually stripped using 'strip' when the user -# run "make install-strip". However 'strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the 'STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 -$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } -if test -z "$MKDIR_P"; then - if ${ac_cv_path_mkdir+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext - break 3;; - esac - done - done - done -IFS=$as_save_IFS - -fi - - test -d ./--version && rmdir ./--version - if test "${ac_cv_path_mkdir+set}" = set; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - MKDIR_P="$ac_install_sh -d" - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -$as_echo "$MKDIR_P" >&6; } - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AWK" && break -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -# Check whether --enable-silent-rules was given. -if test "${enable_silent_rules+set}" = set; then : - enableval=$enable_silent_rules; -fi - -case $enable_silent_rules in # ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=1;; -esac -am_make=${MAKE-make} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 -$as_echo_n "checking whether $am_make supports nested variables... " >&6; } -if ${am_cv_make_support_nested_variables+:} false; then : - $as_echo_n "(cached) " >&6 -else - if $as_echo 'TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 -$as_echo "$am_cv_make_support_nested_variables" >&6; } -if test $am_cv_make_support_nested_variables = yes; then - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AM_BACKSLASH='\' - -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - am__isrc=' -I$(srcdir)' - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE='libpqxx' - VERSION='7.7.3' - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - -# For better backward compatibility. To be removed once Automake 1.9.x -# dies out for good. For more background, see: -# -# -mkdir_p='$(MKDIR_P)' - -# We need awk for the "check" target (and possibly the TAP driver). The -# system "awk" is bad on some platforms. -# Always define AMTAR for backward compatibility. Yes, it's still used -# in the wild :-( We should find a proper way to deprecate it ... -AMTAR='$${TAR-tar}' - - -# We'll loop over all known methods to create a tar archive until one works. -_am_tools='gnutar pax cpio none' - -am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' - - - - - -# Variables for tags utilities; see am/tags.am -if test -z "$CTAGS"; then - CTAGS=ctags -fi - -if test -z "$ETAGS"; then - ETAGS=etags -fi - -if test -z "$CSCOPE"; then - CSCOPE=cscope -fi - - - -# POSIX will say in a future version that running "rm -f" with no argument -# is OK; and we want to be able to make that assumption in our Makefile -# recipes. So use an aggressive probe to check that the usage we want is -# actually supported "in the wild" to an acceptable degree. -# See automake bug#10828. -# To make any issue more visible, cause the running configure to be aborted -# by default if the 'rm' program in use doesn't match our expectations; the -# user can still override this though. -if rm -f && rm -fr && rm -rf; then : OK; else - cat >&2 <<'END' -Oops! - -Your 'rm' program seems unable to run without file operands specified -on the command line, even when the '-f' option is present. This is contrary -to the behaviour of most rm programs out there, and not conforming with -the upcoming POSIX standard: - -Please tell bug-automake@gnu.org about your system, including the value -of your $PATH and any error possibly output before this message. This -can help us improve future automake versions. - -END - if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then - echo 'Configuration will proceed anyway, since you have set the' >&2 - echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 - echo >&2 - else - cat >&2 <<'END' -Aborting the configuration process, to ensure you take notice of the issue. - -You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . - -If you want to complete the configuration process using your problematic -'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM -to "yes", and re-run configure. - -END - as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 - fi -fi - - -PQXX_ABI=7.7 -PQXXVERSION=$PACKAGE_VERSION - - - -ac_config_headers="$ac_config_headers include/pqxx/config.h" - - -# Default prefix for installs. - - - -# Read test programme from config-test. - - - -# Checks for programs. -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -z "$CXX"; then - if test -n "$CCC"; then - CXX=$CCC - else - if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 -$as_echo "$ac_ct_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - fi -fi -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 -$as_echo_n "checking whether the C++ compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` - -# The possible output files: -ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" - -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { { ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "C++ compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 -$as_echo_n "checking for C++ compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } -ac_exeext=$ac_cv_exeext - -rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } -if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -FILE *f = fopen ("conftest.out", "w"); - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -ac_clean_files="$ac_clean_files conftest.out" -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -if test "$cross_compiling" != yes; then - { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if { ac_try='./conftest$ac_cv_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C++ compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if ${ac_cv_objext+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 -$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if ${ac_cv_cxx_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 -$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GXX=yes -else - GXX= -fi -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 -$as_echo_n "checking whether $CXX accepts -g... " >&6; } -if ${ac_cv_prog_cxx_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_cxx_werror_flag=$ac_cxx_werror_flag - ac_cxx_werror_flag=yes - ac_cv_prog_cxx_g=no - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -else - CXXFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - ac_cxx_werror_flag=$ac_save_cxx_werror_flag - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cxx_werror_flag=$ac_save_cxx_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 -$as_echo "$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -DEPDIR="${am__leading_dot}deps" - -ac_config_commands="$ac_config_commands depfiles" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 -$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } -cat > confinc.mk << 'END' -am__doit: - @echo this is the am__doit target >confinc.out -.PHONY: am__doit -END -am__include="#" -am__quote= -# BSD make does it like this. -echo '.include "confinc.mk" # ignored' > confmf.BSD -# Other make implementations (GNU, Solaris 10, AIX) do it like this. -echo 'include confinc.mk # ignored' > confmf.GNU -_am_result=no -for s in GNU BSD; do - { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 - (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - case $?:`cat confinc.out 2>/dev/null` in #( - '0:this is the am__doit target') : - case $s in #( - BSD) : - am__include='.include' am__quote='"' ;; #( - *) : - am__include='include' am__quote='' ;; -esac ;; #( - *) : - ;; -esac - if test "$am__include" != "#"; then - _am_result="yes ($s style)" - break - fi -done -rm -f confinc.* confmf.* -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 -$as_echo "${_am_result}" >&6; } - -# Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then : - enableval=$enable_dependency_tracking; -fi - -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' - am__nodep='_no' -fi - if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - - - -depcc="$CXX" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CXX_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - - - -# Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then : - enableval=$enable_shared; p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS=$lt_save_ifs - ;; - esac -else - enable_shared=no -fi - - - - - - - - - -case `pwd` in - *\ * | *\ *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 -$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; -esac - - - -macro_version='2.4.6' -macro_revision='2.4.6' - - - - - - - - - - - - - -ltmain=$ac_aux_dir/ltmain.sh - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -# Backslashify metacharacters that are still active within -# double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 -$as_echo_n "checking how to print strings... " >&6; } -# Test print first, because it will be a builtin if present. -if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ - test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='print -r --' -elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='printf %s\n' -else - # Use this function as a fallback that always works. - func_fallback_echo () - { - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' - } - ECHO='func_fallback_echo' -fi - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "" -} - -case $ECHO in - printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 -$as_echo "printf" >&6; } ;; - print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 -$as_echo "print -r" >&6; } ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 -$as_echo "cat" >&6; } ;; -esac - - - - - - - - - - - - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 -$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } -if ${am_cv_prog_cc_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF - # Make sure it works both with $CC and with simple cc. - # Following AC_PROG_CC_C_O, we do the test twice because some - # compilers refuse to overwrite an existing .o file with -o, - # though they will create one. - am_cv_prog_cc_c_o=yes - for am_i in 1 2; do - if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 - ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } \ - && test -f conftest2.$ac_objext; then - : OK - else - am_cv_prog_cc_c_o=no - break - fi - done - rm -f core conftest* - unset am_i -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 -$as_echo "$am_cv_prog_cc_c_o" >&6; } -if test "$am_cv_prog_cc_c_o" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 -$as_echo_n "checking for a sed that does not truncate output... " >&6; } -if ${ac_cv_path_SED+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for ac_i in 1 2 3 4 5 6 7; do - ac_script="$ac_script$as_nl$ac_script" - done - echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed - { ac_script=; unset ac_script;} - if test -z "$SED"; then - ac_path_SED_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_SED" || continue -# Check for GNU ac_path_SED and select it if it is found. - # Check for GNU $ac_path_SED -case `"$ac_path_SED" --version 2>&1` in -*GNU*) - ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo '' >> "conftest.nl" - "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_SED_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_SED="$ac_path_SED" - ac_path_SED_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_SED_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_SED"; then - as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 - fi -else - ac_cv_path_SED=$SED -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 -$as_echo "$ac_cv_path_SED" >&6; } - SED="$ac_cv_path_SED" - rm -f conftest.sed - -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if ${ac_cv_path_GREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$GREP"; then - ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_GREP" || continue -# Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_GREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_GREP=$GREP -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_EGREP" || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 -$as_echo_n "checking for fgrep... " >&6; } -if ${ac_cv_path_FGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 - then ac_cv_path_FGREP="$GREP -F" - else - if test -z "$FGREP"; then - ac_path_FGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in fgrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_FGREP" || continue -# Check for GNU ac_path_FGREP and select it if it is found. - # Check for GNU $ac_path_FGREP -case `"$ac_path_FGREP" --version 2>&1` in -*GNU*) - ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'FGREP' >> "conftest.nl" - "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_FGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_FGREP="$ac_path_FGREP" - ac_path_FGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_FGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_FGREP"; then - as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_FGREP=$FGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 -$as_echo "$ac_cv_path_FGREP" >&6; } - FGREP="$ac_cv_path_FGREP" - - -test -z "$GREP" && GREP=grep - - - - - - - - - - - - - - - - - - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -ac_prog=ld -if test yes = "$GCC"; then - # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 -$as_echo_n "checking for ld used by $CC... " >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return, which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD=$ac_prog - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test yes = "$with_gnu_ld"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } -fi -if ${lt_cv_path_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$LD"; then - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD=$ac_dir/$ac_prog - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if ${lt_cv_prog_gnu_ld+:} false; then : - $as_echo_n "(cached) " >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -$as_echo "$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 -$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } -if ${lt_cv_path_NM+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM=$NM -else - lt_nm_to_check=${ac_tool_prefix}nm - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - tmp_nm=$ac_dir/$lt_tmp_nm - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the 'sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty - case $build_os in - mingw*) lt_bad_file=conftest.nm/nofile ;; - *) lt_bad_file=/dev/null ;; - esac - case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in - *$lt_bad_file* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break 2 - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break 2 - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS=$lt_save_ifs - done - : ${lt_cv_path_NM=no} -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 -$as_echo "$lt_cv_path_NM" >&6; } -if test no != "$lt_cv_path_NM"; then - NM=$lt_cv_path_NM -else - # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$DUMPBIN"; then : - # Let the user override the test. - else - if test -n "$ac_tool_prefix"; then - for ac_prog in dumpbin "link -dump" - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DUMPBIN+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DUMPBIN"; then - ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DUMPBIN=$ac_cv_prog_DUMPBIN -if test -n "$DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 -$as_echo "$DUMPBIN" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$DUMPBIN" && break - done -fi -if test -z "$DUMPBIN"; then - ac_ct_DUMPBIN=$DUMPBIN - for ac_prog in dumpbin "link -dump" -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DUMPBIN"; then - ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN -if test -n "$ac_ct_DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 -$as_echo "$ac_ct_DUMPBIN" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_DUMPBIN" && break -done - - if test "x$ac_ct_DUMPBIN" = x; then - DUMPBIN=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DUMPBIN=$ac_ct_DUMPBIN - fi -fi - - case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in - *COFF*) - DUMPBIN="$DUMPBIN -symbols -headers" - ;; - *) - DUMPBIN=: - ;; - esac - fi - - if test : != "$DUMPBIN"; then - NM=$DUMPBIN - fi -fi -test -z "$NM" && NM=nm - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 -$as_echo_n "checking the name lister ($NM) interface... " >&6; } -if ${lt_cv_nm_interface+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&5 - (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&5 - (eval echo "\"\$as_me:$LINENO: output\"" >&5) - cat conftest.out >&5 - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 -$as_echo "$lt_cv_nm_interface" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 -$as_echo_n "checking whether ln -s works... " >&6; } -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 -$as_echo "no, using $LN_S" >&6; } -fi - -# find the maximum length of command line arguments -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 -$as_echo_n "checking the maximum length of command line arguments... " >&6; } -if ${lt_cv_sys_max_cmd_len+:} false; then : - $as_echo_n "(cached) " >&6 -else - i=0 - teststring=ABCD - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - mint*) - # On MiNT this can take a long time and run out of memory. - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - os2*) - # The test takes a long time on OS/2. - lt_cv_sys_max_cmd_len=8192 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len" && \ - test undefined != "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test X`env echo "$teststring$teststring" 2>/dev/null` \ - = "X$teststring$teststring"; } >/dev/null 2>&1 && - test 17 != "$i" # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac - -fi - -if test -n "$lt_cv_sys_max_cmd_len"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 -$as_echo "$lt_cv_sys_max_cmd_len" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 -$as_echo "none" >&6; } -fi -max_cmd_len=$lt_cv_sys_max_cmd_len - - - - - - -: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi - - - - - -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' - ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' - ;; -esac - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 -$as_echo_n "checking how to convert $build file names to $host format... " >&6; } -if ${lt_cv_to_host_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 - ;; - esac - ;; - *-*-cygwin* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin - ;; - esac - ;; - * ) # unhandled hosts (and "normal" native builds) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; -esac - -fi - -to_host_file_cmd=$lt_cv_to_host_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 -$as_echo "$lt_cv_to_host_file_cmd" >&6; } - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 -$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } -if ${lt_cv_to_tool_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - #assume ordinary cross tools, or native build. -lt_cv_to_tool_file_cmd=func_convert_file_noop -case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 - ;; - esac - ;; -esac - -fi - -to_tool_file_cmd=$lt_cv_to_tool_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 -$as_echo "$lt_cv_to_tool_file_cmd" >&6; } - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 -$as_echo_n "checking for $LD option to reload object files... " >&6; } -if ${lt_cv_ld_reload_flag+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_reload_flag='-r' -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 -$as_echo "$lt_cv_ld_reload_flag" >&6; } -reload_flag=$lt_cv_ld_reload_flag -case $reload_flag in -"" | " "*) ;; -*) reload_flag=" $reload_flag" ;; -esac -reload_cmds='$LD$reload_flag -o $output$reload_objs' -case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - if test yes != "$GCC"; then - reload_cmds=false - fi - ;; - darwin*) - if test yes = "$GCC"; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' - else - reload_cmds='$LD$reload_flag -o $output$reload_objs' - fi - ;; -esac - - - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. -set dummy ${ac_tool_prefix}objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OBJDUMP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OBJDUMP"; then - ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OBJDUMP=$ac_cv_prog_OBJDUMP -if test -n "$OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 -$as_echo "$OBJDUMP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OBJDUMP"; then - ac_ct_OBJDUMP=$OBJDUMP - # Extract the first word of "objdump", so it can be a program name with args. -set dummy objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OBJDUMP"; then - ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_OBJDUMP="objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP -if test -n "$ac_ct_OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 -$as_echo "$ac_ct_OBJDUMP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OBJDUMP" = x; then - OBJDUMP="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OBJDUMP=$ac_ct_OBJDUMP - fi -else - OBJDUMP="$ac_cv_prog_OBJDUMP" -fi - -test -z "$OBJDUMP" && OBJDUMP=objdump - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 -$as_echo_n "checking how to recognize dependent libraries... " >&6; } -if ${lt_cv_deplibs_check_method+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# 'unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# that responds to the $file_magic_cmd with a given extended regex. -# If you have 'file' or equivalent on your system and you're not sure -# whether 'pass_all' will *always* work, you probably want this one. - -case $host_os in -aix[4-9]*) - lt_cv_deplibs_check_method=pass_all - ;; - -beos*) - lt_cv_deplibs_check_method=pass_all - ;; - -bsdi[45]*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # func_win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump', - # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc*) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -haiku*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[3-9]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd* | bitrig*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -os2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 -$as_echo "$lt_cv_deplibs_check_method" >&6; } - -file_magic_glob= -want_nocaseglob=no -if test "$build" = "$host"; then - case $host_os in - mingw* | pw32*) - if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then - want_nocaseglob=yes - else - file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` - fi - ;; - esac -fi - -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - - - - - - - - - - - - - - - - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. -set dummy ${ac_tool_prefix}dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DLLTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DLLTOOL"; then - ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DLLTOOL=$ac_cv_prog_DLLTOOL -if test -n "$DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 -$as_echo "$DLLTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_DLLTOOL"; then - ac_ct_DLLTOOL=$DLLTOOL - # Extract the first word of "dlltool", so it can be a program name with args. -set dummy dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DLLTOOL"; then - ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DLLTOOL="dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL -if test -n "$ac_ct_DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 -$as_echo "$ac_ct_DLLTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_DLLTOOL" = x; then - DLLTOOL="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DLLTOOL=$ac_ct_DLLTOOL - fi -else - DLLTOOL="$ac_cv_prog_DLLTOOL" -fi - -test -z "$DLLTOOL" && DLLTOOL=dlltool - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 -$as_echo_n "checking how to associate runtime and link libraries... " >&6; } -if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_sharedlib_from_linklib_cmd='unknown' - -case $host_os in -cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh; - # decide which one to use based on capabilities of $DLLTOOL - case `$DLLTOOL --help 2>&1` in - *--identify-strict*) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib - ;; - *) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback - ;; - esac - ;; -*) - # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd=$ECHO - ;; -esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 -$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } -sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd -test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO - - - - - - - - -if test -n "$ac_tool_prefix"; then - for ac_prog in ar - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AR" && break - done -fi -if test -z "$AR"; then - ac_ct_AR=$AR - for ac_prog in ar -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AR="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_AR" && break -done - - if test "x$ac_ct_AR" = x; then - AR="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - AR=$ac_ct_AR - fi -fi - -: ${AR=ar} -: ${AR_FLAGS=cr} - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 -$as_echo_n "checking for archiver @FILE support... " >&6; } -if ${lt_cv_ar_at_file+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ar_at_file=no - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - echo conftest.$ac_objext > conftest.lst - lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 - (eval $lt_ar_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if test 0 -eq "$ac_status"; then - # Ensure the archiver fails upon bogus file names. - rm -f conftest.$ac_objext libconftest.a - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 - (eval $lt_ar_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if test 0 -ne "$ac_status"; then - lt_cv_ar_at_file=@ - fi - fi - rm -f conftest.* libconftest.a - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 -$as_echo "$lt_cv_ar_at_file" >&6; } - -if test no = "$lt_cv_ar_at_file"; then - archiver_list_spec= -else - archiver_list_spec=$lt_cv_ar_at_file -fi - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -test -z "$STRIP" && STRIP=: - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - RANLIB=$ac_ct_RANLIB - fi -else - RANLIB="$ac_cv_prog_RANLIB" -fi - -test -z "$RANLIB" && RANLIB=: - - - - - - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - bitrig* | openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" -fi - -case $host_os in - darwin*) - lock_old_archive_extraction=yes ;; - *) - lock_old_archive_extraction=no ;; -esac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Check for command to grab the raw symbol name followed by C symbol from nm. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 -$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } -if ${lt_cv_sys_global_symbol_pipe+:} false; then : - $as_echo_n "(cached) " >&6 -else - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw* | pw32* | cegcc*) - symcode='[ABCDGISTW]' - ;; -hpux*) - if test ia64 = "$host_cpu"; then - symcode='[ABCDEGRST]' - fi - ;; -irix* | nonstopux*) - symcode='[BCDEGRST]' - ;; -osf*) - symcode='[BCDEGQRST]' - ;; -solaris*) - symcode='[BDRT]' - ;; -sco3.2v5*) - symcode='[DT]' - ;; -sysv4.2uw2*) - symcode='[DT]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[ABDT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[ABCDGIRSTW]' ;; -esac - -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Gets list of data symbols to import. - lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" - # Adjust the below global symbol transforms to fixup imported variables. - lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" - lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" - lt_c_name_lib_hook="\ - -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ - -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" -else - # Disable hooks by default. - lt_cv_sys_global_symbol_to_import= - lt_cdecl_hook= - lt_c_name_hook= - lt_c_name_lib_hook= -fi - -# Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, -# so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n"\ -$lt_cdecl_hook\ -" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ -$lt_c_name_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" - -# Transform an extracted symbol line into symbol name with lib prefix and -# symbol address. -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ -$lt_c_name_lib_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# Try without a prefix underscore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function, - # D for any global variable and I for any imported variable. - # Also find C++ and __fastcall symbols from MSVC++, - # which start with @ or ?. - lt_cv_sys_global_symbol_pipe="$AWK '"\ -" {last_section=section; section=\$ 3};"\ -" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ -" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ -" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ -" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ -" \$ 0!~/External *\|/{next};"\ -" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ -" {if(hide[section]) next};"\ -" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ -" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ -" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ -" ' prfx=^$ac_symprfx" - else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <<_LT_EOF -#ifdef __cplusplus -extern "C" { -#endif -char nm_test_var; -void nm_test_func(void); -void nm_test_func(void){} -#ifdef __cplusplus -} -#endif -int main(){nm_test_var='a';nm_test_func();return(0);} -_LT_EOF - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - # Now try to grab the symbols. - nlist=conftest.nm - $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 - if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if $GREP ' nm_test_var$' "$nlist" >/dev/null; then - if $GREP ' nm_test_func$' "$nlist" >/dev/null; then - cat <<_LT_EOF > conftest.$ac_ext -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined __osf__ -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -_LT_EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' - - cat <<_LT_EOF >> conftest.$ac_ext - -/* The mapping between symbol names and symbols. */ -LT_DLSYM_CONST struct { - const char *name; - void *address; -} -lt__PROGRAM__LTX_preloaded_symbols[] = -{ - { "@PROGRAM@", (void *) 0 }, -_LT_EOF - $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext - cat <<\_LT_EOF >> conftest.$ac_ext - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt__PROGRAM__LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif -_LT_EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_globsym_save_LIBS=$LIBS - lt_globsym_save_CFLAGS=$CFLAGS - LIBS=conftstm.$ac_objext - CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest$ac_exeext; then - pipe_works=yes - fi - LIBS=$lt_globsym_save_LIBS - CFLAGS=$lt_globsym_save_CFLAGS - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - fi - rm -rf conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test yes = "$pipe_works"; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done - -fi - -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 -$as_echo "failed" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } -fi - -# Response file support. -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - nm_file_list_spec='@' -elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then - nm_file_list_spec='@' -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 -$as_echo_n "checking for sysroot... " >&6; } - -# Check whether --with-sysroot was given. -if test "${with_sysroot+set}" = set; then : - withval=$with_sysroot; -else - with_sysroot=no -fi - - -lt_sysroot= -case $with_sysroot in #( - yes) - if test yes = "$GCC"; then - lt_sysroot=`$CC --print-sysroot 2>/dev/null` - fi - ;; #( - /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` - ;; #( - no|'') - ;; #( - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 -$as_echo "$with_sysroot" >&6; } - as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 - ;; -esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 -$as_echo "${lt_sysroot:-no}" >&6; } - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 -$as_echo_n "checking for a working dd... " >&6; } -if ${ac_cv_path_lt_DD+:} false; then : - $as_echo_n "(cached) " >&6 -else - printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -: ${lt_DD:=$DD} -if test -z "$lt_DD"; then - ac_path_lt_DD_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in dd; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_lt_DD" || continue -if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: -fi - $ac_path_lt_DD_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_lt_DD"; then - : - fi -else - ac_cv_path_lt_DD=$lt_DD -fi - -rm -f conftest.i conftest2.i conftest.out -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 -$as_echo "$ac_cv_path_lt_DD" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 -$as_echo_n "checking how to truncate binary pipes... " >&6; } -if ${lt_cv_truncate_bin+:} false; then : - $as_echo_n "(cached) " >&6 -else - printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -lt_cv_truncate_bin= -if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" -fi -rm -f conftest.i conftest2.i conftest.out -test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 -$as_echo "$lt_cv_truncate_bin" >&6; } - - - - - - - -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in $*""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} - - -# Check whether --enable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then : - enableval=$enable_libtool_lock; -fi - -test no = "$enable_libtool_lock" || enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out what ABI is being produced by ac_compile, and set mode - # options accordingly. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE=32 - ;; - *ELF-64*) - HPUX_IA64_MODE=64 - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '#line '$LINENO' "configure"' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - if test yes = "$lt_cv_prog_gnu_ld"; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -mips64*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '#line '$LINENO' "configure"' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - emul=elf - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - emul="${emul}32" - ;; - *64-bit*) - emul="${emul}64" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *MSB*) - emul="${emul}btsmip" - ;; - *LSB*) - emul="${emul}ltsmip" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *N32*) - emul="${emul}n32" - ;; - esac - LD="${LD-ld} -m $emul" - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ -s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. Note that the listed cases only cover the - # situations where additional linker options are needed (such as when - # doing 32-bit compilation for a host where ld defaults to 64-bit, or - # vice versa); the common cases where no linker options are needed do - # not appear in the list. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - case `/usr/bin/file conftest.o` in - *x86-64*) - LD="${LD-ld} -m elf32_x86_64" - ;; - *) - LD="${LD-ld} -m elf_i386" - ;; - esac - ;; - powerpc64le-*linux*) - LD="${LD-ld} -m elf32lppclinux" - ;; - powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - powerpcle-*linux*) - LD="${LD-ld} -m elf64lppc" - ;; - powerpc-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*|s390*-*tpf*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -belf" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 -$as_echo_n "checking whether the C compiler needs -belf... " >&6; } -if ${lt_cv_cc_needs_belf+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_cc_needs_belf=yes -else - lt_cv_cc_needs_belf=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 -$as_echo "$lt_cv_cc_needs_belf" >&6; } - if test yes != "$lt_cv_cc_needs_belf"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS=$SAVE_CFLAGS - fi - ;; -*-*solaris*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) - case $host in - i?86-*-solaris*|x86_64-*-solaris*) - LD="${LD-ld} -m elf_x86_64" - ;; - sparc*-*-solaris*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - # GNU ld 2.21 introduced _sol2 emulations. Use them if available. - if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD=${LD-ld}_sol2 - fi - ;; - *) - if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then - LD="${LD-ld} -64" - fi - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; -esac - -need_locks=$enable_libtool_lock - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. -set dummy ${ac_tool_prefix}mt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$MANIFEST_TOOL"; then - ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL -if test -n "$MANIFEST_TOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 -$as_echo "$MANIFEST_TOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_MANIFEST_TOOL"; then - ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL - # Extract the first word of "mt", so it can be a program name with args. -set dummy mt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_MANIFEST_TOOL"; then - ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL -if test -n "$ac_ct_MANIFEST_TOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 -$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_MANIFEST_TOOL" = x; then - MANIFEST_TOOL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL - fi -else - MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" -fi - -test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 -$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } -if ${lt_cv_path_mainfest_tool+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_path_mainfest_tool=no - echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 - $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out - cat conftest.err >&5 - if $GREP 'Manifest Tool' conftest.out > /dev/null; then - lt_cv_path_mainfest_tool=yes - fi - rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 -$as_echo "$lt_cv_path_mainfest_tool" >&6; } -if test yes != "$lt_cv_path_mainfest_tool"; then - MANIFEST_TOOL=: -fi - - - - - - - case $host_os in - rhapsody* | darwin*) - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. -set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DSYMUTIL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DSYMUTIL"; then - ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DSYMUTIL=$ac_cv_prog_DSYMUTIL -if test -n "$DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 -$as_echo "$DSYMUTIL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_DSYMUTIL"; then - ac_ct_DSYMUTIL=$DSYMUTIL - # Extract the first word of "dsymutil", so it can be a program name with args. -set dummy dsymutil; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DSYMUTIL"; then - ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL -if test -n "$ac_ct_DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 -$as_echo "$ac_ct_DSYMUTIL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_DSYMUTIL" = x; then - DSYMUTIL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DSYMUTIL=$ac_ct_DSYMUTIL - fi -else - DSYMUTIL="$ac_cv_prog_DSYMUTIL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. -set dummy ${ac_tool_prefix}nmedit; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_NMEDIT+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$NMEDIT"; then - ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -NMEDIT=$ac_cv_prog_NMEDIT -if test -n "$NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 -$as_echo "$NMEDIT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_NMEDIT"; then - ac_ct_NMEDIT=$NMEDIT - # Extract the first word of "nmedit", so it can be a program name with args. -set dummy nmedit; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_NMEDIT"; then - ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_NMEDIT="nmedit" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT -if test -n "$ac_ct_NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 -$as_echo "$ac_ct_NMEDIT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_NMEDIT" = x; then - NMEDIT=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - NMEDIT=$ac_ct_NMEDIT - fi -else - NMEDIT="$ac_cv_prog_NMEDIT" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. -set dummy ${ac_tool_prefix}lipo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_LIPO+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$LIPO"; then - ac_cv_prog_LIPO="$LIPO" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_LIPO="${ac_tool_prefix}lipo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -LIPO=$ac_cv_prog_LIPO -if test -n "$LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 -$as_echo "$LIPO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_LIPO"; then - ac_ct_LIPO=$LIPO - # Extract the first word of "lipo", so it can be a program name with args. -set dummy lipo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_LIPO+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_LIPO"; then - ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_LIPO="lipo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO -if test -n "$ac_ct_LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 -$as_echo "$ac_ct_LIPO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_LIPO" = x; then - LIPO=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - LIPO=$ac_ct_LIPO - fi -else - LIPO="$ac_cv_prog_LIPO" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. -set dummy ${ac_tool_prefix}otool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OTOOL"; then - ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_OTOOL="${ac_tool_prefix}otool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OTOOL=$ac_cv_prog_OTOOL -if test -n "$OTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 -$as_echo "$OTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OTOOL"; then - ac_ct_OTOOL=$OTOOL - # Extract the first word of "otool", so it can be a program name with args. -set dummy otool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OTOOL"; then - ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_OTOOL="otool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL -if test -n "$ac_ct_OTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 -$as_echo "$ac_ct_OTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OTOOL" = x; then - OTOOL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OTOOL=$ac_ct_OTOOL - fi -else - OTOOL="$ac_cv_prog_OTOOL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. -set dummy ${ac_tool_prefix}otool64; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OTOOL64+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OTOOL64"; then - ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OTOOL64=$ac_cv_prog_OTOOL64 -if test -n "$OTOOL64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 -$as_echo "$OTOOL64" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OTOOL64"; then - ac_ct_OTOOL64=$OTOOL64 - # Extract the first word of "otool64", so it can be a program name with args. -set dummy otool64; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OTOOL64"; then - ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_OTOOL64="otool64" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 -if test -n "$ac_ct_OTOOL64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 -$as_echo "$ac_ct_OTOOL64" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OTOOL64" = x; then - OTOOL64=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OTOOL64=$ac_ct_OTOOL64 - fi -else - OTOOL64="$ac_cv_prog_OTOOL64" -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 -$as_echo_n "checking for -single_module linker flag... " >&6; } -if ${lt_cv_apple_cc_single_mod+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_apple_cc_single_mod=no - if test -z "$LT_MULTI_MODULE"; then - # By default we will add the -single_module flag. You can override - # by either setting the environment variable LT_MULTI_MODULE - # non-empty at configure time, or by adding -multi_module to the - # link flags. - rm -rf libconftest.dylib* - echo "int foo(void){return 1;}" > conftest.c - echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ --dynamiclib -Wl,-single_module conftest.c" >&5 - $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ - -dynamiclib -Wl,-single_module conftest.c 2>conftest.err - _lt_result=$? - # If there is a non-empty error log, and "single_module" - # appears in it, assume the flag caused a linker warning - if test -s conftest.err && $GREP single_module conftest.err; then - cat conftest.err >&5 - # Otherwise, if the output was created with a 0 exit code from - # the compiler, it worked. - elif test -f libconftest.dylib && test 0 = "$_lt_result"; then - lt_cv_apple_cc_single_mod=yes - else - cat conftest.err >&5 - fi - rm -rf libconftest.dylib* - rm -f conftest.* - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 -$as_echo "$lt_cv_apple_cc_single_mod" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 -$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } -if ${lt_cv_ld_exported_symbols_list+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_exported_symbols_list=no - save_LDFLAGS=$LDFLAGS - echo "_main" > conftest.sym - LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_ld_exported_symbols_list=yes -else - lt_cv_ld_exported_symbols_list=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 -$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 -$as_echo_n "checking for -force_load linker flag... " >&6; } -if ${lt_cv_ld_force_load+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_force_load=no - cat > conftest.c << _LT_EOF -int forced_loaded() { return 2;} -_LT_EOF - echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 - $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 - echo "$AR cr libconftest.a conftest.o" >&5 - $AR cr libconftest.a conftest.o 2>&5 - echo "$RANLIB libconftest.a" >&5 - $RANLIB libconftest.a 2>&5 - cat > conftest.c << _LT_EOF -int main() { return 0;} -_LT_EOF - echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 - $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err - _lt_result=$? - if test -s conftest.err && $GREP force_load conftest.err; then - cat conftest.err >&5 - elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then - lt_cv_ld_force_load=yes - else - cat conftest.err >&5 - fi - rm -f conftest.err libconftest.a conftest conftest.c - rm -rf conftest.dSYM - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 -$as_echo "$lt_cv_ld_force_load" >&6; } - case $host_os in - rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[912]*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - 10.[012][,.]*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - 10.*|11.*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test yes = "$lt_cv_apple_cc_single_mod"; then - _lt_dar_single_mod='$single_module' - fi - if test yes = "$lt_cv_ld_exported_symbols_list"; then - _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' - fi - if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac - -# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x$2 in - x) - ;; - *:) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" - ;; - x:*) - eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" - ;; - *) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" - ;; - esac -} - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if ${ac_cv_prog_CPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -for ac_header in dlfcn.h -do : - ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default -" -if test "x$ac_cv_header_dlfcn_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DLFCN_H 1 -_ACEOF - -fi - -done - - - -func_stripname_cnf () -{ - case $2 in - .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; - *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; - esac -} # func_stripname_cnf - - - - - -# Set options - - - - enable_dlopen=no - - - enable_win32_dll=no - - - - # Check whether --enable-static was given. -if test "${enable_static+set}" = set; then : - enableval=$enable_static; p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS=$lt_save_ifs - ;; - esac -else - enable_static=yes -fi - - - - - - - - - - -# Check whether --with-pic was given. -if test "${with_pic+set}" = set; then : - withval=$with_pic; lt_p=${PACKAGE-default} - case $withval in - yes|no) pic_mode=$withval ;; - *) - pic_mode=default - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for lt_pkg in $withval; do - IFS=$lt_save_ifs - if test "X$lt_pkg" = "X$lt_p"; then - pic_mode=yes - fi - done - IFS=$lt_save_ifs - ;; - esac -else - pic_mode=default -fi - - - - - - - - - # Check whether --enable-fast-install was given. -if test "${enable_fast_install+set}" = set; then : - enableval=$enable_fast_install; p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS=$lt_save_ifs - ;; - esac -else - enable_fast_install=yes -fi - - - - - - - - - shared_archive_member_spec= -case $host,$enable_shared in -power*-*-aix[5-9]*,yes) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 -$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } - -# Check whether --with-aix-soname was given. -if test "${with_aix_soname+set}" = set; then : - withval=$with_aix_soname; case $withval in - aix|svr4|both) - ;; - *) - as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 - ;; - esac - lt_cv_with_aix_soname=$with_aix_soname -else - if ${lt_cv_with_aix_soname+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_with_aix_soname=aix -fi - - with_aix_soname=$lt_cv_with_aix_soname -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 -$as_echo "$with_aix_soname" >&6; } - if test aix != "$with_aix_soname"; then - # For the AIX way of multilib, we name the shared archive member - # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', - # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. - # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, - # the AIX toolchain works better with OBJECT_MODE set (default 32). - if test 64 = "${OBJECT_MODE-32}"; then - shared_archive_member_spec=shr_64 - else - shared_archive_member_spec=shr - fi - fi - ;; -*) - with_aix_soname=aix - ;; -esac - - - - - - - - - - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS=$ltmain - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -test -z "$LN_S" && LN_S="ln -s" - - - - - - - - - - - - - - -if test -n "${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 -$as_echo_n "checking for objdir... " >&6; } -if ${lt_cv_objdir+:} false; then : - $as_echo_n "(cached) " >&6 -else - rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 -$as_echo "$lt_cv_objdir" >&6; } -objdir=$lt_cv_objdir - - - - - -cat >>confdefs.h <<_ACEOF -#define LT_OBJDIR "$lt_cv_objdir/" -_ACEOF - - - - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test set != "${COLLECT_NAMES+set}"; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a '.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld=$lt_cv_prog_gnu_ld - -old_CC=$CC -old_CFLAGS=$CFLAGS - -# Set sane defaults for various variables -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$LD" && LD=ld -test -z "$ac_objext" && ac_objext=o - -func_cc_basename $compiler -cc_basename=$func_cc_basename_result - - -# Only perform the check for file, if the check method requires it -test -z "$MAGIC_CMD" && MAGIC_CMD=file -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 -$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } -if ${lt_cv_path_MAGIC_CMD+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/${ac_tool_prefix}file"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD - ;; -esac -fi - -MAGIC_CMD=$lt_cv_path_MAGIC_CMD -if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 -$as_echo "$MAGIC_CMD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - - - -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 -$as_echo_n "checking for file... " >&6; } -if ${lt_cv_path_MAGIC_CMD+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/file"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD - ;; -esac -fi - -MAGIC_CMD=$lt_cv_path_MAGIC_CMD -if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 -$as_echo "$MAGIC_CMD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - else - MAGIC_CMD=: - fi -fi - - fi - ;; -esac - -# Use C for the default configuration in the libtool script - -lt_save_CC=$CC -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -objext=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - -# Save the default compiler, since it gets overwritten when the other -# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. -compiler_DEFAULT=$CC - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* - -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* - - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - -lt_prog_compiler_no_builtin_flag= - -if test yes = "$GCC"; then - case $cc_basename in - nvcc*) - lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; - *) - lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; - esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } -if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } - -if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then - lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" -else - : -fi - -fi - - - - - - - lt_prog_compiler_wl= -lt_prog_compiler_pic= -lt_prog_compiler_static= - - - if test yes = "$GCC"; then - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_static='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - fi - lt_prog_compiler_pic='-fPIC' - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - lt_prog_compiler_pic='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. - lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic='-DDLL_EXPORT' - case $host_os in - os2*) - lt_prog_compiler_static='$wl-static' - ;; - esac - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - ;; - - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - lt_prog_compiler_static= - ;; - - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - ;; - - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared=no - enable_shared=no - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic=-Kconform_pic - fi - ;; - - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - - case $cc_basename in - nvcc*) # Cuda Compiler Driver 2.2 - lt_prog_compiler_wl='-Xlinker ' - if test -n "$lt_prog_compiler_pic"; then - lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" - fi - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl='-Wl,' - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - else - lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - case $cc_basename in - nagfor*) - # NAG Fortran compiler - lt_prog_compiler_wl='-Wl,-Wl,,' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - esac - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic='-DDLL_EXPORT' - case $host_os in - os2*) - lt_prog_compiler_static='$wl-static' - ;; - esac - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='$wl-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static='-non_shared' - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - # old Intel for x86_64, which still supported -KPIC. - ecc*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-static' - ;; - # flang / f18. f95 an alias for gfortran or flang on Debian - flang* | f18* | f95*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - # icc used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - icc* | ifort*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - # Lahey Fortran 8.1. - lf95*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='--shared' - lt_prog_compiler_static='--static' - ;; - nagfor*) - # NAG Fortran compiler - lt_prog_compiler_wl='-Wl,-Wl,,' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fpic' - lt_prog_compiler_static='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - xl* | bgxl* | bgf* | mpixl*) - # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-qpic' - lt_prog_compiler_static='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='' - ;; - *Sun\ F* | *Sun*Fortran*) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='-Qoption ld ' - ;; - *Sun\ C*) - # Sun C 5.9 - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='-Wl,' - ;; - *Intel*\ [CF]*Compiler*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - *Portland\ Group*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fpic' - lt_prog_compiler_static='-Bstatic' - ;; - esac - ;; - esac - ;; - - newsos6) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - - rdos*) - lt_prog_compiler_static='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - case $cc_basename in - f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) - lt_prog_compiler_wl='-Qoption ld ';; - *) - lt_prog_compiler_wl='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl='-Qoption ld ' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic='-Kconform_pic' - lt_prog_compiler_static='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_can_build_shared=no - ;; - - uts4*) - lt_prog_compiler_pic='-pic' - lt_prog_compiler_static='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared=no - ;; - esac - fi - -case $host_os in - # For platforms that do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic= - ;; - *) - lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" - ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } -if ${lt_cv_prog_compiler_pic+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic=$lt_prog_compiler_pic -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 -$as_echo "$lt_cv_prog_compiler_pic" >&6; } -lt_prog_compiler_pic=$lt_cv_prog_compiler_pic - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 -$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } -if ${lt_cv_prog_compiler_pic_works+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_works=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_pic_works=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 -$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } - -if test yes = "$lt_cv_prog_compiler_pic_works"; then - case $lt_prog_compiler_pic in - "" | " "*) ;; - *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; - esac -else - lt_prog_compiler_pic= - lt_prog_compiler_can_build_shared=no -fi - -fi - - - - - - - - - - - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if ${lt_cv_prog_compiler_static_works+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_static_works=no - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_static_works=yes - fi - else - lt_cv_prog_compiler_static_works=yes - fi - fi - $RM -r conftest* - LDFLAGS=$save_LDFLAGS - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 -$as_echo "$lt_cv_prog_compiler_static_works" >&6; } - -if test yes = "$lt_cv_prog_compiler_static_works"; then - : -else - lt_prog_compiler_static= -fi - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 -$as_echo "$lt_cv_prog_compiler_c_o" >&6; } - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 -$as_echo "$lt_cv_prog_compiler_c_o" >&6; } - - - - -hard_links=nottested -if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then - # do not overwrite the value of need_locks provided by the user - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 -$as_echo_n "checking if we can lock with hard links... " >&6; } - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 -$as_echo "$hard_links" >&6; } - if test no = "$hard_links"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - - runpath_var= - allow_undefined_flag= - always_export_symbols=no - archive_cmds= - archive_expsym_cmds= - compiler_needs_object=no - enable_shared_with_static_runtimes=no - export_dynamic_flag_spec= - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - hardcode_automatic=no - hardcode_direct=no - hardcode_direct_absolute=no - hardcode_libdir_flag_spec= - hardcode_libdir_separator= - hardcode_minus_L=no - hardcode_shlibpath_var=unsupported - inherit_rpath=no - link_all_deplibs=unknown - module_cmds= - module_expsym_cmds= - old_archive_from_new_cmds= - old_archive_from_expsyms_cmds= - thread_safe_flag_spec= - whole_archive_flag_spec= - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ' (' and ')$', so one must not match beginning or - # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', - # as well as any symbol that contains 'd'. - exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - # Exclude shared library initialization/finalization symbols. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test yes != "$GCC"; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd* | bitrig*) - with_gnu_ld=no - ;; - linux* | k*bsd*-gnu | gnu*) - link_all_deplibs=no - ;; - esac - - ld_shlibs=yes - - # On some targets, GNU ld is compatible enough with the native linker - # that we're better off using the native interface for both. - lt_use_gnu_ld_interface=no - if test yes = "$with_gnu_ld"; then - case $host_os in - aix*) - # The AIX port of GNU ld has always aspired to compatibility - # with the native linker. However, as the warning in the GNU ld - # block says, versions before 2.19.5* couldn't really create working - # shared libraries, regardless of the interface used. - case `$LD -v 2>&1` in - *\ \(GNU\ Binutils\)\ 2.19.5*) ;; - *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; - *\ \(GNU\ Binutils\)\ [3-9]*) ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - fi - - if test yes = "$lt_use_gnu_ld_interface"; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='$wl' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - export_dynamic_flag_spec='$wl--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - else - whole_archive_flag_spec= - fi - supports_anon_versioning=no - case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in - *GNU\ gold*) supports_anon_versioning=yes ;; - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix[3-9]*) - # On AIX/PPC, the GNU linker is very broken - if test ia64 != "$host_cpu"; then - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: the GNU linker, at least up to release 2.19, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to install binutils -*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. -*** You will then need to restart the configuration process. - -_LT_EOF - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='' - ;; - m68k) - archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - ;; - esac - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - export_dynamic_flag_spec='$wl--export-all-symbols' - allow_undefined_flag=unsupported - always_export_symbols=no - enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs=no - fi - ;; - - haiku*) - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - link_all_deplibs=yes - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - shrext_cmds=.dll - archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - enable_shared_with_static_runtimes=yes - ;; - - interix[3-9]*) - hardcode_direct=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='$wl-rpath,$libdir' - export_dynamic_flag_spec='$wl-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) - tmp_diet=no - if test linux-dietlibc = "$host_os"; then - case $cc_basename in - diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) - esac - fi - if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test no = "$tmp_diet" - then - tmp_addflag=' $pic_flag' - tmp_sharedflag='-shared' - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group f77 and f90 compilers - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - lf95*) # Lahey Fortran 8.1 - whole_archive_flag_spec= - tmp_sharedflag='--shared' ;; - nagfor*) # NAGFOR 5.3 - tmp_sharedflag='-Wl,-shared' ;; - xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) - tmp_sharedflag='-qmkshrobj' - tmp_addflag= ;; - nvcc*) # Cuda Compiler Driver 2.2 - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - compiler_needs_object=yes - ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - compiler_needs_object=yes - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - - if test yes = "$supports_anon_versioning"; then - archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' - fi - - case $cc_basename in - tcc*) - export_dynamic_flag_spec='-rdynamic' - ;; - xlf* | bgf* | bgxlf* | mpixlf*) - # IBM XL Fortran 10.1 on PPC cannot create shared libs itself - whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test yes = "$supports_anon_versioning"; then - archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' - fi - ;; - esac - else - ld_shlibs=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - *) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test no = "$ld_shlibs"; then - runpath_var= - hardcode_libdir_flag_spec= - export_dynamic_flag_spec= - whole_archive_flag_spec= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix[4-9]*) - if test ia64 = "$host_cpu"; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag= - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive - case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) - for ld_flag in $LDFLAGS; do - if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then - aix_use_runtimelinking=yes - break - fi - done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds='' - hardcode_direct=yes - hardcode_direct_absolute=yes - hardcode_libdir_separator=':' - link_all_deplibs=yes - file_list_spec='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # traditional, no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - hardcode_direct=no - hardcode_direct_absolute=no - ;; - esac - - if test yes = "$GCC"; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - ;; - esac - shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag="$shared_flag "'$wl-G' - fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' - else - # not using gcc - if test ia64 = "$host_cpu"; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' - else - shared_flag='$wl-bM:SRE' - fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' - fi - fi - - export_dynamic_flag_spec='$wl-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag='-berok' - # Determine the default libpath from the value encoded in an - # empty executable. - if test set = "${lt_cv_aix_libpath+set}"; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath_+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=/usr/lib:/lib - fi - -fi - - aix_libpath=$lt_cv_aix_libpath_ -fi - - hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag - else - if test ia64 = "$host_cpu"; then - hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' - allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - if test set = "${lt_cv_aix_libpath+set}"; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath_+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=/usr/lib:/lib - fi - -fi - - aix_libpath=$lt_cv_aix_libpath_ -fi - - hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag=' $wl-bernotok' - allow_undefined_flag=' $wl-berok' - if test yes = "$with_gnu_ld"; then - # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' - fi - archive_cmds_need_lc=yes - archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' - fi - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='' - ;; - m68k) - archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - ;; - esac - ;; - - bsdi[45]*) - export_dynamic_flag_spec=-rdynamic - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - case $cc_basename in - cl*) - # Native MSVC - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - always_export_symbols=yes - file_list_spec='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, )='true' - enable_shared_with_static_runtimes=yes - exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' - # Don't use ranlib - old_postinstall_cmds='chmod 644 $oldlib' - postlink_cmds='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # Assume MSVC wrapper - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' - enable_shared_with_static_runtimes=yes - ;; - esac - ;; - - darwin* | rhapsody*) - - - archive_cmds_need_lc=no - hardcode_direct=no - hardcode_automatic=yes - hardcode_shlibpath_var=unsupported - if test yes = "$lt_cv_ld_force_load"; then - whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - - else - whole_archive_flag_spec='' - fi - link_all_deplibs=yes - allow_undefined_flag=$_lt_dar_allow_undefined - case $cc_basename in - ifort*|nagfor*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test yes = "$_lt_dar_can_shared"; then - output_verbose_link_cmd=func_echo_all - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" - - else - ld_shlibs=no - fi - - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2.*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - hpux9*) - if test yes = "$GCC"; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec='$wl+b $wl$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - export_dynamic_flag_spec='$wl-E' - ;; - - hpux10*) - if test yes,no = "$GCC,$with_gnu_ld"; then - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test no = "$with_gnu_ld"; then - hardcode_libdir_flag_spec='$wl+b $wl$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - hardcode_direct_absolute=yes - export_dynamic_flag_spec='$wl-E' - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - fi - ;; - - hpux11*) - if test yes,no = "$GCC,$with_gnu_ld"; then - case $host_cpu in - hppa*64*) - archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - - # Older versions of the 11.00 compiler do not understand -b yet - # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 -$as_echo_n "checking if $CC understands -b... " >&6; } -if ${lt_cv_prog_compiler__b+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler__b=no - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -b" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler__b=yes - fi - else - lt_cv_prog_compiler__b=yes - fi - fi - $RM -r conftest* - LDFLAGS=$save_LDFLAGS - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 -$as_echo "$lt_cv_prog_compiler__b" >&6; } - -if test yes = "$lt_cv_prog_compiler__b"; then - archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' -else - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' -fi - - ;; - esac - fi - if test no = "$with_gnu_ld"; then - hardcode_libdir_flag_spec='$wl+b $wl$libdir' - hardcode_libdir_separator=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct=no - hardcode_shlibpath_var=no - ;; - *) - hardcode_direct=yes - hardcode_direct_absolute=yes - export_dynamic_flag_spec='$wl-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test yes = "$GCC"; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - # Try to use the -exported_symbol ld option, if it does not - # work, assume that -exports_file does not work either and - # implicitly export all symbols. - # This should be the same for all languages, so no per-tag cache variable. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 -$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } -if ${lt_cv_irix_exported_symbol+:} false; then : - $as_echo_n "(cached) " >&6 -else - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -int foo (void) { return 0; } -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_irix_exported_symbol=yes -else - lt_cv_irix_exported_symbol=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 -$as_echo "$lt_cv_irix_exported_symbol" >&6; } - if test yes = "$lt_cv_irix_exported_symbol"; then - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' - fi - link_all_deplibs=no - else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' - fi - archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - hardcode_libdir_separator=: - inherit_rpath=yes - link_all_deplibs=yes - ;; - - linux*) - case $cc_basename in - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - ld_shlibs=yes - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - newsos6) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - hardcode_libdir_separator=: - hardcode_shlibpath_var=no - ;; - - *nto* | *qnx*) - ;; - - openbsd* | bitrig*) - if test -f /usr/libexec/ld.so; then - hardcode_direct=yes - hardcode_shlibpath_var=no - hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='$wl-rpath,$libdir' - export_dynamic_flag_spec='$wl-E' - else - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='$wl-rpath,$libdir' - fi - else - ld_shlibs=no - fi - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - shrext_cmds=.dll - archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - enable_shared_with_static_runtimes=yes - ;; - - osf3*) - if test yes = "$GCC"; then - allow_undefined_flag=' $wl-expect_unresolved $wl\*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - fi - archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test yes = "$GCC"; then - allow_undefined_flag=' $wl-expect_unresolved $wl\*' - archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec='-rpath $libdir' - fi - archive_cmds_need_lc='no' - hardcode_libdir_separator=: - ;; - - solaris*) - no_undefined_flag=' -z defs' - if test yes = "$GCC"; then - wlarc='$wl' - archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - else - case `$CC -V 2>&1` in - *"Compilers 5.0"*) - wlarc='' - archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' - ;; - *) - wlarc='$wl' - archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - ;; - esac - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. GCC discards it without '$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test yes = "$GCC"; then - whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' - else - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' - fi - ;; - esac - link_all_deplibs=yes - ;; - - sunos4*) - if test sequent = "$host_vendor"; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds='$CC -r -o $output$reload_objs' - hardcode_direct=no - ;; - motorola) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='$wl-z,text' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - - if test yes = "$GCC"; then - archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag='$wl-z,text' - allow_undefined_flag='$wl-z,nodefs' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='$wl-R,$libdir' - hardcode_libdir_separator=':' - link_all_deplibs=yes - export_dynamic_flag_spec='$wl-Bexport' - runpath_var='LD_RUN_PATH' - - if test yes = "$GCC"; then - archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac - - if test sni = "$host_vendor"; then - case $host in - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='$wl-Blargedynsym' - ;; - esac - fi - fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 -$as_echo "$ld_shlibs" >&6; } -test no = "$ld_shlibs" && can_build_shared=no - -with_gnu_ld=$with_gnu_ld - - - - - - - - - - - - - - - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc=yes - - if test yes,yes = "$GCC,$enable_shared"; then - case $archive_cmds in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 -$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } -if ${lt_cv_archive_cmds_need_lc+:} false; then : - $as_echo_n "(cached) " >&6 -else - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 - (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - then - lt_cv_archive_cmds_need_lc=no - else - lt_cv_archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 -$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } - archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc - ;; - esac - fi - ;; -esac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 -$as_echo_n "checking dynamic linker characteristics... " >&6; } - -if test yes = "$GCC"; then - case $host_os in - darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; - *) lt_awk_arg='/^libraries:/' ;; - esac - case $host_os in - mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; - *) lt_sed_strip_eq='s|=/|/|g' ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` - case $lt_search_path_spec in - *\;*) - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` - ;; - *) - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` - ;; - esac - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary... - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - # ...but if some path component already ends with the multilib dir we assume - # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). - case "$lt_multi_os_dir; $lt_search_path_spec " in - "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) - lt_multi_os_dir= - ;; - esac - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" - elif test -n "$lt_multi_os_dir"; then - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS = " "; FS = "/|\n";} { - lt_foo = ""; - lt_count = 0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo = "/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[lt_foo]++; } - if (lt_freq[lt_foo] == 1) { print lt_foo; } -}'` - # AWK program above erroneously prepends '/' to C:/dos/paths - # for these hosts. - case $host_os in - mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's|/\([A-Za-z]:\)|\1|g'` ;; - esac - sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=.so -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - - - -case $host_os in -aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='$libname$release$shared_ext$major' - ;; - -aix[4-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test ia64 = "$host_cpu"; then - # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line '#! .'. This would cause the generated library to - # depend on '.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # Using Import Files as archive members, it is possible to support - # filename-based versioning of shared library archives on AIX. While - # this would work for both with and without runtime linking, it will - # prevent static linking of such archives. So we do filename-based - # shared library versioning with .so extension only, which is used - # when both runtime linking and shared linking is enabled. - # Unfortunately, runtime linking may impact performance, so we do - # not want this to be the default eventually. Also, we use the - # versioned .so libs for executables only if there is the -brtl - # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. - # To allow for filename-based versioning support, we need to create - # libNAME.so.V as an archive file, containing: - # *) an Import File, referring to the versioned filename of the - # archive as well as the shared archive member, telling the - # bitwidth (32 or 64) of that shared object, and providing the - # list of exported symbols of that shared object, eventually - # decorated with the 'weak' keyword - # *) the shared object with the F_LOADONLY flag set, to really avoid - # it being seen by the linker. - # At run time we better use the real file rather than another symlink, - # but for link time we create the symlink libNAME.so -> libNAME.so.V - - case $with_aix_soname,$aix_use_runtimelinking in - # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - aix,yes) # traditional libtool - dynamic_linker='AIX unversionable lib.so' - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - aix,no) # traditional AIX only - dynamic_linker='AIX lib.a(lib.so.V)' - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - ;; - svr4,*) # full svr4 only - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,yes) # both, prefer svr4 - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # unpreferred sharedlib libNAME.a needs extra handling - postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' - postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,no) # both, prefer aix - dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling - postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' - postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' - ;; - esac - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='$libname$shared_ext' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=.dll - need_version=no - need_lib_prefix=no - - case $GCC,$cc_basename in - yes,*) - # gcc - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - ;; - esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - library_names_spec='$libname.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec=$LIB - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' - ;; - - *) - # Assume MSVC wrapper - library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' - dynamic_linker='Win32 ld.exe' - ;; - esac - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' - soname_spec='$libname$release$major$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[23].*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2.*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - if test 32 = "$HPUX_IA64_MODE"; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - sys_lib_dlsearch_path_spec=/usr/lib/hpux32 - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - sys_lib_dlsearch_path_spec=/usr/lib/hpux64 - fi - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... - postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 - ;; - -interix[3-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test yes = "$lt_cv_prog_gnu_ld"; then - version_type=linux # correct to gnu/linux during the next big refactor - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -linux*android*) - version_type=none # Android doesn't support versioned libraries. - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext' - soname_spec='$libname$release$shared_ext' - finish_cmds= - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. - hardcode_libdir_flag_spec='-L$libdir' - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - - # Some binutils ld are patched to set DT_RUNPATH - if ${lt_cv_shlibpath_overrides_runpath+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - lt_cv_shlibpath_overrides_runpath=yes -fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - -fi - - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Ideally, we could use ldconfig to report *all* directores which are - # searched for libraries, however this is still not possible. Aside from not - # being certain /sbin/ldconfig is available, command - # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, - # even though it is searched at run-time. Try to do the best guess by - # appending ld.so.conf contents (and includes) to the search path. - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd* | bitrig*) - version_type=sunos - sys_lib_dlsearch_path_spec=/usr/lib - need_lib_prefix=no - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - need_version=no - else - need_version=yes - fi - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -os2*) - libname_spec='$name' - version_type=windows - shrext_cmds=.dll - need_version=no - need_lib_prefix=no - # OS/2 can only load a DLL with a base name of 8 characters or less. - soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; - v=$($ECHO $release$versuffix | tr -d .-); - n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); - $ECHO $n$v`$shared_ext' - library_names_spec='${libname}_dll.$libext' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=BEGINLIBPATH - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test yes = "$with_gnu_ld"; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec; then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' - soname_spec='$libname$shared_ext.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=sco - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test yes = "$with_gnu_ld"; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 -$as_echo "$dynamic_linker" >&6; } -test no = "$dynamic_linker" && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test yes = "$GCC"; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then - sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec -fi - -if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then - sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec -fi - -# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... -configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec - -# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code -func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" - -# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool -configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 -$as_echo_n "checking how to hardcode library paths into programs... " >&6; } -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || - test -n "$runpath_var" || - test yes = "$hardcode_automatic"; then - - # We can hardcode non-existent directories. - if test no != "$hardcode_direct" && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && - test no != "$hardcode_minus_L"; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 -$as_echo "$hardcode_action" >&6; } - -if test relink = "$hardcode_action" || - test yes = "$inherit_rpath"; then - # Fast installation is not supported - enable_fast_install=no -elif test yes = "$shlibpath_overrides_runpath" || - test no = "$enable_shared"; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - - - - - - if test yes != "$enable_dlopen"; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen=load_add_on - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen=LoadLibrary - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if ${ac_cv_lib_dl_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_dlopen=yes -else - ac_cv_lib_dl_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl -else - - lt_cv_dlopen=dyld - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - tpf*) - # Don't try to run any link tests for TPF. We know it's impossible - # because TPF is a cross-compiler, and we know how we open DSOs. - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - lt_cv_dlopen_self=no - ;; - - *) - ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" -if test "x$ac_cv_func_shl_load" = xyes; then : - lt_cv_dlopen=shl_load -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 -$as_echo_n "checking for shl_load in -ldld... " >&6; } -if ${ac_cv_lib_dld_shl_load+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dld_shl_load=yes -else - ac_cv_lib_dld_shl_load=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 -$as_echo "$ac_cv_lib_dld_shl_load" >&6; } -if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld -else - ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" -if test "x$ac_cv_func_dlopen" = xyes; then : - lt_cv_dlopen=dlopen -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if ${ac_cv_lib_dl_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_dlopen=yes -else - ac_cv_lib_dl_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 -$as_echo_n "checking for dlopen in -lsvld... " >&6; } -if ${ac_cv_lib_svld_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_svld_dlopen=yes -else - ac_cv_lib_svld_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 -$as_echo "$ac_cv_lib_svld_dlopen" >&6; } -if test "x$ac_cv_lib_svld_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 -$as_echo_n "checking for dld_link in -ldld... " >&6; } -if ${ac_cv_lib_dld_dld_link+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dld_link (); -int -main () -{ -return dld_link (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dld_dld_link=yes -else - ac_cv_lib_dld_dld_link=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 -$as_echo "$ac_cv_lib_dld_dld_link" >&6; } -if test "x$ac_cv_lib_dld_dld_link" = xyes; then : - lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test no = "$lt_cv_dlopen"; then - enable_dlopen=no - else - enable_dlopen=yes - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS=$CPPFLAGS - test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS=$LDFLAGS - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS=$LIBS - LIBS="$lt_cv_dlopen_libs $LIBS" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 -$as_echo_n "checking whether a program can dlopen itself... " >&6; } -if ${lt_cv_dlopen_self+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test yes = "$cross_compiling"; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -#line $LINENO "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -/* When -fvisibility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -} -_LT_EOF - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 -$as_echo "$lt_cv_dlopen_self" >&6; } - - if test yes = "$lt_cv_dlopen_self"; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 -$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } -if ${lt_cv_dlopen_self_static+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test yes = "$cross_compiling"; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -#line $LINENO "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -/* When -fvisibility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -} -_LT_EOF - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 -$as_echo "$lt_cv_dlopen_self_static" >&6; } - fi - - CPPFLAGS=$save_CPPFLAGS - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - - - - - - - - - - - - - - - - - -striplib= -old_striplib= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 -$as_echo_n "checking whether stripping libraries is possible... " >&6; } -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP"; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - ;; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - ;; - esac -fi - - - - - - - - - - - - - # Report what library types will actually be built - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 -$as_echo_n "checking if libtool supports shared libraries... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 -$as_echo "$can_build_shared" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 -$as_echo_n "checking whether to build shared libraries... " >&6; } - test no = "$can_build_shared" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test yes = "$enable_shared" && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - - aix[4-9]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac - fi - ;; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 -$as_echo "$enable_shared" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 -$as_echo_n "checking whether to build static libraries... " >&6; } - # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 -$as_echo "$enable_static" >&6; } - - - - -fi -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -CC=$lt_save_CC - - if test -n "$CXX" && ( test no != "$CXX" && - ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || - (test g++ != "$CXX"))); then - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 -$as_echo_n "checking how to run the C++ preprocessor... " >&6; } -if test -z "$CXXCPP"; then - if ${ac_cv_prog_CXXCPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 -$as_echo "$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -else - _lt_caught_CXX_error=yes -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -archive_cmds_need_lc_CXX=no -allow_undefined_flag_CXX= -always_export_symbols_CXX=no -archive_expsym_cmds_CXX= -compiler_needs_object_CXX=no -export_dynamic_flag_spec_CXX= -hardcode_direct_CXX=no -hardcode_direct_absolute_CXX=no -hardcode_libdir_flag_spec_CXX= -hardcode_libdir_separator_CXX= -hardcode_minus_L_CXX=no -hardcode_shlibpath_var_CXX=unsupported -hardcode_automatic_CXX=no -inherit_rpath_CXX=no -module_cmds_CXX= -module_expsym_cmds_CXX= -link_all_deplibs_CXX=unknown -old_archive_cmds_CXX=$old_archive_cmds -reload_flag_CXX=$reload_flag -reload_cmds_CXX=$reload_cmds -no_undefined_flag_CXX= -whole_archive_flag_spec_CXX= -enable_shared_with_static_runtimes_CXX=no - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -objext_CXX=$objext - -# No sense in running all these tests if we already determined that -# the CXX compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_caught_CXX_error"; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="int some_variable = 0;" - - # Code to be used in simple link tests - lt_simple_link_test_code='int main(int, char *[]) { return(0); }' - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - - # save warnings/boilerplate of simple test code - ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* - - ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* - - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_CFLAGS=$CFLAGS - lt_save_LD=$LD - lt_save_GCC=$GCC - GCC=$GXX - lt_save_with_gnu_ld=$with_gnu_ld - lt_save_path_LD=$lt_cv_path_LD - if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx - else - $as_unset lt_cv_prog_gnu_ld - fi - if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX - else - $as_unset lt_cv_path_LD - fi - test -z "${LDCXX+set}" || LD=$LDCXX - CC=${CXX-"c++"} - CFLAGS=$CXXFLAGS - compiler=$CC - compiler_CXX=$CC - func_cc_basename $compiler -cc_basename=$func_cc_basename_result - - - if test -n "$compiler"; then - # We don't want -fno-exception when compiling C++ code, so set the - # no_builtin_flag separately - if test yes = "$GXX"; then - lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' - else - lt_prog_compiler_no_builtin_flag_CXX= - fi - - if test yes = "$GXX"; then - # Set up default GNU C++ configuration - - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -ac_prog=ld -if test yes = "$GCC"; then - # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 -$as_echo_n "checking for ld used by $CC... " >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return, which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD=$ac_prog - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test yes = "$with_gnu_ld"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } -fi -if ${lt_cv_path_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$LD"; then - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD=$ac_dir/$ac_prog - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if ${lt_cv_prog_gnu_ld+:} false; then : - $as_echo_n "(cached) " >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -$as_echo "$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - - - - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test yes = "$with_gnu_ld"; then - archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='$wl' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | - $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - else - whole_archive_flag_spec_CXX= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' - - else - GXX=no - with_gnu_ld=no - wlarc= - fi - - # PORTME: fill in a description of your system's C++ link characteristics - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - ld_shlibs_CXX=yes - case $host_os in - aix3*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aix[4-9]*) - if test ia64 = "$host_cpu"; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag= - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive - case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_CXX='' - hardcode_direct_CXX=yes - hardcode_direct_absolute_CXX=yes - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - file_list_spec_CXX='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - hardcode_direct_CXX=no - hardcode_direct_absolute_CXX=no - ;; - esac - - if test yes = "$GXX"; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct_CXX=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_CXX=yes - hardcode_libdir_flag_spec_CXX='-L$libdir' - hardcode_libdir_separator_CXX= - fi - esac - shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag=$shared_flag' $wl-G' - fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' - else - # not using gcc - if test ia64 = "$host_cpu"; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' - else - shared_flag='$wl-bM:SRE' - fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' - fi - fi - - export_dynamic_flag_spec_CXX='$wl-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to - # export. - always_export_symbols_CXX=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - # The "-G" linker flag allows undefined symbols. - no_undefined_flag_CXX='-bernotok' - # Determine the default libpath from the value encoded in an empty - # executable. - if test set = "${lt_cv_aix_libpath+set}"; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath__CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=/usr/lib:/lib - fi - -fi - - aix_libpath=$lt_cv_aix_libpath__CXX -fi - - hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" - - archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag - else - if test ia64 = "$host_cpu"; then - hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' - allow_undefined_flag_CXX="-z nodefs" - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - if test set = "${lt_cv_aix_libpath+set}"; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath__CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=/usr/lib:/lib - fi - -fi - - aix_libpath=$lt_cv_aix_libpath__CXX -fi - - hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_CXX=' $wl-bernotok' - allow_undefined_flag_CXX=' $wl-berok' - if test yes = "$with_gnu_ld"; then - # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_CXX='$convenience' - fi - archive_cmds_need_lc_CXX=yes - archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared - # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. - archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_CXX=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - else - ld_shlibs_CXX=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - cygwin* | mingw* | pw32* | cegcc*) - case $GXX,$cc_basename in - ,cl* | no,cl*) - # Native MSVC - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_CXX=' ' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=yes - file_list_spec_CXX='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' - enable_shared_with_static_runtimes_CXX=yes - # Don't use ranlib - old_postinstall_cmds_CXX='chmod 644 $oldlib' - postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # g++ - # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_CXX='-L$libdir' - export_dynamic_flag_spec_CXX='$wl--export-all-symbols' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=no - enable_shared_with_static_runtimes_CXX=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_CXX=no - fi - ;; - esac - ;; - darwin* | rhapsody*) - - - archive_cmds_need_lc_CXX=no - hardcode_direct_CXX=no - hardcode_automatic_CXX=yes - hardcode_shlibpath_var_CXX=unsupported - if test yes = "$lt_cv_ld_force_load"; then - whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - - else - whole_archive_flag_spec_CXX='' - fi - link_all_deplibs_CXX=yes - allow_undefined_flag_CXX=$_lt_dar_allow_undefined - case $cc_basename in - ifort*|nagfor*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test yes = "$_lt_dar_can_shared"; then - output_verbose_link_cmd=func_echo_all - archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" - module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" - if test yes != "$lt_cv_apple_cc_single_mod"; then - archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" - archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" - fi - - else - ld_shlibs_CXX=no - fi - - ;; - - os2*) - hardcode_libdir_flag_spec_CXX='-L$libdir' - hardcode_minus_L_CXX=yes - allow_undefined_flag_CXX=unsupported - shrext_cmds=.dll - archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - enable_shared_with_static_runtimes_CXX=yes - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - freebsd2.*) - # C++ shared libraries reported to be fairly broken before - # switch to ELF - ld_shlibs_CXX=no - ;; - - freebsd-elf*) - archive_cmds_need_lc_CXX=no - ;; - - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - ld_shlibs_CXX=yes - ;; - - haiku*) - archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - link_all_deplibs_CXX=yes - ;; - - hpux9*) - hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' - hardcode_libdir_separator_CXX=: - export_dynamic_flag_spec_CXX='$wl-E' - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes = "$GXX"; then - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - hpux10*|hpux11*) - if test no = "$with_gnu_ld"; then - hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' - hardcode_libdir_separator_CXX=: - - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - export_dynamic_flag_spec_CXX='$wl-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - ;; - *) - hardcode_direct_CXX=yes - hardcode_direct_absolute_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - interix[3-9]*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - export_dynamic_flag_spec_CXX='$wl-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - else - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' - fi - fi - link_all_deplibs_CXX=yes - ;; - esac - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' - hardcode_libdir_separator_CXX=: - inherit_rpath_CXX=yes - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc* | ecpc* ) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - archive_cmds_need_lc_CXX=no - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' - whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - case `$CC -V` in - *pgCC\ [1-5].* | *pgcpp\ [1-5].*) - prelink_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' - old_archive_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' - archive_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 6 and above use weak symbols - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - - hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' - whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - ;; - cxx*) - # Compaq C++ - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' - ;; - xl* | mpixl* | bgxl*) - # IBM XL 8.0 on PPC, with GNU ld - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' - archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test yes = "$supports_anon_versioning"; then - archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' - fi - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' - hardcode_libdir_flag_spec_CXX='-R$libdir' - whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - compiler_needs_object_CXX=yes - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - - lynxos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - m88k*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - - *nto* | *qnx*) - ld_shlibs_CXX=yes - ;; - - openbsd* | bitrig*) - if test -f /usr/libexec/ld.so; then - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - hardcode_direct_absolute_CXX=yes - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' - export_dynamic_flag_spec_CXX='$wl-E' - whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - fi - output_verbose_link_cmd=func_echo_all - else - ld_shlibs_CXX=no - fi - ;; - - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - case $host in - osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; - *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; - esac - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx*) - case $host in - osf3*) - allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' - archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' - ;; - *) - allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ - $RM $lib.exp' - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - ;; - esac - - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes,no = "$GXX,$with_gnu_ld"; then - allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' - case $host in - osf3*) - archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - ;; - *) - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - ;; - esac - - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - psos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - archive_cmds_need_lc_CXX=yes - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_shlibpath_var_CXX=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' - ;; - esac - link_all_deplibs_CXX=yes - - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test yes,no = "$GXX,$with_gnu_ld"; then - no_undefined_flag_CXX=' $wl-z ${wl}defs' - if $CC --version | $GREP -v '^2\.7' > /dev/null; then - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' - else - # g++ 2.7 appears to require '-G' NOT '-shared' on this - # platform. - archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' - fi - - hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag_CXX='$wl-z,text' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag_CXX='$wl-z,text' - allow_undefined_flag_CXX='$wl-z,nodefs' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - export_dynamic_flag_spec_CXX='$wl-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ - '"$old_archive_cmds_CXX" - reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ - '"$reload_cmds_CXX" - ;; - *) - archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - vxworks*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 -$as_echo "$ld_shlibs_CXX" >&6; } - test no = "$ld_shlibs_CXX" && can_build_shared=no - - GCC_CXX=$GXX - LD_CXX=$LD - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - # Dependencies to place before and after the object being linked: -predep_objects_CXX= -postdep_objects_CXX= -predeps_CXX= -postdeps_CXX= -compiler_lib_search_path_CXX= - -cat > conftest.$ac_ext <<_LT_EOF -class Foo -{ -public: - Foo (void) { a = 0; } -private: - int a; -}; -_LT_EOF - - -_lt_libdeps_save_CFLAGS=$CFLAGS -case "$CC $CFLAGS " in #( -*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; -*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; -*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; -esac - -if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - for p in `eval "$output_verbose_link_cmd"`; do - case $prev$p in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test x-L = "$p" || - test x-R = "$p"; then - prev=$p - continue - fi - - # Expand the sysroot to ease extracting the directories later. - if test -z "$prev"; then - case $p in - -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; - -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; - -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; - esac - fi - case $p in - =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; - esac - if test no = "$pre_test_object_deps_done"; then - case $prev in - -L | -R) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$compiler_lib_search_path_CXX"; then - compiler_lib_search_path_CXX=$prev$p - else - compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$postdeps_CXX"; then - postdeps_CXX=$prev$p - else - postdeps_CXX="${postdeps_CXX} $prev$p" - fi - fi - prev= - ;; - - *.lto.$objext) ;; # Ignore GCC LTO objects - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test no = "$pre_test_object_deps_done"; then - if test -z "$predep_objects_CXX"; then - predep_objects_CXX=$p - else - predep_objects_CXX="$predep_objects_CXX $p" - fi - else - if test -z "$postdep_objects_CXX"; then - postdep_objects_CXX=$p - else - postdep_objects_CXX="$postdep_objects_CXX $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling CXX test program" -fi - -$RM -f confest.$objext -CFLAGS=$_lt_libdeps_save_CFLAGS - -# PORTME: override above test on systems where it is broken -case $host_os in -interix[3-9]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - predep_objects_CXX= - postdep_objects_CXX= - postdeps_CXX= - ;; -esac - - -case " $postdeps_CXX " in -*" -lc "*) archive_cmds_need_lc_CXX=no ;; -esac - compiler_lib_search_dirs_CXX= -if test -n "${compiler_lib_search_path_CXX}"; then - compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lt_prog_compiler_wl_CXX= -lt_prog_compiler_pic_CXX= -lt_prog_compiler_static_CXX= - - - # C++ specific cases for pic, static, wl, etc. - if test yes = "$GXX"; then - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - fi - lt_prog_compiler_pic_CXX='-fPIC' - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - lt_prog_compiler_pic_CXX='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. - lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - case $host_os in - os2*) - lt_prog_compiler_static_CXX='$wl-static' - ;; - esac - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_CXX='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - lt_prog_compiler_pic_CXX= - ;; - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - lt_prog_compiler_static_CXX= - ;; - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_CXX=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic_CXX='-fPIC -shared' - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - else - case $host_os in - aix[4-9]*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - else - lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - ;; - dgux*) - case $cc_basename in - ec++*) - lt_prog_compiler_pic_CXX='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='$wl-a ${wl}archive' - if test ia64 != "$host_cpu"; then - lt_prog_compiler_pic_CXX='+Z' - fi - ;; - aCC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='$wl-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_CXX='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - KCC*) - # KAI C++ Compiler - lt_prog_compiler_wl_CXX='--backend -Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - ;; - ecpc* ) - # old Intel C++ for x86_64, which still supported -KPIC. - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-static' - ;; - icpc* ) - # Intel C++, used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - lt_prog_compiler_static_CXX='-static' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-fpic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) - # IBM XL 8.0, 9.0 on PPC and BlueGene - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-qpic' - lt_prog_compiler_static_CXX='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - lt_prog_compiler_pic_CXX='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic_CXX='-fPIC -shared' - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - lt_prog_compiler_wl_CXX='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - lt_prog_compiler_pic_CXX='-pic' - ;; - cxx*) - # Digital/Compaq C++ - lt_prog_compiler_wl_CXX='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - lt_prog_compiler_pic_CXX='-pic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - lcc*) - # Lucid - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - lt_prog_compiler_pic_CXX='-KPIC' - ;; - *) - ;; - esac - ;; - vxworks*) - ;; - *) - lt_prog_compiler_can_build_shared_CXX=no - ;; - esac - fi - -case $host_os in - # For platforms that do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_CXX= - ;; - *) - lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" - ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } -if ${lt_cv_prog_compiler_pic_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } -lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 -$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } -if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_works_CXX=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_pic_works_CXX=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } - -if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then - case $lt_prog_compiler_pic_CXX in - "" | " "*) ;; - *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; - esac -else - lt_prog_compiler_pic_CXX= - lt_prog_compiler_can_build_shared_CXX=no -fi - -fi - - - - - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_static_works_CXX=no - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_static_works_CXX=yes - fi - else - lt_cv_prog_compiler_static_works_CXX=yes - fi - fi - $RM -r conftest* - LDFLAGS=$save_LDFLAGS - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } - -if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then - : -else - lt_prog_compiler_static_CXX= -fi - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } - - - - -hard_links=nottested -if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then - # do not overwrite the value of need_locks provided by the user - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 -$as_echo_n "checking if we can lock with hard links... " >&6; } - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 -$as_echo "$hard_links" >&6; } - if test no = "$hard_links"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' - case $host_os in - aix[4-9]*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - export_symbols_cmds_CXX=$ltdll_cmds - ;; - cygwin* | mingw* | cegcc*) - case $cc_basename in - cl*) - exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' - ;; - esac - ;; - linux* | k*bsd*-gnu | gnu*) - link_all_deplibs_CXX=no - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 -$as_echo "$ld_shlibs_CXX" >&6; } -test no = "$ld_shlibs_CXX" && can_build_shared=no - -with_gnu_ld_CXX=$with_gnu_ld - - - - - - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_CXX" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_CXX=yes - - if test yes,yes = "$GCC,$enable_shared"; then - case $archive_cmds_CXX in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 -$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } -if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_CXX - pic_flag=$lt_prog_compiler_pic_CXX - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_CXX - allow_undefined_flag_CXX= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 - (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - then - lt_cv_archive_cmds_need_lc_CXX=no - else - lt_cv_archive_cmds_need_lc_CXX=yes - fi - allow_undefined_flag_CXX=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 -$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } - archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX - ;; - esac - fi - ;; -esac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 -$as_echo_n "checking dynamic linker characteristics... " >&6; } - -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=.so -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - - - -case $host_os in -aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='$libname$release$shared_ext$major' - ;; - -aix[4-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test ia64 = "$host_cpu"; then - # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line '#! .'. This would cause the generated library to - # depend on '.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # Using Import Files as archive members, it is possible to support - # filename-based versioning of shared library archives on AIX. While - # this would work for both with and without runtime linking, it will - # prevent static linking of such archives. So we do filename-based - # shared library versioning with .so extension only, which is used - # when both runtime linking and shared linking is enabled. - # Unfortunately, runtime linking may impact performance, so we do - # not want this to be the default eventually. Also, we use the - # versioned .so libs for executables only if there is the -brtl - # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. - # To allow for filename-based versioning support, we need to create - # libNAME.so.V as an archive file, containing: - # *) an Import File, referring to the versioned filename of the - # archive as well as the shared archive member, telling the - # bitwidth (32 or 64) of that shared object, and providing the - # list of exported symbols of that shared object, eventually - # decorated with the 'weak' keyword - # *) the shared object with the F_LOADONLY flag set, to really avoid - # it being seen by the linker. - # At run time we better use the real file rather than another symlink, - # but for link time we create the symlink libNAME.so -> libNAME.so.V - - case $with_aix_soname,$aix_use_runtimelinking in - # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - aix,yes) # traditional libtool - dynamic_linker='AIX unversionable lib.so' - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - aix,no) # traditional AIX only - dynamic_linker='AIX lib.a(lib.so.V)' - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - ;; - svr4,*) # full svr4 only - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,yes) # both, prefer svr4 - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # unpreferred sharedlib libNAME.a needs extra handling - postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' - postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,no) # both, prefer aix - dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling - postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' - postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' - ;; - esac - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='$libname$shared_ext' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=.dll - need_version=no - need_lib_prefix=no - - case $GCC,$cc_basename in - yes,*) - # gcc - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - ;; - esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - library_names_spec='$libname.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec=$LIB - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' - ;; - - *) - # Assume MSVC wrapper - library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' - dynamic_linker='Win32 ld.exe' - ;; - esac - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' - soname_spec='$libname$release$major$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[23].*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2.*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - if test 32 = "$HPUX_IA64_MODE"; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - sys_lib_dlsearch_path_spec=/usr/lib/hpux32 - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - sys_lib_dlsearch_path_spec=/usr/lib/hpux64 - fi - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... - postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 - ;; - -interix[3-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test yes = "$lt_cv_prog_gnu_ld"; then - version_type=linux # correct to gnu/linux during the next big refactor - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -linux*android*) - version_type=none # Android doesn't support versioned libraries. - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext' - soname_spec='$libname$release$shared_ext' - finish_cmds= - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. - hardcode_libdir_flag_spec_CXX='-L$libdir' - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - - # Some binutils ld are patched to set DT_RUNPATH - if ${lt_cv_shlibpath_overrides_runpath+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - lt_cv_shlibpath_overrides_runpath=yes -fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - -fi - - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Ideally, we could use ldconfig to report *all* directores which are - # searched for libraries, however this is still not possible. Aside from not - # being certain /sbin/ldconfig is available, command - # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, - # even though it is searched at run-time. Try to do the best guess by - # appending ld.so.conf contents (and includes) to the search path. - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd* | bitrig*) - version_type=sunos - sys_lib_dlsearch_path_spec=/usr/lib - need_lib_prefix=no - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - need_version=no - else - need_version=yes - fi - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -os2*) - libname_spec='$name' - version_type=windows - shrext_cmds=.dll - need_version=no - need_lib_prefix=no - # OS/2 can only load a DLL with a base name of 8 characters or less. - soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; - v=$($ECHO $release$versuffix | tr -d .-); - n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); - $ECHO $n$v`$shared_ext' - library_names_spec='${libname}_dll.$libext' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=BEGINLIBPATH - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test yes = "$with_gnu_ld"; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec; then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' - soname_spec='$libname$shared_ext.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=sco - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test yes = "$with_gnu_ld"; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 -$as_echo "$dynamic_linker" >&6; } -test no = "$dynamic_linker" && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test yes = "$GCC"; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then - sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec -fi - -if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then - sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec -fi - -# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... -configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec - -# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code -func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" - -# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool -configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 -$as_echo_n "checking how to hardcode library paths into programs... " >&6; } -hardcode_action_CXX= -if test -n "$hardcode_libdir_flag_spec_CXX" || - test -n "$runpath_var_CXX" || - test yes = "$hardcode_automatic_CXX"; then - - # We can hardcode non-existent directories. - if test no != "$hardcode_direct_CXX" && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && - test no != "$hardcode_minus_L_CXX"; then - # Linking always hardcodes the temporary library directory. - hardcode_action_CXX=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_CXX=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_CXX=unsupported -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 -$as_echo "$hardcode_action_CXX" >&6; } - -if test relink = "$hardcode_action_CXX" || - test yes = "$inherit_rpath_CXX"; then - # Fast installation is not supported - enable_fast_install=no -elif test yes = "$shlibpath_overrides_runpath" || - test no = "$enable_shared"; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - - - - - - - fi # test -n "$compiler" - - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS - LDCXX=$LD - LD=$lt_save_LD - GCC=$lt_save_GCC - with_gnu_ld=$lt_save_with_gnu_ld - lt_cv_path_LDCXX=$lt_cv_path_LD - lt_cv_path_LD=$lt_save_path_LD - lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld - lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test yes != "$_lt_caught_CXX_error" - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - - - - - - - - - - - - - - ac_config_commands="$ac_config_commands libtool" - - - - -# Only expand once: - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -# Extract the first word of "mkdir", so it can be a program name with args. -set dummy mkdir; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_MKDIR+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $MKDIR in - [\\/]* | ?:[\\/]*) - ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -MKDIR=$ac_cv_path_MKDIR -if test -n "$MKDIR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR" >&5 -$as_echo "$MKDIR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - -# Documentation. -# Check whether --enable-documentation was given. -if test "${enable_documentation+set}" = set; then : - enableval=$enable_documentation; -else - enable_documentation=auto -fi - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}doxygen", so it can be a program name with args. -set dummy ${ac_tool_prefix}doxygen; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_DOXYGEN+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $DOXYGEN in - [\\/]* | ?:[\\/]*) - ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -DOXYGEN=$ac_cv_path_DOXYGEN -if test -n "$DOXYGEN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5 -$as_echo "$DOXYGEN" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_DOXYGEN"; then - ac_pt_DOXYGEN=$DOXYGEN - # Extract the first word of "doxygen", so it can be a program name with args. -set dummy doxygen; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_DOXYGEN+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_DOXYGEN in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_DOXYGEN="$ac_pt_DOXYGEN" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_DOXYGEN="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_DOXYGEN=$ac_cv_path_ac_pt_DOXYGEN -if test -n "$ac_pt_DOXYGEN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_DOXYGEN" >&5 -$as_echo "$ac_pt_DOXYGEN" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_DOXYGEN" = x; then - DOXYGEN="nodoxygen" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DOXYGEN=$ac_pt_DOXYGEN - fi -else - DOXYGEN="$ac_cv_path_DOXYGEN" -fi - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dot", so it can be a program name with args. -set dummy ${ac_tool_prefix}dot; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_HAVE_DOT+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$HAVE_DOT"; then - ac_cv_prog_HAVE_DOT="$HAVE_DOT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in NO -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_HAVE_DOT="${ac_tool_prefix}dot" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -HAVE_DOT=$ac_cv_prog_HAVE_DOT -if test -n "$HAVE_DOT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_DOT" >&5 -$as_echo "$HAVE_DOT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_HAVE_DOT"; then - ac_ct_HAVE_DOT=$HAVE_DOT - # Extract the first word of "dot", so it can be a program name with args. -set dummy dot; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_HAVE_DOT+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_HAVE_DOT"; then - ac_cv_prog_ac_ct_HAVE_DOT="$ac_ct_HAVE_DOT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in NO -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_HAVE_DOT="dot" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_HAVE_DOT=$ac_cv_prog_ac_ct_HAVE_DOT -if test -n "$ac_ct_HAVE_DOT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_HAVE_DOT" >&5 -$as_echo "$ac_ct_HAVE_DOT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_HAVE_DOT" = x; then - HAVE_DOT="YES" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - HAVE_DOT=$ac_ct_HAVE_DOT - fi -else - HAVE_DOT="$ac_cv_prog_HAVE_DOT" -fi - -if test "$enable_documentation" = "yes" && test "$DOXYGEN" = "nodoxygen"; then : - as_fn_error $? "could not find tools necessary to build documentation" "$LINENO" 5 -fi - if test "$enable_documentation" != "no" -a "$DOXYGEN" != "nodoxygen"; then - BUILD_REFERENCE_TRUE= - BUILD_REFERENCE_FALSE='#' -else - BUILD_REFERENCE_TRUE='#' - BUILD_REFERENCE_FALSE= -fi - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 -$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } - # Check whether --enable-maintainer-mode was given. -if test "${enable_maintainer_mode+set}" = set; then : - enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval -else - USE_MAINTAINER_MODE=no -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 -$as_echo "$USE_MAINTAINER_MODE" >&6; } - if test $USE_MAINTAINER_MODE = yes; then - MAINTAINER_MODE_TRUE= - MAINTAINER_MODE_FALSE='#' -else - MAINTAINER_MODE_TRUE='#' - MAINTAINER_MODE_FALSE= -fi - - MAINT=$MAINTAINER_MODE_TRUE - - - -# See if we want stricter compiler warnings. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking maintainer mode" >&5 -$as_echo_n "checking maintainer mode... " >&6; } -# Check whether --enable-maintainer-mode was given. -if test "${enable_maintainer_mode+set}" = set; then : - enableval=$enable_maintainer_mode; -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_maintainer_mode}" >&5 -$as_echo "${enable_maintainer_mode}" >&6; } - -# See if we want runtime debug checking. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking audit" >&5 -$as_echo_n "checking audit... " >&6; } -# Check whether --enable-audit was given. -if test "${enable_audit+set}" = set; then : - enableval=$enable_audit; -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_audit}" >&5 -$as_echo "${enable_audit}" >&6; } - -# See if we want "suggestions," such as "this class could be final." -# (The suggestions are often useful, but can also easily be wrong.) -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking suggest" >&5 -$as_echo_n "checking suggest... " >&6; } -# Check whether --enable-suggest was given. -if test "${enable_suggest+set}" = set; then : - enableval=$enable_suggest; -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_suggest}" >&5 -$as_echo "${enable_suggest}" >&6; } - - -# Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then : - enableval=$enable_shared; -fi - -if test "${shared}" = "yes" ; then : - CPPFLAGS="$CPPFLAGS -DPQXX_SHARED" -fi - - -# Add options to compiler command line, if compiler accepts them. -add_compiler_opts_if_ok() { - for option in $* - do - ACO_SAVE_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $option" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts $option" >&5 -$as_echo_n "checking whether $CXX accepts $option... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - has_option=yes -else - has_option=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_option" >&5 -$as_echo "$has_option" >&6; } - if test "$has_option" = "no" ; then : - CXXFLAGS="$ACO_SAVE_CXXFLAGS" -fi - done -} - - -# Add options to compiler command line, unconditionally. -add_compiler_opts() { - CXXFLAGS="$CXXFLAGS $*" -} - - -# It's tempting to use Autoconf Archive's AX_CXX_COMPILE_STDCXX_17 for this, -# but it's 2022 and the C++20 equivalent isn't quite ready for use. -# Seems simpler and more reliable for the user to arrange for the desired -# language versions by setting the appropriate option for their compiler. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sufficient C++ language/library level" >&5 -$as_echo_n "checking for sufficient C++ language/library level... " >&6; } -sufficient_cxx=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #if __cplusplus < 201611L - #error "Need C++17 or better." - #endif - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - sufficient_cxx=yes -else - sufficient_cxx=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $sufficient_cxx" >&5 -$as_echo "$sufficient_cxx" >&6; } -if test "$sufficient_cxx" != "yes" -then - as_fn_error $? "This libpqxx version needs at least C++17." "$LINENO" 5 -fi - - -# Let's try to get the compiler to be helpful. -# -# (Omit options -Weffc++ and -Wabi because they currently yield too many -# warnings in gcc's standard headers; omit -Wunreachable-code because it isn't -# always right) -if test "$GCC" = "yes" -then - # In maintainer mode, enable all the warning options we can. - if test "$enable_maintainer_mode" = "yes" - then - # "Eternal" (FLW) g++ options. These have been around for - # ages, and both g++ and clang++ support them. Don't bother - # checking for support; just add them to the compiler options. - add_compiler_opts \ - -fstrict-enums \ - -Werror \ - -Wall \ - -pedantic \ - -Wcast-align \ - -Wcast-qual \ - -Wconversion \ - -Wctor-dtor-privacy \ - -Wendif-labels \ - -Wextra \ - -Wfloat-equal \ - -Wformat=2 \ - -Wformat-security \ - -Wmissing-include-dirs \ - -Wno-div-by-zero \ - -Wnon-virtual-dtor \ - -Wold-style-cast \ - -Woverlength-strings \ - -Woverloaded-virtual \ - -Wpointer-arith \ - -Wredundant-decls \ - -Wshadow \ - -Wsign-promo \ - -Wundef \ - -Wunused \ - -Wwrite-strings - - # "Iffy" g++ options. Some reasonably current g++-like - # compilers may not support these. - add_compiler_opts_if_ok \ - -fnothrow-opt \ - -Wattribute-alias=2 \ - -Wextra-semi \ - -Wlogical-op \ - -Wmismatched-tags \ - -Wnoexcept \ - -Wredundant-tags \ - -Wrestrict \ - -Wstringop-overflow \ - -Wzero-as-null-pointer-constant \ - -Warray-bounds=2 \ - -Wduplicated-branches \ - -Wduplicated-cond \ - -Wsuggest-attribute=noreturn \ - -Wsuggest-override \ - -Wtrampolines - fi - - # In "audit," enable all runtime checks we can. - if test "$enable_audit" = "yes" - then - add_compiler_opts_if_ok \ - -D_FORTIFY_SOURCE=2 \ - -fsanitize=address \ - -fsanitize-address-use-after-scope \ - -fsanitize=alignment \ - -fsanitize=bool \ - -fsanitize=bounds \ - -fsanitize=bounds-strict \ - -fsanitize=builtin \ - -fsanitize=enum \ - -fsanitize=float-cast-overflow \ - -fsanitize=float-divide-by-zero \ - -fsanitize=integer-divide-by-zero \ - -fsanitize=leak \ - -fsanitize=nonnull-attribute \ - -fsanitize=null \ - -fsanitize=object-size \ - -fsanitize=pointer-compare \ - -fsanitize=pointer-overflow \ - -fsanitize=pointer-subtract \ - -fsanitize=return \ - -fsanitize=returns-nonnull-attribute \ - -fsanitize=shift \ - -fsanitize=shift-base \ - -fsanitize=shift-exponent \ - -fsanitize=signed-integer-overflow \ - -fsanitize=undefined \ - -fsanitize=unreachable \ - -fsanitize=vla-bound \ - -fsanitize=vptr \ - -fstack-protector-all - fi - - # In "suggest" mode, enable a bunch of code suggestions. - if test "$enable_suggest" = "yes" - then - add_compiler_opts_if_ok \ - -Wsuggest-attribute=cold \ - -Wsuggest-attribute=const \ - -Wsuggest-attribute=malloc \ - -Wsuggest-attribute=pure \ - -Wsuggest-final-types \ - -Wsuggest-final-methods - fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking g++ visibility attribute" >&5 -$as_echo_n "checking g++ visibility attribute... " >&6; } -gcc_visibility=yes -SAVE_CXXFLAGS="$CXXFLAGS" -CXXFLAGS="$CXXFLAGS -Werror" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for gcc-style "visibility" attribute. - -struct __attribute__((visibility("hidden"))) D - -{ - - D() {} - - int f() { return 0; } - -}; - - - -int main() - -{ - - D d; - - return d.f(); - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_GCC_VISIBILITY 1" >>confdefs.h - -else - gcc_visibility=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_visibility" >&5 -$as_echo "$gcc_visibility" >&6; } -CXXFLAGS="$SAVE_CXXFLAGS" -if test "$gcc_visibility" = "yes" -then - # Make internal definitions accessible only to the library itself. - # Only definitions marked PQXX_LIBEXPORT will be accessible. - add_compiler_opts -fvisibility=hidden - add_compiler_opts -fvisibility-inlines-hidden -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking g++ pure attribute" >&5 -$as_echo_n "checking g++ pure attribute... " >&6; } -gcc_pure=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for gcc-style "pure" attribute. - -int __attribute__((pure)) f() - -{ - - return 0; - -} - - - -int main() - -{ - - return f(); - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_GCC_PURE 1" >>confdefs.h - -else - gcc_pure=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_pure" >&5 -$as_echo "$gcc_pure" >&6; } - -fi # End of gcc-specific part. - - -# Check for __cxa_demangle. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __cxa_demangle" >&5 -$as_echo_n "checking __cxa_demangle... " >&6; } -cxa_demangle=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for cross-vendor C++ ABI's __cxa_demangle function. - -#include - -#include - -#include - -#include - - - -#include - - - -int main() - -{ - - int status = 0; - - char *name = - - abi::__cxa_demangle(typeid(10).name(), nullptr, nullptr, &status); - - if (status != 0) - - throw std::runtime_error("Demangle failed!"); - - int result = std::strcmp(name, "int"); - - std::free(name); - - return result; - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_CXA_DEMANGLE 1" >>confdefs.h - -else - cxa_demangle=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cxa_demangle" >&5 -$as_echo "$cxa_demangle" >&6; } - - -# Check for sufficient Concepts support, introduced with C++20. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking concepts" >&5 -$as_echo_n "checking concepts... " >&6; } -concepts=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for concepts support. Not just the language feature; also headers. - -#include - -#include - -#include - - - - - -template - -concept Foo = std::ranges::input_range; - - - - - -template auto foo(F const &r) - -{ - - return std::distance(std::begin(r), std::end(r)); - -} - - - - - -int main() - -{ - - std::vector const v{1, 2, 3}; - - std::cout << foo(v) << '\n'; - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_CONCEPTS 1" >>confdefs.h - -else - concepts=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $concepts" >&5 -$as_echo "$concepts" >&6; } - - -# Check for C++20 std::span. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking std::span" >&5 -$as_echo_n "checking std::span... " >&6; } -span=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for std::span. - -#include - - - -int main(int argc, char **argv) - -{ - - std::span args{argv, static_cast(argc)}; - - return static_cast(std::size(args) - 1u); - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_SPAN 1" >>confdefs.h - -else - span=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $span" >&5 -$as_echo "$span" >&6; } - - -# Check for multidimensional subscript operator support. Proposed for C++23. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for multidimensional subscript operator support" >&5 -$as_echo_n "checking for multidimensional subscript operator support... " >&6; } -multidim_subscript=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for multidimensional subscript operator support. - -// Proposed for C++23: P2128R6. - -struct table - -{ - - int width = 100; - - - - int operator[](int x, int y) const { return x + width * y; } - -}; - - - - - -int main() - -{ - - return table{}[0, 0]; - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT 1" >>confdefs.h - -else - multidim_subscript=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $multidim_subscript" >&5 -$as_echo "$multidim_subscript" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strerror_r()" >&5 -$as_echo_n "checking for strerror_r()... " >&6; } -strerror_r=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Check for strerror_r. - -// It can be either the POSIX version (which returns int) or the GNU version - -// (which returns char *). - - - -#include - -#include - - - -int main() - -{ - - char buffer[200]; - - auto res{strerror_r(1, buffer, 200)}; - - // Sidestep type differences. We don't really care what the value is. - - return not not res; - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_STRERROR_R 1" >>confdefs.h - -else - strerror_r=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $strerror_r" >&5 -$as_echo "$strerror_r" >&6; } - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strerror_s()" >&5 -$as_echo_n "checking for strerror_s()... " >&6; } -strerror_s=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for strerror_s, as defined in Windows and C11. - -// Presumably this'll be part of the C++ standard some day. - - - -#include - - - -int main() - -{ - - using namespace std; - - char buf[200]; - - return strerror_s(buf, 200, 1); - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_STRERROR_S 1" >>confdefs.h - -else - strerror_s=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $strerror_s" >&5 -$as_echo "$strerror_s" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::chrono::year_month_day etc" >&5 -$as_echo_n "checking for std::chrono::year_month_day etc... " >&6; } -year_month_day=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for std::chrono::year_month_day etc. - -#include - - - -int main() - -{ - - return int(std::chrono::year{1}); - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_YEAR_MONTH_DAY 1" >>confdefs.h - -else - year_month_day=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $year_month_day" >&5 -$as_echo "$year_month_day" >&6; } - - -# Check for [[likely]] and [[unlikely]] attributes. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking attributes \"likely\" and \"unlikely\"." >&5 -$as_echo_n "checking attributes \"likely\" and \"unlikely\".... " >&6; } -likely=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for C++20 [[likely]] and [[unlikely]] attributes. - - - -int main(int argc, char **) - -{ - -#if __cplusplus < 202002L - - deliberately_fail(because, older, C++, standard); - -#endif - - - - int x = 0; - - if (argc == 1) [[likely]] - - x = 0; - - else - - x = 1; - - return x; - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_LIKELY 1" >>confdefs.h - -else - likely=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $likely" >&5 -$as_echo "$likely" >&6; } - - -# It's mid-2019, and gcc's charconv supports integers but not yet floats. -# So for now, we test for int and float conversion... separately. -# -# It's worse for older clang versions, which compile the integer conversions -# but then fail at link time because of a missing symbol "__muloti4" with the -# "long long" version. I couldn't resolve that symbol by adding -lm either. -# So don't just compile these tests; link them as well. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++17 charconv integer conversion" >&5 -$as_echo_n "checking for C++17 charconv integer conversion... " >&6; } -have_charconv_int=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for std::to_string/std::from_string for integral types. - -#include - -#include - - - -int main() - -{ - - char z[100]; - - auto rt = std::to_chars(std::begin(z), std::end(z), 9ULL); - - if (rt.ec != std::errc{}) - - return 1; - - unsigned long long n; - - auto rf = std::from_chars(std::cbegin(z), std::cend(z), n); - - if (rf.ec != std::errc{}) - - return 2; - - return (n == 9ULL) ? 0 : 1; - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_CHARCONV_INT 1" >>confdefs.h - -else - have_charconv_int=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_charconv_int" >&5 -$as_echo "$have_charconv_int" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++17 charconv floating-point conversion" >&5 -$as_echo_n "checking for C++17 charconv floating-point conversion... " >&6; } -have_charconv_float=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for std::to_string/std::from_string for floating-point types. - -#include - -#include - - - -int main() - -{ - - char z[100]; - - auto rt = std::to_chars(std::begin(z), std::end(z), 3.14159L); - - if (rt.ec != std::errc{}) - - return 1; - - long double n; - - auto rf = std::from_chars(std::cbegin(z), std::cend(z), n); - - if (rf.ec != std::errc{}) - - return 2; - - return (n > 3 and n < 4) ? 0 : 1; - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_CHARCONV_FLOAT 1" >>confdefs.h - -else - have_charconv_float=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_charconv_float" >&5 -$as_echo "$have_charconv_float" >&6; } - -# As per #262, clang with libcxxrt does not support thread_local on non-POD -# objects. Luckily we can live without those, it's just less efficient. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for full thread_local support" >&5 -$as_echo_n "checking for full thread_local support... " >&6; } -have_thread_local=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for std::to_string/std::from_string for floating-point types. - -#include - -#include - - - -int main(int argc, char **) - -{ - -#if defined(__MINGW32__) && defined(__GNUC__) - -# if __GNUC__ < 11 || ((__GNUC__ == 11) && (__GNU_MINOR__ == 0)) - -# error "On MinGW before gcc 11.1, thread_local breaks at run time." - -# endif - -#endif - - thread_local std::stringstream s; - - s << argc; - - std::cout << s.str(); - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_THREAD_LOCAL 1" >>confdefs.h - -else - have_thread_local=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_thread_local" >&5 -$as_echo "$have_thread_local" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::this_thread::sleep_for" >&5 -$as_echo_n "checking for std::this_thread::sleep_for... " >&6; } -have_sleep_for=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for std::this_thread::sleep_for(). - -/* For some reason MinGW's header seems to be broken. - - * - - * But it gets worse. It looks as if we can include without problems - - * in this configuration test. Why does it break when MinGW users try to build - - * the library, but succeed when we try it here? - - * - - * To try and get close to the situation in the library code itself, we try - - * including some standard headers that we don't strictly need here. - - */ - - - -#if __has_include() - -# include - -#endif - - - -#include - -#include - -#include - -#include - -#include - - - -#include - -#include - - - -int main() - -{ - - std::this_thread::sleep_for(std::chrono::microseconds{10u}); - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_SLEEP_FOR 1" >>confdefs.h - -else - have_sleep_for=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_sleep_for" >&5 -$as_echo "$have_sleep_for" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::cmp_greater, std::cmp_less_equal, etc" >&5 -$as_echo_n "checking for std::cmp_greater, std::cmp_less_equal, etc... " >&6; } -have_cmp=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for C++20 std::cmp_greater etc. support. - -#include - - - - - -int main() - -{ - - return std::cmp_greater(-1, 2u) && std::cmp_less_equal(3, 0); - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_CMP 1" >>confdefs.h - -else - have_cmp=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_cmp" >&5 -$as_echo "$have_cmp" >&6; } - - -# Doing my own check for poll(). There's one built into autoconf-archive, but -# it produces warnings in C++ (about unnecessarily using "struct", and using 0 -# as a null pointer constant). In maintainer mode, those warnings turn into -# errors. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for poll()" >&5 -$as_echo_n "checking for poll()... " >&6; } -ax_cv_have_poll=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Test for poll(). - -#include - - - -int main() - -{ - - return poll(nullptr, 0, 0); - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_POLL 1" >>confdefs.h - -else - ax_cv_have_poll=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have_poll" >&5 -$as_echo "$ax_cv_have_poll" >&6; } - -if test "$ax_cv_have_poll" != "yes" -then -# No poll(); we'll fall back to select(). - -# Some systems keep select() in a separate library which is not linked by -# default. See if we need one of those. -socklibok=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing select" >&5 -$as_echo_n "checking for library containing select... " >&6; } -if ${ac_cv_search_select+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char select (); -int -main () -{ -return select (); - ; - return 0; -} -_ACEOF -for ac_lib in '' socket nsl ws2_32 wsock32 winsock; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_cxx_try_link "$LINENO"; then : - ac_cv_search_select=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_select+:} false; then : - break -fi -done -if ${ac_cv_search_select+:} false; then : - -else - ac_cv_search_select=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_select" >&5 -$as_echo "$ac_cv_search_select" >&6; } -ac_res=$ac_cv_search_select -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - socklibok=yes -fi - - -# Microsoft proprietary libraries do not work with code that is generated with -# autoconf's SEARCH_LIBS macro, so we need to check manually and just use the -# first socket library available. -# We only do this if select() is not available by other means, to avoid picking -# up an unnecessary Windows compatibility library on a non-Windows system. -for l in ws2_32 wsock32 winsock -do - if test "${socklibok}" != "yes" - then - as_ac_Lib=`$as_echo "ac_cv_lib_$l''_main" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l$l" >&5 -$as_echo_n "checking for main in -l$l... " >&6; } -if eval \${$as_ac_Lib+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$l $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ -return main (); - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" -else - eval "$as_ac_Lib=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - LIBS="$LIBS -l$l";socklibok=yes -fi - - fi -done - -if test "${socklibok}" != "yes" -then - as_fn_error $? " -Could not figure out how to link a simple sockets-based program. Please read -the config.log file for more clues as to why this failed. -" "$LINENO" 5 -fi - -fi # No poll() - - -# Find PostgreSQL includes and libraries -# Extract the first word of "pkg-config", so it can be a program name with args. -set dummy pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -PKG_CONFIG=$ac_cv_path_PKG_CONFIG -if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -$as_echo "$PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -for ac_prog in pg_config -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PG_CONFIG="$PG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -PG_CONFIG=$ac_cv_path_PG_CONFIG -if test -n "$PG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PG_CONFIG" >&5 -$as_echo "$PG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$PG_CONFIG" && break -done - - - -# Check whether --with-postgres-include was given. -if test "${with_postgres_include+set}" = set; then : - withval=$with_postgres_include; if test "x$with_postgres_include" = "xyes"; then : - with_postgres_include="" -fi -fi - - -if test -n "$with_postgres_include" -then - POSTGRES_INCLUDE="-I$with_postgres_include" -else - if test -x "$PKG_CONFIG" || test -x "$PG_CONFIG" - then - # We should prefer pkg-config over pg_config, but there seems to be a - # problem in pkg-config 1.6.3. Until that's been resolved (#291), go - # with pg_config if we can. - if test -x "$PG_CONFIG" - then - # From pg_config we can either get the C compiler options used to - # compile postgres, which isn't quite what we want; or we can get - # the headers directory, without the full option. That's something - # we can work with. The compiler must support the "-I" option for - # that, but both scripts assume that anyway. - POSTGRES_INCLUDE="-I$($PG_CONFIG --includedir)" - else - # From pkg-config we can get the compiler options to extend the - # include path. We use that. - POSTGRES_INCLUDE=$($PKG_CONFIG libpq --cflags-only-I) - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: finding PostgreSQL headers using $POSTGRES_INCLUDE" >&5 -$as_echo "$as_me: finding PostgreSQL headers using $POSTGRES_INCLUDE" >&6;} - else - POSTGRES_INCLUDE="" - - # We have nothing to tell us where the libpq headers are. That's fine - # if the compiler can find it, but if not, fail here. - -ac_fn_cxx_check_header_mongrel "$LINENO" "libpq-fe.h" "ac_cv_header_libpq_fe_h" "$ac_includes_default" -if test "x$ac_cv_header_libpq_fe_h" = xyes; then : - -else - as_fn_error $? " -Can't find the main PostgreSQL client header, libpq-fe.h. Make sure that it -is installed, and either use the --with-postgres-include option or install -pkg-config. -" "$LINENO" 5 -fi - - - fi -fi - - -# Add the compiler option so we can compile configure tests which rely on the -# libpq headers. -CPPFLAGS="$CPPFLAGS $POSTGRES_INCLUDE" - - - -# Check whether --with-postgres-lib was given. -if test "${with_postgres_lib+set}" = set; then : - withval=$with_postgres_lib; if test "x$with_postgres_lib" = "xyes"; then : - with_postgres_lib="" -fi -fi - - -# If no --with-postgres-lib was given, and we have pkg-config, use that. -if test -z "$with_postgres_lib" -a -x "$PKG_CONFIG"; then : - with_postgres_lib=$($PKG_CONFIG libpq --libs-only-L | sed 's/^-L//') -fi - -# pg_config is deprecated, but for some users it may still provide the only -# right answer. For instance, `pkg-config` may not know where `libpq` is -# installed. -if test -z "$with_postgres_lib" -a -x "$PG_CONFIG"; then : - with_postgres_lib=$($PG_CONFIG --libdir) -fi - -if test -n "$with_postgres_lib"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: using PostgreSQL libraries at $with_postgres_lib" >&5 -$as_echo "$as_me: using PostgreSQL libraries at $with_postgres_lib" >&6;} -else - { $as_echo "$as_me:${as_lineno-$LINENO}: using PostgreSQL libraries in default location" >&5 -$as_echo "$as_me: using PostgreSQL libraries in default location" >&6;} -fi - - - - -ac_fn_cxx_check_header_mongrel "$LINENO" "libpq-fe.h" "ac_cv_header_libpq_fe_h" "$ac_includes_default" -if test "x$ac_cv_header_libpq_fe_h" = xyes; then : - -else - as_fn_error $? " -Can't find the main PostgreSQL client header, libpq-fe.h. Are you sure the -libpq headers are installed correctly, and that we've got the right path? -" "$LINENO" 5 -fi - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ability to compile source files using libpq" >&5 -$as_echo_n "checking for ability to compile source files using libpq... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -PQexec(nullptr,"") - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - as_fn_error $? " -Could not compile a call to a basic libpq function. There must be something -seriously wrong with the headers that \"pg_config --includedir\" or \"pkg-config -libpq --cflags\" pointed to; the contents of config.log may give you a clue -about the nature of the failure. -Source including the libpq header libpq-fe.h can be compiled, but a call to the -most basic libpq function PQexec() failed to compile successfully. This is the -litmus test for a working libpq. -" "$LINENO" 5 -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - - -if test "x${with_postgres_lib}" = "x"; then - with_postgres_libpath="" -else - with_postgres_libpath="-L${with_postgres_lib}" -fi -LDFLAGS="$LDFLAGS ${with_postgres_libpath}" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQexec in -lpq" >&5 -$as_echo_n "checking for PQexec in -lpq... " >&6; } -if ${ac_cv_lib_pq_PQexec+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpq ${with_postgres_libpath} $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char PQexec (); -int -main () -{ -return PQexec (); - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - ac_cv_lib_pq_PQexec=yes -else - ac_cv_lib_pq_PQexec=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQexec" >&5 -$as_echo "$ac_cv_lib_pq_PQexec" >&6; } -if test "x$ac_cv_lib_pq_PQexec" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPQ 1 -_ACEOF - - LIBS="-lpq $LIBS" - -else - as_fn_error $? " -Did not find the PQexec() function in libpq. This is the litmus test for a -working libpq installation. - -A source file using the PQexec() function did compile without problems, and the -libpq library is available for linking, but for some reason a call to PQexec() -failed to link properly to the libpq library. This may be because the libpq -library file is damaged, or in some incorrect format, or if your libpq is much -more recent than libpqxx version $PQXX_ABI, perhaps libpq has undergone a -radical ABI change. - -The last parts of config.log may give you a clue as to what really went wrong, -but be warned that this is no easy reading. Look for the last error message -occurring in the file. -" "$LINENO" 5 -fi - - - -# PQencryptPasswordConn was added in postgres 10. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQencryptPasswordConn" >&5 -$as_echo_n "checking for PQencryptPasswordConn... " >&6; } -have_pqencryptpasswordconn=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - extern PGconn *conn; - PQencryptPasswordConn( - conn, "pwd", "user", "scram-sha-256") - - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_PQENCRYPTPASSWORDCONN 1" >>confdefs.h - -else - have_pqencryptpasswordconn=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_pqencryptpasswordconn" >&5 -$as_echo "$have_pqencryptpasswordconn" >&6; } - - -# "Pipeline mode" was introduced in libpq 14. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpq pipeline mode" >&5 -$as_echo_n "checking for libpq pipeline mode... " >&6; } -have_pq_pipeline=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - extern PGconn *conn; - PQenterPipelineMode(conn) - - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_PQ_PIPELINE 1" >>confdefs.h - -else - have_pq_pipeline=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_pq_pipeline" >&5 -$as_echo "$have_pq_pipeline" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for usable std::filesystem::path" >&5 -$as_echo_n "checking for usable std::filesystem::path... " >&6; } -have_path=yes -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Check for working std::filesystem support. - -#include - - - - - -int main() - -{ - - // Apparently some versions of MinGW lack this comparison operator. - - return std::filesystem::path{} != std::filesystem::path{}; - -} - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define PQXX_HAVE_PATH 1" >>confdefs.h - -else - have_path=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_path" >&5 -$as_echo "$have_path" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need a link option for support" >&5 -$as_echo_n "checking whether we need a link option for support... " >&6; } -LIBS_SAVE="$LIBS" -found_fslib=no -for l in '' '-lstdc++fs' '-lc++fs' -do - if test "$found_fslib" != "yes" - then - LIBS="$LIBS $l" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -// Check whether we need to link to the stdc++fs library. - -// - -// We assume that the presence of the header means that we have - -// support for the basics of std::filesystem. This check will succeed if - -// either there is no header, or there is one and it works without - -// any special options. If the link fails, we assume that -lstdc++fs will fix - -// it for us. - - - -#include - - - -#if __has_include() - -# include - -#endif - - - - - -int main() - -{ - -#if __has_include() - - std::cout << std::filesystem::path{"foo.bar"}.c_str() << '\n'; - -#endif - -} - - -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - found_fslib=yes -else - LIBS="$LIBS_SAVE" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test "$found_fslib" = "yes" - then - result_msg="$l" - # (And keep our current value of $LIBS.) - fi - fi -done - -if test "$found_fslib" != "yes" -then - as_fn_error $? " -There seems to be support, but I could not figure out now to make -it work. You'll have to add set your own build options for this. - " "$LINENO" 5 -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $result_msg" >&5 -$as_echo "$result_msg" >&6; } - - -# Remove redundant occurrances of -lpq -LIBS=$(echo "$LIBS" | sed -e 's/-lpq * -lpq\>/-lpq/g') - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that type of libpq's Oid is as expected" >&5 -$as_echo_n "checking that type of libpq's Oid is as expected... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - #include"${srcdir}/include/pqxx/internal/libpq-forward.hxx" - extern void f(pqxx::oid&); - -int -main () -{ -Oid o;f(o) - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - as_fn_error $? " -The Oid typedef in libpq has changed. Please notify the libpqxx authors of the -change! -" "$LINENO" 5 -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - - -ac_config_files="$ac_config_files Makefile config/Makefile doc/Makefile doc/Doxyfile src/Makefile test/Makefile tools/Makefile include/Makefile include/pqxx/Makefile libpqxx.pc" - - - -ac_config_commands="$ac_config_commands configitems" - - -ac_config_files="$ac_config_files compile_flags" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -DEFS=-DHAVE_CONFIG_H - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 -$as_echo_n "checking that generated files are newer than configure... " >&6; } - if test -n "$am_sleep_pid"; then - # Hide warnings about reused PIDs. - wait $am_sleep_pid 2>/dev/null - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 -$as_echo "done" >&6; } - if test -n "$EXEEXT"; then - am__EXEEXT_TRUE= - am__EXEEXT_FALSE='#' -else - am__EXEEXT_TRUE='#' - am__EXEEXT_FALSE= -fi - -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - as_fn_error $? "conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${BUILD_REFERENCE_TRUE}" && test -z "${BUILD_REFERENCE_FALSE}"; then - as_fn_error $? "conditional \"BUILD_REFERENCE\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then - as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by libpqxx $as_me 7.7.3, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - -case $ac_config_headers in *" -"*) set x $ac_config_headers; shift; ac_config_headers=$*;; -esac - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" -config_headers="$ac_config_headers" -config_commands="$ac_config_commands" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE - -Configuration files: -$config_files - -Configuration headers: -$config_headers - -Configuration commands: -$config_commands - -Report bugs to ." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -libpqxx config.status 7.7.3 -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -MKDIR_P='$MKDIR_P' -AWK='$AWK' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - as_fn_append CONFIG_HEADERS " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h) - # Conflict between --help and --header - as_fn_error $? "ambiguous option: \`$1' -Try \`$0 --help' for more information.";; - --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# -# INIT-COMMANDS -# -AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" - - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='$sed_quote_subst' -double_quote_subst='$double_quote_subst' -delay_variable_subst='$delay_variable_subst' -enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' -macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' -macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' -enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' -pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' -enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' -shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' -SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' -ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' -PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' -host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' -host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' -host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' -build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' -build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' -build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' -SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' -Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' -GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' -EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' -FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' -LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' -NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' -LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' -max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' -ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' -exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' -lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' -lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' -lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' -lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' -lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' -reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' -reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' -OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' -deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' -file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' -file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' -want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' -DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' -sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' -AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' -AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' -archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' -STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' -RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' -old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' -old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' -old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' -lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' -CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' -CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' -compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' -GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' -lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' -nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' -lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' -lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' -objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' -MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' -need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' -MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' -DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' -NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' -LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' -OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' -OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' -libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' -shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' -extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' -archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' -export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' -whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' -compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' -old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' -archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' -archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' -module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' -module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' -with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' -allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' -no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' -hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' -hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' -hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' -hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' -hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' -inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' -link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' -always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' -export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' -exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' -include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' -prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' -postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' -file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' -variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' -need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' -need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' -version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' -runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' -shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' -shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' -libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' -library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' -soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' -install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' -postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' -postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' -finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' -finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' -hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' -sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' -configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' -configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' -hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' -enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' -enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' -enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' -old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' -striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' -predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' -postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' -predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' -postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' -LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' -reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' -reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' -compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' -GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' -archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' -export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' -archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' -archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' -module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' -module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' -with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' -allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' -no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' -inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' -link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' -always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' -export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' -exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' -include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' -prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' -postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' -file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' -predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' -postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' -predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' -postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' - -LTCC='$LTCC' -LTCFLAGS='$LTCFLAGS' -compiler='$compiler_DEFAULT' - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - -# Quote evaled strings. -for var in SHELL \ -ECHO \ -PATH_SEPARATOR \ -SED \ -GREP \ -EGREP \ -FGREP \ -LD \ -NM \ -LN_S \ -lt_SP2NL \ -lt_NL2SP \ -reload_flag \ -OBJDUMP \ -deplibs_check_method \ -file_magic_cmd \ -file_magic_glob \ -want_nocaseglob \ -DLLTOOL \ -sharedlib_from_linklib_cmd \ -AR \ -AR_FLAGS \ -archiver_list_spec \ -STRIP \ -RANLIB \ -CC \ -CFLAGS \ -compiler \ -lt_cv_sys_global_symbol_pipe \ -lt_cv_sys_global_symbol_to_cdecl \ -lt_cv_sys_global_symbol_to_import \ -lt_cv_sys_global_symbol_to_c_name_address \ -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ -lt_cv_nm_interface \ -nm_file_list_spec \ -lt_cv_truncate_bin \ -lt_prog_compiler_no_builtin_flag \ -lt_prog_compiler_pic \ -lt_prog_compiler_wl \ -lt_prog_compiler_static \ -lt_cv_prog_compiler_c_o \ -need_locks \ -MANIFEST_TOOL \ -DSYMUTIL \ -NMEDIT \ -LIPO \ -OTOOL \ -OTOOL64 \ -shrext_cmds \ -export_dynamic_flag_spec \ -whole_archive_flag_spec \ -compiler_needs_object \ -with_gnu_ld \ -allow_undefined_flag \ -no_undefined_flag \ -hardcode_libdir_flag_spec \ -hardcode_libdir_separator \ -exclude_expsyms \ -include_expsyms \ -file_list_spec \ -variables_saved_for_relink \ -libname_spec \ -library_names_spec \ -soname_spec \ -install_override_mode \ -finish_eval \ -old_striplib \ -striplib \ -compiler_lib_search_dirs \ -predep_objects \ -postdep_objects \ -predeps \ -postdeps \ -compiler_lib_search_path \ -LD_CXX \ -reload_flag_CXX \ -compiler_CXX \ -lt_prog_compiler_no_builtin_flag_CXX \ -lt_prog_compiler_pic_CXX \ -lt_prog_compiler_wl_CXX \ -lt_prog_compiler_static_CXX \ -lt_cv_prog_compiler_c_o_CXX \ -export_dynamic_flag_spec_CXX \ -whole_archive_flag_spec_CXX \ -compiler_needs_object_CXX \ -with_gnu_ld_CXX \ -allow_undefined_flag_CXX \ -no_undefined_flag_CXX \ -hardcode_libdir_flag_spec_CXX \ -hardcode_libdir_separator_CXX \ -exclude_expsyms_CXX \ -include_expsyms_CXX \ -file_list_spec_CXX \ -compiler_lib_search_dirs_CXX \ -predep_objects_CXX \ -postdep_objects_CXX \ -predeps_CXX \ -postdeps_CXX \ -compiler_lib_search_path_CXX; do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in reload_cmds \ -old_postinstall_cmds \ -old_postuninstall_cmds \ -old_archive_cmds \ -extract_expsyms_cmds \ -old_archive_from_new_cmds \ -old_archive_from_expsyms_cmds \ -archive_cmds \ -archive_expsym_cmds \ -module_cmds \ -module_expsym_cmds \ -export_symbols_cmds \ -prelink_cmds \ -postlink_cmds \ -postinstall_cmds \ -postuninstall_cmds \ -finish_cmds \ -sys_lib_search_path_spec \ -configure_time_dlsearch_path \ -configure_time_lt_sys_library_path \ -reload_cmds_CXX \ -old_archive_cmds_CXX \ -old_archive_from_new_cmds_CXX \ -old_archive_from_expsyms_cmds_CXX \ -archive_cmds_CXX \ -archive_expsym_cmds_CXX \ -module_cmds_CXX \ -module_expsym_cmds_CXX \ -export_symbols_cmds_CXX \ -prelink_cmds_CXX \ -postlink_cmds_CXX; do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -ac_aux_dir='$ac_aux_dir' - -# See if we are running on zsh, and set the options that allow our -# commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST -fi - - - PACKAGE='$PACKAGE' - VERSION='$VERSION' - RM='$RM' - ofile='$ofile' - - - - - - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "include/pqxx/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/pqxx/config.h" ;; - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "config/Makefile") CONFIG_FILES="$CONFIG_FILES config/Makefile" ;; - "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; - "doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;; - "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; - "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; - "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; - "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; - "include/pqxx/Makefile") CONFIG_FILES="$CONFIG_FILES include/pqxx/Makefile" ;; - "libpqxx.pc") CONFIG_FILES="$CONFIG_FILES libpqxx.pc" ;; - "configitems") CONFIG_COMMANDS="$CONFIG_COMMANDS configitems" ;; - "compile_flags") CONFIG_FILES="$CONFIG_FILES compile_flags" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - -# Set up the scripts for CONFIG_HEADERS section. -# No need to generate them if there are no CONFIG_HEADERS. -# This happens for instance with `./config.status Makefile'. -if test -n "$CONFIG_HEADERS"; then -cat >"$ac_tmp/defines.awk" <<\_ACAWK || -BEGIN { -_ACEOF - -# Transform confdefs.h into an awk script `defines.awk', embedded as -# here-document in config.status, that substitutes the proper values into -# config.h.in to produce config.h. - -# Create a delimiter string that does not exist in confdefs.h, to ease -# handling of long lines. -ac_delim='%!_!# ' -for ac_last_try in false false :; do - ac_tt=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_tt"; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done - -# For the awk script, D is an array of macro values keyed by name, -# likewise P contains macro parameters if any. Preserve backslash -# newline sequences. - -ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* -sed -n ' -s/.\{148\}/&'"$ac_delim"'/g -t rset -:rset -s/^[ ]*#[ ]*define[ ][ ]*/ / -t def -d -:def -s/\\$// -t bsnl -s/["\\]/\\&/g -s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ -D["\1"]=" \3"/p -s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p -d -:bsnl -s/["\\]/\\&/g -s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ -D["\1"]=" \3\\\\\\n"\\/p -t cont -s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p -t cont -d -:cont -n -s/.\{148\}/&'"$ac_delim"'/g -t clear -:clear -s/\\$// -t bsnlc -s/["\\]/\\&/g; s/^/"/; s/$/"/p -d -:bsnlc -s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p -b cont -' >$CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - for (key in D) D_is_set[key] = 1 - FS = "" -} -/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { - line = \$ 0 - split(line, arg, " ") - if (arg[1] == "#") { - defundef = arg[2] - mac1 = arg[3] - } else { - defundef = substr(arg[1], 2) - mac1 = arg[2] - } - split(mac1, mac2, "(") #) - macro = mac2[1] - prefix = substr(line, 1, index(line, defundef) - 1) - if (D_is_set[macro]) { - # Preserve the white space surrounding the "#". - print prefix "define", macro P[macro] D[macro] - next - } else { - # Replace #undef with comments. This is necessary, for example, - # in the case of _POSIX_SOURCE, which is predefined and required - # on some systems where configure will not decide to define it. - if (defundef == "undef") { - print "/*", prefix defundef, macro, "*/" - next - } - } -} -{ print } -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 -fi # test -n "$CONFIG_HEADERS" - - -eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac - ac_MKDIR_P=$MKDIR_P - case $MKDIR_P in - [\\/$]* | ?:[\\/]* ) ;; - */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -s&@MKDIR_P@&$ac_MKDIR_P&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - :H) - # - # CONFIG_HEADER - # - if test x"$ac_file" != x-; then - { - $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" - } >"$ac_tmp/config.h" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 -$as_echo "$as_me: $ac_file is unchanged" >&6;} - else - rm -f "$ac_file" - mv "$ac_tmp/config.h" "$ac_file" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - fi - else - $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error $? "could not create -" "$LINENO" 5 - fi -# Compute "$ac_file"'s index in $config_headers. -_am_arg="$ac_file" -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $_am_arg | $_am_arg:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || -$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$_am_arg" : 'X\(//\)[^/]' \| \ - X"$_am_arg" : 'X\(//\)$' \| \ - X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$_am_arg" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'`/stamp-h$_am_stamp_count - ;; - - :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 -$as_echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Older Autoconf quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - # TODO: see whether this extra hack can be removed once we start - # requiring Autoconf 2.70 or later. - case $CONFIG_FILES in #( - *\'*) : - eval set x "$CONFIG_FILES" ;; #( - *) : - set x $CONFIG_FILES ;; #( - *) : - ;; -esac - shift - # Used to flag and report bootstrapping failures. - am_rc=0 - for am_mf - do - # Strip MF so we end up with the name of the file. - am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile which includes - # dependency-tracking related rules and includes. - # Grep'ing the whole file directly is not great: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ - || continue - am_dirpart=`$as_dirname -- "$am_mf" || -$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$am_mf" : 'X\(//\)[^/]' \| \ - X"$am_mf" : 'X\(//\)$' \| \ - X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$am_mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - am_filepart=`$as_basename -- "$am_mf" || -$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ - X"$am_mf" : 'X\(//\)$' \| \ - X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$am_mf" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - { echo "$as_me:$LINENO: cd "$am_dirpart" \ - && sed -e '/# am--include-marker/d' "$am_filepart" \ - | $MAKE -f - am--depfiles" >&5 - (cd "$am_dirpart" \ - && sed -e '/# am--include-marker/d' "$am_filepart" \ - | $MAKE -f - am--depfiles) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } || am_rc=$? - done - if test $am_rc -ne 0; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "Something went wrong bootstrapping makefile fragments - for automatic dependency tracking. If GNU make was not used, consider - re-running the configure script with MAKE=\"gmake\" (or whatever is - necessary). You can also try re-running configure with the - '--disable-dependency-tracking' option to at least be able to build - the package (albeit without support for automatic dependency tracking). -See \`config.log' for more details" "$LINENO" 5; } - fi - { am_dirpart=; unset am_dirpart;} - { am_filepart=; unset am_filepart;} - { am_mf=; unset am_mf;} - { am_rc=; unset am_rc;} - rm -f conftest-deps.mk -} - ;; - "libtool":C) - - # See if we are running on zsh, and set the options that allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST - fi - - cfgfile=${ofile}T - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL -# Generated automatically by $as_me ($PACKAGE) $VERSION -# NOTE: Changes made to this file will be lost: look at ltmain.sh. - -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit, 1996 - -# Copyright (C) 2014 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program or library that is built -# using GNU Libtool, you may include this file under the same -# distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -# The names of the tagged configurations supported by this script. -available_tags='CXX ' - -# Configured defaults for sys_lib_dlsearch_path munging. -: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} - -# ### BEGIN LIBTOOL CONFIG - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Which release of libtool.m4 was used? -macro_version=$macro_version -macro_revision=$macro_revision - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# What type of objects to build. -pic_mode=$pic_mode - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# Shared archive member basename,for filename based shared library versioning on AIX. -shared_archive_member_spec=$shared_archive_member_spec - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# An echo program that protects backslashes. -ECHO=$lt_ECHO - -# The PATH separator for the build system. -PATH_SEPARATOR=$lt_PATH_SEPARATOR - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="\$SED -e 1s/^X//" - -# A grep program that handles long lines. -GREP=$lt_GREP - -# An ERE matcher. -EGREP=$lt_EGREP - -# A literal string matcher. -FGREP=$lt_FGREP - -# A BSD- or MS-compatible name lister. -NM=$lt_NM - -# Whether we need soft or hard links. -LN_S=$lt_LN_S - -# What is the maximum length of a command? -max_cmd_len=$max_cmd_len - -# Object file suffix (normally "o"). -objext=$ac_objext - -# Executable file suffix (normally ""). -exeext=$exeext - -# whether the shell understands "unset". -lt_unset=$lt_unset - -# turn spaces into newlines. -SP2NL=$lt_lt_SP2NL - -# turn newlines into spaces. -NL2SP=$lt_lt_NL2SP - -# convert \$build file names to \$host format. -to_host_file_cmd=$lt_cv_to_host_file_cmd - -# convert \$build files to toolchain format. -to_tool_file_cmd=$lt_cv_to_tool_file_cmd - -# An object symbol dumper. -OBJDUMP=$lt_OBJDUMP - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method = "file_magic". -file_magic_cmd=$lt_file_magic_cmd - -# How to find potential files when deplibs_check_method = "file_magic". -file_magic_glob=$lt_file_magic_glob - -# Find potential files using nocaseglob when deplibs_check_method = "file_magic". -want_nocaseglob=$lt_want_nocaseglob - -# DLL creation program. -DLLTOOL=$lt_DLLTOOL - -# Command to associate shared and link libraries. -sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd - -# The archiver. -AR=$lt_AR - -# Flags to create an archive. -AR_FLAGS=$lt_AR_FLAGS - -# How to feed a file listing to the archiver. -archiver_list_spec=$lt_archiver_list_spec - -# A symbol stripping program. -STRIP=$lt_STRIP - -# Commands used to install an old-style archive. -RANLIB=$lt_RANLIB -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Whether to use a lock for old archive extraction. -lock_old_archive_extraction=$lock_old_archive_extraction - -# A C compiler. -LTCC=$lt_CC - -# LTCC compiler flags. -LTCFLAGS=$lt_CFLAGS - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration. -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm into a list of symbols to manually relocate. -global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import - -# Transform the output of nm in a C name address pair. -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# Transform the output of nm in a C name address pair when lib prefix is needed. -global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix - -# The name lister interface. -nm_interface=$lt_lt_cv_nm_interface - -# Specify filename containing input files for \$NM. -nm_file_list_spec=$lt_nm_file_list_spec - -# The root where to search for dependent libraries,and where our libraries should be installed. -lt_sysroot=$lt_sysroot - -# Command to truncate a binary pipe. -lt_truncate_bin=$lt_lt_cv_truncate_bin - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# Used to examine libraries when file_magic_cmd begins with "file". -MAGIC_CMD=$MAGIC_CMD - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Manifest tool. -MANIFEST_TOOL=$lt_MANIFEST_TOOL - -# Tool to manipulate archived DWARF debug symbol files on Mac OS X. -DSYMUTIL=$lt_DSYMUTIL - -# Tool to change global to local symbols on Mac OS X. -NMEDIT=$lt_NMEDIT - -# Tool to manipulate fat objects and archives on Mac OS X. -LIPO=$lt_LIPO - -# ldd/readelf like tool for Mach-O binaries on Mac OS X. -OTOOL=$lt_OTOOL - -# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. -OTOOL64=$lt_OTOOL64 - -# Old archive suffix (normally "a"). -libext=$libext - -# Shared library suffix (normally ".so"). -shrext_cmds=$lt_shrext_cmds - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at link time. -variables_saved_for_relink=$lt_variables_saved_for_relink - -# Do we need the "lib" prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Library versioning type. -version_type=$version_type - -# Shared library runtime path variable. -runpath_var=$runpath_var - -# Shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Permission mode override for installation of shared libraries. -install_override_mode=$lt_install_override_mode - -# Command to use after installation of a shared archive. -postinstall_cmds=$lt_postinstall_cmds - -# Command to use after uninstallation of a shared archive. -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# As "finish_cmds", except a single script fragment to be evaled but -# not shown. -finish_eval=$lt_finish_eval - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Compile-time system search path for libraries. -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Detected run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path - -# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. -configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - - -# The linker used to build libraries. -LD=$lt_LD - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# Commands used to build an old-style archive. -old_archive_cmds=$lt_old_archive_cmds - -# A language specific compiler. -CC=$lt_compiler - -# Is the compiler the GNU compiler? -with_gcc=$GCC - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc - -# Whether or not to disallow shared libs when runtime libs are static. -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec - -# Whether the compiler copes with passing no objects directly. -compiler_needs_object=$lt_compiler_needs_object - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds - -# Commands used to build a shared archive. -archive_cmds=$lt_archive_cmds -archive_expsym_cmds=$lt_archive_expsym_cmds - -# Commands used to build a loadable module if different from building -# a shared archive. -module_cmds=$lt_module_cmds -module_expsym_cmds=$lt_module_expsym_cmds - -# Whether we are building with GNU ld or not. -with_gnu_ld=$lt_with_gnu_ld - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag - -# Flag that enforces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec - -# Whether we need a single "-rpath" flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator - -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes -# DIR into the resulting binary. -hardcode_direct=$hardcode_direct - -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes -# DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \$shlibpath_var if the -# library is relocated. -hardcode_direct_absolute=$hardcode_direct_absolute - -# Set to "yes" if using the -LDIR flag during linking hardcodes DIR -# into the resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR -# into the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Set to "yes" if building a shared library automatically hardcodes DIR -# into the library and all subsequent libraries and executables linked -# against it. -hardcode_automatic=$hardcode_automatic - -# Set to yes if linker adds runtime paths of dependent libraries -# to runtime path list. -inherit_rpath=$inherit_rpath - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs - -# Set to "yes" if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms - -# Commands necessary for linking programs (against libraries) with templates. -prelink_cmds=$lt_prelink_cmds - -# Commands necessary for finishing linking programs. -postlink_cmds=$lt_postlink_cmds - -# Specify filename containing input files. -file_list_spec=$lt_file_list_spec - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# The directories searched by this compiler when creating a shared library. -compiler_lib_search_dirs=$lt_compiler_lib_search_dirs - -# Dependencies to place before and after the objects being linked to -# create a shared library. -predep_objects=$lt_predep_objects -postdep_objects=$lt_postdep_objects -predeps=$lt_predeps -postdeps=$lt_postdeps - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path - -# ### END LIBTOOL CONFIG - -_LT_EOF - - cat <<'_LT_EOF' >> "$cfgfile" - -# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE - -# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x$2 in - x) - ;; - *:) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" - ;; - x:*) - eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" - ;; - *) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" - ;; - esac -} - - -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in $*""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} - - -# ### END FUNCTIONS SHARED WITH CONFIGURE - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test set != "${COLLECT_NAMES+set}"; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - -ltmain=$ac_aux_dir/ltmain.sh - - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" - - - cat <<_LT_EOF >> "$ofile" - -# ### BEGIN LIBTOOL TAG CONFIG: CXX - -# The linker used to build libraries. -LD=$lt_LD_CXX - -# How to create reloadable object files. -reload_flag=$lt_reload_flag_CXX -reload_cmds=$lt_reload_cmds_CXX - -# Commands used to build an old-style archive. -old_archive_cmds=$lt_old_archive_cmds_CXX - -# A language specific compiler. -CC=$lt_compiler_CXX - -# Is the compiler the GNU compiler? -with_gcc=$GCC_CXX - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_CXX - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_CXX - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_CXX - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_CXX - -# Whether or not to disallow shared libs when runtime libs are static. -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX - -# Whether the compiler copes with passing no objects directly. -compiler_needs_object=$lt_compiler_needs_object_CXX - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX - -# Commands used to build a shared archive. -archive_cmds=$lt_archive_cmds_CXX -archive_expsym_cmds=$lt_archive_expsym_cmds_CXX - -# Commands used to build a loadable module if different from building -# a shared archive. -module_cmds=$lt_module_cmds_CXX -module_expsym_cmds=$lt_module_expsym_cmds_CXX - -# Whether we are building with GNU ld or not. -with_gnu_ld=$lt_with_gnu_ld_CXX - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_CXX - -# Flag that enforces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_CXX - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX - -# Whether we need a single "-rpath" flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX - -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes -# DIR into the resulting binary. -hardcode_direct=$hardcode_direct_CXX - -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes -# DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \$shlibpath_var if the -# library is relocated. -hardcode_direct_absolute=$hardcode_direct_absolute_CXX - -# Set to "yes" if using the -LDIR flag during linking hardcodes DIR -# into the resulting binary. -hardcode_minus_L=$hardcode_minus_L_CXX - -# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR -# into the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX - -# Set to "yes" if building a shared library automatically hardcodes DIR -# into the library and all subsequent libraries and executables linked -# against it. -hardcode_automatic=$hardcode_automatic_CXX - -# Set to yes if linker adds runtime paths of dependent libraries -# to runtime path list. -inherit_rpath=$inherit_rpath_CXX - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_CXX - -# Set to "yes" if exported symbols are required. -always_export_symbols=$always_export_symbols_CXX - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_CXX - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_CXX - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_CXX - -# Commands necessary for linking programs (against libraries) with templates. -prelink_cmds=$lt_prelink_cmds_CXX - -# Commands necessary for finishing linking programs. -postlink_cmds=$lt_postlink_cmds_CXX - -# Specify filename containing input files. -file_list_spec=$lt_file_list_spec_CXX - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_CXX - -# The directories searched by this compiler when creating a shared library. -compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX - -# Dependencies to place before and after the objects being linked to -# create a shared library. -predep_objects=$lt_predep_objects_CXX -postdep_objects=$lt_postdep_objects_CXX -predeps=$lt_predeps_CXX -postdeps=$lt_postdeps_CXX - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_CXX - -# ### END LIBTOOL TAG CONFIG: CXX -_LT_EOF - - ;; - "configitems":C) "${srcdir}/tools/splitconfig" "${srcdir}" ;; - - esac -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - diff --git a/ext/libpqxx-7.7.3/configure.ac b/ext/libpqxx-7.7.3/configure.ac deleted file mode 100644 index d6351faf2..000000000 --- a/ext/libpqxx-7.7.3/configure.ac +++ /dev/null @@ -1,738 +0,0 @@ -# Generate configure script for libpqxx. This needs the autoconf archive -# package installed. (The configure script itself does not require it though.) - -AC_PREREQ(2.69) -AC_INIT( - libpqxx, - [m4_esyscmd_s([./tools/extract_version])], - [Jeroen T. Vermeulen]) -AC_LANG(C++) - -AC_CONFIG_SRCDIR([src/connection.cxx]) -AC_CONFIG_AUX_DIR(config) -AC_CONFIG_MACRO_DIR([config/m4]) -AM_INIT_AUTOMAKE([subdir-objects]) - -PQXX_ABI=m4_esyscmd_s([./tools/extract_version --abi]) -AC_SUBST(PQXXVERSION, $PACKAGE_VERSION) -AC_SUBST(PQXX_ABI) - -AC_CONFIG_HEADER([include/pqxx/config.h]) - -# Default prefix for installs. -AC_PREFIX_DEFAULT(/usr/local) - - -# Read test programme from config-test. -AC_DEFUN([read_test], [AC_LANG_SOURCE( - esyscmd(tools/m4esc.py --input=config-tests/$1))]) - - -# Checks for programs. -AC_PROG_CXX -AC_PROG_INSTALL -AC_DISABLE_SHARED -AC_PROG_LIBTOOL -AC_PROG_MAKE_SET -AC_PATH_PROG([MKDIR], [mkdir]) - -# Documentation. -AC_ARG_ENABLE( - documentation, - [AS_HELP_STRING([--enable-documentation], [Generate documentation])], - [], - [enable_documentation=auto]) -AC_ARG_VAR([DOXYGEN], - [Path to doxygen needed to build reference documentation]) -AC_PATH_TOOL([DOXYGEN], [doxygen], [nodoxygen]) -AC_ARG_VAR([HAVE_DOT], - [Variable used by doxygen to declare availibility of dot]) -AC_CHECK_TOOL([HAVE_DOT], [dot], [YES], [NO]) -AS_IF([test "$enable_documentation" = "yes" && test "$DOXYGEN" = "nodoxygen"], - [AC_MSG_ERROR([could not find tools necessary to build documentation])]) -AM_CONDITIONAL([BUILD_REFERENCE], - [test "$enable_documentation" != "no" -a "$DOXYGEN" != "nodoxygen"]) - -AM_MAINTAINER_MODE - -# See if we want stricter compiler warnings. -AC_MSG_CHECKING([maintainer mode]) -AC_ARG_ENABLE(maintainer-mode) -AC_MSG_RESULT(${enable_maintainer_mode}) - -# See if we want runtime debug checking. -AC_MSG_CHECKING([audit]) -AC_ARG_ENABLE(audit) -AC_MSG_RESULT(${enable_audit}) - -# See if we want "suggestions," such as "this class could be final." -# (The suggestions are often useful, but can also easily be wrong.) -AC_MSG_CHECKING([suggest]) -AC_ARG_ENABLE(suggest) -AC_MSG_RESULT(${enable_suggest}) - - -AC_ARG_ENABLE(shared) -AS_IF( - [test "${shared}" = "yes" ], - [CPPFLAGS="$CPPFLAGS -DPQXX_SHARED"]) - - -# Add options to compiler command line, if compiler accepts them. -add_compiler_opts_if_ok() { - for option in $* - do - ACO_SAVE_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $option" - AC_MSG_CHECKING([whether $CXX accepts $option]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([], [])], - has_option=yes, - has_option=no) - AC_MSG_RESULT($has_option) - AS_IF( - [test "$has_option" = "no" ], - [CXXFLAGS="$ACO_SAVE_CXXFLAGS"]) - done -} - - -# Add options to compiler command line, unconditionally. -add_compiler_opts() { - CXXFLAGS="$CXXFLAGS $*" -} - - -# It's tempting to use Autoconf Archive's AX_CXX_COMPILE_STDCXX_17 for this, -# but it's 2022 and the C++20 equivalent isn't quite ready for use. -# Seems simpler and more reliable for the user to arrange for the desired -# language versions by setting the appropriate option for their compiler. -AC_MSG_CHECKING([for sufficient C++ language/library level]) -sufficient_cxx=yes -AC_COMPILE_IFELSE( - [AC_LANG_SOURCE([ - #if __cplusplus < 201611L - #error "Need C++17 or better." - #endif - ])], - sufficient_cxx=yes, - sufficient_cxx=no) -AC_MSG_RESULT($sufficient_cxx) -if test "$sufficient_cxx" != "yes" -then - AC_MSG_ERROR([This libpqxx version needs at least C++17.]) -fi - - -# Let's try to get the compiler to be helpful. -# -# (Omit options -Weffc++ and -Wabi because they currently yield too many -# warnings in gcc's standard headers; omit -Wunreachable-code because it isn't -# always right) -if test "$GCC" = "yes" -then - # In maintainer mode, enable all the warning options we can. - if test "$enable_maintainer_mode" = "yes" - then - # "Eternal" (FLW) g++ options. These have been around for - # ages, and both g++ and clang++ support them. Don't bother - # checking for support; just add them to the compiler options. - add_compiler_opts \ - -fstrict-enums \ - -Werror \ - -Wall \ - -pedantic \ - -Wcast-align \ - -Wcast-qual \ - -Wconversion \ - -Wctor-dtor-privacy \ - -Wendif-labels \ - -Wextra \ - -Wfloat-equal \ - -Wformat=2 \ - -Wformat-security \ - -Wmissing-include-dirs \ - -Wno-div-by-zero \ - -Wnon-virtual-dtor \ - -Wold-style-cast \ - -Woverlength-strings \ - -Woverloaded-virtual \ - -Wpointer-arith \ - -Wredundant-decls \ - -Wshadow \ - -Wsign-promo \ - -Wundef \ - -Wunused \ - -Wwrite-strings - - # "Iffy" g++ options. Some reasonably current g++-like - # compilers may not support these. - add_compiler_opts_if_ok \ - -fnothrow-opt \ - -Wattribute-alias=2 \ - -Wextra-semi \ - -Wlogical-op \ - -Wmismatched-tags \ - -Wnoexcept \ - -Wredundant-tags \ - -Wrestrict \ - -Wstringop-overflow \ - -Wzero-as-null-pointer-constant \ - -Warray-bounds=2 \ - -Wduplicated-branches \ - -Wduplicated-cond \ - -Wsuggest-attribute=noreturn \ - -Wsuggest-override \ - -Wtrampolines - fi - - # In "audit," enable all runtime checks we can. - if test "$enable_audit" = "yes" - then - add_compiler_opts_if_ok \ - -D_FORTIFY_SOURCE=2 \ - -fsanitize=address \ - -fsanitize-address-use-after-scope \ - -fsanitize=alignment \ - -fsanitize=bool \ - -fsanitize=bounds \ - -fsanitize=bounds-strict \ - -fsanitize=builtin \ - -fsanitize=enum \ - -fsanitize=float-cast-overflow \ - -fsanitize=float-divide-by-zero \ - -fsanitize=integer-divide-by-zero \ - -fsanitize=leak \ - -fsanitize=nonnull-attribute \ - -fsanitize=null \ - -fsanitize=object-size \ - -fsanitize=pointer-compare \ - -fsanitize=pointer-overflow \ - -fsanitize=pointer-subtract \ - -fsanitize=return \ - -fsanitize=returns-nonnull-attribute \ - -fsanitize=shift \ - -fsanitize=shift-base \ - -fsanitize=shift-exponent \ - -fsanitize=signed-integer-overflow \ - -fsanitize=undefined \ - -fsanitize=unreachable \ - -fsanitize=vla-bound \ - -fsanitize=vptr \ - -fstack-protector-all - fi - - # In "suggest" mode, enable a bunch of code suggestions. - if test "$enable_suggest" = "yes" - then - add_compiler_opts_if_ok \ - -Wsuggest-attribute=cold \ - -Wsuggest-attribute=const \ - -Wsuggest-attribute=malloc \ - -Wsuggest-attribute=pure \ - -Wsuggest-final-types \ - -Wsuggest-final-methods - fi - -AC_MSG_CHECKING([g++ visibility attribute]) -gcc_visibility=yes -SAVE_CXXFLAGS="$CXXFLAGS" -CXXFLAGS="$CXXFLAGS -Werror" -AC_COMPILE_IFELSE( - [read_test(gcc_visibility.cxx)], - AC_DEFINE( - [PQXX_HAVE_GCC_VISIBILITY], - 1, - [Define if g++ supports visibility attribute.]), - gcc_visibility=no) -AC_MSG_RESULT($gcc_visibility) -CXXFLAGS="$SAVE_CXXFLAGS" -if test "$gcc_visibility" = "yes" -then - # Make internal definitions accessible only to the library itself. - # Only definitions marked PQXX_LIBEXPORT will be accessible. - add_compiler_opts -fvisibility=hidden - add_compiler_opts -fvisibility-inlines-hidden -fi - -AC_MSG_CHECKING([g++ pure attribute]) -gcc_pure=yes -AC_COMPILE_IFELSE( - [read_test(gcc_pure.cxx)], - AC_DEFINE( - [PQXX_HAVE_GCC_PURE], - 1, - [Define if g++ supports pure attribute]), - gcc_pure=no) -AC_MSG_RESULT($gcc_pure) - -fi # End of gcc-specific part. - - -# Check for __cxa_demangle. -AC_MSG_CHECKING([__cxa_demangle]) -cxa_demangle=yes -AC_COMPILE_IFELSE( - [read_test(cxa_demangle.cxx)], - AC_DEFINE( - [PQXX_HAVE_CXA_DEMANGLE], - 1, - [Define if compiler supports __cxa_demangle]), - cxa_demangle=no) -AC_MSG_RESULT($cxa_demangle) - - -# Check for sufficient Concepts support, introduced with C++20. -AC_MSG_CHECKING([concepts]) -concepts=yes -AC_COMPILE_IFELSE( - [read_test(concepts.cxx)], - AC_DEFINE( - [PQXX_HAVE_CONCEPTS], - 1, - [Define if compiler supports Concepts and header.]), - concepts=no) -AC_MSG_RESULT($concepts) - - -# Check for C++20 std::span. -AC_MSG_CHECKING([std::span]) -span=yes -AC_COMPILE_IFELSE( - [read_test(span.cxx)], - AC_DEFINE([PQXX_HAVE_SPAN], 1, [Define if compiler has std::span.]), - span=no) -AC_MSG_RESULT($span) - - -# Check for multidimensional subscript operator support. Proposed for C++23. -AC_MSG_CHECKING([for multidimensional subscript operator support]) -multidim_subscript=yes -AC_COMPILE_IFELSE( - [read_test(multidim-subscript.cxx)], - AC_DEFINE( - [PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT], 1, - [Define if operator[] can take multiple arguments.]), - multidim_subscript=no) -AC_MSG_RESULT($multidim_subscript) - - -AC_MSG_CHECKING([for strerror_r()]) -strerror_r=yes -AC_LINK_IFELSE( - [read_test(strerror_r.cxx)], - AC_DEFINE( - [PQXX_HAVE_STRERROR_R], - 1, - [Define if strerror_r() is available.]), - strerror_r=no) -AC_MSG_RESULT($strerror_r) - - - -AC_MSG_CHECKING([for strerror_s()]) -strerror_s=yes -AC_LINK_IFELSE( - [read_test(strerror_s.cxx)], - AC_DEFINE( - [PQXX_HAVE_STRERROR_S], - 1, - [Define if strerror_s() is available.]), - strerror_s=no) -AC_MSG_RESULT($strerror_s) - - -AC_MSG_CHECKING([for std::chrono::year_month_day etc]) -year_month_day=yes -AC_LINK_IFELSE( - [read_test(year_month_day.cxx)], - AC_DEFINE( - [PQXX_HAVE_YEAR_MONTH_DAY], - 1, - [Define if std::chrono has year_month_day etc.]), - year_month_day=no) -AC_MSG_RESULT($year_month_day) - - -# Check for [[likely]] and [[unlikely]] attributes. -AC_MSG_CHECKING([attributes "likely" and "unlikely".]) -likely=yes -AC_COMPILE_IFELSE( - [read_test(likely.cxx)], - AC_DEFINE([PQXX_HAVE_LIKELY], 1, [Define if likely & unlikely work.]), - likely=no) -AC_MSG_RESULT($likely) - - -# It's mid-2019, and gcc's charconv supports integers but not yet floats. -# So for now, we test for int and float conversion... separately. -# -# It's worse for older clang versions, which compile the integer conversions -# but then fail at link time because of a missing symbol "__muloti4" with the -# "long long" version. I couldn't resolve that symbol by adding -lm either. -# So don't just compile these tests; link them as well. -AC_MSG_CHECKING([for C++17 charconv integer conversion]) -have_charconv_int=yes -AC_LINK_IFELSE( - [read_test(charconv_int.cxx)], - AC_DEFINE( - [PQXX_HAVE_CHARCONV_INT], - 1, - [Define if supports integer conversion.]), - have_charconv_int=no) -AC_MSG_RESULT($have_charconv_int) - -AC_MSG_CHECKING([for C++17 charconv floating-point conversion]) -have_charconv_float=yes -AC_LINK_IFELSE( - [read_test(charconv_float.cxx)], - AC_DEFINE( - [PQXX_HAVE_CHARCONV_FLOAT], - 1, - [Define if supports floating-point conversion.]), - have_charconv_float=no) -AC_MSG_RESULT($have_charconv_float) - -# As per #262, clang with libcxxrt does not support thread_local on non-POD -# objects. Luckily we can live without those, it's just less efficient. -AC_MSG_CHECKING([for full thread_local support]) -have_thread_local=yes -AC_LINK_IFELSE( - [read_test(thread_local.cxx)], - AC_DEFINE( - [PQXX_HAVE_THREAD_LOCAL], - 1, - [Define if thread_local is fully supported.]), - have_thread_local=no) -AC_MSG_RESULT($have_thread_local) - -AC_MSG_CHECKING([for std::this_thread::sleep_for]) -have_sleep_for=yes -AC_LINK_IFELSE( - [read_test(sleep_for.cxx)], - AC_DEFINE( - [PQXX_HAVE_SLEEP_FOR], - 1, - [Define if std::this_thread::sleep_for works.]), - have_sleep_for=no) -AC_MSG_RESULT($have_sleep_for) - - -AC_MSG_CHECKING([for std::cmp_greater, std::cmp_less_equal, etc]) -have_cmp=yes -AC_COMPILE_IFELSE( - [read_test(cmp.cxx)], - AC_DEFINE( - [PQXX_HAVE_CMP], - 1, - [Define if compiler has C++20 std::cmp_greater etc.]), - have_cmp=no) -AC_MSG_RESULT($have_cmp) - - -# Doing my own check for poll(). There's one built into autoconf-archive, but -# it produces warnings in C++ (about unnecessarily using "struct", and using 0 -# as a null pointer constant). In maintainer mode, those warnings turn into -# errors. -AC_MSG_CHECKING([for poll()]) -ax_cv_have_poll=yes -AC_LINK_IFELSE( - [read_test(poll.cxx)], - AC_DEFINE( - [PQXX_HAVE_POLL], - 1, - [Define if poll() is available.]), - ax_cv_have_poll=no) -AC_MSG_RESULT($ax_cv_have_poll) - -if test "$ax_cv_have_poll" != "yes" -then -# No poll(); we'll fall back to select(). - -# Some systems keep select() in a separate library which is not linked by -# default. See if we need one of those. -socklibok=no -AC_SEARCH_LIBS(select, socket nsl ws2_32 wsock32 winsock, [socklibok=yes]) - -# Microsoft proprietary libraries do not work with code that is generated with -# autoconf's SEARCH_LIBS macro, so we need to check manually and just use the -# first socket library available. -# We only do this if select() is not available by other means, to avoid picking -# up an unnecessary Windows compatibility library on a non-Windows system. -for l in ws2_32 wsock32 winsock -do - if test "${socklibok}" != "yes" - then - AC_CHECK_LIB($l,main,LIBS="$LIBS -l$l";[socklibok=yes]) - fi -done - -if test "${socklibok}" != "yes" -then - AC_MSG_ERROR([ -Could not figure out how to link a simple sockets-based program. Please read -the config.log file for more clues as to why this failed. -]) -fi - -fi # No poll() - - -# Find PostgreSQL includes and libraries -AC_PATH_PROG([PKG_CONFIG], [pkg-config]) -AC_PATH_PROGS(PG_CONFIG, pg_config) - -AC_ARG_WITH( - [postgres-include], - [AS_HELP_STRING( - [--with-postgres-include=DIR], - [Use PostgreSQL includes from DIR. Defaults to querying pg_config or pkg-config, whichever is available.])], - AS_IF( - [test "x$with_postgres_include" = "xyes"], - [with_postgres_include=""])) - -if test -n "$with_postgres_include" -then - POSTGRES_INCLUDE="-I$with_postgres_include" -else - if test -x "$PKG_CONFIG" || test -x "$PG_CONFIG" - then - # We should prefer pkg-config over pg_config, but there seems to be a - # problem in pkg-config 1.6.3. Until that's been resolved (#291), go - # with pg_config if we can. - if test -x "$PG_CONFIG" - then - # From pg_config we can either get the C compiler options used to - # compile postgres, which isn't quite what we want; or we can get - # the headers directory, without the full option. That's something - # we can work with. The compiler must support the "-I" option for - # that, but both scripts assume that anyway. - POSTGRES_INCLUDE="-I$($PG_CONFIG --includedir)" - else - # From pkg-config we can get the compiler options to extend the - # include path. We use that. - POSTGRES_INCLUDE=$($PKG_CONFIG libpq --cflags-only-I) - fi - AC_MSG_NOTICE([finding PostgreSQL headers using $POSTGRES_INCLUDE]) - else - POSTGRES_INCLUDE="" - - # We have nothing to tell us where the libpq headers are. That's fine - # if the compiler can find it, but if not, fail here. - AC_CHECK_HEADER( - [libpq-fe.h], - [], - [AC_MSG_ERROR([ -Can't find the main PostgreSQL client header, libpq-fe.h. Make sure that it -is installed, and either use the --with-postgres-include option or install -pkg-config. -])]) - fi -fi -AC_SUBST(POSTGRES_INCLUDE) - -# Add the compiler option so we can compile configure tests which rely on the -# libpq headers. -CPPFLAGS="$CPPFLAGS $POSTGRES_INCLUDE" - - -AC_ARG_WITH( - [postgres-lib], - [AS_HELP_STRING( - [--with-postgres-lib=DIR], - [Use PostgreSQL libraries from DIR. Defaults to querying pg_config.])], - AS_IF( - [test "x$with_postgres_lib" = "xyes"], - [with_postgres_lib=""])) - -# If no --with-postgres-lib was given, and we have pkg-config, use that. -AS_IF( - [test -z "$with_postgres_lib" -a -x "$PKG_CONFIG"], - [with_postgres_lib=$($PKG_CONFIG libpq --libs-only-L | sed 's/^-L//')]) - -# pg_config is deprecated, but for some users it may still provide the only -# right answer. For instance, `pkg-config` may not know where `libpq` is -# installed. -AS_IF( - [test -z "$with_postgres_lib" -a -x "$PG_CONFIG"], - [with_postgres_lib=$($PG_CONFIG --libdir)]) - -AS_IF( - [test -n "$with_postgres_lib"], - [AC_MSG_NOTICE([using PostgreSQL libraries at $with_postgres_lib])], - [AC_MSG_NOTICE([using PostgreSQL libraries in default location])]) - -AC_SUBST(with_postgres_lib) - - -AC_CHECK_HEADER( - [libpq-fe.h], - [], - [AC_MSG_ERROR([ -Can't find the main PostgreSQL client header, libpq-fe.h. Are you sure the -libpq headers are installed correctly, and that we've got the right path? -])]) - - -AC_MSG_CHECKING([for ability to compile source files using libpq]) -AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#include]], - [[PQexec(nullptr,"")]] - )], - [], - [AC_MSG_ERROR([ -Could not compile a call to a basic libpq function. There must be something -seriously wrong with the headers that "pg_config --includedir" or "pkg-config -libpq --cflags" pointed to; the contents of config.log may give you a clue -about the nature of the failure. -Source including the libpq header libpq-fe.h can be compiled, but a call to the -most basic libpq function PQexec() failed to compile successfully. This is the -litmus test for a working libpq. -])]) -AC_MSG_RESULT(yes) - - -if test "x${with_postgres_lib}" = "x"; then - with_postgres_libpath="" -else - with_postgres_libpath="-L${with_postgres_lib}" -fi -LDFLAGS="$LDFLAGS ${with_postgres_libpath}" - -AC_CHECK_LIB( - [pq], - [PQexec], - [], - [AC_MSG_ERROR([ -Did not find the PQexec() function in libpq. This is the litmus test for a -working libpq installation. - -A source file using the PQexec() function did compile without problems, and the -libpq library is available for linking, but for some reason a call to PQexec() -failed to link properly to the libpq library. This may be because the libpq -library file is damaged, or in some incorrect format, or if your libpq is much -more recent than libpqxx version $PQXX_ABI, perhaps libpq has undergone a -radical ABI change. - -The last parts of config.log may give you a clue as to what really went wrong, -but be warned that this is no easy reading. Look for the last error message -occurring in the file. -])], - ${with_postgres_libpath}) - - -# PQencryptPasswordConn was added in postgres 10. -AC_MSG_CHECKING([for PQencryptPasswordConn]) -have_pqencryptpasswordconn=yes -AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [#include], - [ - extern PGconn *conn; - PQencryptPasswordConn( - conn, "pwd", "user", "scram-sha-256") - ] - )], - AC_DEFINE( - [PQXX_HAVE_PQENCRYPTPASSWORDCONN], - 1, - [Define if libpq has PQencryptPasswordConn (since pg 10).]), - [have_pqencryptpasswordconn=no]) -AC_MSG_RESULT($have_pqencryptpasswordconn) - - -# "Pipeline mode" was introduced in libpq 14. -AC_MSG_CHECKING([for libpq pipeline mode]) -have_pq_pipeline=yes -AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [#include], - [ - extern PGconn *conn; - PQenterPipelineMode(conn) - ] - )], - AC_DEFINE( - [PQXX_HAVE_PQ_PIPELINE], - 1, - [Define if libpq has pipeline mode (since pg 14).]), - [have_pq_pipeline=no]) -AC_MSG_RESULT($have_pq_pipeline) - - -AC_MSG_CHECKING([for usable std::filesystem::path]) -have_path=yes -AC_COMPILE_IFELSE( - [read_test(fs.cxx)], - AC_DEFINE( - [PQXX_HAVE_PATH], - 1, - [Define if compiler has usable std::filesystem::path.]), - have_path=no) -AC_MSG_RESULT($have_path) - - -AC_MSG_CHECKING([whether we need a link option for support]) -LIBS_SAVE="$LIBS" -found_fslib=no -for l in '' '-lstdc++fs' '-lc++fs' -do - if test "$found_fslib" != "yes" - then - LIBS="$LIBS $l" - AC_LINK_IFELSE( - [read_test(need_fslib.cxx)], - [found_fslib=yes], - [LIBS="$LIBS_SAVE"]) - if test "$found_fslib" = "yes" - then - result_msg="$l" - # (And keep our current value of $LIBS.) - fi - fi -done - -if test "$found_fslib" != "yes" -then - AC_MSG_ERROR([ -There seems to be support, but I could not figure out now to make -it work. You'll have to add set your own build options for this. - ]) -fi -AC_MSG_RESULT($result_msg) - - -# Remove redundant occurrances of -lpq -LIBS=[$(echo "$LIBS" | sed -e 's/-lpq * -lpq\>/-lpq/g')] - - -AC_MSG_CHECKING([that type of libpq's Oid is as expected]) -AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [ - #include - #include"${srcdir}/include/pqxx/internal/libpq-forward.hxx" - extern void f(pqxx::oid&); - ], - [Oid o;f(o)], - )], - [], - [AC_MSG_ERROR([ -The Oid typedef in libpq has changed. Please notify the libpqxx authors of the -change! -])]) -AC_MSG_RESULT(yes) - - -AC_PROG_MAKE_SET - -AC_CONFIG_FILES([ - Makefile config/Makefile doc/Makefile doc/Doxyfile src/Makefile - test/Makefile tools/Makefile include/Makefile include/pqxx/Makefile - libpqxx.pc]) - - -AC_CONFIG_COMMANDS([configitems], ["${srcdir}/tools/splitconfig" "${srcdir}"]) - -AC_OUTPUT(compile_flags) diff --git a/ext/libpqxx-7.7.3/doc/CMakeLists.txt b/ext/libpqxx-7.7.3/doc/CMakeLists.txt deleted file mode 100644 index d48d2a6f0..000000000 --- a/ext/libpqxx-7.7.3/doc/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -find_program(HAVE_DOXYGEN doxygen) - -if(NOT HAVE_DOXYGEN) - message(FATAL_ERROR "***************************************************** -Doxygen not found. -Install it, or configure with -DBUILD_DOC=OFF -*****************************************************" - ) -endif() - -set(PQXXVERSION "${CMAKE_PROJECT_VERSION}") -set(top_srcdir "${PROJECT_SOURCE_DIR}") -set(PQXX_ABI "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") -set(PQXX_MAJOR "${PROJECT_VERSION_MAJOR}") -set(PQXX_MINOR "${PROJECT_VERSION_MINOR}") - -find_program(HAVE_DOT dot) -if(HAVE_DOT) - set(HAVE_DOT YES) -else() - set(HAVE_DOT NO) -endif() - -configure_file(Doxyfile.in Doxyfile) - -if(HAVE_DOXYGEN) - file( - GLOB DOXYGEN_SOURCES - "${PROJECT_SOURCE_DIR}/include/pqxx/*.hxx" - "${PROJECT_SOURCE_DIR}/include/pqxx/doc/*.md" - "${PROJECT_SOURCE_DIR}/*.cxx" - ) - set(DOXYGEN_STAMP_FILE "${CMAKE_CURRENT_BINARY_DIR}/doxygen.stamp") - add_custom_command(OUTPUT ${DOXYGEN_STAMP_FILE} - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/html - COMMAND doxygen Doxyfile - COMMAND ${CMAKE_COMMAND} -E touch ${DOXYGEN_STAMP_FILE} - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ${DOXYGEN_SOURCES} - COMMENT "Generate API documentation" - VERBATIM - ) - add_custom_target(doxygen ALL - DEPENDS ${DOXYGEN_STAMP_FILE} - SOURCES ${DOXYGEN_SOURCES} - ) - install( - DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html - DESTINATION ${CMAKE_INSTALL_DOCDIR}/html - ) -endif() diff --git a/ext/libpqxx-7.7.3/doc/Doxyfile.in b/ext/libpqxx-7.7.3/doc/Doxyfile.in deleted file mode 100644 index f349fe80c..000000000 --- a/ext/libpqxx-7.7.3/doc/Doxyfile.in +++ /dev/null @@ -1,1280 +0,0 @@ -# Doxyfile 1.5.5 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = libpqxx - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = @PQXXVERSION@ - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = html - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, -# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, -# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, -# and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = ../ - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = YES - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = NO - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = NO - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = NO - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = NO - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = NO - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = @top_srcdir@/include/pqxx \ - @top_srcdir@/include/pqxx/doc \ - @top_srcdir@/src - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = *.cxx \ - *.hxx \ - *.h \ - *.md - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = *.o \ - *.lo \ - *.a \ - .cvsignore - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentstion. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = . - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = YES - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = YES - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = YES - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = YES - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = "../include" "@top_srcdir@/include" - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = *.h *.hxx - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = PQXX_ABI="@PQXX_ABI@" \ - PQXX_LIBEXPORT= \ - PQXX_NOVTABLE= \ - PQXX_PRIVATE= \ - PQXX_TYPENAME=typename \ - PQXX_VERSION="@PQXXVERSION@" \ - PQXX_MAJOR=@PQXX_MAJOR@ \ - PQXX_MINOR=@PQXX_MINOR@ - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = @HAVE_DOT@ - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = NO - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is enabled by default, which results in a transparent -# background. Warning: Depending on the platform used, enabling this option -# may lead to badly anti-aliased labels on the edges of a graph (i.e. they -# become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/ext/libpqxx-7.7.3/doc/Makefile.am b/ext/libpqxx-7.7.3/doc/Makefile.am deleted file mode 100644 index 38caa9181..000000000 --- a/ext/libpqxx-7.7.3/doc/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -maintainer-clean-local: - $(RM) -rf html - $(RM) reference-stamp - $(MKDIR) html - -EXTRA_DIST= Doxyfile.in libpqxx.xml reference-stamp - -all-local: docs - -if BUILD_REFERENCE -DOCS = reference -else -DOCS = -endif - -if MAINTAINER_MODE -REFERENCE_STAMP_DEP = ../src/libpqxx.la -else -REFERENCE_STAMP_DEP = -endif - -docs: $(DOCS) - -reference: reference-stamp -reference-stamp: Doxyfile.in $(REFERENCE_STAMP_DEP) - if [ -x "$(DOXYGEN)" ]; then \ - $(MKDIR_P) html; \ - $(DOXYGEN) Doxyfile; \ - touch $@; \ - else \ - echo >&2; \ - echo >&2 "*****************************************************"; \ - echo >&2; \ - echo >&2 "Doxygen not found."; \ - echo >&2 "Install it, or configure with --disable-documentation"; \ - echo >&2; \ - echo >&2 "*****************************************************"; \ - exit 1; \ - fi - -../src/libpqxx.la: - cd ../src; \ - $(MAKE) libpqxx.la - - -dist-hook: reference - if [ -d $(srcdir)/html ]; then \ - cp -pR html $(distdir)/ ; \ - fi diff --git a/ext/libpqxx-7.7.3/doc/Makefile.in b/ext/libpqxx-7.7.3/doc/Makefile.in deleted file mode 100644 index 835845bf7..000000000 --- a/ext/libpqxx-7.7.3/doc/Makefile.in +++ /dev/null @@ -1,507 +0,0 @@ -# Makefile.in generated by automake 1.16.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2021 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = doc -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ - $(top_srcdir)/config/m4/ltoptions.m4 \ - $(top_srcdir)/config/m4/ltsugar.m4 \ - $(top_srcdir)/config/m4/ltversion.m4 \ - $(top_srcdir)/config/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h -CONFIG_CLEAN_FILES = Doxyfile -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Doxyfile.in $(srcdir)/Makefile.in \ - $(top_srcdir)/config/mkinstalldirs -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSCOPE = @CSCOPE@ -CTAGS = @CTAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ETAGS = @ETAGS@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_DOT = @HAVE_DOT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR = @MKDIR@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PG_CONFIG = @PG_CONFIG@ -PKG_CONFIG = @PKG_CONFIG@ -POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ -PQXXVERSION = @PQXXVERSION@ -PQXX_ABI = @PQXX_ABI@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_postgres_lib = @with_postgres_lib@ -MAINTAINERCLEANFILES = Makefile.in -EXTRA_DIST = Doxyfile.in libpqxx.xml reference-stamp -@BUILD_REFERENCE_FALSE@DOCS = -@BUILD_REFERENCE_TRUE@DOCS = reference -@MAINTAINER_MODE_FALSE@REFERENCE_STAMP_DEP = -@MAINTAINER_MODE_TRUE@REFERENCE_STAMP_DEP = ../src/libpqxx.la -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu doc/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -tags TAGS: - -ctags CTAGS: - -cscope cscopelist: - -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-hook -check-am: all-am -check: check-am -all-am: Makefile all-local -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic \ - maintainer-clean-local - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: all all-am all-local check check-am clean clean-generic \ - clean-libtool cscopelist-am ctags-am dist-hook distclean \ - distclean-generic distclean-libtool distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic maintainer-clean-local mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags-am uninstall uninstall-am - -.PRECIOUS: Makefile - - -maintainer-clean-local: - $(RM) -rf html - $(RM) reference-stamp - $(MKDIR) html - -all-local: docs - -docs: $(DOCS) - -reference: reference-stamp -reference-stamp: Doxyfile.in $(REFERENCE_STAMP_DEP) - if [ -x "$(DOXYGEN)" ]; then \ - $(MKDIR_P) html; \ - $(DOXYGEN) Doxyfile; \ - touch $@; \ - else \ - echo >&2; \ - echo >&2 "*****************************************************"; \ - echo >&2; \ - echo >&2 "Doxygen not found."; \ - echo >&2 "Install it, or configure with --disable-documentation"; \ - echo >&2; \ - echo >&2 "*****************************************************"; \ - exit 1; \ - fi - -../src/libpqxx.la: - cd ../src; \ - $(MAKE) libpqxx.la - -dist-hook: reference - if [ -d $(srcdir)/html ]; then \ - cp -pR html $(distdir)/ ; \ - fi - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ext/libpqxx-7.7.3/doc/conf.py b/ext/libpqxx-7.7.3/doc/conf.py deleted file mode 100644 index 1cac1c2ca..000000000 --- a/ext/libpqxx-7.7.3/doc/conf.py +++ /dev/null @@ -1,199 +0,0 @@ -# -*- coding: utf-8 -*- -""" -libpqxx documentation build configuration file, created by -sphinx-quickstart on Sun Dec 3 00:43:33 2017. - -This file is execfile()d with the current directory set to its containing dir. - -All configuration values have a default; values that are commented out serve -to show the default. -""" - -import codecs -import os -from subprocess import check_call - - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import sys -# sys.path.insert(0, os.path.abspath(os.path.curdir)) - - -read_the_docs_build = os.environ.get('READTHEDOCS') == 'True' - -if read_the_docs_build: - check_call( - [os.path.join(os.path.curdir, 'configure'), 'CXXFLAGS=-std=c++17 -O0'], - cwd=os.path.pardir) - check_call('doxygen', cwd=os.path.join(os.path.pardir, 'doc')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - ] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'libpqxx' -copyright = u'2000-2022, Jeroen T. Vermeulen' -author = u'Jeroen T. Vermeulen' - - -def read_version(): - """Return version number as specified in the VERSION file.""" - version_file = os.path.join( - os.path.dirname(__file__), os.path.pardir, 'VERSION') - with codecs.open(version_file, encoding='ascii') as stream: - return stream.read().strip() - - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The full version, including alpha/beta/rc tags. -release = read_version() - -# The short X.Y version. -version = '.'.join(release.split('.')[:2]) - -html_title = "libpqxx %s" % release -html_short_title = "libpqxx" - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'alabaster' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# This is required for the alabaster theme -# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars -html_sidebars = { - '**': [ - 'relations.html', # needs 'show_related': True theme option to display - 'searchbox.html', - ] -} - -# Looks like the setup is that our build generates the HTML itself, and then -# has readthedocs copy the full generated HTML tree to the output directory. -# -# Problem is, that doesn't seem to be working now. This needs debugging. -html_extra_path = ["html"] - -# -- Options for HTMLHelp output ------------------------------------------ - -# Output file base name for HTML help builder. -htmlhelp_basename = 'libpqxxdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - 'libpqxx.tex', - u'libpqxx Documentation', - u'Jeroen T. Vermeulen', - 'manual', - ), -] - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'libpqxx', u'libpqxx Documentation', [author], 1) -] - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'libpqxx', u'libpqxx Documentation', - author, 'libpqxx', "C++ client API for PostgreSQL.", - 'Miscellaneous'), -] diff --git a/ext/libpqxx-7.7.3/doc/index.rst b/ext/libpqxx-7.7.3/doc/index.rst deleted file mode 100644 index 30f2cfdc1..000000000 --- a/ext/libpqxx-7.7.3/doc/index.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. x documentation master file, created by - sphinx-quickstart on Sun Dec 3 01:30:12 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -libpqxx -======= - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/ext/libpqxx-7.7.3/include/CMakeLists.txt b/ext/libpqxx-7.7.3/include/CMakeLists.txt deleted file mode 100644 index 263dd2e9e..000000000 --- a/ext/libpqxx-7.7.3/include/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# ############################################################################## -# AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. -# -# This file is generated automatically by libpqxx's template2mak.py script, and -# will be rewritten from time to time. -# -# If you modify this file, chances are your modifications will be lost. -# -# The template2mak.py script should be available in the tools directory of the -# libpqxx source archive. -# -# Generated from template './include/CMakeLists.txt.template'. -# ############################################################################## -install( - DIRECTORY pqxx "${PROJECT_BINARY_DIR}/include/pqxx" - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING - # For each X.hxx, install both X.hxx itself and plain X. - PATTERN *.hxx - # TODO: Is there any way to do this with CMake's globbing? - PATTERN array - PATTERN binarystring - PATTERN blob - PATTERN composite - PATTERN connection - PATTERN cursor - PATTERN dbtransaction - PATTERN errorhandler - PATTERN except - PATTERN field - PATTERN isolation - PATTERN largeobject - PATTERN nontransaction - PATTERN notification - PATTERN params - PATTERN pipeline - PATTERN prepared_statement - PATTERN range - PATTERN result - PATTERN robusttransaction - PATTERN row - PATTERN separated_list - PATTERN strconv - PATTERN stream_from - PATTERN stream_to - PATTERN subtransaction - PATTERN time - PATTERN transaction - PATTERN transaction_base - PATTERN transaction_focus - PATTERN transactor - PATTERN types - PATTERN util - PATTERN version - PATTERN zview - PATTERN internal/*.hxx - PATTERN internal/gates/*.hxx - PATTERN config-public-compiler.h - PATTERN pqxx - PATTERN doc EXCLUDE -) - -install( - DIRECTORY pqxx/doc/ - DESTINATION ${CMAKE_INSTALL_DOCDIR} - FILES_MATCHING - PATTERN *.md -) diff --git a/ext/libpqxx-7.7.3/include/CMakeLists.txt.template b/ext/libpqxx-7.7.3/include/CMakeLists.txt.template deleted file mode 100644 index 5ebc6664e..000000000 --- a/ext/libpqxx-7.7.3/include/CMakeLists.txt.template +++ /dev/null @@ -1,23 +0,0 @@ -install( - DIRECTORY pqxx "${PROJECT_BINARY_DIR}/include/pqxx" - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING - # For each X.hxx, install both X.hxx itself and plain X. - PATTERN *.hxx - # TODO: Is there any way to do this with CMake's globbing? -###MAKTEMPLATE:FOREACH include/pqxx/*.hxx - PATTERN ###BASENAME### -###MAKTEMPLATE:ENDFOREACH - PATTERN internal/*.hxx - PATTERN internal/gates/*.hxx - PATTERN config-public-compiler.h - PATTERN pqxx - PATTERN doc EXCLUDE -) - -install( - DIRECTORY pqxx/doc/ - DESTINATION ${CMAKE_INSTALL_DOCDIR} - FILES_MATCHING - PATTERN *.md -) diff --git a/ext/libpqxx-7.7.3/include/Makefile.am b/ext/libpqxx-7.7.3/include/Makefile.am deleted file mode 100644 index 83d2b1970..000000000 --- a/ext/libpqxx-7.7.3/include/Makefile.am +++ /dev/null @@ -1,79 +0,0 @@ -SUBDIRS = pqxx - -nobase_include_HEADERS= pqxx/pqxx \ - pqxx/array pqxx/array.hxx \ - pqxx/binarystring pqxx/binarystring.hxx \ - pqxx/blob pqxx/blob.hxx \ - pqxx/composite pqxx/composite.hxx \ - pqxx/connection pqxx/connection.hxx \ - pqxx/cursor pqxx/cursor.hxx \ - pqxx/dbtransaction pqxx/dbtransaction.hxx \ - pqxx/errorhandler pqxx/errorhandler.hxx \ - pqxx/except pqxx/except.hxx \ - pqxx/field pqxx/field.hxx \ - pqxx/isolation pqxx/isolation.hxx \ - pqxx/largeobject pqxx/largeobject.hxx \ - pqxx/nontransaction pqxx/nontransaction.hxx \ - pqxx/notification pqxx/notification.hxx \ - pqxx/params pqxx/params.hxx \ - pqxx/pipeline pqxx/pipeline.hxx \ - pqxx/prepared_statement pqxx/prepared_statement.hxx \ - pqxx/range pqxx/range.hxx \ - pqxx/result pqxx/result.hxx \ - pqxx/robusttransaction pqxx/robusttransaction.hxx \ - pqxx/separated_list pqxx/separated_list.hxx \ - pqxx/strconv pqxx/strconv.hxx \ - pqxx/stream_from pqxx/stream_from.hxx \ - pqxx/stream_to pqxx/stream_to.hxx \ - pqxx/subtransaction pqxx/subtransaction.hxx \ - pqxx/time pqxx/time.hxx \ - pqxx/transaction pqxx/transaction.hxx \ - pqxx/transaction_base pqxx/transaction_base.hxx \ - pqxx/transaction_focus pqxx/transaction_focus.hxx \ - pqxx/transactor pqxx/transactor.hxx \ - pqxx/row pqxx/row.hxx \ - pqxx/util pqxx/util.hxx \ - pqxx/types pqxx/types.hxx \ - pqxx/zview pqxx/zview.hxx \ - pqxx/version pqxx/version.hxx \ - pqxx/internal/array-composite.hxx \ - pqxx/internal/callgate.hxx \ - pqxx/internal/concat.hxx \ - pqxx/internal/conversions.hxx \ - pqxx/internal/encoding_group.hxx \ - pqxx/internal/encodings.hxx \ - pqxx/internal/header-pre.hxx \ - pqxx/internal/header-post.hxx \ - pqxx/internal/ignore-deprecated-post.hxx \ - pqxx/internal/ignore-deprecated-pre.hxx \ - pqxx/internal/libpq-forward.hxx \ - pqxx/internal/result_iter.hxx \ - pqxx/internal/result_iterator.hxx \ - pqxx/internal/sql_cursor.hxx \ - pqxx/internal/statement_parameters.hxx \ - pqxx/internal/stream_iterator.hxx \ - pqxx/internal/wait.hxx \ - pqxx/internal/gates/connection-errorhandler.hxx \ - pqxx/internal/gates/connection-largeobject.hxx \ - pqxx/internal/gates/connection-notification_receiver.hxx \ - pqxx/internal/gates/connection-pipeline.hxx \ - pqxx/internal/gates/connection-sql_cursor.hxx \ - pqxx/internal/gates/connection-transaction.hxx \ - pqxx/internal/gates/errorhandler-connection.hxx \ - pqxx/internal/gates/icursorstream-icursor_iterator.hxx \ - pqxx/internal/gates/icursor_iterator-icursorstream.hxx \ - pqxx/internal/gates/result-connection.hxx \ - pqxx/internal/gates/result-creation.hxx \ - pqxx/internal/gates/result-pipeline.hxx \ - pqxx/internal/gates/result-sql_cursor.hxx \ - pqxx/internal/gates/transaction-sql_cursor.hxx \ - pqxx/internal/gates/transaction-transaction_focus.hxx - - -nobase_nodist_include_HEADERS = \ - pqxx/config-public-compiler.h - -EXTRA_DIST = \ - pqxx/doc/*.md \ - pqxx/doc/mainpage.md.template \ - pqxx/version.hxx.template diff --git a/ext/libpqxx-7.7.3/include/Makefile.in b/ext/libpqxx-7.7.3/include/Makefile.in deleted file mode 100644 index 6b9eac914..000000000 --- a/ext/libpqxx-7.7.3/include/Makefile.in +++ /dev/null @@ -1,802 +0,0 @@ -# Makefile.in generated by automake 1.16.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2021 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = include -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ - $(top_srcdir)/config/m4/ltoptions.m4 \ - $(top_srcdir)/config/m4/ltsugar.m4 \ - $(top_srcdir)/config/m4/ltversion.m4 \ - $(top_srcdir)/config/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(nobase_include_HEADERS) \ - $(am__DIST_COMMON) -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ - ctags-recursive dvi-recursive html-recursive info-recursive \ - install-data-recursive install-dvi-recursive \ - install-exec-recursive install-html-recursive \ - install-info-recursive install-pdf-recursive \ - install-ps-recursive install-recursive installcheck-recursive \ - installdirs-recursive pdf-recursive ps-recursive \ - tags-recursive uninstall-recursive -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)" -HEADERS = $(nobase_include_HEADERS) $(nobase_nodist_include_HEADERS) -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -am__recursive_targets = \ - $(RECURSIVE_TARGETS) \ - $(RECURSIVE_CLEAN_TARGETS) \ - $(am__extra_recursive_targets) -AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - distdir distdir-am -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -DIST_SUBDIRS = $(SUBDIRS) -am__DIST_COMMON = $(srcdir)/Makefile.in \ - $(top_srcdir)/config/mkinstalldirs -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSCOPE = @CSCOPE@ -CTAGS = @CTAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ETAGS = @ETAGS@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_DOT = @HAVE_DOT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR = @MKDIR@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PG_CONFIG = @PG_CONFIG@ -PKG_CONFIG = @PKG_CONFIG@ -POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ -PQXXVERSION = @PQXXVERSION@ -PQXX_ABI = @PQXX_ABI@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_postgres_lib = @with_postgres_lib@ -SUBDIRS = pqxx -nobase_include_HEADERS = pqxx/pqxx \ - pqxx/array pqxx/array.hxx \ - pqxx/binarystring pqxx/binarystring.hxx \ - pqxx/blob pqxx/blob.hxx \ - pqxx/composite pqxx/composite.hxx \ - pqxx/connection pqxx/connection.hxx \ - pqxx/cursor pqxx/cursor.hxx \ - pqxx/dbtransaction pqxx/dbtransaction.hxx \ - pqxx/errorhandler pqxx/errorhandler.hxx \ - pqxx/except pqxx/except.hxx \ - pqxx/field pqxx/field.hxx \ - pqxx/isolation pqxx/isolation.hxx \ - pqxx/largeobject pqxx/largeobject.hxx \ - pqxx/nontransaction pqxx/nontransaction.hxx \ - pqxx/notification pqxx/notification.hxx \ - pqxx/params pqxx/params.hxx \ - pqxx/pipeline pqxx/pipeline.hxx \ - pqxx/prepared_statement pqxx/prepared_statement.hxx \ - pqxx/range pqxx/range.hxx \ - pqxx/result pqxx/result.hxx \ - pqxx/robusttransaction pqxx/robusttransaction.hxx \ - pqxx/separated_list pqxx/separated_list.hxx \ - pqxx/strconv pqxx/strconv.hxx \ - pqxx/stream_from pqxx/stream_from.hxx \ - pqxx/stream_to pqxx/stream_to.hxx \ - pqxx/subtransaction pqxx/subtransaction.hxx \ - pqxx/time pqxx/time.hxx \ - pqxx/transaction pqxx/transaction.hxx \ - pqxx/transaction_base pqxx/transaction_base.hxx \ - pqxx/transaction_focus pqxx/transaction_focus.hxx \ - pqxx/transactor pqxx/transactor.hxx \ - pqxx/row pqxx/row.hxx \ - pqxx/util pqxx/util.hxx \ - pqxx/types pqxx/types.hxx \ - pqxx/zview pqxx/zview.hxx \ - pqxx/version pqxx/version.hxx \ - pqxx/internal/array-composite.hxx \ - pqxx/internal/callgate.hxx \ - pqxx/internal/concat.hxx \ - pqxx/internal/conversions.hxx \ - pqxx/internal/encoding_group.hxx \ - pqxx/internal/encodings.hxx \ - pqxx/internal/header-pre.hxx \ - pqxx/internal/header-post.hxx \ - pqxx/internal/ignore-deprecated-post.hxx \ - pqxx/internal/ignore-deprecated-pre.hxx \ - pqxx/internal/libpq-forward.hxx \ - pqxx/internal/result_iter.hxx \ - pqxx/internal/result_iterator.hxx \ - pqxx/internal/sql_cursor.hxx \ - pqxx/internal/statement_parameters.hxx \ - pqxx/internal/stream_iterator.hxx \ - pqxx/internal/wait.hxx \ - pqxx/internal/gates/connection-errorhandler.hxx \ - pqxx/internal/gates/connection-largeobject.hxx \ - pqxx/internal/gates/connection-notification_receiver.hxx \ - pqxx/internal/gates/connection-pipeline.hxx \ - pqxx/internal/gates/connection-sql_cursor.hxx \ - pqxx/internal/gates/connection-transaction.hxx \ - pqxx/internal/gates/errorhandler-connection.hxx \ - pqxx/internal/gates/icursorstream-icursor_iterator.hxx \ - pqxx/internal/gates/icursor_iterator-icursorstream.hxx \ - pqxx/internal/gates/result-connection.hxx \ - pqxx/internal/gates/result-creation.hxx \ - pqxx/internal/gates/result-pipeline.hxx \ - pqxx/internal/gates/result-sql_cursor.hxx \ - pqxx/internal/gates/transaction-sql_cursor.hxx \ - pqxx/internal/gates/transaction-transaction_focus.hxx - -nobase_nodist_include_HEADERS = \ - pqxx/config-public-compiler.h - -EXTRA_DIST = \ - pqxx/doc/*.md \ - pqxx/doc/mainpage.md.template \ - pqxx/version.hxx.template - -all: all-recursive - -.SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu include/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-nobase_includeHEADERS: $(nobase_include_HEADERS) - @$(NORMAL_INSTALL) - @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ - fi; \ - $(am__nobase_list) | while read dir files; do \ - xfiles=; for file in $$files; do \ - if test -f "$$file"; then xfiles="$$xfiles $$file"; \ - else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ - test -z "$$xfiles" || { \ - test "x$$dir" = x. || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ - $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ - echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ - $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ - done - -uninstall-nobase_includeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ - $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ - dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) -install-nobase_nodist_includeHEADERS: $(nobase_nodist_include_HEADERS) - @$(NORMAL_INSTALL) - @list='$(nobase_nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ - fi; \ - $(am__nobase_list) | while read dir files; do \ - xfiles=; for file in $$files; do \ - if test -f "$$file"; then xfiles="$$xfiles $$file"; \ - else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ - test -z "$$xfiles" || { \ - test "x$$dir" = x. || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ - $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ - echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ - $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ - done - -uninstall-nobase_nodist_includeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(nobase_nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ - $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ - dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) - -# This directory's subdirectories are mostly independent; you can cd -# into them and run 'make' without going through this Makefile. -# To change the values of 'make' variables: instead of editing Makefiles, -# (1) if the variable is set in 'config.status', edit 'config.status' -# (which will cause the Makefiles to be regenerated when you run 'make'); -# (2) otherwise, pass the desired values on the 'make' command line. -$(am__recursive_targets): - @fail=; \ - if $(am__make_keepgoing); then \ - failcom='fail=yes'; \ - else \ - failcom='exit 1'; \ - fi; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-recursive -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-recursive - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-recursive - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-recursive -all-am: Makefile $(HEADERS) -installdirs: installdirs-recursive -installdirs-am: - for dir in "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-recursive - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-tags - -dvi: dvi-recursive - -dvi-am: - -html: html-recursive - -html-am: - -info: info-recursive - -info-am: - -install-data-am: install-nobase_includeHEADERS \ - install-nobase_nodist_includeHEADERS - -install-dvi: install-dvi-recursive - -install-dvi-am: - -install-exec-am: - -install-html: install-html-recursive - -install-html-am: - -install-info: install-info-recursive - -install-info-am: - -install-man: - -install-pdf: install-pdf-recursive - -install-pdf-am: - -install-ps: install-ps-recursive - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-recursive - -pdf-am: - -ps: ps-recursive - -ps-am: - -uninstall-am: uninstall-nobase_includeHEADERS \ - uninstall-nobase_nodist_includeHEADERS - -.MAKE: $(am__recursive_targets) install-am install-strip - -.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ - check-am clean clean-generic clean-libtool cscopelist-am ctags \ - ctags-am distclean distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-nobase_includeHEADERS \ - install-nobase_nodist_includeHEADERS install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs installdirs-am \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am \ - uninstall-nobase_includeHEADERS \ - uninstall-nobase_nodist_includeHEADERS - -.PRECIOUS: Makefile - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ext/libpqxx-7.7.3/include/pqxx/Makefile.am b/ext/libpqxx-7.7.3/include/pqxx/Makefile.am deleted file mode 100644 index c7f68813d..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -MAINTAINERCLEANFILES=Makefile.in stamp-h.in - -noinst_HEADERS = \ - config-internal-autotools.h - -nodist_noinst_HEADERS = \ - config.h \ - config-internal-compiler.h - -DISTCLEANFILES = \ - config-internal-autotools.h \ - config-internal-compiler.h \ - config-public-compiler.h diff --git a/ext/libpqxx-7.7.3/include/pqxx/Makefile.in b/ext/libpqxx-7.7.3/include/pqxx/Makefile.in deleted file mode 100644 index 4b02fb771..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/Makefile.in +++ /dev/null @@ -1,556 +0,0 @@ -# Makefile.in generated by automake 1.16.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2021 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = include/pqxx -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ - $(top_srcdir)/config/m4/ltoptions.m4 \ - $(top_srcdir)/config/m4/ltsugar.m4 \ - $(top_srcdir)/config/m4/ltversion.m4 \ - $(top_srcdir)/config/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ - $(am__DIST_COMMON) -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -HEADERS = $(nodist_noinst_HEADERS) $(noinst_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ - config.h.in -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ - $(top_srcdir)/config/mkinstalldirs -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSCOPE = @CSCOPE@ -CTAGS = @CTAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ETAGS = @ETAGS@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_DOT = @HAVE_DOT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR = @MKDIR@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PG_CONFIG = @PG_CONFIG@ -PKG_CONFIG = @PKG_CONFIG@ -POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ -PQXXVERSION = @PQXXVERSION@ -PQXX_ABI = @PQXX_ABI@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_postgres_lib = @with_postgres_lib@ -MAINTAINERCLEANFILES = Makefile.in stamp-h.in -noinst_HEADERS = \ - config-internal-autotools.h - -nodist_noinst_HEADERS = \ - config.h \ - config-internal-compiler.h - -DISTCLEANFILES = \ - config-internal-autotools.h \ - config-internal-compiler.h \ - config-public-compiler.h - -all: config.h - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/pqxx/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu include/pqxx/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -config.h: stamp-h1 - @test -f $@ || rm -f stamp-h1 - @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 - -stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status include/pqxx/config.h -$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f config.h stamp-h1 - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(HEADERS) config.h -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-hdr distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: all install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool cscopelist-am ctags ctags-am distclean \ - distclean-generic distclean-hdr distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - -.PRECIOUS: Makefile - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ext/libpqxx-7.7.3/include/pqxx/array b/ext/libpqxx-7.7.3/include/pqxx/array deleted file mode 100644 index 689f5b27b..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/array +++ /dev/null @@ -1,6 +0,0 @@ -/** Handling of SQL arrays. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/array.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/array.hxx b/ext/libpqxx-7.7.3/include/pqxx/array.hxx deleted file mode 100644 index 8440a244f..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/array.hxx +++ /dev/null @@ -1,103 +0,0 @@ -/* Handling of SQL arrays. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ARRAY -#define PQXX_H_ARRAY - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/internal/encodings.hxx" - - -namespace pqxx -{ -/// Low-level array parser. -/** Use this to read an array field retrieved from the database. - * - * This parser will only work reliably if your client encoding is UTF-8, ASCII, - * or a single-byte encoding which is a superset of ASCII (such as Latin-1). - * - * Also, the parser only supports array element types which use either a comma - * or a semicolon ("," or ";") as the separator between array elements. All - * built-in types use comma, except for one which uses semicolon, but some - * custom types may not work. - * - * The input is a C-style string containing the textual representation of an - * array, as returned by the database. The parser reads this representation - * on the fly. The string must remain in memory until parsing is done. - * - * Parse the array by making calls to @ref get_next until it returns a - * @ref juncture of "done". The @ref juncture tells you what the parser found - * in that step: did the array "nest" to a deeper level, or "un-nest" back up? - */ -class PQXX_LIBEXPORT array_parser -{ -public: - /// What's the latest thing found in the array? - enum class juncture - { - /// Starting a new row. - row_start, - /// Ending the current row. - row_end, - /// Found a NULL value. - null_value, - /// Found a string value. - string_value, - /// Parsing has completed. - done, - }; - - // TODO: constexpr noexcept. Breaks ABI. - /// Constructor. You don't need this; use @ref field::as_array instead. - /** The parser only remains valid while the data underlying the @ref result - * remains valid. Once all `result` objects referring to that data have been - * destroyed, the parser will no longer refer to valid memory. - */ - explicit array_parser( - std::string_view input, - internal::encoding_group = internal::encoding_group::MONOBYTE); - - /// Parse the next step in the array. - /** Returns what it found. If the juncture is @ref juncture::string_value, - * the string will contain the value. Otherwise, it will be empty. - * - * Call this until the @ref array_parser::juncture it returns is - * @ref juncture::done. - */ - std::pair get_next(); - -private: - std::string_view m_input; - internal::glyph_scanner_func *const m_scan; - - /// Current parsing position in the input. - std::string::size_type m_pos = 0u; - - std::string::size_type scan_single_quoted_string() const; - std::string parse_single_quoted_string(std::string::size_type end) const; - std::string::size_type scan_double_quoted_string() const; - std::string parse_double_quoted_string(std::string::size_type end) const; - std::string::size_type scan_unquoted_string() const; - std::string parse_unquoted_string(std::string::size_type end) const; - - std::string::size_type scan_glyph(std::string::size_type pos) const; - std::string::size_type - scan_glyph(std::string::size_type pos, std::string::size_type end) const; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/binarystring b/ext/libpqxx-7.7.3/include/pqxx/binarystring deleted file mode 100644 index 77551d9f7..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/binarystring +++ /dev/null @@ -1,6 +0,0 @@ -/** BYTEA (binary string) conversions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/binarystring.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/binarystring.hxx b/ext/libpqxx-7.7.3/include/pqxx/binarystring.hxx deleted file mode 100644 index 47c82a035..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/binarystring.hxx +++ /dev/null @@ -1,236 +0,0 @@ -/* Deprecated representation for raw, binary data. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_BINARYSTRING -#define PQXX_H_BINARYSTRING - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/result.hxx" -#include "pqxx/strconv.hxx" - -namespace pqxx -{ -class binarystring; -template<> struct string_traits; - - -/// Binary data corresponding to PostgreSQL's "BYTEA" binary-string type. -/** @ingroup escaping-functions - * @deprecated Use @c std::basic_string and - * @c std::basic_string_view for binary data. In C++20 or better, - * any @c contiguous_range of @c std::byte will do. - * - * This class represents a binary string as stored in a field of type @c bytea. - * - * Internally a binarystring is zero-terminated, but it may also contain null - * bytes, they're just like any other byte value. So don't assume that it's - * safe to treat the contents as a C-style string. - * - * The binarystring retains its value even if the result it was obtained from - * is destroyed, but it cannot be copied or assigned. - * - * \relatesalso transaction_base::quote_raw - * - * To include a @c binarystring value in an SQL query, escape and quote it - * using the transaction's @c quote_raw function. - * - * @warning This class is implemented as a reference-counting smart pointer. - * Copying, swapping, and destroying binarystring objects that refer to the - * same underlying data block is not thread-safe. If you wish to pass - * binarystrings around between threads, make sure that each of these - * operations is protected against concurrency with similar operations on the - * same object, or other objects pointing to the same data block. - */ -class PQXX_LIBEXPORT binarystring -{ -public: - using char_type = unsigned char; - using value_type = std::char_traits::char_type; - using size_type = std::size_t; - using difference_type = long; - using const_reference = value_type const &; - using const_pointer = value_type const *; - using const_iterator = const_pointer; - using const_reverse_iterator = std::reverse_iterator; - - [[deprecated("Use std::byte for binary data.")]] binarystring( - binarystring const &) = default; - - /// Read and unescape bytea field. - /** The field will be zero-terminated, even if the original bytea field - * isn't. - * @param F the field to read; must be a bytea field - */ - [[deprecated("Use std::byte for binary data.")]] explicit binarystring( - field const &); - - /// Copy binary data from std::string_view on binary data. - /** This is inefficient in that it copies the data to a buffer allocated on - * the heap. - */ - [[deprecated("Use std::byte for binary data.")]] explicit binarystring( - std::string_view); - - /// Copy binary data of given length straight out of memory. - [[deprecated("Use std::byte for binary data.")]] binarystring( - void const *, std::size_t); - - /// Efficiently wrap a buffer of binary data in a @c binarystring. - [[deprecated("Use std::byte for binary data.")]] binarystring( - std::shared_ptr ptr, size_type size) : - m_buf{std::move(ptr)}, m_size{size} - {} - - /// Size of converted string in bytes. - [[nodiscard]] size_type size() const noexcept { return m_size; } - /// Size of converted string in bytes. - [[nodiscard]] size_type length() const noexcept { return size(); } - [[nodiscard]] bool empty() const noexcept { return size() == 0; } - - [[nodiscard]] const_iterator begin() const noexcept { return data(); } - [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); } - [[nodiscard]] const_iterator end() const noexcept { return data() + m_size; } - [[nodiscard]] const_iterator cend() const noexcept { return end(); } - - [[nodiscard]] const_reference front() const noexcept { return *begin(); } - [[nodiscard]] const_reference back() const noexcept - { - return *(data() + m_size - 1); - } - - [[nodiscard]] const_reverse_iterator rbegin() const - { - return const_reverse_iterator{end()}; - } - [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); } - [[nodiscard]] const_reverse_iterator rend() const - { - return const_reverse_iterator{begin()}; - } - [[nodiscard]] const_reverse_iterator crend() const { return rend(); } - - /// Unescaped field contents. - [[nodiscard]] value_type const *data() const noexcept { return m_buf.get(); } - - [[nodiscard]] const_reference operator[](size_type i) const noexcept - { - return data()[i]; - } - - [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const noexcept; - [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept - { - return not operator==(rhs); - } - - binarystring &operator=(binarystring const &); - - /// Index contained string, checking for valid index. - const_reference at(size_type) const; - - /// Swap contents with other binarystring. - void swap(binarystring &); - - /// Raw character buffer (no terminating zero is added). - /** @warning No terminating zero is added! If the binary data did not end in - * a null character, you will not find one here. - */ - [[nodiscard]] char const *get() const noexcept - { - return reinterpret_cast(m_buf.get()); - } - - /// Read contents as a std::string_view. - [[nodiscard]] std::string_view view() const noexcept - { - return std::string_view(get(), size()); - } - - /// Read as regular C++ string (may include null characters). - /** This creates and returns a new string object. Don't call this - * repeatedly; retrieve your string once and keep it in a local variable. - * Also, do not expect to be able to compare the string's address to that of - * an earlier invocation. - */ - [[nodiscard]] std::string str() const; - - /// Access data as a pointer to @c std::byte. - [[nodiscard]] std::byte const *bytes() const - { - return reinterpret_cast(get()); - } - - /// Read data as a @c std::basic_string_view. - [[nodiscard]] std::basic_string_view bytes_view() const - { - return std::basic_string_view{bytes(), size()}; - } - -private: - std::shared_ptr m_buf; - size_type m_size{0}; -}; - - -template<> struct nullness : no_null -{}; - - -/// String conversion traits for @c binarystring. -/** Defines the conversions between a @c binarystring and its PostgreSQL - * textual format, for communication with the database. - * - * These conversions rely on the "hex" format which was introduced in - * PostgreSQL 9.0. Both your libpq and the server must be recent enough to - * speak this format. - */ -template<> struct string_traits -{ - static std::size_t size_buffer(binarystring const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf(char *begin, char *end, binarystring const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, binarystring const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - std::string_view text{value.view()}; - internal::esc_bin(binary_cast(text), begin); - return begin + budget; - } - - static binarystring from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::shared_ptr buf{ - new unsigned char[size], [](unsigned char const *x) { delete[] x; }}; - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.get())); -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return binarystring{std::move(buf), size}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - } -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/blob b/ext/libpqxx-7.7.3/include/pqxx/blob deleted file mode 100644 index 3fd0afac9..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/blob +++ /dev/null @@ -1,6 +0,0 @@ -/** Binary Large Objects interface. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/blob.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/blob.hxx b/ext/libpqxx-7.7.3/include/pqxx/blob.hxx deleted file mode 100644 index 6d77be724..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/blob.hxx +++ /dev/null @@ -1,351 +0,0 @@ -/* Binary Large Objects interface. - * - * Read or write large objects, stored in their own storage on the server. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_BLOB -#define PQXX_H_BLOB - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#if defined(PQXX_HAVE_PATH) -# include -#endif - -#if defined(PQXX_HAVE_RANGES) && __has_include() -# include -#endif - -#if defined(PQXX_HAVE_SPAN) && __has_include() -# include -#endif - -#include "pqxx/dbtransaction.hxx" - - -namespace pqxx -{ -/** Binary large object. - * - * This is how you store data that may be too large for the `BYTEA` type. - * Access operations are similar to those for a file: you can read, write, - * query or set the current reading/writing position, and so on. - * - * These large objects live in their own storage on the server, indexed by an - * integer object identifier ("oid"). - * - * Two `blob` objects may refer to the same actual large object in the - * database at the same time. Each will have its own reading/writing position, - * but writes to the one will of course affect what the other sees. - */ -class PQXX_LIBEXPORT blob -{ -public: - /// Create a new, empty large object. - /** You may optionally specify an oid for the new blob. If you do, then - * the new object will have that oid -- or creation will fail if there - * already is an object with that oid. - */ - [[nodiscard]] static oid create(dbtransaction &, oid = 0); - - /// Delete a large object, or fail if it does not exist. - static void remove(dbtransaction &, oid); - - /// Open blob for reading. Any attempt to write to it will fail. - [[nodiscard]] static blob open_r(dbtransaction &, oid); - // Open blob for writing. Any attempt to read from it will fail. - [[nodiscard]] static blob open_w(dbtransaction &, oid); - // Open blob for reading and/or writing. - [[nodiscard]] static blob open_rw(dbtransaction &, oid); - - /// You can default-construct a blob, but it won't do anything useful. - /** Most operations on a default-constructed blob will throw @ref - * usage_error. - */ - blob() = default; - - /// You can move a blob, but not copy it. The original becomes unusable. - blob(blob &&); - /// You can move a blob, but not copy it. The original becomes unusable. - blob &operator=(blob &&); - - blob(blob const &) = delete; - blob &operator=(blob const &) = delete; - ~blob(); - - /// Maximum number of bytes that can be read or written at a time. - /** The underlying protocol only supports reads and writes up to 2 GB - * exclusive. - * - * If you need to read or write more data to or from a binary large object, - * you'll have to break it up into chunks. - */ - static constexpr std::size_t chunk_limit = 0x7fffffff; - - /// Read up to `size` bytes of the object into `buf`. - /** Uses a buffer that you provide, resizing it as needed. If it suits you, - * this lets you allocate the buffer once and then re-use it multiple times. - * - * Resizes `buf` as needed. - * - * @warning The underlying protocol only supports reads up to 2GB at a time. - * If you need to read more, try making repeated calls to @ref append_to_buf. - */ - std::size_t read(std::basic_string &buf, std::size_t size); - -#if defined(PQXX_HAVE_SPAN) - /// Read up to `std::size(buf)` bytes from the object. - /** Retrieves bytes from the blob, at the current position, until `buf` is - * full or there are no more bytes to read, whichever comes first. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template - std::span read(std::span buf) - { - return buf.subspan(0, raw_read(std::data(buf), std::size(buf))); - } -#endif // PQXX_HAVE_SPAN - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Read up to `std::size(buf)` bytes from the object. - /** Retrieves bytes from the blob, at the current position, until `buf` is - * full or there are no more bytes to read, whichever comes first. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template std::span read(DATA &buf) - { - return {std::data(buf), raw_read(std::data(buf), std::size(buf))}; - } -#else // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN - /// Read up to `std::size(buf)` bytes from the object. - /** @deprecated As libpqxx moves to C++20 as its baseline language version, - * this will take and return `std::span`. - * - * Retrieves bytes from the blob, at the current position, until `buf` is - * full (i.e. its current size is reached), or there are no more bytes to - * read, whichever comes first. - * - * This function will not change either the size or the capacity of `buf`, - * only its contents. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template - std::basic_string_view read(std::vector &buf) - { - return {std::data(buf), raw_read(std::data(buf), std::size(buf))}; - } -#endif // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN - -#if defined(PQXX_HAVE_CONCEPTS) - /// Write `data` to large object, at the current position. - /** If the writing position is at the end of the object, this will append - * `data` to the object's contents and move the writing position so that - * it's still at the end. - * - * If the writing position was not at the end, writing will overwrite the - * prior data, but it will not remove data that follows the part where you - * wrote your new data. - * - * @warning This is a big difference from writing to a file. You can - * overwrite some data in a large object, but this does not truncate the - * data that was already there. For example, if the object contained binary - * data "abc", and you write "12" at the starting position, the object will - * contain "12c". - * - * @warning The underlying protocol only supports writes up to 2 GB at a - * time. If you need to write more, try making repeated calls to - * @ref append_from_buf. - */ - template void write(DATA const &data) - { - raw_write(std::data(data), std::size(data)); - } -#else - /// Write `data` large object, at the current position. - /** If the writing position is at the end of the object, this will append - * `data` to the object's contents and move the writing position so that - * it's still at the end. - * - * If the writing position was not at the end, writing will overwrite the - * prior data, but it will not remove data that follows the part where you - * wrote your new data. - * - * @warning This is a big difference from writing to a file. You can - * overwrite some data in a large object, but this does not truncate the - * data that was already there. For example, if the object contained binary - * data "abc", and you write "12" at the starting position, the object will - * contain "12c". - * - * @warning The underlying protocol only supports writes up to 2 GB at a - * time. If you need to write more, try making repeated calls to - * @ref append_from_buf. - */ - template void write(DATA const &data) - { - raw_write(std::data(data), std::size(data)); - } -#endif - - /// Resize large object to `size` bytes. - /** If the blob is more than `size` bytes long, this removes the end so as - * to make the blob the desired length. - * - * If the blob is less than `size` bytes long, it adds enough zero bytes to - * make it the desired length. - */ - void resize(std::int64_t size); - - /// Return the current reading/writing position in the large object. - [[nodiscard]] std::int64_t tell() const; - - /// Set the current reading/writing position to an absolute offset. - /** Returns the new file offset. */ - std::int64_t seek_abs(std::int64_t offset = 0); - /// Move the current reading/writing position forwards by an offset. - /** To move backwards, pass a negative offset. - * - * Returns the new file offset. - */ - std::int64_t seek_rel(std::int64_t offset = 0); - /// Set the current position to an offset relative to the end of the blob. - /** You'll probably want an offset of zero or less. - * - * Returns the new file offset. - */ - std::int64_t seek_end(std::int64_t offset = 0); - - /// Create a binary large object containing given `data`. - /** You may optionally specify an oid for the new object. If you do, and an - * object with that oid already exists, creation will fail. - */ - static oid from_buf( - dbtransaction &tx, std::basic_string_view data, oid id = 0); - - /// Append `data` to binary large object. - /** The underlying protocol only supports appending blocks up to 2 GB. - */ - static void append_from_buf( - dbtransaction &tx, std::basic_string_view data, oid id); - - /// Read client-side file and store it server-side as a binary large object. - [[nodiscard]] static oid from_file(dbtransaction &, char const path[]); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Read client-side file and store it server-side as a binary large object. - /** This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - [[nodiscard]] static oid - from_file(dbtransaction &tx, std::filesystem::path const &path) - { - return from_file(tx, path.c_str()); - } -#endif - - /// Read client-side file and store it server-side as a binary large object. - /** In this version, you specify the binary large object's oid. If that oid - * is already in use, the operation will fail. - */ - static oid from_file(dbtransaction &, char const path[], oid); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Read client-side file and store it server-side as a binary large object. - /** In this version, you specify the binary large object's oid. If that oid - * is already in use, the operation will fail. - * - * This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - static oid - from_file(dbtransaction &tx, std::filesystem::path const &path, oid id) - { - return from_file(tx, path.c_str(), id); - } -#endif - - /// Convenience function: Read up to `max_size` bytes from blob with `id`. - /** You could easily do this yourself using the @ref open_r and @ref read - * functions, but it can save you a bit of code to do it this way. - */ - static void to_buf( - dbtransaction &, oid, std::basic_string &, - std::size_t max_size); - - /// Read part of the binary large object with `id`, and append it to `buf`. - /** Use this to break up a large read from one binary large object into one - * massive buffer. Just keep calling this function until it returns zero. - * - * The `offset` is how far into the large object your desired chunk is, and - * `append_max` says how much to try and read in one go. - */ - static std::size_t append_to_buf( - dbtransaction &tx, oid id, std::int64_t offset, - std::basic_string &buf, std::size_t append_max); - - /// Write a binary large object's contents to a client-side file. - static void to_file(dbtransaction &, oid, char const path[]); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Write a binary large object's contents to a client-side file. - /** This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - static void - to_file(dbtransaction &tx, oid id, std::filesystem::path const &path) - { - to_file(tx, id, path.c_str()); - } -#endif - - /// Close this blob. - /** This does not delete the blob from the database; it only terminates your - * local object for accessing the blob. - * - * Resets the blob to a useless state similar to one that was - * default-constructed. - * - * The destructor will do this for you automatically. Still, there is a - * reason to `close()` objects explicitly where possible: if an error should - * occur while closing, `close()` can throw an exception. A destructor - * cannot. - */ - void close(); - -private: - PQXX_PRIVATE blob(connection &conn, int fd) noexcept : - m_conn{&conn}, m_fd{fd} - {} - static PQXX_PRIVATE blob open_internal(dbtransaction &, oid, int); - static PQXX_PRIVATE pqxx::internal::pq::PGconn * - raw_conn(pqxx::connection *) noexcept; - static PQXX_PRIVATE pqxx::internal::pq::PGconn * - raw_conn(pqxx::dbtransaction const &) noexcept; - static PQXX_PRIVATE std::string errmsg(connection const *); - static PQXX_PRIVATE std::string errmsg(dbtransaction const &tx) - { - return errmsg(&tx.conn()); - } - PQXX_PRIVATE std::string errmsg() const { return errmsg(m_conn); } - PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence); - std::size_t raw_read(std::byte buf[], std::size_t size); - void raw_write(std::byte const buf[], std::size_t size); - - connection *m_conn = nullptr; - int m_fd = -1; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/composite b/ext/libpqxx-7.7.3/include/pqxx/composite deleted file mode 100644 index 2bfa7ade9..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/composite +++ /dev/null @@ -1,6 +0,0 @@ -/** Handling of SQL "composite types." - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/composite.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/composite.hxx b/ext/libpqxx-7.7.3/include/pqxx/composite.hxx deleted file mode 100644 index 439b133a8..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/composite.hxx +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef PQXX_H_COMPOSITE -#define PQXX_H_COMPOSITE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/internal/array-composite.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Parse a string representation of a value of a composite type. -/** @warning This code is still experimental. Use with care. - * - * You may use this as a helper while implementing your own @ref string_traits - * for a composite type. - * - * This function interprets `text` as the string representation of a value of - * some composite type, and sets each of `fields` to the respective values of - * its fields. The field types must be copy-assignable. - * - * The number of fields must match the number of fields in the composite type, - * and there must not be any other text in the input. The function is meant to - * handle any value string that the backend can produce, but not necessarily - * every valid alternative spelling. - * - * Fields in composite types can be null. When this happens, the C++ type of - * the corresponding field reference must be of a type that can handle nulls. - * If you are working with a type that does not have an inherent null value, - * such as e.g. `int`, consider using `std::optional`. - */ -template -inline void parse_composite( - pqxx::internal::encoding_group enc, std::string_view text, T &...fields) -{ - static_assert(sizeof...(fields) > 0); - - auto const scan{pqxx::internal::get_glyph_scanner(enc)}; - auto const data{std::data(text)}; - auto const size{std::size(text)}; - if (size == 0) - throw conversion_error{"Cannot parse composite value from empty string."}; - - std::size_t here{0}, next{scan(data, size, here)}; - if (next != 1 or data[here] != '(') - throw conversion_error{ - internal::concat("Invalid composite value string: ", text)}; - - here = next; - - constexpr auto num_fields{sizeof...(fields)}; - std::size_t index{0}; - (pqxx::internal::parse_composite_field( - index, text, here, fields, scan, num_fields - 1), - ...); - if (here != std::size(text)) - throw conversion_error{internal::concat( - "Composite value did not end at the closing parenthesis: '", text, - "'.")}; - if (text[here - 1] != ')') - throw conversion_error{internal::concat( - "Composive value did not end in parenthesis: '", text, "'")}; -} - - -/// Parse a string representation of a value of a composite type. -/** @warning This version only works for UTF-8 and single-byte encodings. - * - * For proper encoding support, use the composite-type support in the - * `field` class. - */ -template -inline void parse_composite(std::string_view text, T &...fields) -{ - parse_composite(pqxx::internal::encoding_group::MONOBYTE, text, fields...); -} -} // namespace pqxx - - -namespace pqxx::internal -{ -constexpr char empty_composite_str[]{"()"}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// Estimate the buffer size needed to represent a value of a composite type. -/** Returns a conservative estimate. - */ -template -[[nodiscard]] inline std::size_t -composite_size_buffer(T const &...fields) noexcept -{ - constexpr auto num{sizeof...(fields)}; - - // Size for a multi-field composite includes room for... - // + opening parenthesis - // + field budgets - // + separating comma per field - // - comma after final field - // + closing parenthesis - // + terminating zero - - if constexpr (num == 0) - return std::size(pqxx::internal::empty_composite_str); - else - return 1 + (pqxx::internal::size_composite_field_buffer(fields) + ...) + - num + 1; -} - - -/// Render a series of values as a single composite SQL value. -/** @warning This code is still experimental. Use with care. - * - * You may use this as a helper while implementing your own `string_traits` - * for a composite type. - */ -template -inline char *composite_into_buf(char *begin, char *end, T const &...fields) -{ - if (std::size_t(end - begin) < composite_size_buffer(fields...)) - throw conversion_error{ - "Buffer space may not be enough to represent composite value."}; - - constexpr auto num_fields{sizeof...(fields)}; - if constexpr (num_fields == 0) - { - constexpr char empty[]{"()"}; - std::memcpy(begin, empty, std::size(empty)); - return begin + std::size(empty); - } - - char *pos{begin}; - *pos++ = '('; - - (pqxx::internal::write_composite_field(pos, end, fields), ...); - - // If we've got multiple fields, "backspace" that last comma. - if constexpr (num_fields > 1) - --pos; - *pos++ = ')'; - *pos++ = '\0'; - return pos; -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/config.h.in b/ext/libpqxx-7.7.3/include/pqxx/config.h.in deleted file mode 100644 index 743579967..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/config.h.in +++ /dev/null @@ -1,121 +0,0 @@ -/* include/pqxx/config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the `pq' library (-lpq). */ -#undef HAVE_LIBPQ - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#undef LT_OBJDIR - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define if supports floating-point conversion. */ -#undef PQXX_HAVE_CHARCONV_FLOAT - -/* Define if supports integer conversion. */ -#undef PQXX_HAVE_CHARCONV_INT - -/* Define if compiler has C++20 std::cmp_greater etc. */ -#undef PQXX_HAVE_CMP - -/* Define if compiler supports Concepts and header. */ -#undef PQXX_HAVE_CONCEPTS - -/* Define if compiler supports __cxa_demangle */ -#undef PQXX_HAVE_CXA_DEMANGLE - -/* Define if g++ supports pure attribute */ -#undef PQXX_HAVE_GCC_PURE - -/* Define if g++ supports visibility attribute. */ -#undef PQXX_HAVE_GCC_VISIBILITY - -/* Define if likely & unlikely work. */ -#undef PQXX_HAVE_LIKELY - -/* Define if operator[] can take multiple arguments. */ -#undef PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT - -/* Define if compiler has usable std::filesystem::path. */ -#undef PQXX_HAVE_PATH - -/* Define if poll() is available. */ -#undef PQXX_HAVE_POLL - -/* Define if libpq has PQencryptPasswordConn (since pg 10). */ -#undef PQXX_HAVE_PQENCRYPTPASSWORDCONN - -/* Define if libpq has pipeline mode (since pg 14). */ -#undef PQXX_HAVE_PQ_PIPELINE - -/* Define if std::this_thread::sleep_for works. */ -#undef PQXX_HAVE_SLEEP_FOR - -/* Define if compiler has std::span. */ -#undef PQXX_HAVE_SPAN - -/* Define if strerror_r() is available. */ -#undef PQXX_HAVE_STRERROR_R - -/* Define if strerror_s() is available. */ -#undef PQXX_HAVE_STRERROR_S - -/* Define if thread_local is fully supported. */ -#undef PQXX_HAVE_THREAD_LOCAL - -/* Define if std::chrono has year_month_day etc. */ -#undef PQXX_HAVE_YEAR_MONTH_DAY - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Version number of package */ -#undef VERSION diff --git a/ext/libpqxx-7.7.3/include/pqxx/connection b/ext/libpqxx-7.7.3/include/pqxx/connection deleted file mode 100644 index 82ff43aa5..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/connection +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::connection class. - * - * pqxx::connection encapsulates a connection to a database. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/connection.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/connection.hxx b/ext/libpqxx-7.7.3/include/pqxx/connection.hxx deleted file mode 100644 index 92454bb47..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/connection.hxx +++ /dev/null @@ -1,1261 +0,0 @@ -/* Definition of the connection class. - * - * pqxx::connection encapsulates a connection to a database. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_CONNECTION -#define PQXX_H_CONNECTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Double-check in order to suppress an overzealous Visual C++ warning (#418). -#if defined(PQXX_HAVE_CONCEPTS) && __has_include() -# include -#endif - -#include "pqxx/errorhandler.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/params.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - - -/** - * @addtogroup connections - * - * Use of the libpqxx library starts here. - * - * Everything that can be done with a database through libpqxx must go through - * a @ref pqxx::connection object. It connects to a database when you create - * it, and it terminates that communication during destruction. - * - * Many things come together in this class. Handling of error and warning - * messages, for example, is defined by @ref pqxx::errorhandler objects in the - * context of a connection. Prepared statements are also defined here. - * - * When you connect to a database, you pass a connection string containing any - * parameters and options, such as the server address and the database name. - * - * These are identical to the ones in libpq, the C language binding upon which - * libpqxx itself is built: - * - * https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING - * - * There are also environment variables you can set to provide defaults, again - * as defined by libpq: - * - * https://www.postgresql.org/docs/current/libpq-envars.html - * - * You can also create a database connection _asynchronously_ using an - * intermediate @ref pqxx::connecting object. - */ - -namespace pqxx::internal -{ -class sql_cursor; - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: T is a range of pairs of zero-terminated strings. -template -concept ZKey_ZValues = std::ranges::input_range and requires(T t) -{ - {std::cbegin(t)}; - { - std::get<0>(*std::cbegin(t)) - } -> ZString; - { - std::get<1>(*std::cbegin(t)) - } -> ZString; -} and std::tuple_size_v::value_type> -== 2; -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx::internal - - -namespace pqxx::internal::gate -{ -class connection_dbtransaction; -class connection_errorhandler; -class connection_largeobject; -class connection_notification_receiver; -class connection_pipeline; -class connection_sql_cursor; -class connection_stream_from; -class connection_stream_to; -class connection_transaction; -class const_connection_largeobject; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Representation of a PostgreSQL table path. -/** A "table path" consists of a table name, optionally prefixed by a schema - * name, which in turn is optionally prefixed by a database name. - * - * A minimal example of a table path would be `{mytable}`. But a table path - * may also take the forms `{myschema,mytable}` or - * `{mydb,myschema,mytable}`. - */ -using table_path = std::initializer_list; - - -/// Encrypt a password. @deprecated Use connection::encrypt_password instead. -[[nodiscard, - deprecated("Use connection::encrypt_password instead.")]] std::string - PQXX_LIBEXPORT - encrypt_password(char const user[], char const password[]); - -/// Encrypt password. @deprecated Use connection::encrypt_password instead. -[[nodiscard, - deprecated("Use connection::encrypt_password instead.")]] inline std::string -encrypt_password(zview user, zview password) -{ -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return encrypt_password(user.c_str(), password.c_str()); -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -/// Error verbosity levels. -enum class error_verbosity : int -{ - // These values must match those in libpq's PGVerbosity enum. - terse = 0, - normal = 1, - verbose = 2 -}; - - -/// Connection to a database. -/** This is the first class to look at when you wish to work with a database - * through libpqxx. The connection opens during construction, and closes upon - * destruction. - * - * When creating a connection, you can pass a connection URI or a postgres - * connection string, to specify the database server's address, a login - * username, and so on. If you don't, the connection will try to obtain them - * from certain environment variables. If those are not set either, the - * default is to try and connect to the local system's port 5432. - * - * Find more about connection strings here: - * - * https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING - * - * The variables are documented here: - * - * https://www.postgresql.org/docs/current/libpq-envars.html - * - * To query or manipulate the database once connected, use one of the - * transaction classes (see pqxx/transaction_base.hxx) and perhaps also the - * transactor framework (see pqxx/transactor.hxx). - * - * When a connection breaks, you will typically get a @ref broken_connection - * exception. This can happen at almost any point. - * - * @warning On Unix-like systems, including GNU and BSD systems, your program - * may receive the SIGPIPE signal when the connection to the backend breaks. By - * default this signal will abort your program. Use "signal(SIGPIPE, SIG_IGN)" - * if you want your program to continue running after a connection fails. - */ -class PQXX_LIBEXPORT connection -{ -public: - connection() : connection{""} {} - - /// Connect to a database, using `options` string. - explicit connection(char const options[]) - { - check_version(); - init(options); - } - - /// Connect to a database, using `options` string. - explicit connection(zview options) : connection{options.c_str()} - { - // (Delegates to other constructor which calls check_version for us.) - } - - /// Move constructor. - /** Moving a connection is not allowed if it has an open transaction, or has - * error handlers or notification receivers registered on it. In those - * situations, other objects may hold references to the old object which - * would become invalid and might produce hard-to-diagnose bugs. - */ - connection(connection &&rhs); - -#if defined(PQXX_HAVE_CONCEPTS) - /// Connect to a database, passing options as a range of key/value pairs. - /** @warning Experimental. Requires C++20 "concepts" support. Define - * `PQXX_HAVE_CONCEPTS` to enable it. - * - * There's no need to escape the parameter values. - * - * See the PostgreSQL libpq documentation for the full list of possible - * options: - * - * https://postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS - * - * The options can be anything that can be iterated as a series of pairs of - * zero-terminated strings: `std::pair`, or - * `std::tuple`, or - * `std::map`, and so on. - */ - template - inline connection(MAPPING const ¶ms); -#endif // PQXX_HAVE_CONCEPTS - - ~connection() - { - try - { - close(); - } - catch (std::exception const &) - {} - } - - /// Move assignment. - /** Neither connection can have an open transaction, registered error - * handlers, or registered notification receivers. - */ - connection &operator=(connection &&rhs); - - connection(connection const &) = delete; - connection &operator=(connection const &) = delete; - - /// Is this connection open at the moment? - /** @warning This function is **not** needed in most code. Resist the - * temptation to check it after opening a connection. The `connection` - * constructor will throw a @ref broken_connection exception if can't connect - * to the database. - */ - [[nodiscard]] bool PQXX_PURE is_open() const noexcept; - - /// Invoke notice processor function. The message should end in newline. - void process_notice(char const[]) noexcept; - /// Invoke notice processor function. Newline at end is recommended. - /** The zview variant, with a message ending in newline, is the most - * efficient way to call process_notice. - */ - void process_notice(zview) noexcept; - - /// Enable tracing to a given output stream, or nullptr to disable. - void trace(std::FILE *) noexcept; - - /** - * @name Connection properties - * - * These are probably not of great interest, since most are derived from - * information supplied by the client program itself, but they are included - * for completeness. - * - * The connection needs to be currently active for these to work. - */ - //@{ - /// Name of database we're connected to, if any. - [[nodiscard]] char const *dbname() const; - - /// Database user ID we're connected under, if any. - [[nodiscard]] char const *username() const; - - /// Address of server, or nullptr if none specified (i.e. default or local) - [[nodiscard]] char const *hostname() const; - - /// Server port number we're connected to. - [[nodiscard]] char const *port() const; - - /// Process ID for backend process, or 0 if inactive. - [[nodiscard]] int PQXX_PURE backendpid() const &noexcept; - - /// Socket currently used for connection, or -1 for none. Use with care! - /** Query the current socket number. This is intended for event loops based - * on functions such as select() or poll(), where you're waiting for any of - * multiple file descriptors to become ready for communication. - * - * Please try to stay away from this function. It is really only meant for - * event loops that need to wait on more than one file descriptor. If all - * you need is to block until a notification arrives, for instance, use - * await_notification(). If you want to issue queries and retrieve results - * in nonblocking fashion, check out the pipeline class. - */ - [[nodiscard]] int PQXX_PURE sock() const &noexcept; - - /// What version of the PostgreSQL protocol is this connection using? - /** The answer can be 0 (when there is no connection); 3 for protocol 3.0; or - * possibly higher values as newer protocol versions come into use. - */ - [[nodiscard]] int PQXX_PURE protocol_version() const noexcept; - - /// What version of the PostgreSQL server are we connected to? - /** The result is a bit complicated: each of the major, medium, and minor - * release numbers is written as a two-digit decimal number, and the three - * are then concatenated. Thus server version 9.4.2 will be returned as the - * decimal number 90402. If there is no connection to the server, this - * returns zero. - * - * @warning When writing version numbers in your code, don't add zero at the - * beginning! Numbers beginning with zero are interpreted as octal (base-8) - * in C++. Thus, 070402 is not the same as 70402, and 080000 is not a number - * at all because there is no digit "8" in octal notation. Use strictly - * decimal notation when it comes to these version numbers. - */ - [[nodiscard]] int PQXX_PURE server_version() const noexcept; - //@} - - /// @name Text encoding - /** - * Each connection is governed by a "client encoding," which dictates how - * strings and other text is represented in bytes. The database server will - * send text data to you in this encoding, and you should use it for the - * queries and data which you send to the server. - * - * Search the PostgreSQL documentation for "character set encodings" to find - * out more about the available encodings, how to extend them, and how to use - * them. Not all server-side encodings are compatible with all client-side - * encodings or vice versa. - * - * Encoding names are case-insensitive, so e.g. "UTF8" is equivalent to - * "utf8". - * - * You can change the client encoding, but this may not work when the - * connection is in a special state, such as when streaming a table. It's - * not clear what happens if you change the encoding during a transaction, - * and then abort the transaction. - */ - //@{ - /// Get client-side character encoding, by name. - [[nodiscard]] std::string get_client_encoding() const; - - /// Set client-side character encoding, by name. - /** - * @param encoding Name of the character set encoding to use. - */ - void set_client_encoding(zview encoding) & - { - set_client_encoding(encoding.c_str()); - } - - /// Set client-side character encoding, by name. - /** - * @param encoding Name of the character set encoding to use. - */ - void set_client_encoding(char const encoding[]) &; - - /// Get the connection's encoding, as a PostgreSQL-defined code. - [[nodiscard]] int PQXX_PRIVATE encoding_id() const; - - //@} - - /// Set session variable, using SQL's `SET` command. - /** @deprecated To set a session variable, use @ref set_session_var. To set - * a transaction-local variable, execute an SQL `SET` command. - * - * @warning When setting a string value, you must escape and quote it first. - * Use the @ref quote() function to do that. - * - * @warning This executes an SQL query, so do not get or set variables while - * a table stream or pipeline is active on the same connection. - * - * @param var Variable to set. - * @param value New value for Var. This can be any SQL expression. If it's - * a string, be sure that it's properly escaped and quoted. - */ - [[deprecated("To set session variables, use set_session_var.")]] void - set_variable(std::string_view var, std::string_view value) &; - - /// Set one of the session variables to a new value. - /** This executes SQL, so do not do it while a pipeline or stream is active - * on the connection. - * - * The value you set here will last for the rest of the connection's - * duration, or until you set a new value. - * - * If you set the value while in a @ref dbtransaction (i.e. any transaction - * that is not a @ref nontransaction), then rolling back the transaction will - * undo the change. - * - * All applies to setting _session_ variables. You can also set the same - * variables as _local_ variables, in which case they will always revert to - * their previous value when the transaction ends (or when you overwrite them - * of course). To set a local variable, simply execute an SQL statement - * along the lines of "`SET LOCAL var = 'value'`" inside your transaction. - * - * @param var The variable to set. - * @param value The new value for the variable. - * @throw @ref variable_set_to_null if the value is null; this is not - * allowed. - */ - template - void set_session_var(std::string_view var, TYPE const &value) & - { - if constexpr (nullness::has_null) - { - if (nullness::is_null(value)) - throw variable_set_to_null{ - internal::concat("Attempted to set variable ", var, " to null.")}; - } - exec(internal::concat("SET ", quote_name(var), "=", quote(value))); - } - - /// Read session variable, using SQL's `SHOW` command. - /** @warning This executes an SQL query, so do not get or set variables while - * a table stream or pipeline is active on the same connection. - */ - [[deprecated("Use get_var instead.")]] std::string - get_variable(std::string_view); - - /// Read currently applicable value of a variable. - /** This function executes an SQL statement, so it won't work while a - * @ref pipeline or query stream is active on the connection. - * - * @return a blank `std::optional` if the variable's value is null, or its - * string value otherwise. - */ - std::string get_var(std::string_view var); - - /// Read currently applicable value of a variable. - /** This function executes an SQL statement, so it won't work while a - * @ref pipeline or query stream is active on the connection. - * - * If there is any possibility that the variable is null, ensure that `TYPE` - * can represent null values. - */ - template TYPE get_var_as(std::string_view var) - { - return from_string(get_var(var)); - } - - /** - * @name Notifications and Receivers - */ - //@{ - /// Check for pending notifications and take appropriate action. - /** This does not block. To wait for incoming notifications, either call - * await_notification() (it calls this function); or wait for incoming data - * on the connection's socket (i.e. wait to read), and then call this - * function repeatedly until it returns zero. After that, there are no more - * pending notifications so you may want to wait again. - * - * If any notifications are pending when you call this function, it - * processes them by finding any receivers that match the notification string - * and invoking those. If no receivers match, there is nothing to invoke but - * we do consider the notification processed. - * - * If any of the client-registered receivers throws an exception, the - * function will report it using the connection's errorhandlers. It does not - * re-throw the exceptions. - * - * @return Number of notifications processed. - */ - int get_notifs(); - - /// Wait for a notification to come in. - /** There are other events that will also terminate the wait, such as the - * backend failing. It will also wake up periodically. - * - * If a notification comes in, the call will process it, along with any other - * notifications that may have been pending. - * - * To wait for notifications into your own event loop instead, wait until - * there is incoming data on the connection's socket to be read, then call - * @ref get_notifs() repeatedly until it returns zero. - * - * @return Number of notifications processed. - */ - int await_notification(); - - /// Wait for a notification to come in, or for given timeout to pass. - /** There are other events that will also terminate the wait, such as the - * backend failing, or timeout expiring. - * - * If a notification comes in, the call will process it, along with any other - * notifications that may have been pending. - * - * To wait for notifications into your own event loop instead, wait until - * there is incoming data on the connection's socket to be read, then call - * @ref get_notifs repeatedly until it returns zero. - * - * @return Number of notifications processed - */ - int await_notification(std::time_t seconds, long microseconds); - //@} - - /** - * @name Password encryption - * - * Use this when setting a new password for the user if password encryption - * is enabled. Inputs are the SQL name for the user for whom you with to - * encrypt a password; the plaintext password; and the hash algorithm. - * - * The algorithm must be one of "md5", "scram-sha-256" (introduced in - * PostgreSQL 10), or `nullptr`. If the pointer is null, this will query - * the `password_encryption setting` from the server, and use the default - * algorithm as defined there. - * - * @return encrypted version of the password, suitable for encrypted - * PostgreSQL authentication. - * - * Thus you can change a user's password with: - * ```cxx - * void setpw(transaction_base &t, string const &user, string const &pw) - * { - * t.exec0("ALTER USER " + user + " " - * "PASSWORD '" + t.conn().encrypt_password(user,pw) + "'"); - * } - * ``` - * - * When building this against a libpq older than version 10, this will use - * an older function which only supports md5. In that case, requesting a - * different algorithm than md5 will result in a @ref feature_not_supported - * exception. - */ - //@{ - /// Encrypt a password for a given user. - [[nodiscard]] std::string - encrypt_password(zview user, zview password, zview algorithm) - { - return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str()); - } - /// Encrypt a password for a given user. - [[nodiscard]] std::string encrypt_password( - char const user[], char const password[], char const *algorithm = nullptr); - //@} - - /** - * @name Prepared statements - * - * PostgreSQL supports prepared SQL statements, i.e. statements that you can - * register under a name you choose, optimized once by the backend, and - * executed any number of times under the given name. - * - * Prepared statement definitions are not sensitive to transaction - * boundaries. A statement defined inside a transaction will remain defined - * outside that transaction, even if the transaction itself is subsequently - * aborted. Once a statement has been prepared, it will only go away if you - * close the connection or explicitly "unprepare" the statement. - * - * Use the `pqxx::transaction_base::exec_prepared` functions to execute a - * prepared statement. See @ref prepared for a full discussion. - * - * @warning Using prepared statements can save time, but if your statement - * takes parameters, it may also make your application significantly slower! - * The reason is that the server works out a plan for executing the query - * when you prepare it. At that time, of course it does not know the values - * for the parameters that you will pass. If you execute a query without - * preparing it, then the server works out the plan on the spot, with full - * knowledge of the parameter values. - * - * A statement's definition can refer to its parameters as `$1`, `$2`, etc. - * The first parameter you pass to the call provides a value for `$1`, and - * so on. - * - * Here's an example of how to use prepared statements. - * - * ```cxx - * using namespace pqxx; - * void foo(connection &c) - * { - * c.prepare("findtable", "select * from pg_tables where name=$1"); - * work tx{c}; - * result r = tx.exec_prepared("findtable", "mytable"); - * if (std::empty(r)) throw runtime_error{"mytable not found!"}; - * } - * ``` - */ - //@{ - - /// Define a prepared statement. - /** - * @param name unique name for the new prepared statement. - * @param definition SQL statement to prepare. - */ - void prepare(zview name, zview definition) & - { - prepare(name.c_str(), definition.c_str()); - } - - /** - * @param name unique name for the new prepared statement. - * @param definition SQL statement to prepare. - */ - void prepare(char const name[], char const definition[]) &; - - /// Define a nameless prepared statement. - /** - * This can be useful if you merely want to pass large binary parameters to a - * statement without otherwise wishing to prepare it. If you use this - * feature, always keep the definition and the use close together to avoid - * the nameless statement being redefined unexpectedly by code somewhere - * else. - */ - void prepare(char const definition[]) &; - void prepare(zview definition) & { return prepare(definition.c_str()); } - - /// Drop prepared statement. - void unprepare(std::string_view name); - - //@} - - // C++20: constexpr. Breaks ABI. - /// Suffix unique number to name to make it unique within session context. - /** Used internally to generate identifiers for SQL objects (such as cursors - * and nested transactions) based on a given human-readable base name. - */ - [[nodiscard]] std::string adorn_name(std::string_view); - - /** - * @defgroup escaping-functions String-escaping functions - */ - //@{ - - /// Escape string for use as SQL string literal on this connection. - /** @warning This accepts a length, and it does not require a terminating - * zero byte. But if there is a zero byte, escaping stops there even if - * it's not at the end of the string! - */ - [[deprecated("Use std::string_view or pqxx:zview.")]] std::string - esc(char const text[], std::size_t maxlen) const - { - return esc(std::string_view{text, maxlen}); - } - - /// Escape string for use as SQL string literal on this connection. - [[nodiscard]] std::string esc(char const text[]) const - { - return esc(std::string_view{text}); - } - -#if defined(PQXX_HAVE_SPAN) - /// Escape string for use as SQL string literal, into `buffer`. - /** Use this variant when you want to re-use the same buffer across multiple - * calls. If that's not the case, or convenience and simplicity are more - * important, use the single-argument variant. - * - * For every byte in `text`, there must be at least 2 bytes of space in - * `buffer`; plus there must be one byte of space for a trailing zero. - * Throws @ref range_error if this space is not available. - * - * Returns a reference to the escaped string, which is actually stored in - * `buffer`. - */ - [[nodiscard]] std::string_view - esc(std::string_view text, std::span buffer) - { - auto const size{std::size(text)}, space{std::size(buffer)}; - auto const needed{2 * size + 1}; - if (space < needed) - throw range_error{internal::concat( - "Not enough room to escape string of ", size, " byte(s): need ", - needed, " bytes of buffer space, but buffer size is ", space, ".")}; - auto const data{buffer.data()}; - return {data, esc_to_buf(text, data)}; - } -#endif - - /// Escape string for use as SQL string literal on this connection. - /** @warning This is meant for text strings only. It cannot contain bytes - * whose value is zero ("nul bytes"). - */ - [[nodiscard]] std::string esc(std::string_view text) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape binary string for use as SQL string literal on this connection. - /** This is identical to `esc_raw(data)`. */ - template [[nodiscard]] std::string esc(DATA const &data) const - { - return esc_raw(data); - } -#endif - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - /** Use this variant when you want to re-use the same buffer across multiple - * calls. If that's not the case, or convenience and simplicity are more - * important, use the single-argument variant. - * - * For every byte in `data`, there must be at least two bytes of space in - * `buffer`; plus there must be two bytes of space for a header and one for - * a trailing zero. Throws @ref range_error if this space is not available. - * - * Returns a reference to the escaped string, which is actually stored in - * `buffer`. - */ - template - [[nodiscard]] zview esc(DATA const &data, std::span buffer) const - { - auto const size{std::size(data)}, space{std::size(buffer)}; - auto const needed{internal::size_esc_bin(std::size(data))}; - if (space < needed) - throw range_error{internal::concat( - "Not enough room to escape binary string of ", size, " byte(s): need ", - needed, " bytes of buffer space, but buffer size is ", space, ".")}; - - std::basic_string_view view{std::data(data), std::size(data)}; - auto const out{std::data(buffer)}; - // Actually, in the modern format, we know beforehand exactly how many - // bytes we're going to fill. Just leave out the trailing zero. - internal::esc_bin(view, out); - return zview{out, needed - 1}; - } -#endif - - /// Escape binary string for use as SQL string literal on this connection. - [[deprecated("Use std::byte for binary data.")]] std::string - esc_raw(unsigned char const bin[], std::size_t len) const; - - /// Escape binary string for use as SQL string literal on this connection. - /** You can also just use @ref esc with a binary string. */ - [[nodiscard]] std::string esc_raw(std::basic_string_view) const; - -#if defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - /** You can also just use @ref esc with a binary string. */ - [[nodiscard]] std::string - esc_raw(std::basic_string_view, std::span buffer) const; -#endif - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape binary string for use as SQL string literal on this connection. - /** You can also just use @ref esc with a binary string. */ - template - [[nodiscard]] std::string esc_raw(DATA const &data) const - { - return esc_raw( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - template - [[nodiscard]] zview esc_raw(DATA const &data, std::span buffer) const - { - return this->esc(binary_cast(data), buffer); - } -#endif - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(zview text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return unesc_raw(text.c_str()); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(char const text[]) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - * - * (The data must be encoded in PostgreSQL's "hex" format. The legacy - * "bytea" escape format, used prior to PostgreSQL 9.0, is no longer - * supported.) - */ - [[nodiscard]] std::basic_string - unesc_bin(std::string_view text) const - { - std::basic_string buf; - buf.resize(pqxx::internal::size_unesc_bin(std::size(text))); - pqxx::internal::unesc_bin(text, buf.data()); - return buf; - } - - /// Escape and quote a string of binary data. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(unsigned char const bin[], std::size_t len) const; - - /// Escape and quote a string of binary data. - std::string quote_raw(std::basic_string_view) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape and quote a string of binary data. - /** You can also just use @ref quote with binary data. */ - template - [[nodiscard]] std::string quote_raw(DATA const &data) const - { - return quote_raw( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote an SQL identifier for use in a query. - [[nodiscard]] std::string quote_name(std::string_view identifier) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote a table name. - /** When passing just a table name, this is just another name for - * @ref quote_name. - */ - [[nodiscard]] std::string quote_table(std::string_view name) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote a table path. - /** A table path consists of a table name, optionally prefixed by a schema - * name; and if both are given, they are in turn optionally prefixed by a - * database name. - * - * Each portion of the path (database name, schema name, table name) will be - * quoted separately, and they will be joined together by dots. So for - * example, `myschema.mytable` will become `"myschema"."mytable"`. - */ - [[nodiscard]] std::string quote_table(table_path) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Quote and comma-separate a series of column names. - /** Use this to save a bit of work in cases where you repeatedly need to pass - * the same list of column names, e.g. with @ref stream_to and @ref - * stream_from. Some functions that need to quote the columns list - * internally, will have a "raw" alternative which let you do the quoting - * yourself. It's a bit of extra work, but it can in rare cases let you - * eliminate some duplicate work in quoting them repeatedly. - */ - template - inline std::string quote_columns(STRINGS const &columns) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Represent object as SQL string, including quoting & escaping. - /** - * Recognises nulls and represents them as SQL nulls. They get no quotes. - */ - template - [[nodiscard]] inline std::string quote(T const &t) const; - - [[deprecated("Use std::byte for binary data.")]] std::string - quote(binarystring const &) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote binary data for use as a BYTEA value in SQL statement. - [[nodiscard]] std::string - quote(std::basic_string_view bytes) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape string for literal LIKE match. - /** Use this when part of an SQL "LIKE" pattern should match only as a - * literal string, not as a pattern, even if it contains "%" or "_" - * characters that would normally act as wildcards. - * - * The string does not get string-escaped or quoted. You do that later. - * - * For instance, let's say you have a string `name` entered by the user, - * and you're searching a `file` column for items that match `name` - * followed by a dot and three letters. Even if `name` contains wildcard - * characters "%" or "_", you only want those to match literally, so "_" - * only matches "_" and "%" only matches a single "%". - * - * You do that by "like-escaping" `name`, appending the wildcard pattern - * `".___"`, and finally, escaping and quoting the result for inclusion in - * your query: - * - * ```cxx - * tx.exec( - * "SELECT file FROM item WHERE file LIKE " + - * tx.quote(tx.esc_like(name) + ".___")); - * ``` - * - * The SQL "LIKE" operator also lets you choose your own escape character. - * This is supported, but must be a single-byte character. - */ - [[nodiscard]] std::string - esc_like(std::string_view text, char escape_char = '\\') const; - //@} - - /// Attempt to cancel the ongoing query, if any. - /** You can use this from another thread, and/or while a query is executing - * in a pipeline, but it's up to you to ensure that you're not canceling the - * wrong query. This may involve locking. - */ - void cancel_query(); - -#if defined(_WIN32) || __has_include() - /// Set socket to blocking (true) or nonblocking (false). - /** @warning Do not use this unless you _really_ know what you're doing. - * @warning This function is available on most systems, but not necessarily - * all. - */ - void set_blocking(bool block) &; -#endif // defined(_WIN32) || __has_include() - - /// Set session verbosity. - /** Set the verbosity of error messages to "terse", "normal" (the default), - * or "verbose." - * - * If "terse", returned messages include severity, primary text, and - * position only; this will normally fit on a single line. "normal" produces - * messages that include the above plus any detail, hint, or context fields - * (these might span multiple lines). "verbose" includes all available - * fields. - */ - void set_verbosity(error_verbosity verbosity) &noexcept; - - /// Return pointers to the active errorhandlers. - /** The entries are ordered from oldest to newest handler. - * - * You may use this to find errorhandlers that your application wants to - * delete when destroying the connection. Be aware, however, that libpqxx - * may also add errorhandlers of its own, and those will be included in the - * list. If this is a problem for you, derive your errorhandlers from a - * custom base class derived from pqxx::errorhandler. Then use dynamic_cast - * to find which of the error handlers are yours. - * - * The pointers point to the real errorhandlers. The container it returns - * however is a copy of the one internal to the connection, not a reference. - */ - [[nodiscard]] std::vector get_errorhandlers() const; - - /// Return a connection string encapsulating this connection's options. - /** The connection must be currently open for this to work. - * - * Returns a reconstruction of this connection's connection string. It may - * not exactly match the connection string you passed in when creating this - * connection. - */ - [[nodiscard]] std::string connection_string() const; - - /// Explicitly close the connection. - /** The destructor will do this for you automatically. Still, there is a - * reason to `close()` objects explicitly where possible: if an error should - * occur while closing, `close()` can throw an exception. A destructor - * cannot. - * - * Closing a connection is idempotent. Closing a connection that's already - * closed does nothing. - */ - void close(); - - /// Seize control of a raw libpq connection. - /** @warning Do not do this. Please. It's for very rare, very specific - * use-cases. The mechanism may change (or break) in unexpected ways in - * future versions. - * - * @param raw_conn a raw libpq `PQconn` pointer. - */ - static connection seize_raw_connection(internal::pq::PGconn *raw_conn) - { - return connection{raw_conn}; - } - - /// Release the raw connection without closing it. - /** @warning Do not do this. It's for very rare, very specific use-cases. - * The mechanism may change (or break) in unexpected ways in future versions. - * - * The `connection` object becomes unusable after this. - */ - internal::pq::PGconn *release_raw_connection() && - { - return std::exchange(m_conn, nullptr); - } - -private: - friend class connecting; - enum connect_mode - { - connect_nonblocking - }; - connection(connect_mode, zview connection_string); - - /// For use by @ref seize_raw_connection. - explicit connection(internal::pq::PGconn *raw_conn) : m_conn{raw_conn} {} - - /// Poll for ongoing connection, try to progress towards completion. - /** Returns a pair of "now please wait to read data from socket" and "now - * please wait to write data to socket." Both will be false when done. - * - * Throws an exception if polling indicates that the connection has failed. - */ - std::pair poll_connect(); - - // Initialise based on connection string. - void init(char const options[]); - // Initialise based on parameter names and values. - void init(char const *params[], char const *values[]); - void complete_init(); - - result make_result( - internal::pq::PGresult *pgr, std::shared_ptr const &query, - std::string_view desc = ""sv); - - void PQXX_PRIVATE set_up_state(); - - int PQXX_PRIVATE PQXX_PURE status() const noexcept; - - /// Escape a string, into a buffer allocated by the caller. - /** The buffer must have room for at least `2*std::size(text) + 1` bytes. - * - * Returns the number of bytes written, including the trailing zero. - */ - std::size_t esc_to_buf(std::string_view text, char *buf) const; - - friend class internal::gate::const_connection_largeobject; - char const *PQXX_PURE err_msg() const noexcept; - - void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept; - - result exec_prepared(std::string_view statement, internal::c_params const &); - - /// Throw @ref usage_error if this connection is not in a movable state. - void check_movable() const; - /// Throw @ref usage_error if not in a state where it can be move-assigned. - void check_overwritable() const; - - friend class internal::gate::connection_errorhandler; - void PQXX_PRIVATE register_errorhandler(errorhandler *); - void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept; - - friend class internal::gate::connection_transaction; - result exec(std::string_view, std::string_view = ""sv); - result - PQXX_PRIVATE exec(std::shared_ptr, std::string_view = ""sv); - void PQXX_PRIVATE register_transaction(transaction_base *); - void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept; - - friend class internal::gate::connection_stream_from; - std::pair>, std::size_t> - PQXX_PRIVATE read_copy_line(); - - friend class internal::gate::connection_stream_to; - void PQXX_PRIVATE write_copy_line(std::string_view); - void PQXX_PRIVATE end_copy_write(); - - friend class internal::gate::connection_largeobject; - internal::pq::PGconn *raw_connection() const { return m_conn; } - - friend class internal::gate::connection_notification_receiver; - void add_receiver(notification_receiver *); - void remove_receiver(notification_receiver *) noexcept; - - friend class internal::gate::connection_pipeline; - void PQXX_PRIVATE start_exec(char const query[]); - bool PQXX_PRIVATE consume_input() noexcept; - bool PQXX_PRIVATE is_busy() const noexcept; - internal::pq::PGresult *get_result(); - - friend class internal::gate::connection_dbtransaction; - friend class internal::gate::connection_sql_cursor; - - result exec_params(std::string_view query, internal::c_params const &args); - - /// Connection handle. - internal::pq::PGconn *m_conn = nullptr; - - /// Active transaction on connection, if any. - /** We don't use this for anything, except to check for open transactions - * when we close the connection or start a new transaction. - * - * We also don't allow move construction or move assignment while there's a - * transaction, since moving the connection in that case would leave one or - * more pointers back from the transaction to the connection dangling. - */ - transaction_base const *m_trans = nullptr; - - std::list m_errorhandlers; - - using receiver_list = - std::multimap; - /// Notification receivers. - receiver_list m_receivers; - - /// Unique number to use as suffix for identifiers (see adorn_name()). - int m_unique_id = 0; -}; - - -/// @deprecated Old base class for connection. They are now the same class. -using connection_base = connection; - - -/// An ongoing, non-blocking stepping stone to a connection. -/** Use this when you want to create a connection to the database, but without - * blocking your whole thread. It is only available on systems that have - * the `` header, and Windows. - * - * Connecting in this way is probably not "faster" (it's more complicated and - * has some extra overhead), but in some situations you can use it to make your - * application as a whole faster. It all depends on having other useful work - * to do in the same thread, and being able to wait on a socket. If you have - * other I/O going on at the same time, your event loop can wait for both the - * libpqxx socket and your own sockets, and wake up whenever any of them is - * ready to do work. - * - * Connecting in this way is not properly "asynchronous;" it's merely - * "nonblocking." This means it's not a super-high-performance mechanism like - * you might get with e.g. `io_uring`. In particular, if we need to look up - * the database hostname in DNS, that will happen synchronously. - * - * To use this, create the `connecting` object, passing a connection string. - * Then loop: If @ref wait_to_read returns true, wait for the socket to have - * incoming data on it. If @ref wait_to_write returns true, wait for the - * socket to be ready for writing. Then call @ref process to process any - * incoming or outgoing data. Do all of this until @ref done returns true (or - * there is an exception). Finally, call @ref produce to get the completed - * connection. - * - * For example: - * - * ```cxx - * pqxx::connecting cg{}; - * - * // Loop until we're done connecting. - * while (!cg.done()) - * { - * wait_for_fd(cg.sock(), cg.wait_to_read(), cg.wait_to_write()); - * cg.process(); - * } - * - * pqxx::connection conn = std::move(cg).produce(); - * - * // At this point, conn is a working connection. You can no longer use - * // cg at all. - * ``` - */ -class PQXX_LIBEXPORT connecting -{ -public: - /// Start connecting. - connecting(zview connection_string = ""_zv); - - connecting(connecting const &) = delete; - connecting(connecting &&) = default; - connecting &operator=(connecting const &) = delete; - connecting &operator=(connecting &&) = default; - - /// Get the socket. The socket may change during the connection process. - [[nodiscard]] int sock() const &noexcept { return m_conn.sock(); } - - /// Should we currently wait to be able to _read_ from the socket? - [[nodiscard]] constexpr bool wait_to_read() const &noexcept - { - return m_reading; - } - - /// Should we currently wait to be able to _write_ to the socket? - [[nodiscard]] constexpr bool wait_to_write() const &noexcept - { - return m_writing; - } - - /// Progress towards completion (but don't block). - void process() &; - - /// Is our connection finished? - [[nodiscard]] constexpr bool done() const &noexcept - { - return not m_reading and not m_writing; - } - - /// Produce the completed connection object. - /** Use this only once, after @ref done returned `true`. Once you have - * called this, the `connecting` instance has no more use or meaning. You - * can't call any of its member functions afterwards. - * - * This member function is rvalue-qualified, meaning that you can only call - * it on an rvalue instance of the class. If what you have is not an rvalue, - * turn it into one by wrapping it in `std::move()`. - */ - [[nodiscard]] connection produce() &&; - -private: - connection m_conn; - bool m_reading{false}; - bool m_writing{true}; -}; - - -template inline std::string connection::quote(T const &t) const -{ - if constexpr (nullness::always_null) - { - return "NULL"; - } - else - { - if (is_null(t)) - return "NULL"; - auto const text{to_string(t)}; - - // Okay, there's an easy way to do this and there's a hard way. The easy - // way was "quote, esc(to_string(t)), quote". I'm going with the hard way - // because it's going to save some string manipulation that will probably - // incur some unnecessary memory allocations and deallocations. - std::string buf{'\''}; - buf.resize(2 + 2 * std::size(text) + 1); - auto const content_bytes{esc_to_buf(text, buf.data() + 1)}; - auto const closing_quote{1 + content_bytes}; - buf[closing_quote] = '\''; - auto const end{closing_quote + 1}; - buf.resize(end); - return buf; - } -} - - -template -inline std::string connection::quote_columns(STRINGS const &columns) const -{ - return separated_list( - ","sv, std::cbegin(columns), std::cend(columns), - [this](auto col) { return this->quote_name(*col); }); -} - - -#if defined(PQXX_HAVE_CONCEPTS) -template -inline connection::connection(MAPPING const ¶ms) -{ - check_version(); - - std::vector keys, values; - if constexpr (std::ranges::sized_range) - { - auto const size{std::ranges::size(params) + 1}; - keys.reserve(size); - values.reserve(size); - } - for (auto const &[key, value] : params) - { - keys.push_back(internal::as_c_string(key)); - values.push_back(internal::as_c_string(value)); - } - keys.push_back(nullptr); - values.push_back(nullptr); - init(std::data(keys), std::data(values)); -} -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/cursor b/ext/libpqxx-7.7.3/include/pqxx/cursor deleted file mode 100644 index e20b3a4fa..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/cursor +++ /dev/null @@ -1,8 +0,0 @@ -/** Definition of the iterator/container-style cursor classes. - * - * C++-style wrappers for SQL cursors - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/cursor.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/cursor.hxx b/ext/libpqxx-7.7.3/include/pqxx/cursor.hxx deleted file mode 100644 index b392e2407..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/cursor.hxx +++ /dev/null @@ -1,483 +0,0 @@ -/* Definition of the iterator/container-style cursor classes. - * - * C++-style wrappers for SQL cursors. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_CURSOR -#define PQXX_H_CURSOR - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/result.hxx" -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -/// Common definitions for cursor types -/** In C++ terms, fetches are always done in pre-increment or pre-decrement - * fashion--i.e. the result does not include the row the cursor is on at the - * beginning of the fetch, and the cursor ends up being positioned on the last - * row in the result. - * - * There are singular positions akin to `end()` at both the beginning and the - * end of the cursor's range of movement, although these fit in so naturally - * with the semantics that one rarely notices them. The cursor begins at the - * first of these, but any fetch in the forward direction will move the cursor - * off this position and onto the first row before returning anything. - */ -class PQXX_LIBEXPORT cursor_base -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - - /// Cursor access-pattern policy - /** Allowing a cursor to move forward only can result in better performance, - * so use this access policy whenever possible. - */ - enum access_policy - { - /// Cursor can move forward only - forward_only, - /// Cursor can move back and forth - random_access - }; - - /// Cursor update policy - /** - * @warning Not all PostgreSQL versions support updatable cursors. - */ - enum update_policy - { - /// Cursor can be used to read data but not to write - read_only, - /// Cursor can be used to update data as well as read it - update - }; - - /// Cursor destruction policy - /** The normal thing to do is to make a cursor object the owner of the SQL - * cursor it represents. There may be cases, however, where a cursor needs - * to persist beyond the end of the current transaction (and thus also beyond - * the lifetime of the cursor object that created it!), where it can be - * "adopted" into a new cursor object. See the basic_cursor documentation - * for an explanation of cursor adoption. - * - * If a cursor is created with "loose" ownership policy, the object - * representing the underlying SQL cursor will not take the latter with it - * when its own lifetime ends, nor will its originating transaction. - * - * @warning Use this feature with care and moderation. Only one cursor - * object should be responsible for any one underlying SQL cursor at any - * given time. - */ - enum ownership_policy - { - /// Destroy SQL cursor when cursor object is closed at end of transaction - owned, - /// Leave SQL cursor in existence after close of object and transaction - loose - }; - - cursor_base() = delete; - cursor_base(cursor_base const &) = delete; - cursor_base &operator=(cursor_base const &) = delete; - - /** - * @name Special movement distances. - */ - //@{ - - // TODO: Make constexpr inline (but breaks ABI). - /// Special value: read until end. - /** @return Maximum value for result::difference_type, so the cursor will - * attempt to read the largest possible result set. - */ - [[nodiscard]] static difference_type all() noexcept; - - /// Special value: read one row only. - /** @return Unsurprisingly, 1. - */ - [[nodiscard]] static constexpr difference_type next() noexcept { return 1; } - - /// Special value: read backwards, one row only. - /** @return Unsurprisingly, -1. - */ - [[nodiscard]] static constexpr difference_type prior() noexcept - { - return -1; - } - - // TODO: Make constexpr inline (but breaks ABI). - /// Special value: read backwards from current position back to origin. - /** @return Minimum value for result::difference_type. - */ - [[nodiscard]] static difference_type backward_all() noexcept; - - //@} - - /// Name of underlying SQL cursor - /** - * @returns Name of SQL cursor, which may differ from original given name. - * @warning Don't use this to access the SQL cursor directly without going - * through the provided wrapper classes! - */ - [[nodiscard]] constexpr std::string const &name() const noexcept - { - return m_name; - } - -protected: - cursor_base(connection &, std::string_view Name, bool embellish_name = true); - - std::string const m_name; -}; -} // namespace pqxx - - -#include - - -namespace pqxx -{ -/// "Stateless cursor" class: easy API for retrieving parts of result sets -/** This is a front-end for SQL cursors, but with a more C++-like API. - * - * Actually, stateless_cursor feels entirely different from SQL cursors. You - * don't keep track of positions, fetches, and moves; you just say which rows - * you want. See the retrieve() member function. - */ -template -class stateless_cursor -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - - /// Create cursor. - /** - * @param tx The transaction within which you want to create the cursor. - * @param query The SQL query whose results the cursor should traverse. - * @param cname A hint for the cursor's name. The actual SQL cursor's name - * will be based on this (though not necessarily identical). - * @param hold Create a `WITH HOLD` cursor? Such cursors stay alive after - * the transaction has ended, so you can continue to use it. - */ - stateless_cursor( - transaction_base &tx, std::string_view query, std::string_view cname, - bool hold) : - m_cur{tx, query, cname, cursor_base::random_access, up, op, hold} - {} - - /// Adopt an existing scrolling SQL cursor. - /** This lets you define a cursor yourself, and then wrap it in a - * libpqxx-managed `stateless_cursor` object. - * - * @param tx The transaction within which you want to manage the cursor. - * @param adopted_cursor Your cursor's SQL name. - */ - stateless_cursor(transaction_base &tx, std::string_view adopted_cursor) : - m_cur{tx, adopted_cursor, op} - { - // Put cursor in known position - m_cur.move(cursor_base::backward_all()); - } - - /// Close this cursor. - /** The destructor will do this for you automatically. - * - * Closing a cursor is idempotent. Closing a cursor that's already closed - * does nothing. - */ - void close() noexcept { m_cur.close(); } - - /// Number of rows in cursor's result set - /** @note This function is not const; it may need to scroll to find the size - * of the result set. - */ - [[nodiscard]] size_type size() - { - return internal::obtain_stateless_cursor_size(m_cur); - } - - /// Retrieve rows from begin_pos (inclusive) to end_pos (exclusive) - /** Rows are numbered starting from 0 to size()-1. - * - * @param begin_pos First row to retrieve. May be one row beyond the end of - * the result set, to avoid errors for empty result sets. Otherwise, must be - * a valid row number in the result set. - * @param end_pos Row up to which to fetch. Rows are returned ordered from - * begin_pos to end_pos, i.e. in ascending order if begin_pos < end_pos but - * in descending order if begin_pos > end_pos. The end_pos may be - * arbitrarily inside or outside the result set; only existing rows are - * included in the result. - */ - result retrieve(difference_type begin_pos, difference_type end_pos) - { - return internal::stateless_cursor_retrieve( - m_cur, result::difference_type(size()), begin_pos, end_pos); - } - - /// Return this cursor's name. - [[nodiscard]] constexpr std::string const &name() const noexcept - { - return m_cur.name(); - } - -private: - internal::sql_cursor m_cur; -}; - - -class icursor_iterator; -} // namespace pqxx - - -namespace pqxx::internal::gate -{ -class icursor_iterator_icursorstream; -class icursorstream_icursor_iterator; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Simple read-only cursor represented as a stream of results -/** SQL cursors can be tricky, especially in C++ since the two languages seem - * to have been designed on different planets. An SQL cursor has two singular - * positions akin to `end()` on either side of the underlying result set. - * - * These cultural differences are hidden from view somewhat by libpqxx, which - * tries to make SQL cursors behave more like familiar C++ entities such as - * iterators, sequences, streams, and containers. - * - * Data is fetched from the cursor as a sequence of result objects. Each of - * these will contain the number of rows defined as the stream's stride, except - * of course the last block of data which may contain fewer rows. - * - * This class can create or adopt cursors that live outside any backend - * transaction, which your backend version may not support. - */ -class PQXX_LIBEXPORT icursorstream -{ -public: - using size_type = cursor_base::size_type; - using difference_type = cursor_base::difference_type; - - /// Set up a read-only, forward-only cursor. - /** Roughly equivalent to a C++ Standard Library istream, this cursor type - * supports only two operations: reading a block of rows while moving - * forward, and moving forward without reading any data. - * - * @param context Transaction context in which this cursor will be active. - * @param query SQL query whose results this cursor shall iterate. - * @param basename Suggested name for the SQL cursor; the library will append - * a unique code to ensure its uniqueness. - * @param sstride Number of rows to fetch per read operation; must be a - * positive number. - */ - icursorstream( - transaction_base &context, std::string_view query, - std::string_view basename, difference_type sstride = 1); - - /// Adopt existing SQL cursor. Use with care. - /** Forms a cursor stream around an existing SQL cursor, as returned by e.g. - * a server-side function. The SQL cursor will be cleaned up by the stream's - * destructor as if it had been created by the stream; cleaning it up by hand - * or adopting the same cursor twice is an error. - * - * Passing the name of the cursor as a string is not allowed, both to avoid - * confusion with the other constructor and to discourage unnecessary use of - * adopted cursors. - * - * @warning It is technically possible to adopt a "WITH HOLD" cursor, i.e. a - * cursor that stays alive outside its creating transaction. However, any - * cursor stream (including the underlying SQL cursor, naturally) must be - * destroyed before its transaction context object is destroyed. Therefore - * the only way to use SQL's WITH HOLD feature is to adopt the cursor, but - * defer doing so until after entering the transaction context that will - * eventually destroy it. - * - * @param context Transaction context in which this cursor will be active. - * @param cname Result field containing the name of the SQL cursor to adopt. - * @param sstride Number of rows to fetch per read operation; must be a - * positive number. - * @param op Ownership policy. Determines whether the cursor underlying this - * stream will be destroyed when the stream is closed. - */ - icursorstream( - transaction_base &context, field const &cname, difference_type sstride = 1, - cursor_base::ownership_policy op = cursor_base::owned); - - /// Return `true` if this stream may still return more data. - constexpr operator bool() const &noexcept { return not m_done; } - - /// Read new value into given result object; same as operator `>>`. - /** The result set may continue any number of rows from zero to the chosen - * stride, inclusive. An empty result will only be returned if there are no - * more rows to retrieve. - * - * @param res Write the retrieved data into this result object. - * @return Reference to this very stream, to facilitate "chained" invocations - * ("C.get(r1).get(r2);") - */ - icursorstream &get(result &res) - { - res = fetchblock(); - return *this; - } - /// Read new value into given result object; same as `get(result&)`. - /** The result set may continue any number of rows from zero to the chosen - * stride, inclusive. An empty result will only be returned if there are no - * more rows to retrieve. - * - * @param res Write the retrieved data into this result object. - * @return Reference to this very stream, to facilitate "chained" invocations - * ("C >> r1 >> r2;") - */ - icursorstream &operator>>(result &res) { return get(res); } - - /// Move given number of rows forward without reading data. - /** Ignores any stride that you may have set. It moves by a given number of - * rows, not a number of strides. - * - * @return Reference to this stream itself, to facilitate "chained" - * invocations. - */ - icursorstream &ignore(std::streamsize n = 1) &; - - /// Change stride, i.e. the number of rows to fetch per read operation. - /** - * @param stride Must be a positive number. - */ - void set_stride(difference_type stride) &; - [[nodiscard]] constexpr difference_type stride() const noexcept - { - return m_stride; - } - -private: - result fetchblock(); - - friend class internal::gate::icursorstream_icursor_iterator; - size_type forward(size_type n = 1); - void insert_iterator(icursor_iterator *) noexcept; - void remove_iterator(icursor_iterator *) const noexcept; - - void service_iterators(difference_type); - - internal::sql_cursor m_cur; - - difference_type m_stride; - difference_type m_realpos, m_reqpos; - - mutable icursor_iterator *m_iterators; - - bool m_done; -}; - - -/// Approximate istream_iterator for icursorstream. -/** Intended as an implementation of an input_iterator (as defined by the C++ - * Standard Library), this class supports only two basic operations: reading - * the current element, and moving forward. In addition to the minimal - * guarantees for istream_iterators, this class supports multiple successive - * reads of the same position (the current result set is cached in the - * iterator) even after copying and even after new data have been read from the - * stream. This appears to be a requirement for input_iterators. Comparisons - * are also supported in the general case. - * - * The iterator does not care about its own position, however. Moving an - * iterator forward moves the underlying stream forward and reads the data from - * the new stream position, regardless of the iterator's old position in the - * stream. - * - * The stream's stride defines the granularity for all iterator movement or - * access operations, i.e. "ici += 1" advances the stream by one stride's worth - * of rows, and "*ici++" reads one stride's worth of rows from the stream. - * - * @warning Do not read from the underlying stream or its cursor, move its read - * position, or change its stride, between the time the first icursor_iterator - * on it is created and the time its last icursor_iterator is destroyed. - * - * @warning Manipulating these iterators within the context of a single cursor - * stream is not thread-safe. Creating a new iterator, copying one, - * or destroying one affects the stream as a whole. - */ -class PQXX_LIBEXPORT icursor_iterator -{ -public: - using iterator_category = std::input_iterator_tag; - using value_type = result; - using pointer = result const *; - using reference = result const &; - using istream_type = icursorstream; - using size_type = istream_type::size_type; - using difference_type = istream_type::difference_type; - - icursor_iterator() noexcept; - explicit icursor_iterator(istream_type &) noexcept; - icursor_iterator(icursor_iterator const &) noexcept; - ~icursor_iterator() noexcept; - - result const &operator*() const - { - refresh(); - return m_here; - } - result const *operator->() const - { - refresh(); - return &m_here; - } - icursor_iterator &operator++(); - icursor_iterator operator++(int); - icursor_iterator &operator+=(difference_type); - icursor_iterator &operator=(icursor_iterator const &) noexcept; - - [[nodiscard]] bool operator==(icursor_iterator const &rhs) const; - [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept - { - return not operator==(rhs); - } - [[nodiscard]] bool operator<(icursor_iterator const &rhs) const; - [[nodiscard]] bool operator>(icursor_iterator const &rhs) const - { - return rhs < *this; - } - [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const - { - return not(*this > rhs); - } - [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const - { - return not(*this < rhs); - } - -private: - void refresh() const; - - friend class internal::gate::icursor_iterator_icursorstream; - difference_type pos() const noexcept { return m_pos; } - void fill(result const &); - - icursorstream *m_stream{nullptr}; - result m_here; - difference_type m_pos; - icursor_iterator *m_prev{nullptr}, *m_next{nullptr}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/dbtransaction b/ext/libpqxx-7.7.3/include/pqxx/dbtransaction deleted file mode 100644 index fa8d26476..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/dbtransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::dbtransaction abstract base class. - * - * pqxx::dbransaction defines a real transaction on the database. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/dbtransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/dbtransaction.hxx b/ext/libpqxx-7.7.3/include/pqxx/dbtransaction.hxx deleted file mode 100644 index d85cb170f..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/dbtransaction.hxx +++ /dev/null @@ -1,70 +0,0 @@ -/* Definition of the pqxx::dbtransaction abstract base class. - * - * pqxx::dbransaction defines a real transaction on the database. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_DBTRANSACTION -#define PQXX_H_DBTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/transaction_base.hxx" - -namespace pqxx -{ -/// Abstract transaction base class: bracket transactions on the database. -/** - * @ingroup transactions - * - * Use a dbtransaction-derived object such as "work" (transaction<>) to enclose - * operations on a database in a single "unit of work." This ensures that the - * whole series of operations either succeeds as a whole or fails completely. - * In no case will it leave half-finished work behind in the database. - * - * Once processing on a transaction has succeeded and any changes should be - * allowed to become permanent in the database, call commit(). If something - * has gone wrong and the changes should be forgotten, call abort() instead. - * If you do neither, an implicit abort() is executed at destruction time. - * - * It is an error to abort a transaction that has already been committed, or to - * commit a transaction that has already been aborted. Aborting an already - * aborted transaction or committing an already committed one is allowed, to - * make error handling easier. Repeated aborts or commits have no effect after - * the first one. - * - * Database transactions are not suitable for guarding long-running processes. - * If your transaction code becomes too long or too complex, consider ways to - * break it up into smaller ones. Unfortunately there is no universal recipe - * for this. - * - * The actual operations for committing/aborting the backend transaction are - * implemented by a derived class. The implementing concrete class must also - * call @ref close from its destructor. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base -{ -protected: - /// Begin transaction. - explicit dbtransaction(connection &c) : transaction_base{c} {} - /// Begin transaction. - dbtransaction(connection &c, std::string_view tname) : - transaction_base{c, tname} - {} - /// Begin transaction. - dbtransaction( - connection &c, std::string_view tname, - std::shared_ptr rollback_cmd) : - transaction_base{c, tname, rollback_cmd} - {} -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/accessing-results.md b/ext/libpqxx-7.7.3/include/pqxx/doc/accessing-results.md deleted file mode 100644 index 920fb6f3b..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/accessing-results.md +++ /dev/null @@ -1,157 +0,0 @@ -Accessing results and result rows {#accessing-results} ---------------------------------- - -When you execute a query using one of the transaction `exec` functions, you -normally get a `result` object back. A `result` is a container of `row`s. - -(There are exceptions. The `exec1` functions expect exactly one row of data, -so they return just a `row`, not a full `result`.) - -Result objects are an all-or-nothing affair. The `exec` function waits until -it's received all the result data, and then gives it to you in the form of the -`result`. _(There is a faster, easier way of executing simple queries, so see -"streaming rows" below as well.)_ - -For example, your code might do: - -```cxx - pqxx::result r = tx.exec("SELECT * FROM mytable"); -``` - -Now, how do you access the data inside `r`? - -Result sets act as standard C++ containers of rows. Rows act as standard -C++ containers of fields. So the easiest way to go through them is: - -```cxx - for (auto const &row: r) - { - for (auto const &field: row) std::cout << field.c_str() << '\t'; - std::cout << '\n'; - } -``` - -But results and rows also support other kinds of access. Array-style -indexing, for instance, such as `r[rownum]`: - -```cxx - std::size_t const num_rows = std::size(r); - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - pqxx::row const row = r[rownum]; - std::size_t const num_cols = std::size(row); - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - { - pqxx::field const field = row[colnum]; - std::cout << field.c_str() << '\t'; - } - - std::cout << '\n'; - } -``` - -Every row in the result has the same number of columns, so you don't need to -look up the number of fields again for each one: - -```cxx - std::size_t const num_rows = std::size(r); - std::size_t const num_cols = r.columns(); - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - pqxx::row const row = r[rownum]; - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - { - pqxx::field const field = row[colnum]; - std::cout << field.c_str() << '\t'; - } - - std::cout << '\n'; - } -``` - -You can even address a field by indexing the `row` using the field's _name:_ - -```cxx - std::cout << row["salary"] << '\n'; -``` - -But try not to do that if speed matters, because looking up the column by name -takes time. At least you'd want to look up the column index before your loop -and then use numerical indexes inside the loop. - -For C++23 or better, there's also a two-dimensional array access operator: - -```cxx - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - std::cout result[rownum, colnum].c_str() << '\t'; - std::cout << '\n'; - } -``` - -And of course you can use classic "begin/end" loops: - -```cxx - for (auto row = std::begin(r); row != std::end(r); row++) - { - for (auto field = std::begin(row); field != std::end(row); field++) - std::cout << field->c_str() << '\t'; - std::cout << '\n'; - } -``` - -Result sets are immutable, so all iterators on results and rows are actually -`const_iterator`s. There are also `const_reverse_iterator` types, which -iterate backwards from `rbegin()` to `rend()` exclusive. - -All these iterator types provide one extra bit of convenience that you won't -normally find in C++ iterators: referential transparency. You don't need to -dereference them to get to the row or field they refer to. That is, instead -of `row->end()` you can also choose to say `row.end()`. Similarly, you -may prefer `field.c_str()` over `field->c_str()`. - -This becomes really helpful with the array-indexing operator. With regular -C++ iterators you would need ugly expressions like `(*row)[0]` or -`row->operator[](0)`. With the iterator types defined by the result and -row classes you can simply say `row[0]`. - - -Streaming rows --------------- - -There's another way to go through the rows coming out of a query. It's -usually easier and faster, but there are drawbacks. - -**One,** you start getting rows before all the data has come in from the -database. That speeds things up, but what happens if you lose your network -connection while transferring the data? Your application may already have -processed some of the data before finding out that the rest isn't coming. If -that is a problem for your application, streaming may not be the right choice. - -**Two,** streaming only works for some types of query. The `stream()` function -wraps your query in a PostgreSQL `COPY` command, and `COPY` only supports a few -commands: `SELECT`, `VALUES`, `or an `INSERT`, `UPDATE`, or `DELETE` with a -`RETURNING` clause. See the `COPY` documentation here: -https://www.postgresql.org/docs/current/sql-copy.html - -**Three,** when you convert a field to a "view" type (such as -`std::string_view` or `std::basic_string_view`), the view points to -underlying data which only stays valid until you iterate to the next row or -exit the loop. So if you want to use that data for longer than a single -iteration of the streaming loop, you'll have to store it somewhere yourself. - -Now for the good news. Streaming does make it very easy to query data and loop -over it: - -```cxx - for (auto [id, name, x, y] : - tx.stream( - "SELECT id, name, x, y FROM point")) - process(id + 1, "point-" + name, x * 10.0, y * 10.0); -``` - -The conversion to C++ types (here `int`, `std::string_view`, and two `float`s) -is built into the function. You never even see `row` objects, `field` objects, -iterators, or conversion methods. You just put in your query and you receive -your data. diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/binary-data.md b/ext/libpqxx-7.7.3/include/pqxx/doc/binary-data.md deleted file mode 100644 index 20da8dc0c..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/binary-data.md +++ /dev/null @@ -1,56 +0,0 @@ -Binary data {#binary} -=========== - -The database has two ways of storing binary data: `BYTEA` is like a string, but -containing bytes rather than text characters. And _large objects_ are more -like a separate table containing binary objects. - -Generally you'll want to use `BYTEA` for reasonably-sized values, and large -objects for very large values. - -That's the database side. On the C++ side, in libpqxx, all binary data must be -either `std::basic_string` or `std::basic_string_view`; -or if you're building in C++20 or better, anything that's a block of -contiguous `std::byte` in memory. - -So for example, if you want to write a large object, you'd create a -`pqxx::blob` object. And you might use that to write data in the form of -`std::basic_string_view`. - -Your particular binary data may look different though. You may have it in a -`std::string`, or a `std::vector`, or a pointer to `char` -accompanied by a size (which could be signed or unsigned, and of any of a few -different widths). Sometimes that's your choice, or sometimes some other -library will dictate what form it takes. - -So long as it's _basically_ still a block of bytes though, you can use -`pqxx::binary_cast` to construct a `std::basic_string_view` from it. - -There are two forms of `binary_cast`. One takes a single argument that must -support `std::data()` and `std::size()`: - - std::string hi{"Hello binary world"}; - my_blob.write(pqxx::binary_cast(hi); - -The other takes a pointer and a size: - - char const greeting[] = "Hello binary world"; - char const *hi = greeting; - my_blob.write(pqxx::binary_cast(hi, sizeof(greeting))); - - -Caveats -------- - -There are some restrictions on `binary_cast` that you must be aware of. - -First, your data must of a type that gives us _bytes._ So: `char`, -`unsigned char`, `signed char`, `int8_t`, `uint8_t`, or of course `std::byte`. -You can't feed in a vector of `double`, or anything like that. - -Second, the data must be laid out as a contiguous block in memory. If there's -no `std::data()` implementation for your type, it's not suitable. - -Third, `binary_cast` only constructs something like a `std::string_view`. It -does not make a copy of your actual data. So, make sure that your data remains -alive and in the same place while you're using it. diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/datatypes.md b/ext/libpqxx-7.7.3/include/pqxx/doc/datatypes.md deleted file mode 100644 index bc14c8b90..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/datatypes.md +++ /dev/null @@ -1,373 +0,0 @@ -Supporting additional data types {#datatypes} -================================ - -Communication with the database mostly happens in a text format. When you -include an integer value in a query, you use `to_string` to convert it to that -text format. When you get a query result field "as a float," it converts from -the text format to a floating-point type. These conversions are everywhere in -libpqxx. - -The conversion sydstem supports many built-in types, but it is also extensible. -You can "teach" libpqxx (in the scope of your own application) to convert -additional types of values to and from PostgreSQL's string format. - -This is massively useful, but it's not for the faint of heart. You'll need to -specialise some templates. And, **the API for doing this can change with any -major libpqxx release.** - - -Converting types ----------------- - -In your application, a conversion is driven entirely by a C++ type you specify. -The value's SQL type has nothing to do with it, nor is there anything in the -string that would identify its type. - -So, if you've SELECTed a 64-bit integer from the database, and you try to -convert it to a C++ "short," one of two things will happen: either the number -is small enough to fit in your `short` (and it just works), or else it throws a -conversion exception. - -Or, your database table might have a text column, but a given field may contain -a string that _looks_ just like a number. You can convert that value to an -integer type just fine. Or to a floating-point type. All that matters to the -conversion is the actual value, and the type. - -In some cases the templates for these conversions can tell the type from the -arguments you pass them: - - auto x = to_string(99); - -In other cases you may need to instantiate template explicitly: - - auto y = from_string("99"); - - -Supporting a new type ---------------------- - -Let's say you have some other SQL type which you want to be able to store in, -or retrieve from, the database. What would it take to support that? - -Sometimes you do not need _complete_ support. You might need a conversion _to_ -a string but not _from_ a string, for example. The conversion is defined at -compile time, so don't be too afraid to be incomplete. If you leave out one of -these steps, it's not going to crash at run time or mess up your data. The -worst that can happen is that your code won't build. - -So what do you need for a complete conversion? - -First off, of course, you need a C++ type. It may be your own, but it -doesn't have to be. It could be a type from a third-party library, or even one -from the standard library that libpqxx does not yet support. - -You also specialise the `pqxx::type_name` variable to specify the type's name. -This is important for all code which mentions your type in human-readable text, -such as error messages. - -Then, does your type have a built-in null value? You specialise the -`pqxx::nullness` template to specify the details. - -Finally, you specialise the `pqxx::string_traits` template. This is where you -define the actual conversions. - -Let's go through these steps one by one. - - -Your type ---------- - -You'll need a type for which the conversions are not yet defined, because the -C++ type is what determines the right conversion. One type, one set of -conversions. - -The type doesn't have to be one that you create. The conversion logic was -designed such that you can build it around any type. So you can just as -easily build a conversion for a type that's defined somewhere else. There's -no need to include any special methods or other members inside it. That's also -how libpqxx can support converting built-in types like `int`. - -By the way, if the type is an enum, you don't need to do any of this. Just -invoke the preprocessor macro `PQXX_DECLARE_ENUM_CONVERSION`, from the global -namespace near the top of your translation unit, and pass the type as an -argument. - -The library also provides specialisations for `std::optional`, -`std::shared_ptr`, and `std::unique_ptr`. If you have conversions for -`T`, you'll also have conversions for those. - - -Specialise `type_name` ----------------------- - -When errors happen during conversion, libpqxx will compose error messages for -the user. Sometimes these will include the name of the type that's being -converted. - -To tell libpqxx the name of each type, there's a template variable called -`pqxx::type_name`. For any given type `T`, it should have a specialisation -that provides that `T`'s human-readable name: - - namespace pqxx - { - template<> std::string const type_name{"T"}; - } - -(Yes, this means that you need to define something inside the pqxx namespace. -Future versions of libpqxx may move this into a separate namespace.) - -Define this early on in your translation unit, before any code that might cause -libpqxx to need the name. That way, the libpqxx code which needs to know the -type's name can see your definition. - - -Specialise `nullness` ---------------------- - -A struct template `pqxx::nullness` defines whether your type has a natural -"null value" built in. If so, it also provides member functions for producing -and recognising null values. - -The simplest scenario is also the most common: most types don't have a null -value built in. In that case, derive your nullness traits from -`pqxx::no_null`: - - namespace pqxx - { - template<> struct nullness : pqxx::no_null {}; - } - -(Here again you're defining this in the pqxx namespace.) - -If your type does have a natural null value, the definition gets a little more -complex: - - namespace pqxx - { - template<> struct nullness - { - static constexpr bool has_null{true}; - static constexpr bool always_null{false}; - - static bool is_null(T const &value) - { - // Return whether "value" is null. - return ...; - } - - [[nodiscard]] static T null() - { - // Return a null value. - return ...; - } - }; - } - -You may be wondering why there's a function to produce a null value, but also a -function to check whether a value is null. Why not just compare the value to -the result of `null()`? Because two null values may not be equal. `T` may -have several different null values. Or it may override the comparison -operator, similar to SQL where NULL is not equal to NULL. - -As a third case, your type may be one that _always_ represents a null value. -This is the case for `std::nullptr_t` and `std::nullopt_t`. In that case, you -set `nullness::always_null` to `true` (as well as `has_null` of course), -and you won't need to define any actual conversions. - - -Specialise `string_traits` -------------------------- - -This part is more work. (You can skip it for types that are _always_ null, -but those will be rare.) Specialise the `pqxx::string_traits` template: - - namespace pqxx - { - template<> struct string_traits - { - static T from_string(std::string_view text); - static zview to_buf(char *begin, char *end, T const &value); - static char *into_buf(char *begin, char *end, T const &value); - static std::size_t size_buffer(T const &value) noexcept; - }; - } - -You'll also need to write those member functions, or as many of them as needed -to get your code to build. - - -### `from_string` - -We start off simple: `from_string` parses a string as a value of `T`, and -returns that value. - -The string may not be zero-terminated; it's just the `string_view` from -beginning to end (exclusive). In your tests, cover cases where the string -does not end in a zero byte. - -It's perfectly possible that the string isn't actually a `T` value. Mistakes -happen. In that case, throw a `pqxx::conversion_error`. - -(Of course it's also possible that you run into some other error, so it's fine -to throw different exceptions as well. But when it's definitely "this is not -the right format for a `T`," throw `conversion_error`.) - - -### `to_buf` - -In this function, you convert a value of `T` into a string that the postgres -server will understand. - -The caller will provide you with a buffer where you can write the string, if -you need it: from `begin` to `end` exclusive. It's a half-open interval, so -don't access `*end`. - -If the buffer is insufficient for you to do the conversion, throw a -`pqxx::conversion_overrun`. It doesn't have to be exact: you can be a little -pessimistic and demand a bit more space than you need. Just be sure to throw -the exception if there's any risk of overrunning the buffer. - -You don't _have_ to use the buffer for this function though. For example, -`pqxx::string_traits::to_buf` returns a compile-time constant string and -ignores the buffer. - -Even if you do use the buffer, your string does not _have_ to start at the -beginning of the buffer. For example, the integer conversions start by writing -the _least_ significant digit to the _end_ of the buffer, and then writes the -more significant digits before it. It was just more convenient. - -Return a `pqxx::zview`. This is basically a `std::string_view`, but with one -difference: a `zview` guarantees that there will be a valid zero byte right -after the `string_view`. The zero byte is not counted as part of its size, but -it will be there. - -Expressed in code, this rule must hold: - - void invariant(zview z) - { - assert(z[std::size(z)] == 0); - } - -Make sure you write your trailing zero _before_ the `end`. If the trailing -zero doesn't fit in the buffer, then there's just not enough room to perform -the conversion. - -Beware of locales when converting. If you use standard library features like -`sprintf`, they may obey whatever locale is currently set on the system. That -means that a simple integer like 1000000 may come out as "1000000" on your -system, but as "1,000,000" on mine, or as "1.000.000" for somebody else, and on -an Indian system it may be "1,00,000". Values coming from or going to the -database should be in non-localised formats. You can use libpqxx functions for -those conversions: `pqxx::from_string`, `pqxx::to_string`, `pqxx::to_buf`. - - -### `into_buf` - -This is a stricter version of `to_buf`. All the same requirements apply, but -in addition you must write your string into the buffer provided, starting -_exactly_ at `begin`. - -That's why this function returns just a simple pointer: the address right -behind the trailing zero. If the caller wants to use the string, they can -find it at `begin`. If they want to write a different value into the rest of -the buffer, they can start at the location you returned. - - -### `size_buffer` - -Here you estimate how much buffer space you need for converting a `T` to a -string. Be precise if you can, but pessimistic if you must. It's usually -better to waste a few unnecessary bytes than to spend a lot of time computing -the exact buffer space you need. And failing the conversion because you -under-budgeted the buffer is worst of all. - -Include the trailing zero in the buffer size. If your `to_buf` takes more -space than just what's needed to store the result, include that too. - -Make `size_buffer` a `constexpr` function if you can. It can allow the caller -to allocate the buffer on the stack, with a size known at compile time. - - -Optional: Specialise `is_unquoted_safe` ---------------------------------------- - -When converting arrays or composite values to strings, libpqxx may need to -quote values and escape any special characters. This takes time. - -Some types though, such as integral or floating-point types, can never have -any special characters such as quotes, commas, or backslashes in their string -representations. In such cases, there's no need to quote or escape such values -in arrays or composite types. - -If your type is like that, you can tell libpqxx about this by defining: - - namespace pqxx - { - template<> inline constexpr bool is_unquoted_safe{true}; - } - -The code that converts this type of field to strings in an array or a composite -type can then use a simpler, more efficient variant of the code. It's always -safe to leave this out; it's _just_ an optimisation for when you're completely -sure that it's safe. - -Do not do this if a string representation of your type may contain a comma; -semicolon; parenthesis; brace; quote; backslash; newline; or any other -character that might need escaping. - - -Optional: Specialise `param_format` ------------------------------------ - -This one you don't generally need to worry about. Read on if you're writing a -type which represents raw binary data, or if you're writing a template where -_some specialisations_ may contain raw binary data. - -When you call parameterised statements, or prepared statements with parameters, -libpqxx needs to your parameters on to libpq, the underlying C-level PostgreSQL -client library. - -There are two formats for doing that: _text_ and _binary._ In the first, we -represent all values as strings, and the server then converts them into its own -internal binary representation. That's what the string conversions are all -about, and it's what we do for almost all types of parameters. - -But we do it differently when the parameter is a contiguous series of raw bytes -and the corresponding SQL type is `BYTEA`. There is a text format for those, -but we bypass it for efficiency. The server can use the binary data in the -exact same form, without any conversion or extra processing. The binary data -is also twice as compact during transport. - -(People sometimes ask why we can't just treat all types as binary. However the -general case isn't so clear-cut. The binary formats are not documented, there -are no guarantees that they will be platform-independent or that they will -remain stable, and there's no really solid way to detect when we might get the -format wrong. But also, the conversions aren't necessarily as straightforward -and efficient as they sound. So, for the general case, libpqxx sticks with the -text formats. Raw binary data alone stands out as a clear win.) - -Long story short, the machinery for passing parameters needs to know: is this -parameter a binary string, or not? In the normal case it can assume "no," and -that's what it does. The text format is always a safe choice; we just try to -use the binary format where it's faster. - -The `param_format` function template is what makes the decision. We specialise -it for types which may be binary strings, and use the default for all other -types. - -"Types which _may_ be binary"? You might think we know whether a type is a -binary type or not. But there are some complications with generic types. - -Templates like `std::shared_ptr`, `std::optional`, and so on act like -"wrappers" for another type. A `std::optional` is binary if `T` is binary. -Otherwise, it's not. If you're building support for a template of this nature, -you'll probably want to implement `param_format` for it. - -The decision to use binary format is made based on a given object, not -necessarily based on the type in general. Look at `std::variant`. If you have -a `std::variant` type which can hold an `int` or a binary string, is that a -binary parameter? We can't decide without knowing the individual object. - -Containers are another hard case. Should we pass `std::vector` in binary? -Even when `T` is a binary type, we don't currently have any way to pass an -array in binary format, so we always pass it as text. diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/escaping.md b/ext/libpqxx-7.7.3/include/pqxx/doc/escaping.md deleted file mode 100644 index 2ad9fe3db..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/escaping.md +++ /dev/null @@ -1,74 +0,0 @@ -String escaping {#escaping} -=============== - -Writing queries as strings is easy. But sometimes you need a variable in -there: `"SELECT id FROM user WHERE name = '" + name + "'"`. - -This is dangerous. See the bug? If `name` can contain quotes, you may have -an SQL injection vulnerability there, where users can enter nasty stuff like -"`.'; DROP TABLE user`". Or if you're lucky, it's just a nasty bug that you -discover when `name` happens to be "d'Arcy". - -So, you'll need to _escape_ the `name` before you insert it. This is where -quotes and other problematic characters are marked as "this is just a character -in the string, not the end of the string." There are -[several functions](@ref escaping-functions) in libpqxx to do this for you. - - -SQL injection -------------- - -To understand what SQL injection vulnerabilities are and why they should be -prevented, imagine you use the following SQL statement somewhere in your -program: - - TX.exec( - "SELECT number,amount " - "FROM accounts " - "WHERE allowed_to_see('" + userid + "','" + password + "')"); - -This shows a logged-in user important information on all accounts he is -authorized to view. The userid and password strings are variables entered -by the user himself. - -Now, if the user is actually an attacker who knows (or can guess) the -general shape of this SQL statement, imagine he enters the following -password: - - x') OR ('x' = 'x - -Does that make sense to you? Probably not. But if this is inserted into -the SQL string by the C++ code above, the query becomes: - - SELECT number,amount - FROM accounts - WHERE allowed_to_see('user','x') OR ('x' = 'x') - -Is this what you wanted to happen? Probably not! The neat `allowed_to_see()` -clause is completely circumvented by the "`OR ('x' = 'x')`" clause, which is -always `true`. Therefore, the attacker will get to see all accounts in the -database! - - -Using the esc functions ------------------------ - -Here's how you can fix the problem in the example above: - - TX.exec( - "SELECT number,amount " - "FROM accounts " - "WHERE allowed_to_see('" + TX.esc(userid) + "', " - "'" + TX.esc(password) + "')"); - -Now, the quotes embedded in the attacker's string will be neatly escaped so -they can't "break out" of the quoted SQL string they were meant to go into: - - SELECT number,amount - FROM accounts - WHERE allowed_to_see('user', 'x'') OR (''x'' = ''x') - -If you look carefully, you'll see that thanks to the added escape characters -(a single-quote is escaped in SQL by doubling it) all we get is a very -strange-looking password string--but not a change in the SQL statement. - diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/getting-started.md b/ext/libpqxx-7.7.3/include/pqxx/doc/getting-started.md deleted file mode 100644 index 1b87b881f..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/getting-started.md +++ /dev/null @@ -1,142 +0,0 @@ -Getting started {#getting-started} -=============== - -The most basic three types in libpqxx are the _connection_, the _transaction_, -and the _result_. - -They fit together as follows: -* You connect to the database by creating a `pqxx::connection` object (see - @ref connections). - -* You create a transaction object (see @ref transactions) operating on that - connection. You'll usually want the `pqxx::work` variety. - - Once you're done you call the transaction's `commit` function to make its - work final. If you don't call this, the work will be rolled back when the - transaction object is destroyed. - -* Until then, use the transaction's `exec`, `query_value`, and `stream` - functions (and variants) to execute SQL statements. You pass the statements - themselves in as simple strings. (See @ref streams for more about data - streaming). - -* Most of the `exec` functions return a `pqxx::result` object, which acts - as a standard container of rows: `pqxx::row`. - - Each row in a result, in turn, acts as a container of fields: `pqxx::field`. - See @ref accessing-results for more about results, rows, and fields. - -* Each field's data is stored internally as a text string, in a format defined - by PostgreSQL. You can convert field or row values using their `as()` and - `to()` member functions. - -* After you've closed the transaction, the connection is free to run a next - transaction. - -Here's a very basic example. It connects to the default database (you'll -need to have one set up), queries it for a very simple result, converts it to -an `int`, and prints it out. It also contains some basic error handling. - - #include - #include - - int main() - { - try - { - // Connect to the database. In practice we may have to pass some - // arguments to say where the database server is, and so on. - // The constructor parses options exactly like libpq's - // PQconnectdb/PQconnect, see: - // https://www.postgresql.org/docs/10/static/libpq-connect.html - pqxx::connection c; - - // Start a transaction. In libpqxx, you always work in one. - pqxx::work w(c); - - // work::exec1() executes a query returning a single row of data. - // We'll just ask the database to return the number 1 to us. - pqxx::row r = w.exec1("SELECT 1"); - - // Commit your transaction. If an exception occurred before this - // point, execution will have left the block, and the transaction will - // have been destroyed along the way. In that case, the failed - // transaction would implicitly abort instead of getting to this point. - w.commit(); - - // Look at the first and only field in the row, parse it as an integer, - // and print it. - // - // "r[0]" returns the first field, which has an "as<...>()" member - // function template to convert its contents from their string format - // to a type of your choice. - std::cout << r[0].as() << std::endl; - } - catch (std::exception const &e) - { - std::cerr << e.what() << std::endl; - return 1; - } - } - -This prints the number 1. Notice that you can keep the result object around -after you've closed the transaction or even the connection. There are -situations where you can't do it, but generally it's fine. If you're -interested: you can install your own callbacks for receiving error messages -from the database, and in that case you'll have to keep the connection object -alive. But otherwise, it's nice to be able to "fire and forget" your -connection and deal with the data. - -You can also convert an entire row to a series of C++-side types in one go, -using the @c as member function on the row: - - pqxx::connection c; - pqxx::work w(c); - pqxx::row r = w.exec1("SELECT 1, 2, 'Hello'"); - auto [one, two, hello] = r.as(); - std::cout << (one + two) << ' ' << std::strlen(hello) << std::endl; - -Here's a slightly more complicated example. It takes an argument from the -command line and retrieves a string with that value. The interesting part is -that it uses the escaping-and-quoting function `quote` to embed this -string value in SQL safely. It also reads the result field's value as a -plain C-style string using its `c_str` function. - - #include - #include - #include - - int main(int argc, char *argv[]) - { - try - { - if (!argv[1]) throw std::runtime_error("Give me a string!"); - - pqxx::connection c; - pqxx::work w(c); - - // work::exec() returns a full result set, which can consist of any - // number of rows. - pqxx::result r = w.exec("SELECT " + w.quote(argv[1])); - - // End our transaction here. We can still use the result afterwards. - w.commit(); - - // Print the first field of the first row. Read it as a C string, - // just like std::string::c_str() does. - std::cout << r[0][0].c_str() << std::endl; - } - catch (std::exception const &e) - { - std::cerr << e.what() << std::endl; - return 1; - } - } - -You can find more about converting field values to native types, or -converting values to strings for use with libpqxx, under -@ref stringconversion. More about getting to the rows and fields of a -result is under @ref accessing-results. - -If you want to handle exceptions thrown by libpqxx in more detail, for -example to print the SQL contents of a query that failed, see @ref exception. diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/mainpage.md b/ext/libpqxx-7.7.3/include/pqxx/doc/mainpage.md deleted file mode 100644 index 5d4b8f9b2..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/mainpage.md +++ /dev/null @@ -1,28 +0,0 @@ -libpqxx {#mainpage} -======= - -@version 7.7.3 -@author Jeroen T. Vermeulen -@see http://pqxx.org -@see https://github.com/jtv/libpqxx - -Welcome to libpqxx, the C++ API to the PostgreSQL database management system. - -Compiling this package requires PostgreSQL to be installed -- including the -C headers for client development. The library builds on top of PostgreSQL's -standard C API, libpq. The libpq headers are not needed to compile client -programs, however. - -For a quick introduction to installing and using libpqxx, see the README.md -file. The latest information can be found at http://pqxx.org/ - - -Some links that should help you find your bearings: -* @ref getting-started -* @ref thread-safety -* @ref connections -* @ref transactions -* @ref escaping -* @ref performance -* @ref transactor -* @ref datatypes diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/mainpage.md.template b/ext/libpqxx-7.7.3/include/pqxx/doc/mainpage.md.template deleted file mode 100644 index d5afb2427..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/mainpage.md.template +++ /dev/null @@ -1,28 +0,0 @@ -libpqxx {#mainpage} -======= - -@version @PQXXVERSION@ -@author Jeroen T. Vermeulen -@see http://pqxx.org -@see https://github.com/jtv/libpqxx - -Welcome to libpqxx, the C++ API to the PostgreSQL database management system. - -Compiling this package requires PostgreSQL to be installed -- including the -C headers for client development. The library builds on top of PostgreSQL's -standard C API, libpq. The libpq headers are not needed to compile client -programs, however. - -For a quick introduction to installing and using libpqxx, see the README.md -file. The latest information can be found at http://pqxx.org/ - - -Some links that should help you find your bearings: -* @ref getting-started -* @ref thread-safety -* @ref connections -* @ref transactions -* @ref escaping -* @ref performance -* @ref transactor -* @ref datatypes diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/parameters.md b/ext/libpqxx-7.7.3/include/pqxx/doc/parameters.md deleted file mode 100644 index 7ac792025..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/parameters.md +++ /dev/null @@ -1,90 +0,0 @@ -Statement parameters {#parameters} -==================== - -When you execute a prepared statement (see @ref prepared), or a parameterised -statement (using functions like `pqxx::connection::exec_params`), you may write -special _placeholders_ in the query text. They look like `$1`, `$2`, and so -on. - -If you execute the query and pass parameter values, the call will respectively -substitute the first where it finds `$1`, the second where it finds `$2`, et -cetera. - -Doing this saves you work. If you don't use statement parameters, you'll need -to quote and escape your values (see `connection::quote()` and friends) as you -insert them into your query as literal values. - -Or if you forget to do that, you leave yourself open to horrible -[SQL injection attacks](https://xkcd.com/327/). Trust me, I was born in a town -whose name started with an apostrophe! - -Statement parameters save you this work. With these parameters you can pass -your values as-is, and they will go across the wire to the database in a safe -format. - -In some cases it may even be faster! When a parameter represents binary data -(as in the SQL `BYTEA` type), libpqxx will send it directly as binary, which is -a bit more efficient. If you insert the binary data directly in your query -text, your CPU will have some extra work to do, converting the data into a text -format, escaping it, and adding quotes. - - -Dynamic parameter lists ------------------------ - -In rare cases you may just not know how many parameters you'll pass into your -statement when you call it. - -For these situations, have a look at `params`. It lets you compose your -parameters list on the fly, even add whole ranges of parameters at a time. - -You can pass a `params` into your statement as a normal parameter. It will -fill in all the parameter values it contains into that position of the -statement's overall parameter list. - -So if you call your statement passing a regular parameter `a`, a -`params` containing just a parameter `b`, and another regular parameter `c`, -then your call will pass parameters `a`, `b`, and `c`. Or if the params object -is empty, it will pass just `a` and `c`. If the params object contains `x` and -`y`, your call will pass `a, x, y, c`. - -You can mix static and dynamic parameters freely. Don't go overboard though: -complexity is where bugs happen! - - -Generating placeholders ------------------------ - -If your code gets particularly complex, it may sometimes happen that it becomes -hard to track which parameter value belongs with which placeholder. Did you -intend to pass this numeric value as `$7`, or as `$8`? The answer may depend -on an `if` that happened earlier in a different function. - -(Generally if things get that complex, it's a good idea to look for simpler -solutions. But especially when performance matters, sometimes you can't avoid -complexity like that.) - -There's a little helper class called `placeholders`. You can use it as a -counter which produces those placeholder strings, `$1`, `$2`, `$3`, et cetera. -When you start generating a complex statement, you can create both a `params` -and a `placeholders`: - - pqxx::params values; - pqxx::placeholders name; - -Let's say you've got some complex code to generate the conditions for an SQL -"WHERE" clause. You'll generally want to do these things close together in -your, so that you don't accidentally update one part and forget another: - - if (extra_clause) - { - // Extend the query text, using the current placeholder. - query += " AND x = " + name.get(); - // Add the parameter value. - values.append(my_x); - // Move on to the next placeholder value. - name.next(); - } - -Depending on the starting value of `name`, this might add to `query` a fragment -like "` AND x = $3`" or "` AND x = $5`". diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/performance.md b/ext/libpqxx-7.7.3/include/pqxx/doc/performance.md deleted file mode 100644 index 6c403684f..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/performance.md +++ /dev/null @@ -1,24 +0,0 @@ -Performance features {#performance} -==================== - -If your program's database interaction is not as efficient as it needs to be, -the first place to look is usually the SQL you're executing. But libpqxx -has a few specialized features to help you squeeze more performance out -of how you issue commands and retrieve data: - -* @ref streams. Use these as a faster way to transfer data between your - code and the database. -* `std::string_view` and `pqxx::zview`. In places where traditional C++ worked - with `std::string`, see whether `std::string_view` or `pqxx::zview` will - do. Of course that means that you'll have to look at the data's lifetime - more carefully, but it'll save the computer a lot of copying. -* @ref prepared. These can be executed many times without the server - parsing and planning them anew each time. They also save you having to - escape string parameters. -* `pqxx::pipeline` lets you send queries to the database in batches, and - continue other processing while they are executing. -* `pqxx::connecting` lets you start setting up a database connection, but - without blocking the thread. - -As always of course, don't risk the quality of your code for optimizations -that you don't need! diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/prepared-statement.md b/ext/libpqxx-7.7.3/include/pqxx/doc/prepared-statement.md deleted file mode 100644 index 5193866a6..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/prepared-statement.md +++ /dev/null @@ -1,125 +0,0 @@ -Prepared statements {#prepared} -=================== - -Prepared statements are SQL queries that you define once and then invoke -as many times as you like, typically with varying parameters. It's basically -a function that you can define ad hoc. - -If you have an SQL statement that you're going to execute many times in -quick succession, it may be more efficient to prepare it once and reuse it. -This saves the database backend the effort of parsing complex SQL and -figuring out an efficient execution plan. Another nice side effect is that -you don't need to worry about escaping parameters. Some corporate coding -standards require all SQL parameters to be passed in this way, to reduce the -risk of programmer mistakes leaving room for SQL injections. - - -Preparing a statement ---------------------- - -You create a prepared statement by preparing it on the connection (using the -`pqxx::connection::prepare` functions), passing an identifier and its SQL text. - -The identifier is the name by which the prepared statement will be known; it -should consist of ASCII letters, digits, and underscores only, and start with -an ASCII letter. The name is case-sensitive. - -```cxx - void prepare_my_statement(pqxx::connection &c) - { - c.prepare( - "my_statement", - "SELECT * FROM Employee WHERE name = 'Xavier'"); - } -``` - -Once you've done this, you'll be able to call `my_statement` from any -transaction you execute on the same connection. For this, use the -`pqxx::transaction_base::exec_prepared` functions. - -```cxx - pqxx::result execute_my_statement(pqxx::transaction_base &t) - { - return t.exec_prepared("my_statement"); - } -``` - - -Parameters ----------- - -Did I mention that prepared statements can have parameters? The query text -can contain `$1`, `$2` etc. as placeholders for parameter values that you -will provide when you invoke the prepared satement. - -See @ref parameters for more about this. And here's a simple example of -preparing a statement and invoking it with parameters: - -```cxx - void prepare_find(pqxx::connection &c) - { - // Prepare a statement called "find" that looks for employees with a - // given name (parameter 1) whose salary exceeds a given number - // (parameter 2). - c.prepare( - "find", - "SELECT * FROM Employee WHERE name = $1 AND salary > $2"); - } -``` - -This example looks up the prepared statement "find," passes `name` and -`min_salary` as parameters, and invokes the statement with those values: - -```cxx - pqxx::result execute_find( - pqxx::transaction_base &t, std::string name, int min_salary) - { - return t.exec_prepared("find", name, min_salary); - } -``` - - -A special prepared statement ----------------------------- - -There is one special case: the _nameless_ prepared statement. You may prepare -a statement without a name, i.e. whose name is an empty string. The unnamed -statement can be redefined at any time, without un-preparing it first. - - -Performance note ----------------- - -Don't assume that using prepared statements will speed up your application. -There are cases where prepared statements are actually slower than plain SQL. - -The reason is that the backend can often produce a better execution plan when -it knows the statement's actual parameter values. - -For example, say you've got a web application and you're querying for users -with status "inactive" who have email addresses in a given domain name X. If -X is a very popular provider, the best way for the database engine to plan the -query may be to list the inactive users first and then filter for the email -addresses you're looking for. But in other cases, it may be much faster to -find matching email addresses first and then see which of their owners are -"inactive." A prepared statement must be planned to fit either case, but a -direct query will be optimised based on table statistics, partial indexes, etc. - - -Zero bytes ----------- - -@warning Beware of "nul" bytes! - -Any string you pass as a parameter will end at the _first char with value -zero._ If you pass a string that contains a zero byte, the last byte in the -value will be the one just before the zero. - -So, if you need a zero byte in a string, consider that it's really a _binary -string,_ which is not the same thing as a text string. SQL represents binary -data as the `BYTEA` type, or in binary large objects ("blobs"). - -In libpqxx, you represent binary data as a range of `std::byte`. They must be -contiguous in memory, so that libpqxx can pass pointers to the underlying C -library. So you might use `std::basic_string`, or -`std::basic_string_view`, or `std::vector`. diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/streams.md b/ext/libpqxx-7.7.3/include/pqxx/doc/streams.md deleted file mode 100644 index 3df4d6126..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/streams.md +++ /dev/null @@ -1,107 +0,0 @@ -Streams {#streams} -======= - -Most of the time it's fine to retrieve data from the database using `SELECT` -queries, and store data using `INSERT`. But for those cases where efficiency -matters, there are two classes to help you do this better: `stream_from` and -`stream_to`. They're less flexible than SQL queries, and there's the risk of -losing your connection while you're in mid-stream, but you get some speed and -memory efficiencies in return. - -Both stream classes do data conversion for you: `stream_from` receives values -from the database in PostgreSQL's text format, and converts them to the C++ -types you specify. Likewise, `stream_to` converts C++ values you provide to -PostgreSQL's text format for transfer. (On its end, the database of course -converts values to and from their SQL types.) - - -Null values ------------ - -So how do you deal with nulls? It depends on the C++ type you're using. Some -types may have a built-in null value. For instance, if you have a -`char const *` value and you convert it to an SQL string, then converting a -`nullptr` will produce a NULL SQL value. - -But what do you do about C++ types which don't have a built-in null value, such -as `int`? The trick is to wrap it in `std::optional`. The difference between -`int` and `std::optional` is that the former always has an `int` value, -and the latter doesn't have to. - -Actually it's not just `std::optional`. You can do the same thing with -`std::unique_ptr` or `std::shared_ptr`. A smart pointer is less efficient than -`std::optional` in most situations because they allocate their value on the -heap, but sometimes that's what you want in order to save moving or copying -large values around. - -This part is not generic though. It won't work with just any smart-pointer -type, just the ones which are explicitly supported: `shared_ptr` and -`unique_ptr`. If you really need to, you can build support for additional -wrappers and smart pointers by copying the implementation patterns from the -existing smart-pointer support. - - -stream\_from ------------- - -Use `stream_from` to read data directly from the database. It's faster than -the transaction's `exec` functions if the result contains enough rows. But -also, you won't need to keep your full result set in memory. That can really -matter with larger data sets. - -And, you can start processing your data right after the first row of data comes -in from the server. With `exec()` you need to wait to receive all data, and -then you begin processing. With `stream_from` you can be processing data on -the client side while the server is still sending you the rest. - -You don't actually need to create a `stream_from` object yourself, though you -can. Two shorthand functions, @ref pqxx::transaction_base::stream -and @ref pqxx::transaction_base::for_each, can create the streams for you with -a minimum of overhead. - -Not all kinds of queries will work in a stream. Internally the streams make -use of PostgreSQL's `COPY` command, so see the PostgreSQL documentation for -`COPY` for the exact limitations. Basic `SELECT` and `UPDATE ... RETURNING` -queries should just work. - -As you read a row, the stream converts its fields to a tuple type containing -the value types you ask for: - - auto stream pqxx::stream_from::query( - tx, "SELECT name, points FROM score"); - std::tuple row; - while (stream >> row) - process(row); - stream.complete(); - -As the stream reads each row, it converts that row's data into your tuple, -goes through your loop body, and then promptly forgets that row's data. This -means you can easily process more data than will fit in memory. - - -stream\_to ----------- - -Use `stream_to` to write data directly to a database table. This saves you -having to perform an `INSERT` for every row, and so it can be significantly -faster if you want to insert more than just one or two rows at a time. - -As with `stream_from`, you can specify the table and the columns, and not much -else. You insert tuple-like objects of your choice: - - pqxx::stream_to stream{ - tx, - "score", - std::vector{"name", "points"}}; - for (auto const &entry: scores) - stream << entry; - stream.complete(); - -Each row is processed as you provide it, and not retained in memory after that. - -The call to `complete()` is more important here than it is for `stream_from`. -It's a lot like a "commit" or "abort" at the end of a transaction. If you omit -it, it will be done automatically during the stream's destructor. But since -destructors can't throw exceptions, any failures at that stage won't be visible -in your code. So, always call `complete()` on a `stream_to` to close it off -properly! diff --git a/ext/libpqxx-7.7.3/include/pqxx/doc/thread-safety.md b/ext/libpqxx-7.7.3/include/pqxx/doc/thread-safety.md deleted file mode 100644 index 07c7f9984..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/doc/thread-safety.md +++ /dev/null @@ -1,29 +0,0 @@ -Thread safety {#thread-safety} -============= - -This library does not contain any locking code to protect objects against -simultaneous modification in multi-threaded programs. Therefore it is up -to you, the user of the library, to ensure that your threaded client -programs perform no conflicting operations concurrently. - -Most of the time this isn't hard. Result sets are immutable, so you can -share them between threads without problem. The main rule is: - -@li Treat a connection, together with any and all objects related to it, as -a "world" of its own. You should generally make sure that the same "world" -is never accessed by another thread while you're doing anything non-const -in there. - -That means: don't issue a query on a transaction while you're also opening -a subtransaction, don't access a cursor while you may also be committing, -and so on. - -In particular, cursors are tricky. It's easy to perform a non-const -operation without noticing. So, if you're going to share cursors or -cursor-related objects between threads, lock very conservatively! - -Use `pqxx::describe_thread_safety` to find out at runtime what level of -thread safety is implemented in your build and version of libpqxx. It -returns a `pqxx::thread_safety_model` describing what you can and cannot rely -on. A command-line utility `tools/pqxxthreadsafety` prints out the same -information. diff --git a/ext/libpqxx-7.7.3/include/pqxx/errorhandler b/ext/libpqxx-7.7.3/include/pqxx/errorhandler deleted file mode 100644 index ea572ee79..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/errorhandler +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::errorhandler class. - * - * Callbacks for handling errors and warnings. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/errorhandler.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/errorhandler.hxx b/ext/libpqxx-7.7.3/include/pqxx/errorhandler.hxx deleted file mode 100644 index 2ffb5703c..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/errorhandler.hxx +++ /dev/null @@ -1,92 +0,0 @@ -/* Definition of the pqxx::errorhandler class. - * - * pqxx::errorhandler handlers errors and warnings in a database session. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/errorhandler instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ERRORHANDLER -#define PQXX_H_ERRORHANDLER - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/types.hxx" - - -namespace pqxx::internal::gate -{ -class errorhandler_connection; -} - - -namespace pqxx -{ -/** - * @addtogroup errorhandler - */ -//@{ - -/// Base class for error-handler callbacks. -/** To receive errors and warnings from a connection, subclass this with your - * own error-handler functor, and instantiate it for the connection. Destroying - * the handler un-registers it. - * - * A connection can have multiple error handlers at the same time. When the - * database connection emits an error or warning message, it passes the message - * to each error handler, starting with the most recently registered one and - * progressing towards the oldest one. However an error handler may also - * instruct the connection not to pass the message to further handlers by - * returning "false." - * - * @warning Strange things happen when a result object outlives its parent - * connection. If you register an error handler on a connection, then you must - * not access the result after destroying the connection. This applies even if - * you destroy the error handler first! - */ -class PQXX_LIBEXPORT errorhandler -{ -public: - explicit errorhandler(connection &); - virtual ~errorhandler(); - - /// Define in subclass: receive an error or warning message from the - /// database. - /** - * @return Whether the same error message should also be passed to the - * remaining, older errorhandlers. - */ - virtual bool operator()(char const msg[]) noexcept = 0; - - errorhandler() = delete; - errorhandler(errorhandler const &) = delete; - errorhandler &operator=(errorhandler const &) = delete; - -private: - connection *m_home; - - friend class internal::gate::errorhandler_connection; - void unregister() noexcept; -}; - - -/// An error handler that suppresses any previously registered error handlers. -class quiet_errorhandler : public errorhandler -{ -public: - /// Suppress error notices. - quiet_errorhandler(connection &conn) : errorhandler{conn} {} - - /// Revert to previous handling of error notices. - virtual bool operator()(char const[]) noexcept override { return false; } -}; - -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/except b/ext/libpqxx-7.7.3/include/pqxx/except deleted file mode 100644 index e5dd508bf..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/except +++ /dev/null @@ -1,8 +0,0 @@ -/** libpqxx exception classes. - * - * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/except.hxx b/ext/libpqxx-7.7.3/include/pqxx/except.hxx deleted file mode 100644 index 24f959437..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/except.hxx +++ /dev/null @@ -1,447 +0,0 @@ -/* Definition of libpqxx exception classes. - * - * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_EXCEPT -#define PQXX_H_EXCEPT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - - -namespace pqxx -{ -/** - * @addtogroup exception Exception classes - * - * These exception classes follow, roughly, the two-level hierarchy defined by - * the PostgreSQL SQLSTATE error codes (see Appendix A of the PostgreSQL - * documentation corresponding to your server version). This is not a complete - * mapping though. There are other differences as well, e.g. the error code - * for `statement_completion_unknown` has a separate status in libpqxx as - * @ref in_doubt_error, and `too_many_connections` is classified as a - * `broken_connection` rather than a subtype of `insufficient_resources`. - * - * @see http://www.postgresql.org/docs/9.4/interactive/errcodes-appendix.html - * - * @{ - */ - -/// Run-time failure encountered by libpqxx, similar to std::runtime_error. -struct PQXX_LIBEXPORT failure : std::runtime_error -{ - explicit failure(std::string const &); -}; - - -/// Exception class for lost or failed backend connection. -/** - * @warning When this happens on Unix-like systems, you may also get a SIGPIPE - * signal. That signal aborts the program by default, so if you wish to be - * able to continue after a connection breaks, be sure to disarm this signal. - * - * If you're working on a Unix-like system, see the manual page for - * `signal` (2) on how to deal with SIGPIPE. The easiest way to make this - * signal harmless is to make your program ignore it: - * - * ```cxx - * #include - * - * int main() - * { - * signal(SIGPIPE, SIG_IGN); - * // ... - * ``` - */ -struct PQXX_LIBEXPORT broken_connection : failure -{ - broken_connection(); - explicit broken_connection(std::string const &); -}; - - -/// The caller attempted to set a variable to null, which is not allowed. -struct PQXX_LIBEXPORT variable_set_to_null : failure -{ - variable_set_to_null(); - explicit variable_set_to_null(std::string const &); -}; - - -/// Exception class for failed queries. -/** Carries, in addition to a regular error message, a copy of the failed query - * and (if available) the SQLSTATE value accompanying the error. - */ -class PQXX_LIBEXPORT sql_error : public failure -{ - /// Query string. Empty if unknown. - std::string const m_query; - /// SQLSTATE string describing the error type, if known; or empty string. - std::string const m_sqlstate; - -public: - explicit sql_error( - std::string const &whatarg = "", std::string const &Q = "", - char const sqlstate[] = nullptr); - virtual ~sql_error() noexcept override; - - /// The query whose execution triggered the exception - [[nodiscard]] PQXX_PURE std::string const &query() const noexcept; - - /// SQLSTATE error code if known, or empty string otherwise. - [[nodiscard]] PQXX_PURE std::string const &sqlstate() const noexcept; -}; - - -/// "Help, I don't know whether transaction was committed successfully!" -/** Exception that might be thrown in rare cases where the connection to the - * database is lost while finishing a database transaction, and there's no way - * of telling whether it was actually executed by the backend. In this case - * the database is left in an indeterminate (but consistent) state, and only - * manual inspection will tell which is the case. - */ -struct PQXX_LIBEXPORT in_doubt_error : failure -{ - explicit in_doubt_error(std::string const &); -}; - - -/// The backend saw itself forced to roll back the ongoing transaction. -struct PQXX_LIBEXPORT transaction_rollback : sql_error -{ - explicit transaction_rollback( - std::string const &whatarg, std::string const &q = "", - char const sqlstate[] = nullptr); -}; - - -/// Transaction failed to serialize. Please retry it. -/** Can only happen at transaction isolation levels REPEATABLE READ and - * SERIALIZABLE. - * - * The current transaction cannot be committed without violating the guarantees - * made by its isolation level. This is the effect of a conflict with another - * ongoing transaction. The transaction may still succeed if you try to - * perform it again. - */ -struct PQXX_LIBEXPORT serialization_failure : transaction_rollback -{ - explicit serialization_failure( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// We can't tell whether our last statement succeeded. -struct PQXX_LIBEXPORT statement_completion_unknown : transaction_rollback -{ - explicit statement_completion_unknown( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// The ongoing transaction has deadlocked. Retrying it may help. -struct PQXX_LIBEXPORT deadlock_detected : transaction_rollback -{ - explicit deadlock_detected( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// Internal error in libpqxx library -struct PQXX_LIBEXPORT internal_error : std::logic_error -{ - explicit internal_error(std::string const &); -}; - - -/// Error in usage of libpqxx library, similar to std::logic_error -struct PQXX_LIBEXPORT usage_error : std::logic_error -{ - explicit usage_error(std::string const &); -}; - - -/// Invalid argument passed to libpqxx, similar to std::invalid_argument -struct PQXX_LIBEXPORT argument_error : std::invalid_argument -{ - explicit argument_error(std::string const &); -}; - - -/// Value conversion failed, e.g. when converting "Hello" to int. -struct PQXX_LIBEXPORT conversion_error : std::domain_error -{ - explicit conversion_error(std::string const &); -}; - - -/// Could not convert value to string: not enough buffer space. -struct PQXX_LIBEXPORT conversion_overrun : conversion_error -{ - explicit conversion_overrun(std::string const &); -}; - - -/// Something is out of range, similar to std::out_of_range -struct PQXX_LIBEXPORT range_error : std::out_of_range -{ - explicit range_error(std::string const &); -}; - - -/// Query returned an unexpected number of rows. -struct PQXX_LIBEXPORT unexpected_rows : public range_error -{ - explicit unexpected_rows(std::string const &msg) : range_error{msg} {} -}; - - -/// Database feature not supported in current setup. -struct PQXX_LIBEXPORT feature_not_supported : sql_error -{ - explicit feature_not_supported( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Error in data provided to SQL statement. -struct PQXX_LIBEXPORT data_exception : sql_error -{ - explicit data_exception( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT integrity_constraint_violation : sql_error -{ - explicit integrity_constraint_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT restrict_violation : integrity_constraint_violation -{ - explicit restrict_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT not_null_violation : integrity_constraint_violation -{ - explicit not_null_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT foreign_key_violation : integrity_constraint_violation -{ - explicit foreign_key_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT unique_violation : integrity_constraint_violation -{ - explicit unique_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT check_violation : integrity_constraint_violation -{ - explicit check_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_cursor_state : sql_error -{ - explicit invalid_cursor_state( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_sql_statement_name : sql_error -{ - explicit invalid_sql_statement_name( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_cursor_name : sql_error -{ - explicit invalid_cursor_name( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT syntax_error : sql_error -{ - /// Approximate position in string where error occurred, or -1 if unknown. - int const error_position; - - explicit syntax_error( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr, int pos = -1) : - sql_error{err, Q, sqlstate}, error_position{pos} - {} -}; - -struct PQXX_LIBEXPORT undefined_column : syntax_error -{ - explicit undefined_column( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT undefined_function : syntax_error -{ - explicit undefined_function( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT undefined_table : syntax_error -{ - explicit undefined_table( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT insufficient_privilege : sql_error -{ - explicit insufficient_privilege( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Resource shortage on the server -struct PQXX_LIBEXPORT insufficient_resources : sql_error -{ - explicit insufficient_resources( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT disk_full : insufficient_resources -{ - explicit disk_full( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - insufficient_resources{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT out_of_memory : insufficient_resources -{ - explicit out_of_memory( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - insufficient_resources{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT too_many_connections : broken_connection -{ - explicit too_many_connections(std::string const &err) : - broken_connection{err} - {} -}; - -/// PL/pgSQL error -/** Exceptions derived from this class are errors from PL/pgSQL procedures. - */ -struct PQXX_LIBEXPORT plpgsql_error : sql_error -{ - explicit plpgsql_error( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Exception raised in PL/pgSQL procedure -struct PQXX_LIBEXPORT plpgsql_raise : plpgsql_error -{ - explicit plpgsql_raise( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT plpgsql_no_data_found : plpgsql_error -{ - explicit plpgsql_no_data_found( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT plpgsql_too_many_rows : plpgsql_error -{ - explicit plpgsql_too_many_rows( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT blob_already_exists : failure -{ - explicit blob_already_exists(std::string const &); -}; - -/** - * @} - */ -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/field b/ext/libpqxx-7.7.3/include/pqxx/field deleted file mode 100644 index 37cb69e84..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/field +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::field class. - * - * pqxx::field refers to a field in a query result. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/field.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/field.hxx b/ext/libpqxx-7.7.3/include/pqxx/field.hxx deleted file mode 100644 index b8b869fe4..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/field.hxx +++ /dev/null @@ -1,542 +0,0 @@ -/* Definitions for the pqxx::field class. - * - * pqxx::field refers to a field in a query result. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_FIELD -#define PQXX_H_FIELD - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/array.hxx" -#include "pqxx/composite.hxx" -#include "pqxx/result.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/types.hxx" - -namespace pqxx -{ -/// Reference to a field in a result set. -/** A field represents one entry in a row. It represents an actual value - * in the result set, and can be converted to various types. - */ -class PQXX_LIBEXPORT field -{ -public: - using size_type = field_size_type; - - /// Constructor. Do not call this yourself; libpqxx will do it for you. - /** Create field as reference to a field in a result set. - * @param r Row that this field is part of. - * @param c Column number of this field. - */ - [[deprecated( - "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept; - - /// Constructor. Do not call this yourself; libpqxx will do it for you. - [[deprecated( - "Do not construct fields yourself. Get them from the " - "row.")]] field() noexcept = default; - - /** - * @name Comparison - */ - //@{ - // TODO: noexcept. Breaks ABI. - /// Byte-by-byte comparison of two fields (all nulls are considered equal) - /** @warning null handling is still open to discussion and change! - * - * Handling of null values differs from that in SQL where a comparison - * involving a null value yields null, so nulls are never considered equal - * to one another or even to themselves. - * - * Null handling also probably differs from the closest equivalent in C++, - * which is the NaN (Not-a-Number) value, a singularity comparable to - * SQL's null. This is because the builtin == operator demands that a == a. - * - * The usefulness of this operator is questionable. No interpretation - * whatsoever is imposed on the data; 0 and 0.0 are considered different, - * as are null vs. the empty string, or even different (but possibly - * equivalent and equally valid) encodings of the same Unicode character - * etc. - */ - [[nodiscard]] PQXX_PURE bool operator==(field const &) const; - - /// Byte-by-byte comparison (all nulls are considered equal) - /** @warning See operator==() for important information about this operator - */ - [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - /** - * @name Column information - */ - //@{ - /// Column name. - [[nodiscard]] PQXX_PURE char const *name() const &; - - /// Column type. - [[nodiscard]] oid PQXX_PURE type() const; - - /// What table did this column come from? - [[nodiscard]] PQXX_PURE oid table() const; - - /// Return row number. The first row is row 0, the second is row 1, etc. - PQXX_PURE constexpr row_size_type num() const noexcept { return col(); } - - /// What column number in its originating table did this column come from? - [[nodiscard]] PQXX_PURE row_size_type table_column() const; - //@} - - /** - * @name Content access - */ - //@{ - /// Read as `string_view`, or an empty one if null. - /** The result only remains usable while the data for the underlying - * @ref result exists. Once all `result` objects referring to that data have - * been destroyed, the `string_view` will no longer point to valid memory. - */ - [[nodiscard]] PQXX_PURE std::string_view view() const & - { - return std::string_view(c_str(), size()); - } - - /// Read as plain C string. - /** Since the field's data is stored internally in the form of a - * zero-terminated C string, this is the fastest way to read it. Use the - * to() or as() functions to convert the string to other types such as - * `int`, or to C++ strings. - * - * Do not use this for BYTEA values, or other binary values. To read those, - * convert the value to your desired type using `to()` or `as()`. For - * example: `f.as>()`. - */ - [[nodiscard]] PQXX_PURE char const *c_str() const &; - - /// Is this field's value null? - [[nodiscard]] PQXX_PURE bool is_null() const noexcept; - - /// Return number of bytes taken up by the field's value. - [[nodiscard]] PQXX_PURE size_type size() const noexcept; - - /// Read value into obj; or if null, leave obj untouched and return `false`. - /** This can be used with optional types (except pointers other than C-style - * strings). - */ - template - auto to(T &obj) const -> typename std::enable_if_t< - (not std::is_pointer::value or std::is_same::value), - bool> - { - if (is_null()) - { - return false; - } - else - { - auto const bytes{c_str()}; - from_string(bytes, obj); - return true; - } - } - - /// Read field as a composite value, write its components into `fields`. - /** @warning This is still experimental. It may change or be replaced. - * - * Returns whether the field was null. If it was, it will not touch the - * values in `fields`. - */ - template bool composite_to(T &...fields) const - { - if (is_null()) - { - return false; - } - else - { - parse_composite(m_home.m_encoding, view(), fields...); - return true; - } - } - - /// Read value into obj; or leave obj untouched and return `false` if null. - template bool operator>>(T &obj) const { return to(obj); } - - /// Read value into obj; or if null, use default value and return `false`. - /** This can be used with `std::optional`, as well as with standard smart - * pointer types, but not with raw pointers. If the conversion from a - * PostgreSQL string representation allocates a pointer (e.g. using `new`), - * then the object's later deallocation should be baked in as well, right - * from the point where the object is created. So if you want a pointer, use - * a smart pointer, not a raw pointer. - * - * There is one exception, of course: C-style strings. Those are just - * pointers to the field's internal text data. - */ - template - auto to(T &obj, T const &default_value) const -> typename std::enable_if_t< - (not std::is_pointer::value or std::is_same::value), - bool> - { - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = from_string(this->view()); - return not null; - } - - /// Return value as object of given type, or default value if null. - /** Note that unless the function is instantiated with an explicit template - * argument, the Default value's type also determines the result type. - */ - template T as(T const &default_value) const - { - if (is_null()) - return default_value; - else - return from_string(this->view()); - } - - /// Return value as object of given type, or throw exception if null. - /** Use as `as>()` or `as()` as - * an alternative to `get()`; this is disabled for use with raw pointers - * (other than C-strings) because storage for the value can't safely be - * allocated here - */ - template T as() const - { - if (is_null()) - { - if constexpr (not nullness::has_null) - internal::throw_null_conversion(type_name); - else - return nullness::null(); - } - else - { - return from_string(this->view()); - } - } - - /// Return value wrapped in some optional type (empty for nulls). - /** Use as `get()` as before to obtain previous behavior, or specify - * container type with `get()` - */ - template class O = std::optional> - constexpr O get() const - { - return as>(); - } - - // TODO: constexpr noexcept, once array_parser constructor gets those. - /// Parse the field as an SQL array. - /** Call the parser to retrieve values (and structure) from the array. - * - * Make sure the @ref result object stays alive until parsing is finished. If - * you keep the @ref row of `field` object alive, it will keep the @ref - * result object alive as well. - */ - array_parser as_array() const & - { - return array_parser{c_str(), m_home.m_encoding}; - } - //@} - - -protected: - constexpr result const &home() const noexcept { return m_home; } - constexpr result::size_type idx() const noexcept { return m_row; } - constexpr row_size_type col() const noexcept { return m_col; } - - // TODO: Create gates. - friend class pqxx::result; - friend class pqxx::row; - field( - result const &r, result_size_type row_num, row_size_type col_num) noexcept - : - m_col{col_num}, m_home{r}, m_row{row_num} - {} - - /** - * You'd expect this to be unsigned, but due to the way reverse iterators - * are related to regular iterators, it must be allowed to underflow to -1. - */ - row_size_type m_col; - -private: - result m_home; - result::size_type m_row; -}; - - -template<> inline bool field::to(std::string &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = std::string{view()}; - return not null; -} - - -template<> -inline bool field::to( - std::string &obj, std::string const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = std::string{view()}; - return not null; -} - - -/// Specialization: `to(char const *&)`. -/** The buffer has the same lifetime as the data in this result (i.e. of this - * result object, or the last remaining one copied from it etc.), so take care - * not to use it after the last result object referring to this query result is - * destroyed. - */ -template<> inline bool field::to(char const *&obj) const -{ - bool const null{is_null()}; - if (not null) - obj = c_str(); - return not null; -} - - -template<> inline bool field::to(std::string_view &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = view(); - return not null; -} - - -template<> -inline bool field::to( - std::string_view &obj, std::string_view const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = view(); - return not null; -} - - -template<> inline std::string_view field::as() const -{ - if (is_null()) - PQXX_UNLIKELY - internal::throw_null_conversion(type_name); - return view(); -} - - -template<> -inline std::string_view -field::as(std::string_view const &default_value) const -{ - return is_null() ? default_value : view(); -} - - -template<> inline bool field::to(zview &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = zview{c_str(), size()}; - return not null; -} - - -template<> -inline bool field::to(zview &obj, zview const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = zview{c_str(), size()}; - return not null; -} - - -template<> inline zview field::as() const -{ - if (is_null()) - PQXX_UNLIKELY - internal::throw_null_conversion(type_name); - return zview{c_str(), size()}; -} - - -template<> inline zview field::as(zview const &default_value) const -{ - return is_null() ? default_value : zview{c_str(), size()}; -} - - -template> -class field_streambuf : public std::basic_streambuf -{ -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - using openmode = std::ios::openmode; - using seekdir = std::ios::seekdir; - - explicit field_streambuf(field const &f) : m_field{f} { initialize(); } - -protected: - virtual int sync() override { return traits_type::eof(); } - - virtual pos_type seekoff(off_type, seekdir, openmode) override - { - return traits_type::eof(); - } - virtual pos_type seekpos(pos_type, openmode) override - { - return traits_type::eof(); - } - virtual int_type overflow(int_type) override { return traits_type::eof(); } - virtual int_type underflow() override { return traits_type::eof(); } - -private: - field const &m_field; - - int_type initialize() - { - auto g{static_cast(const_cast(m_field.c_str()))}; - this->setg(g, g, g + std::size(m_field)); - return int_type(std::size(m_field)); - } -}; - - -/// Input stream that gets its data from a result field -/** Use this class exactly as you would any other istream to read data from a - * field. All formatting and streaming operations of `std::istream` are - * supported. What you'll typically want to use, however, is the fieldstream - * alias (which defines a @ref basic_fieldstream for `char`). This is similar - * to how e.g. `std::ifstream` relates to `std::basic_ifstream`. - * - * This class has only been tested for the char type (and its default traits). - */ -template> -class basic_fieldstream : public std::basic_istream -{ - using super = std::basic_istream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - - basic_fieldstream(field const &f) : super{nullptr}, m_buf{f} - { - super::init(&m_buf); - } - -private: - field_streambuf m_buf; -}; - -using fieldstream = basic_fieldstream; - -/// Write a result field to any type of stream -/** This can be convenient when writing a field to an output stream. More - * importantly, it lets you write a field to e.g. a `stringstream` which you - * can then use to read, format and convert the field in ways that to() does - * not support. - * - * Example: parse a field into a variable of the nonstandard - * "long long" type. - * - * ```cxx - * extern result R; - * long long L; - * stringstream S; - * - * // Write field's string into S - * S << R[0][0]; - * - * // Parse contents of S into L - * S >> L; - * ``` - */ -template -inline std::basic_ostream & -operator<<(std::basic_ostream &s, field const &value) -{ - s.write(value.c_str(), std::streamsize(std::size(value))); - return s; -} - - -/// Convert a field's value to type `T`. -/** Unlike the "regular" `from_string`, this knows how to deal with null - * values. - */ -template inline T from_string(field const &value) -{ - if (value.is_null()) - { - if constexpr (nullness::has_null) - return nullness::null(); - else - internal::throw_null_conversion(type_name); - } - else - { - return from_string(value.view()); - } -} - - -/// Convert a field's value to `nullptr_t`. -/** Yes, you read that right. This conversion does nothing useful. It always - * returns `nullptr`. - * - * Except... what if the field is not null? In that case, this throws - * @ref conversion_error. - */ -template<> -inline std::nullptr_t from_string(field const &value) -{ - if (not value.is_null()) - throw conversion_error{ - "Extracting non-null field into nullptr_t variable."}; - return nullptr; -} - - -/// Convert a field to a string. -template<> PQXX_LIBEXPORT std::string to_string(field const &value); -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/array-composite.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/array-composite.hxx deleted file mode 100644 index d2b6603e5..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/array-composite.hxx +++ /dev/null @@ -1,305 +0,0 @@ -#if !defined(PQXX_ARRAY_COMPOSITE_HXX) -# define PQXX_ARRAY_COMPOSITE_HXX - -# include - -# include "pqxx/strconv.hxx" - -namespace pqxx::internal -{ -// Find the end of a double-quoted string. -/** `input[pos]` must be the opening double quote. - * - * Returns the offset of the first position after the closing quote. - */ -inline std::size_t scan_double_quoted_string( - char const input[], std::size_t size, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - // XXX: find_char<'"', '\\'>(). - auto next{scan(input, size, pos)}; - bool at_quote{false}; - for (pos = next, next = scan(input, size, pos); pos < size; - pos = next, next = scan(input, size, pos)) - { - if (at_quote) - { - if (next - pos == 1 and input[pos] == '"') - { - // We just read a pair of double quotes. Carry on. - at_quote = false; - } - else - { - // We just read one double quote, and now we're at a character that's - // not a second double quote. Ergo, that last character was the - // closing double quote and this is the position right after it. - return pos; - } - } - else if (next - pos == 1) - { - switch (input[pos]) - { - case '\\': - // Backslash escape. Skip ahead by one more character. - pos = next; - next = scan(input, size, pos); - break; - - case '"': - // This is either the closing double quote, or the first of a pair of - // double quotes. - at_quote = true; - break; - } - } - else - { - // Multibyte character. Carry on. - } - } - if (not at_quote) - throw argument_error{ - "Missing closing double-quote: " + std::string{input}}; - return pos; -} - - -/// Un-quote and un-escape a double-quoted SQL string. -inline std::string parse_double_quoted_string( - char const input[], std::size_t end, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - std::string output; - // Maximum output size is same as the input size, minus the opening and - // closing quotes. Or in the extreme opposite case, the real number could be - // half that. Usually it'll be a pretty close estimate. - output.reserve(std::size_t(end - pos - 2)); - - for (auto here{scan(input, end, pos)}, next{scan(input, end, here)}; - here < end - 1; here = next, next = scan(input, end, here)) - { - // A backslash here is always an escape. So is a double-quote, since we're - // inside the double-quoted string. In either case, we can just ignore the - // escape character and use the next character. This is the one redeeming - // feature of SQL's escaping system. - if ((next - here == 1) and (input[here] == '\\' or input[here] == '"')) - { - // Skip escape. - here = next; - next = scan(input, end, here); - } - output.append(input + here, input + next); - } - return output; -} - - -/// Find the end of an unquoted string in an array or composite-type value. -/** Stops when it gets to the end of the input; or when it sees any of the - * characters in STOP which has not been escaped. - * - * For array values, STOP is a comma, a semicolon, or a closing brace. For - * a value of a composite type, STOP is a comma or a closing parenthesis. - */ -template -inline std::size_t scan_unquoted_string( - char const input[], std::size_t size, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - bool at_backslash{false}; - auto next{scan(input, size, pos)}; - while ((pos < size) and - ((next - pos) > 1 or at_backslash or ((input[pos] != STOP) and ...))) - { - pos = next; - next = scan(input, size, pos); - at_backslash = - ((not at_backslash) and ((next - pos) == 1) and (input[pos] == '\\')); - } - return pos; -} - - -/// Parse an unquoted array entry or cfield of a composite-type field. -inline std::string parse_unquoted_string( - char const input[], std::size_t end, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - std::string output; - bool at_backslash{false}; - output.reserve(end - pos); - for (auto next{scan(input, end, pos)}; pos < end; - pos = next, next = scan(input, end, pos)) - { - at_backslash = - ((not at_backslash) and ((next - pos) == 1) and (input[pos] == '\\')); - if (not at_backslash) - output.append(input + pos, next - pos); - } - return output; -} - - -/// Parse a field of a composite-type value. -/** `T` is the C++ type of the field we're parsing, and `index` is its - * zero-based number. - * - * Strip off the leading parenthesis or bracket yourself before parsing. - * However, this function will parse the lcosing parenthesis or bracket. - * - * After a successful parse, `pos` will point at `std::end(text)`. - * - * For the purposes of parsing, ranges and arrays count as compositve values, - * so this function supports parsing those. If you specifically need a closing - * parenthesis, check afterwards that `text` did not end in a bracket instead. - * - * @param index Index of the current field, zero-based. It will increment for - * the next field. - * @param input Full input text for the entire composite-type value. - * @param pos Starting position (in `input`) of the field that we're parsing. - * After parsing, this will point at the beginning of the next field if - * there is one, or one position past the last character otherwise. - * @param field Destination for the parsed value. - * @param scan Glyph scanning function for the relevant encoding type. - * @param last_field Number of the last field in the value (zero-based). When - * parsing the last field, this will equal `index`. - */ -template -inline void parse_composite_field( - std::size_t &index, std::string_view input, std::size_t &pos, T &field, - glyph_scanner_func *scan, std::size_t last_field) -{ - assert(index <= last_field); - auto next{scan(std::data(input), std::size(input), pos)}; - if ((next - pos) != 1) - throw conversion_error{"Non-ASCII character in composite-type syntax."}; - - // Expect a field. - switch (input[pos]) - { - case ',': - case ')': - case ']': - // The field is empty, i.e, null. - if constexpr (nullness::has_null) - field = nullness::null(); - else - throw conversion_error{ - "Can't read composite field " + to_string(index) + ": C++ type " + - type_name + " does not support nulls."}; - break; - - case '"': { - auto const stop{scan_double_quoted_string( - std::data(input), std::size(input), pos, scan)}; - auto const text{ - parse_double_quoted_string(std::data(input), stop, pos, scan)}; - field = from_string(text); - pos = stop; - } - break; - - default: { - auto const stop{scan_unquoted_string<',', ')', ']'>( - std::data(input), std::size(input), pos, scan)}; - auto const text{parse_unquoted_string(std::data(input), stop, pos, scan)}; - field = from_string(text); - pos = stop; - } - break; - } - - // Expect a comma or a closing parenthesis. - next = scan(std::data(input), std::size(input), pos); - - if ((next - pos) != 1) - throw conversion_error{ - "Unexpected non-ASCII character after composite field: " + - std::string{input}}; - - if (index < last_field) - { - if (input[pos] != ',') - throw conversion_error{ - "Found '" + std::string{input[pos]} + - "' in composite value where comma was expected: " + std::data(input)}; - } - else - { - if (input[pos] == ',') - throw conversion_error{ - "Composite value contained more fields than the expected " + - to_string(last_field) + ": " + std::data(input)}; - if (input[pos] != ')' and input[pos] != ']') - throw conversion_error{ - "Composite value has unexpected characters where closing parenthesis " - "was expected: " + - std::string{input}}; - if (next != std::size(input)) - throw conversion_error{ - "Composite value has unexpected text after closing parenthesis: " + - std::string{input}}; - } - - pos = next; - ++index; -} - - -/// Conservatively estimate buffer size needed for a composite field. -template -inline std::size_t size_composite_field_buffer(T const &field) -{ - if constexpr (is_unquoted_safe) - { - // Safe to copy, without quotes or escaping. Drop the terminating zero. - return size_buffer(field) - 1; - } - else - { - // + Opening quote. - // + Field budget. - // - Terminating zero. - // + Escaping for each byte in the field's string representation. - // - Escaping for terminating zero. - // + Closing quote. - return 1 + 2 * (size_buffer(field) - 1) + 1; - } -} - - -template -inline void write_composite_field(char *&pos, char *end, T const &field) -{ - if constexpr (is_unquoted_safe) - { - // No need for quoting or escaping. Convert it straight into its final - // place in the buffer, and "backspace" the trailing zero. - pos = string_traits::into_buf(pos, end, field) - 1; - } - else - { - // The field may need escaping, which means we need an intermediate buffer. - // To avoid allocating that at run time, we use the end of the buffer that - // we have. - auto const budget{size_buffer(field)}; - *pos++ = '"'; - - // Now escape buf into its final position. - for (char const c : string_traits::to_buf(end - budget, end, field)) - { - if ((c == '"') or (c == '\\')) - *pos++ = '\\'; - - *pos++ = c; - } - - *pos++ = '"'; - } - - *pos++ = ','; -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/callgate.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/callgate.hxx deleted file mode 100644 index 42f7703e3..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/callgate.hxx +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef PQXX_H_CALLGATE -#define PQXX_H_CALLGATE - -/* -Here's what a typical gate class definition looks like: - -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE @gateclass@ : callgate<@host@> -{ - friend class @client@; - - @gateclass@(reference x) : super(x) {} - - // Methods here. Use home() to access the host-class object. -}; -} // namespace pqxx::internal::gate -*/ - -namespace pqxx::internal -{ -/// Base class for call gates. -/** - * A call gate defines a limited, private interface on the host class that - * specified client classes can access. - * - * The metaphor works as follows: the gate stands in front of a "home," which - * is really a class, and only lets specific friends in. - * - * To implement a call gate that gives client C access to host H, - * * derive a gate class from callgate; - * * make the gate class a friend of H; - * * make C a friend of the gate class; and - * * implement "stuff C can do with H" as private members in the gate class. - * - * This special kind of "gated" friendship gives C private access to H, but - * only through an expressly limited interface. The gate class can access its - * host object as home(). - * - * Keep gate classes entirely stateless. They should be ultra-lightweight - * wrappers for their host classes, and be optimized away as much as possible - * by the compiler. Once you start adding state, you're on a slippery slope - * away from the pure, clean, limited interface pattern that gate classes are - * meant to implement. - * - * Ideally, all member functions of the gate class should be one-liners passing - * calls straight on to the host class. It can be useful however to break this - * rule temporarily during inter-class refactoring. - */ -template class PQXX_PRIVATE callgate -{ -protected: - /// This class, to keep constructors easy. - using super = callgate; - /// A reference to the host class. Helps keep constructors easy. - using reference = HOME &; - - callgate(reference x) : m_home(x) {} - - /// The home object. The gate class has full "private" access. - reference home() const noexcept { return m_home; } - -private: - reference m_home; -}; -} // namespace pqxx::internal - -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/concat.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/concat.hxx deleted file mode 100644 index cd28bde7c..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/concat.hxx +++ /dev/null @@ -1,45 +0,0 @@ -#if !defined(PQXX_CONCAT_HXX) -# define PQXX_CONCAT_HXX - -# include -# include - -# include "pqxx/strconv.hxx" - -namespace pqxx::internal -{ -/// Convert item to a string, write it into [here, end). -template -void render_item(TYPE const &item, char *&here, char *end) -{ - here = string_traits::into_buf(here, end, item) - 1; -} - - -// C++20: Support non-random_access_range ranges. -/// Efficiently combine a bunch of items into one big string. -/** Use this as an optimised version of string concatentation. It takes just - * about any type; it will represent each item as a string according to its - * @ref string_traits. - * - * This is a simpler, more specialised version of @ref separated_list for a - * statically known series of items, possibly of different types. - */ -template -[[nodiscard]] inline std::string concat(TYPE... item) -{ - std::string buf; - // Size to accommodate string representations of all inputs, minus their - // terminating zero bytes. - buf.resize(size_buffer(item...)); - - char *const data{buf.data()}; - char *here = data; - char *end = data + std::size(buf); - (render_item(item, here, end), ...); - - buf.resize(static_cast(here - data)); - return buf; -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/conversions.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/conversions.hxx deleted file mode 100644 index 1df4fdead..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/conversions.hxx +++ /dev/null @@ -1,1188 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#if defined(PQXX_HAVE_SPAN) && __has_include() -# include -#endif - -#include -#include -#include - -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" - - -/* Internal helpers for string conversion, and conversion implementations. - * - * Do not include this header directly. The libpqxx headers do it for you. - */ -namespace pqxx::internal -{ -/// Convert a number in [0, 9] to its ASCII digit. -inline constexpr char number_to_digit(int i) noexcept -{ - return static_cast(i + '0'); -} - - -/// Compute numeric value of given textual digit (assuming that it is a digit). -constexpr int digit_to_number(char c) noexcept -{ - return c - '0'; -} - - -/// Summarize buffer overrun. -/** Don't worry about the exact parameter types: the sizes will be reasonably - * small, and nonnegative. - */ -std::string PQXX_LIBEXPORT -state_buffer_overrun(int have_bytes, int need_bytes); - - -template -inline std::string state_buffer_overrun(HAVE have_bytes, NEED need_bytes) -{ - return state_buffer_overrun( - static_cast(have_bytes), static_cast(need_bytes)); -} - - -/// Throw exception for attempt to convert null to given type. -[[noreturn]] PQXX_LIBEXPORT void -throw_null_conversion(std::string const &type); - - -/// Deliberately nonfunctional conversion traits for `char` types. -/** There are no string conversions for `char` and its signed and unsigned - * variants. Such a conversion would be dangerously ambiguous: should we treat - * it as text, or as a small integer? It'd be an open invitation for bugs. - * - * But the error message when you get this wrong is very cryptic. So, we - * derive dummy @ref string_traits implementations from this dummy type, and - * ensure that the compiler disallows their use. The compiler error message - * will at least contain a hint of the root of the problem. - */ -template struct disallowed_ambiguous_char_conversion -{ - static char *into_buf(char *, char *, CHAR_TYPE) = delete; - static constexpr zview - to_buf(char *, char *, CHAR_TYPE const &) noexcept = delete; - - static constexpr std::size_t - size_buffer(CHAR_TYPE const &) noexcept = delete; - static CHAR_TYPE from_string(std::string_view) = delete; -}; - - -template PQXX_LIBEXPORT extern std::string to_string_float(T); - - -/// Generic implementation for into_buf, on top of to_buf. -template -inline char *generic_into_buf(char *begin, char *end, T const &value) -{ - zview const text{string_traits::to_buf(begin, end, value)}; - auto const space{end - begin}; - // Include the trailing zero. - auto const len = std::size(text) + 1; - if (internal::cmp_greater(len, space)) - throw conversion_overrun{ - "Not enough buffer space to insert " + type_name + ". " + - state_buffer_overrun(space, len)}; - std::memmove(begin, text.data(), len); - return begin + len; -} - - -/// String traits for builtin integral types (though not bool). -template struct integral_traits -{ - static PQXX_LIBEXPORT T from_string(std::string_view text); - static PQXX_LIBEXPORT zview to_buf(char *begin, char *end, T const &value); - static PQXX_LIBEXPORT char *into_buf(char *begin, char *end, T const &value); - - static constexpr std::size_t size_buffer(T const &) noexcept - { - /** Includes a sign if needed; the number of base-10 digits which the type - * can reliably represent; the one extra base-10 digit which the type can - * only partially represent; and the terminating zero. - */ - return std::is_signed_v + std::numeric_limits::digits10 + 1 + 1; - } -}; - - -/// String traits for builtin floating-point types. -template struct float_traits -{ - static PQXX_LIBEXPORT T from_string(std::string_view text); - static PQXX_LIBEXPORT zview to_buf(char *begin, char *end, T const &value); - static PQXX_LIBEXPORT char *into_buf(char *begin, char *end, T const &value); - - // Return a nonnegative integral value's number of decimal digits. - static constexpr std::size_t digits10(std::size_t value) noexcept - { - if (value < 10) - return 1; - else - return 1 + digits10(value / 10); - } - - static constexpr std::size_t size_buffer(T const &) noexcept - { - using lims = std::numeric_limits; - // See #328 for a detailed discussion on the maximum number of digits. - // - // In a nutshell: for the big cases, the scientific notation is always - // the shortest one, and therefore the one that to_chars will pick. - // - // So... How long can the scientific notation get? 1 (for sign) + 1 (for - // decimal point) + 1 (for 'e') + 1 (for exponent sign) + max_digits10 + - // max number of digits in the exponent + 1 (terminating zero). - // - // What's the max number of digits in the exponent? It's the max number of - // digits out of the most negative exponent and the most positive one. - // - // The longest positive exponent is easy: 1 + ceil(log10(max_exponent10)). - // (The extra 1 is because 10^n takes up 1 + n digits, not n.) - // - // The longest negative exponent is a bit harder: min_exponent10 gives us - // the smallest power of 10 which a normalised version of T can represent. - // But the smallest denormalised power of 10 that T can represent is - // another max_digits10 powers of 10 below that. - // needs a minus sign. - // - // All this stuff messes with my head a bit because it's on the order of - // log10(log10(n)). It's easy to get the number of logs wrong. - auto const max_pos_exp{digits10(lims::max_exponent10)}; - // Really want std::abs(lims::min_exponent10), but MSVC 2017 apparently has - // problems with std::abs. So we use -lims::min_exponent10 instead. - auto const max_neg_exp{ - digits10(lims::max_digits10 - lims::min_exponent10)}; - return 1 + // Sign. - 1 + // Decimal point. - std::numeric_limits::max_digits10 + // Mantissa digits. - 1 + // Exponent "e". - 1 + // Exponent sign. - // Spell this weirdly to stop Windows compilers from reading this as - // a call to their "max" macro when NOMINMAX is not defined. - (std::max)(max_pos_exp, max_neg_exp) + // Exponent digits. - 1; // Terminating zero. - } -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// The built-in arithmetic types do not have inherent null values. -template -struct nullness>> : no_null -{}; - - -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits - : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits - : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; - - -template<> struct string_traits -{ - static PQXX_LIBEXPORT bool from_string(std::string_view text); - - static constexpr zview to_buf(char *, char *, bool const &value) noexcept - { - return value ? "true"_zv : "false"_zv; - } - - static char *into_buf(char *begin, char *end, bool const &value) - { - return pqxx::internal::generic_into_buf(begin, end, value); - } - - static constexpr std::size_t size_buffer(bool const &) noexcept { return 6; } -}; - - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - - -template<> inline constexpr bool is_unquoted_safe{true}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - /// Technically, you could have an optional of an always-null type. - static constexpr bool always_null = nullness::always_null; - static constexpr bool is_null(std::optional const &v) noexcept - { - return ((not v.has_value()) or pqxx::is_null(*v)); - } - static constexpr std::optional null() { return {}; } -}; - - -template -inline constexpr format param_format(std::optional const &value) -{ - return param_format(*value); -} - - -template struct string_traits> -{ - static char *into_buf(char *begin, char *end, std::optional const &value) - { - return string_traits::into_buf(begin, end, *value); - } - - static zview to_buf(char *begin, char *end, std::optional const &value) - { - if (value.has_value()) - return string_traits::to_buf(begin, end, *value); - else - return {}; - } - - static std::optional from_string(std::string_view text) - { - return std::optional{ - std::in_place, string_traits::from_string(text)}; - } - - static std::size_t size_buffer(std::optional const &value) noexcept - { - return pqxx::size_buffer(value.value()); - } -}; - - -template -inline constexpr bool is_unquoted_safe>{is_unquoted_safe}; - - -template struct nullness> -{ - static constexpr bool has_null = (nullness::has_null or ...); - static constexpr bool always_null = (nullness::always_null and ...); - static constexpr bool is_null(std::variant const &value) noexcept - { - return std::visit( - [](auto const &i) noexcept { - return nullness>::is_null(i); - }, - value); - } - - // We don't support `null()` for `std::variant`. - /** It would be technically possible to have a `null` in the case where just - * one of the types has a null, but it gets complicated and arbitrary. - */ - static constexpr std::variant null() = delete; -}; - - -template struct string_traits> -{ - static char * - into_buf(char *begin, char *end, std::variant const &value) - { - return std::visit( - [begin, end](auto const &i) { - return string_traits>::into_buf(begin, end, i); - }, - value); - } - static zview to_buf(char *begin, char *end, std::variant const &value) - { - return std::visit( - [begin, end](auto const &i) { - return string_traits>::to_buf(begin, end, i); - }, - value); - } - static std::size_t size_buffer(std::variant const &value) noexcept - { - return std::visit( - [](auto const &i) noexcept { return pqxx::size_buffer(i); }, value); - } - - /** There's no from_string for std::variant. We could have one with a rule - * like "pick the first type which fits the value," but we'd have to look - * into how natural that API feels to users. - */ - static std::variant from_string(std::string_view) = delete; -}; - - -template -inline constexpr format param_format(std::variant const &value) -{ - return std::visit([](auto &v) { return param_format(v); }, value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - (is_unquoted_safe and ...)}; - - -template inline T from_string(std::stringstream const &text) -{ - return from_string(text.str()); -} - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::nullptr_t) = delete; - - static constexpr zview - to_buf(char *, char *, std::nullptr_t const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::nullptr_t = nullptr) noexcept - { - return 0; - } - static std::nullptr_t from_string(std::string_view) = delete; -}; - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::nullopt_t) = delete; - - static constexpr zview - to_buf(char *, char *, std::nullopt_t const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::nullopt_t) noexcept - { - return 0; - } - static std::nullopt_t from_string(std::string_view) = delete; -}; - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::monostate) = delete; - - static constexpr zview - to_buf(char *, char *, std::monostate const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::monostate) noexcept - { - return 0; - } - static std::monostate from_string(std::string_view) = delete; -}; - - -template<> inline constexpr bool is_unquoted_safe{true}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(char const *t) noexcept - { - return t == nullptr; - } - static constexpr char const *null() noexcept { return nullptr; } -}; - - -/// String traits for C-style string ("pointer to char const"). -template<> struct string_traits -{ - static char const *from_string(std::string_view text) { return text.data(); } - - static zview to_buf(char *begin, char *end, char const *const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, char const *const &value) - { - auto const space{end - begin}; - // Count the trailing zero, even though std::strlen() and friends don't. - auto const len{std::strlen(value) + 1}; - if (space < ptrdiff_t(len)) - throw conversion_overrun{ - "Could not copy string: buffer too small. " + - pqxx::internal::state_buffer_overrun(space, len)}; - std::memmove(begin, value, len); - return begin + len; - } - - static std::size_t size_buffer(char const *const &value) noexcept - { - return std::strlen(value) + 1; - } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(char const *t) noexcept - { - return t == nullptr; - } - static constexpr char const *null() { return nullptr; } -}; - - -/// String traits for non-const C-style string ("pointer to char"). -template<> struct string_traits -{ - static char *into_buf(char *begin, char *end, char *const &value) - { - return string_traits::into_buf(begin, end, value); - } - static zview to_buf(char *begin, char *end, char *const &value) - { - return string_traits::to_buf(begin, end, value); - } - static std::size_t size_buffer(char *const &value) noexcept - { - return string_traits::size_buffer(value); - } - - /// Don't allow conversion to this type since it breaks const-safety. - static char *from_string(std::string_view) = delete; -}; - - -template struct nullness : no_null -{}; - - -/// String traits for C-style string constant ("array of char"). -/** @warning This assumes that every array-of-char is a C-style string literal. - * So, it must include a trailing zero. and it must have static duration. - */ -template struct string_traits -{ - static constexpr zview - to_buf(char *, char *, char const (&value)[N]) noexcept - { - return zview{value, N - 1}; - } - - static char *into_buf(char *begin, char *end, char const (&value)[N]) - { - if (internal::cmp_less(end - begin, size_buffer(value))) - throw conversion_overrun{ - "Could not convert char[] to string: too long for buffer."}; - std::memcpy(begin, value, N); - return begin + N; - } - static constexpr std::size_t size_buffer(char const (&)[N]) noexcept - { - return N; - } - - /// Don't allow conversion to this type. - static void from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -template<> struct string_traits -{ - static std::string from_string(std::string_view text) - { - return std::string{text}; - } - - static char *into_buf(char *begin, char *end, std::string const &value) - { - if (internal::cmp_greater_equal(std::size(value), end - begin)) - throw conversion_overrun{ - "Could not convert string to string: too long for buffer."}; - // Include the trailing zero. - value.copy(begin, std::size(value)); - begin[std::size(value)] = '\0'; - return begin + std::size(value) + 1; - } - - static zview to_buf(char *begin, char *end, std::string const &value) - { - return generic_to_buf(begin, end, value); - } - - static std::size_t size_buffer(std::string const &value) noexcept - { - return std::size(value) + 1; - } -}; - - -/// There's no real null for `std::string_view`. -/** I'm not sure how clear-cut this is: a `string_view` may have a null - * data pointer, which is analogous to a null `char` pointer. - */ -template<> struct nullness : no_null -{}; - - -/// String traits for `string_view`. -template<> struct string_traits -{ - static constexpr std::size_t - size_buffer(std::string_view const &value) noexcept - { - return std::size(value) + 1; - } - - static char *into_buf(char *begin, char *end, std::string_view const &value) - { - if (internal::cmp_greater_equal(std::size(value), end - begin)) - throw conversion_overrun{ - "Could not store string_view: too long for buffer."}; - value.copy(begin, std::size(value)); - begin[std::size(value)] = '\0'; - return begin + std::size(value) + 1; - } - - /// Don't convert to this type; it has nowhere to store its contents. - static std::string_view from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -/// String traits for `zview`. -template<> struct string_traits -{ - static constexpr std::size_t - size_buffer(std::string_view const &value) noexcept - { - return std::size(value) + 1; - } - - static char *into_buf(char *begin, char *end, zview const &value) - { - auto const size{std::size(value)}; - if (internal::cmp_less_equal(end - begin, std::size(value))) - throw conversion_overrun{"Not enough buffer space to store this zview."}; - value.copy(begin, size); - begin[size] = '\0'; - return begin + size + 1; - } - - static std::string_view to_buf(char *begin, char *end, zview const &value) - { - return {into_buf(begin, end, value), std::size(value)}; - } - - /// Don't convert to this type; it has nowhere to store its contents. - static zview from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -template<> struct string_traits -{ - static std::size_t size_buffer(std::stringstream const &) = delete; - - static std::stringstream from_string(std::string_view text) - { - std::stringstream stream; - stream.write(text.data(), std::streamsize(std::size(text))); - return stream; - } - - static char *into_buf(char *, char *, std::stringstream const &) = delete; - static std::string_view - to_buf(char *, char *, std::stringstream const &) = delete; -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::nullptr_t const &) noexcept - { - return true; - } - static constexpr std::nullptr_t null() noexcept { return nullptr; } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::nullopt_t const &) noexcept - { - return true; - } - static constexpr std::nullopt_t null() noexcept { return std::nullopt; } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::monostate const &) noexcept - { - return true; - } - static constexpr std::monostate null() noexcept { return {}; } -}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(std::unique_ptr const &t) noexcept - { - return not t or pqxx::is_null(*t); - } - static constexpr std::unique_ptr null() { return {}; } -}; - - -template -struct string_traits> -{ - static std::unique_ptr from_string(std::string_view text) - { - return std::make_unique(string_traits::from_string(text)); - } - - static char * - into_buf(char *begin, char *end, std::unique_ptr const &value) - { - return string_traits::into_buf(begin, end, *value); - } - - static zview - to_buf(char *begin, char *end, std::unique_ptr const &value) - { - if (value) - return string_traits::to_buf(begin, end, *value); - else - return {}; - } - - static std::size_t - size_buffer(std::unique_ptr const &value) noexcept - { - return pqxx::size_buffer(*value.get()); - } -}; - - -template -inline format param_format(std::unique_ptr const &value) -{ - return param_format(*value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - is_unquoted_safe}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(std::shared_ptr const &t) noexcept - { - return not t or pqxx::is_null(*t); - } - static constexpr std::shared_ptr null() { return {}; } -}; - - -template struct string_traits> -{ - static std::shared_ptr from_string(std::string_view text) - { - return std::make_shared(string_traits::from_string(text)); - } - - static zview to_buf(char *begin, char *end, std::shared_ptr const &value) - { - return string_traits::to_buf(begin, end, *value); - } - static char * - into_buf(char *begin, char *end, std::shared_ptr const &value) - { - return string_traits::into_buf(begin, end, *value); - } - static std::size_t size_buffer(std::shared_ptr const &value) noexcept - { - return pqxx::size_buffer(*value); - } -}; - - -template format param_format(std::shared_ptr const &value) -{ - return param_format(*value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - is_unquoted_safe}; - - -template<> -struct nullness> - : no_null> -{}; - - -#if defined(PQXX_HAVE_CONCEPTS) -template struct nullness : no_null -{}; - - -template inline constexpr format param_format(DATA const &) -{ - return format::binary; -} - - -template struct string_traits -{ - static std::size_t size_buffer(DATA const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf(char *begin, char *end, DATA const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, DATA const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - static DATA from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::basic_string buf; - buf.resize(size); - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.data())); - return buf; - } -}; -#endif // PQXX_HAVE_CONCEPTS - - -template<> struct string_traits> -{ - static std::size_t - size_buffer(std::basic_string const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview - to_buf(char *begin, char *end, std::basic_string const &value) - { - return generic_to_buf(begin, end, value); - } - - static char * - into_buf(char *begin, char *end, std::basic_string const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - static std::basic_string from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::basic_string buf; - buf.resize(size); - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.data())); - return buf; - } -}; - - -template<> -inline constexpr format param_format(std::basic_string const &) -{ - return format::binary; -} - - -template<> -struct nullness> - : no_null> -{}; - - -template<> struct string_traits> -{ - static std::size_t - size_buffer(std::basic_string_view const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf( - char *begin, char *end, std::basic_string_view const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf( - char *begin, char *end, std::basic_string_view const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - // There's no from_string, because there's nobody to hold the data. -}; - -template<> -inline constexpr format param_format(std::basic_string_view const &) -{ - return format::binary; -} -} // namespace pqxx - - -namespace pqxx::internal -{ -/// String traits for SQL arrays. -template struct array_string_traits -{ -private: - using elt_type = strip_t>; - using elt_traits = string_traits; - static constexpr zview s_null{"NULL"}; - -public: - static zview to_buf(char *begin, char *end, Container const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, Container const &value) - { - std::size_t const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to convert array to string."}; - - char *here = begin; - *here++ = '{'; - - bool nonempty{false}; - for (auto const &elt : value) - { - if (is_null(elt)) - { - s_null.copy(here, std::size(s_null)); - here += std::size(s_null); - } - else if constexpr (is_sql_array) - { - // Render nested array in-place. Then erase the trailing zero. - here = elt_traits::into_buf(here, end, elt) - 1; - } - else if constexpr (is_unquoted_safe) - { - // No need to quote or escape. Just convert the value straight into - // its place in the array, and "backspace" the trailing zero. - here = elt_traits::into_buf(here, end, elt) - 1; - } - else - { - *here++ = '"'; - - // Use the tail end of the destination buffer as an intermediate - // buffer. - auto const elt_budget{pqxx::size_buffer(elt)}; - for (char const c : elt_traits::to_buf(end - elt_budget, end, elt)) - { - if (c == '\\' or c == '"') - *here++ = '\\'; - *here++ = c; - } - *here++ = '"'; - } - *here++ = array_separator; - nonempty = true; - } - - // Erase that last comma, if present. - if (nonempty) - here--; - - *here++ = '}'; - *here++ = '\0'; - - return here; - } - - static std::size_t size_buffer(Container const &value) noexcept - { - if constexpr (is_unquoted_safe) - return 3 + std::accumulate( - std::begin(value), std::end(value), std::size_t{}, - [](std::size_t acc, elt_type const &elt) { - return acc + - (pqxx::is_null(elt) ? - std::size(s_null) : - elt_traits::size_buffer(elt)) - - 1; - }); - else - return 3 + std::accumulate( - std::begin(value), std::end(value), std::size_t{}, - [](std::size_t acc, elt_type const &elt) { - // Opening and closing quotes, plus worst-case escaping, - // but don't count the trailing zeroes. - std::size_t const elt_size{ - pqxx::is_null(elt) ? std::size(s_null) : - elt_traits::size_buffer(elt) - 1}; - return acc + 2 * elt_size + 2; - }); - } - - // We don't yet support parsing of array types using from_string. Doing so - // would require a reference to the connection. -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -template -struct nullness> : no_null> -{}; - - -template -struct string_traits> - : internal::array_string_traits> -{}; - - -/// We don't know how to pass array params in binary format, so pass as text. -template -inline constexpr format param_format(std::vector const &) -{ - return format::text; -} - - -/// A `std::vector` is a binary string. Other vectors are not. -template -inline constexpr format param_format(std::vector const &) -{ - return format::binary; -} - - -template inline constexpr bool is_sql_array>{true}; - - -template -struct nullness> : no_null> -{}; - - -template -struct string_traits> - : internal::array_string_traits> -{}; - - -/// We don't know how to pass array params in binary format, so pass as text. -template -inline constexpr format param_format(std::array const &) -{ - return format::text; -} - - -/// An array of `std::byte` is a binary string. -template -inline constexpr format param_format(std::array const &) -{ - return format::binary; -} - - -template -inline constexpr bool is_sql_array>{true}; -} // namespace pqxx - - -namespace pqxx -{ -template inline std::string to_string(T const &value) -{ - if (is_null(value)) - throw conversion_error{ - "Attempt to convert null " + type_name + " to a string."}; - - std::string buf; - // We can't just reserve() space; modifying the terminating zero leads to - // undefined behaviour. - buf.resize(size_buffer(value)); - auto const data{buf.data()}; - auto const end{ - string_traits::into_buf(data, data + std::size(buf), value)}; - buf.resize(static_cast(end - data - 1)); - return buf; -} - - -template<> inline std::string to_string(float const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(double const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(long double const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(std::stringstream const &value) -{ - return value.str(); -} - - -template inline void into_string(T const &value, std::string &out) -{ - if (is_null(value)) - throw conversion_error{ - "Attempt to convert null " + type_name + " to a string."}; - - // We can't just reserve() data; modifying the terminating zero leads to - // undefined behaviour. - out.resize(size_buffer(value) + 1); - auto const data{out.data()}; - auto const end{ - string_traits::into_buf(data, data + std::size(out), value)}; - out.resize(static_cast(end - data - 1)); -} -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/encoding_group.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/encoding_group.hxx deleted file mode 100644 index e17736e5b..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/encoding_group.hxx +++ /dev/null @@ -1,60 +0,0 @@ -/** Enum type for supporting encodings in libpqxx - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ENCODING_GROUP -#define PQXX_H_ENCODING_GROUP - -#include - -namespace pqxx::internal -{ -// Types of encodings supported by PostgreSQL, see -// https://www.postgresql.org/docs/current/static/multibyte.html#CHARSET-TABLE -enum class encoding_group -{ - // Handles all single-byte fixed-width encodings - MONOBYTE, - - // Multibyte encodings. - // Many of these can embed ASCII-like bytes inside multibyte characters, - // notably Big5, SJIS, SHIFT_JIS_2004, GP18030, GBK, JOHAB, UHC. - BIG5, - EUC_CN, - // TODO: Merge EUC_JP and EUC_JIS_2004? - EUC_JP, - EUC_JIS_2004, - EUC_KR, - EUC_TW, - GB18030, - GBK, - JOHAB, - MULE_INTERNAL, - // TODO: Merge SJIS and SHIFT_JIS_2004? - SJIS, - SHIFT_JIS_2004, - UHC, - UTF8, -}; - - -// TODO:: Can we just use string_view now? -/// Function type: "find the end of the current glyph." -/** This type of function takes a text buffer, and a location in that buffer, - * and returns the location one byte past the end of the current glyph. - * - * The start offset marks the beginning of the current glyph. It must fall - * within the buffer. - * - * There are multiple different glyph scanner implementations, for different - * kinds of encodings. - */ -using glyph_scanner_func = - std::size_t(char const buffer[], std::size_t buffer_len, std::size_t start); -} // namespace pqxx::internal - -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/encodings.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/encodings.hxx deleted file mode 100644 index ba7fecc70..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/encodings.hxx +++ /dev/null @@ -1,90 +0,0 @@ -/** Internal string encodings support for libpqxx - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ENCODINGS -#define PQXX_H_ENCODINGS - -#include "pqxx/internal/encoding_group.hxx" - -#include -#include - - -namespace pqxx::internal -{ -char const *name_encoding(int encoding_id); - -/// Convert libpq encoding enum or encoding name to its libpqxx group. -encoding_group enc_group(int /* libpq encoding ID */); -encoding_group enc_group(std::string_view); - - -/// Look up the glyph scanner function for a given encoding group. -/** To identify the glyph boundaries in a buffer, call this to obtain the - * scanner function appropriate for the buffer's encoding. Then, repeatedly - * call the scanner function to find the glyphs. - */ -PQXX_LIBEXPORT glyph_scanner_func *get_glyph_scanner(encoding_group); - - -// TODO: For ASCII search, treat UTF8/EUC_*/MULE_INTERNAL as MONOBYTE. - -/// Find any of the ASCII characters `NEEDLE` in `haystack`. -/** Scans through `haystack` until it finds a single-byte character that - * matches any value in `NEEDLE`. - * - * If it finds one, returns its offset. If not, returns the end of the - * haystack. - */ -template -inline std::size_t find_char( - glyph_scanner_func *scanner, std::string_view haystack, - std::size_t here = 0u) -{ - auto const sz{std::size(haystack)}; - auto const data{std::data(haystack)}; - while (here < sz) - { - auto next{scanner(data, sz, here)}; - // (For some reason gcc had a problem with a right-fold here. But clang - // was fine.) - if ((... or (data[here] == NEEDLE))) - { - // Also check against a multibyte character starting with a bytes which - // just happens to match one of the ASCII bytes we're looking for. It'd - // be cleaner to check that first, but either works. So, let's apply the - // most selective filter first and skip this check in almost all cases. - if (next == here + 1) - return here; - } - - // Nope, no hit. Move on. - here = next; - } - return sz; -} - - -/// Iterate over the glyphs in a buffer. -/** Scans the glyphs in the buffer, and for each, passes its begin and its - * one-past-end pointers to `callback`. - */ -template -inline void for_glyphs( - encoding_group enc, CALLABLE callback, char const buffer[], - std::size_t buffer_len, std::size_t start = 0) -{ - auto const scan{get_glyph_scanner(enc)}; - for (std::size_t here = start, next; here < buffer_len; here = next) - { - next = scan(buffer, buffer_len, here); - callback(buffer + here, buffer + next); - } -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-errorhandler.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-errorhandler.hxx deleted file mode 100644 index ffc12a6cf..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-errorhandler.hxx +++ /dev/null @@ -1,26 +0,0 @@ -#include - -namespace pqxx -{ -class connection; -class errorhandler; -} // namespace pqxx - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_errorhandler : callgate -{ - friend class pqxx::errorhandler; - - connection_errorhandler(reference x) : super(x) {} - - void register_errorhandler(errorhandler *h) - { - home().register_errorhandler(h); - } - void unregister_errorhandler(errorhandler *h) - { - home().unregister_errorhandler(h); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-largeobject.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-largeobject.hxx deleted file mode 100644 index 49feaf9e6..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-largeobject.hxx +++ /dev/null @@ -1,35 +0,0 @@ -#include - -#include -#include - -namespace pqxx -{ -class blob; -class largeobject; -} // namespace pqxx - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_largeobject : callgate -{ - friend class pqxx::blob; - friend class pqxx::largeobject; - - connection_largeobject(reference x) : super(x) {} - - pq::PGconn *raw_connection() const { return home().raw_connection(); } -}; - - -class PQXX_PRIVATE const_connection_largeobject : callgate -{ - friend class pqxx::blob; - friend class pqxx::largeobject; - - const_connection_largeobject(reference x) : super(x) {} - - std::string error_message() const { return home().err_msg(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-notification_receiver.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-notification_receiver.hxx deleted file mode 100644 index 0bcb2db17..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-notification_receiver.hxx +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#include "pqxx/connection.hxx" - - -namespace pqxx -{ -class notification_receiver; -} - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_notification_receiver : callgate -{ - friend class pqxx::notification_receiver; - - connection_notification_receiver(reference x) : super(x) {} - - void add_receiver(notification_receiver *receiver) - { - home().add_receiver(receiver); - } - void remove_receiver(notification_receiver *receiver) noexcept - { - home().remove_receiver(receiver); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-pipeline.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-pipeline.hxx deleted file mode 100644 index c6ae6e17a..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-pipeline.hxx +++ /dev/null @@ -1,23 +0,0 @@ -#include "pqxx/internal/libpq-forward.hxx" -#include - -#include "pqxx/pipeline.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_pipeline : callgate -{ - friend class pqxx::pipeline; - - connection_pipeline(reference x) : super(x) {} - - void start_exec(char const query[]) { home().start_exec(query); } - pqxx::internal::pq::PGresult *get_result() { return home().get_result(); } - void cancel_query() { home().cancel_query(); } - - bool consume_input() noexcept { return home().consume_input(); } - bool is_busy() const noexcept { return home().is_busy(); } - - int encoding_id() { return home().encoding_id(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-sql_cursor.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-sql_cursor.hxx deleted file mode 100644 index 51a889844..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-sql_cursor.hxx +++ /dev/null @@ -1,19 +0,0 @@ -#include - -namespace pqxx::internal -{ -class sql_cursor; -} - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - - connection_sql_cursor(reference x) : super(x) {} - - result exec(char const query[]) { return home().exec(query); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-stream_from.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-stream_from.hxx deleted file mode 100644 index 8961e7146..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-stream_from.hxx +++ /dev/null @@ -1,15 +0,0 @@ -#include - -#include "pqxx/connection.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_stream_from : callgate -{ - friend class pqxx::stream_from; - - connection_stream_from(reference x) : super{x} {} - - auto read_copy_line() { return home().read_copy_line(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-stream_to.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-stream_to.hxx deleted file mode 100644 index a6974fb21..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-stream_to.hxx +++ /dev/null @@ -1,17 +0,0 @@ -#include - -#include "pqxx/stream_to.hxx" - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_stream_to : callgate -{ - friend class pqxx::stream_to; - - connection_stream_to(reference x) : super(x) {} - - void write_copy_line(std::string_view line) { home().write_copy_line(line); } - void end_copy_write() { home().end_copy_write(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-transaction.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-transaction.hxx deleted file mode 100644 index 74d659253..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/connection-transaction.hxx +++ /dev/null @@ -1,44 +0,0 @@ -#include - -namespace pqxx -{ -class connection; -} - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_transaction : callgate -{ - friend class pqxx::transaction_base; - - connection_transaction(reference x) : super(x) {} - - template result exec(STRING query, std::string_view desc) - { - return home().exec(query, desc); - } - - void register_transaction(transaction_base *t) - { - home().register_transaction(t); - } - void unregister_transaction(transaction_base *t) noexcept - { - home().unregister_transaction(t); - } - - auto read_copy_line() { return home().read_copy_line(); } - void write_copy_line(std::string_view line) { home().write_copy_line(line); } - void end_copy_write() { home().end_copy_write(); } - - result exec_prepared(zview statement, internal::c_params const &args) - { - return home().exec_prepared(statement, args); - } - - result exec_params(zview query, internal::c_params const &args) - { - return home().exec_params(query, args); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/errorhandler-connection.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/errorhandler-connection.hxx deleted file mode 100644 index 5560cedec..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/errorhandler-connection.hxx +++ /dev/null @@ -1,13 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE errorhandler_connection : callgate -{ - friend class pqxx::connection; - - errorhandler_connection(reference x) : super(x) {} - - void unregister() noexcept { home().unregister(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx deleted file mode 100644 index 296d22145..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx +++ /dev/null @@ -1,24 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE icursor_iterator_icursorstream : callgate -{ - friend class pqxx::icursorstream; - - icursor_iterator_icursorstream(reference x) : super(x) {} - - icursor_iterator::difference_type pos() const noexcept - { - return home().pos(); - } - - icursor_iterator *get_prev() { return home().m_prev; } - void set_prev(icursor_iterator *i) { home().m_prev = i; } - - icursor_iterator *get_next() { return home().m_next; } - void set_next(icursor_iterator *i) { home().m_next = i; } - - void fill(result const &r) { home().fill(r); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx deleted file mode 100644 index 56056d5ef..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx +++ /dev/null @@ -1,32 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE icursorstream_icursor_iterator : callgate -{ - friend class pqxx::icursor_iterator; - - icursorstream_icursor_iterator(reference x) : super(x) {} - - void insert_iterator(icursor_iterator *i) noexcept - { - home().insert_iterator(i); - } - - void remove_iterator(icursor_iterator *i) const noexcept - { - home().remove_iterator(i); - } - - icursorstream::size_type forward() { return home().forward(); } - icursorstream::size_type forward(icursorstream::size_type n) - { - return home().forward(n); - } - - void service_iterators(icursorstream::difference_type p) - { - home().service_iterators(p); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-connection.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-connection.hxx deleted file mode 100644 index daa0808c0..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-connection.hxx +++ /dev/null @@ -1,14 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_connection : callgate -{ - friend class pqxx::connection; - - result_connection(reference x) : super(x) {} - - operator bool() const { return bool(home()); } - bool operator!() const { return not home(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-creation.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-creation.hxx deleted file mode 100644 index 3d9205f2c..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-creation.hxx +++ /dev/null @@ -1,24 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_creation : callgate -{ - friend class pqxx::connection; - friend class pqxx::pipeline; - - result_creation(reference x) : super(x) {} - - static result create( - internal::pq::PGresult *rhs, std::shared_ptr const &query, - encoding_group enc) - { - return result(rhs, query, enc); - } - - void check_status(std::string_view desc = ""sv) const - { - return home().check_status(desc); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-pipeline.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-pipeline.hxx deleted file mode 100644 index 3ebe436d2..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-pipeline.hxx +++ /dev/null @@ -1,16 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_pipeline : callgate -{ - friend class pqxx::pipeline; - - result_pipeline(reference x) : super(x) {} - - std::shared_ptr query_ptr() const - { - return home().query_ptr(); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-sql_cursor.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-sql_cursor.hxx deleted file mode 100644 index 78b450739..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/result-sql_cursor.hxx +++ /dev/null @@ -1,13 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - - result_sql_cursor(reference x) : super(x) {} - - char const *cmd_status() const noexcept { return home().cmd_status(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/transaction-sql_cursor.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/transaction-sql_cursor.hxx deleted file mode 100644 index 4ed78dc93..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/transaction-sql_cursor.hxx +++ /dev/null @@ -1,10 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE transaction_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - transaction_sql_cursor(reference x) : super(x) {} -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/transaction-transaction_focus.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/gates/transaction-transaction_focus.hxx deleted file mode 100644 index ca7939a99..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/gates/transaction-transaction_focus.hxx +++ /dev/null @@ -1,30 +0,0 @@ -#include - -#include "pqxx/transaction_base.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE transaction_transaction_focus : callgate -{ - friend class pqxx::transaction_focus; - - transaction_transaction_focus(reference x) : super(x) {} - - void register_focus(transaction_focus *focus) - { - home().register_focus(focus); - } - void unregister_focus(transaction_focus *focus) noexcept - { - home().unregister_focus(focus); - } - void register_pending_error(zview error) - { - home().register_pending_error(error); - } - void register_pending_error(std::string &&error) - { - home().register_pending_error(std::move(error)); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/header-post.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/header-post.hxx deleted file mode 100644 index ff6bf8986..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/header-post.hxx +++ /dev/null @@ -1,22 +0,0 @@ -/* Compiler deficiency workarounds for compiling libpqxx headers. - * - * To be included at the end of each libpqxx header, in order to restore the - * client program's settings. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -// NO GUARDS HERE! This code should be executed every time! - -#if defined(_MSC_VER) -# pragma warning(pop) // Restore compiler's warning state -#endif - -#if !defined(PQXX_HEADER_PRE) -# error "Include pqxx/internal/header-post.hxx AFTER its 'pre' counterpart." -#endif - -#undef PQXX_HEADER_PRE diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/header-pre.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/header-pre.hxx deleted file mode 100644 index abc1a398d..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/header-pre.hxx +++ /dev/null @@ -1,169 +0,0 @@ -/* Compiler settings for compiling libpqxx headers, and workarounds for all. - * - * Include this before including any other libpqxx headers from within libpqxx. - * And to balance it out, also include header-post.hxx at the end of the batch - * of headers. - * - * The public libpqxx headers (e.g. ``) include this already; - * there's no need to do this from within an application. - * - * Include this file at the highest aggregation level possible to avoid nesting - * and to keep things simple. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ - -// NO GUARD HERE! This part should be included every time this file is. -#if defined(_MSC_VER) - -// Save compiler's warning state, and set warning level 4 for maximum -// sensitivity to warnings. -# pragma warning(push, 4) - -// Visual C++ generates some entirely unreasonable warnings. Disable them. -// Copy constructor could not be generated. -# pragma warning(disable : 4511) -// Assignment operator could not be generated. -# pragma warning(disable : 4512) -// Can't expose outside classes without exporting them. Except the MSVC docs -// say please ignore the warning if it's a standard library class. -# pragma warning(disable : 4251) -// Can't derive library classes from outside classes without exporting them. -// Except the MSVC docs say please ignore the warning if the parent class is -// in the standard library. -# pragma warning(disable : 4275) -// Can't inherit from non-exported class. -# pragma warning(disable : 4275) - -#endif // _MSC_VER - - -#if defined(PQXX_HEADER_PRE) -# error "Avoid nesting #include of pqxx/internal/header-pre.hxx." -#endif - -#define PQXX_HEADER_PRE - - -// Workarounds & definitions that need to be included even in library's headers -#include "pqxx/config-public-compiler.h" - -// Enable ISO-646 alternative operaotr representations: "and" instead of "&&" -// etc. on older compilers. C++20 removes this header. -#if __has_include() -# include -#endif - - -#if defined(PQXX_HAVE_GCC_PURE) -/// Declare function "pure": no side effects, only reads globals and its args. -# define PQXX_PURE __attribute__((pure)) -#else -# define PQXX_PURE /* pure */ -#endif - - -#if defined(__GNUC__) -/// Tell the compiler to optimise a function for size, not speed. -# define PQXX_COLD __attribute__((cold)) -#else -# define PQXX_COLD /* cold */ -#endif - - -// Workarounds for Windows -#ifdef _WIN32 - -/* For now, export DLL symbols if _DLL is defined. This is done automatically - * by the compiler when linking to the dynamic version of the runtime library, - * according to "gzh" - */ -# if defined(PQXX_SHARED) && !defined(PQXX_LIBEXPORT) -# define PQXX_LIBEXPORT __declspec(dllimport) -# endif // PQXX_SHARED && !PQXX_LIBEXPORT - - -// Workarounds for Microsoft Visual C++ -# ifdef _MSC_VER - -// Suppress vtables on abstract classes. -# define PQXX_NOVTABLE __declspec(novtable) - -// Automatically link with the appropriate libpq (static or dynamic, debug or -// release). The default is to use the release DLL. Define PQXX_PQ_STATIC to -// link to a static version of libpq, and _DEBUG to link to a debug version. -// The two may be combined. -# if defined(PQXX_AUTOLINK) -# if defined(PQXX_PQ_STATIC) -# ifdef _DEBUG -# pragma comment(lib, "libpqd") -# else -# pragma comment(lib, "libpq") -# endif -# else -# ifdef _DEBUG -# pragma comment(lib, "libpqddll") -# else -# pragma comment(lib, "libpqdll") -# endif -# endif -# endif - -// If we're not compiling libpqxx itself, automatically link with the -// appropriate libpqxx library. To link with the libpqxx DLL, define -// PQXX_SHARED; the default is to link with the static library. A static link -// is the recommended practice. -// -// The preprocessor macro PQXX_INTERNAL is used to detect whether we -// are compiling the libpqxx library itself. When you compile the library -// yourself using your own project file, make sure to include this macro. -# if defined(PQXX_AUTOLINK) && !defined(PQXX_INTERNAL) -# ifdef PQXX_SHARED -# ifdef _DEBUG -# pragma comment(lib, "libpqxxD") -# else -# pragma comment(lib, "libpqxx") -# endif -# else // !PQXX_SHARED -# ifdef _DEBUG -# pragma comment(lib, "libpqxx_staticD") -# else -# pragma comment(lib, "libpqxx_static") -# endif -# endif -# endif - -# endif // _MSC_VER - -#elif defined(PQXX_HAVE_GCC_VISIBILITY) // !_WIN32 - -# define PQXX_LIBEXPORT __attribute__((visibility("default"))) -# define PQXX_PRIVATE __attribute__((visibility("hidden"))) - -#endif // PQXX_HAVE_GCC_VISIBILITY - - -#ifndef PQXX_LIBEXPORT -# define PQXX_LIBEXPORT /* libexport */ -#endif - -#ifndef PQXX_PRIVATE -# define PQXX_PRIVATE /* private */ -#endif - -#ifndef PQXX_NOVTABLE -# define PQXX_NOVTABLE /* novtable */ -#endif - -// C++20: Assume support. -#if defined(PQXX_HAVE_LIKELY) -# define PQXX_LIKELY [[likely]] -# define PQXX_UNLIKELY [[unlikely]] -#else -# define PQXX_LIKELY /* [[likely]] */ -# define PQXX_UNLIKELY /* [[unlikely]] */ -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/ignore-deprecated-post.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/ignore-deprecated-post.hxx deleted file mode 100644 index cebcf0594..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/ignore-deprecated-post.hxx +++ /dev/null @@ -1,15 +0,0 @@ -/// End a code block started by "ignore-deprecated-pre.hxx". - -#if !defined(PQXX_IGNORING_DEPRECATED) -# error "Ended an 'ignore-deprecated' block while none was active." -#endif - -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#endif // __GNUC__ - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -#undef PQXX_IGNORING_DEPRECATED diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/ignore-deprecated-pre.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/ignore-deprecated-pre.hxx deleted file mode 100644 index 8ac57afaa..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/ignore-deprecated-pre.hxx +++ /dev/null @@ -1,28 +0,0 @@ -/** Start a block of deprecated code which may call other deprecated code. - * - * Most compilers will emit warnings when deprecated code is invoked from - * non-deprecated code. But some compilers (notably gcc) will always emit the - * warning even when the calling code is also deprecated. - * - * This header starts a block where those warnings are suppressed. It can be - * included inside a code block. - * - * Always match the #include with a closing #include of - * "ignore-deprecated-post.hxx". To avoid mistakes, keep the enclosed area as - * small as possible. - */ -#if defined(PQXX_IGNORING_DEPRECATED) -# error "Started an 'ignore-deprecated' block inside another." -#endif - -#define PQXX_IGNORING_DEPRECATED - -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif // __GNUC__ - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4996) -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/libpq-forward.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/libpq-forward.hxx deleted file mode 100644 index 9e74f79ec..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/libpq-forward.hxx +++ /dev/null @@ -1,31 +0,0 @@ -/** Minimal forward declarations of libpq types needed in libpqxx headers. - * - * DO NOT INCLUDE THIS FILE when building client programs. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -extern "C" -{ - struct pg_conn; - struct pg_result; - struct pgNotify; -} - -/// Forward declarations of libpq types as needed in libpqxx headers. -namespace pqxx::internal::pq -{ -using PGconn = pg_conn; -using PGresult = pg_result; -using PGnotify = pgNotify; -using PQnoticeProcessor = void (*)(void *, char const *); -} // namespace pqxx::internal::pq - -namespace pqxx -{ -/// PostgreSQL database row identifier. -using oid = unsigned int; -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/result_iter.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/result_iter.hxx deleted file mode 100644 index 1fa1f7d8a..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/result_iter.hxx +++ /dev/null @@ -1,124 +0,0 @@ -/** Result loops. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT_ITER -#define PQXX_H_RESULT_ITER - -#include - -#include "pqxx/strconv.hxx" - -namespace pqxx -{ -class result; -} // namespace pqxx - - -namespace pqxx::internal -{ -// C++20: Replace with generator? -/// Iterator for looped unpacking of a result. -template class result_iter -{ -public: - using value_type = std::tuple; - - /// Construct an "end" iterator. - result_iter() = default; - - explicit result_iter(result const &home) : - m_home{&home}, m_size{std::size(home)} - { - if (not std::empty(home)) - read(); - } - result_iter(result_iter const &) = default; - - result_iter &operator++() - { - m_index++; - if (m_index >= m_size) - m_home = nullptr; - else - read(); - return *this; - } - - /// Comparison only works for comparing to end(). - bool operator==(result_iter const &rhs) const - { - return m_home == rhs.m_home; - } - bool operator!=(result_iter const &rhs) const { return not(*this == rhs); } - - value_type const &operator*() const { return m_value; } - -private: - void read() { (*m_home)[m_index].convert(m_value); } - - result const *m_home{nullptr}; - result::size_type m_index{0}; - result::size_type m_size; - value_type m_value; -}; - - -template class result_iteration -{ -public: - using iterator = result_iter; - explicit result_iteration(result const &home) : m_home{home} - { - constexpr auto tup_size{sizeof...(TYPE)}; - if (home.columns() != tup_size) - throw usage_error{internal::concat( - "Tried to extract ", to_string(tup_size), - " field(s) from a result with ", to_string(home.columns()), - " column(s).")}; - } - iterator begin() const - { - if (std::size(m_home) == 0) - return end(); - else - return iterator{m_home}; - } - iterator end() const { return {}; } - -private: - pqxx::result const &m_home; -}; -} // namespace pqxx::internal - - -template inline auto pqxx::result::iter() const -{ - return pqxx::internal::result_iteration{*this}; -} - - -template -inline void pqxx::result::for_each(CALLABLE &&func) const -{ - using args_tuple = internal::args_t; - constexpr auto sz{std::tuple_size_v}; - static_assert( - sz > 0, - "Callback for for_each must take parameters, one for each column in the " - "result."); - - auto const cols{this->columns()}; - if (sz != cols) - throw usage_error{internal::concat( - "Callback to for_each takes ", sz, "parameter", (sz == 1) ? "" : "s", - ", but result set has ", cols, "field", (cols == 1) ? "" : "s", ".")}; - - using pass_tuple = pqxx::internal::strip_types_t; - for (auto const r : *this) std::apply(func, r.as_tuple()); -} -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/result_iterator.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/result_iterator.hxx deleted file mode 100644 index 3f27a1d3f..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/result_iterator.hxx +++ /dev/null @@ -1,389 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT_ITERATOR -#define PQXX_H_RESULT_ITERATOR - -#include "pqxx/row.hxx" - - -/* Result iterator. - * - * Don't include this header from your own application; it is included for you - * by other libpqxx headers. - */ - -namespace pqxx -{ -/// Iterator for rows in a result. Use as result::const_iterator. -/** A result, once obtained, cannot be modified. Therefore there is no - * plain iterator type for result. However its const_iterator type can be - * used to inspect its rows without changing them. - */ -class PQXX_LIBEXPORT const_result_iterator : public row -{ -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = row const; - using pointer = row const *; - using reference = row; - using size_type = result_size_type; - using difference_type = result_difference_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create an iterator, but in an unusable state. - const_result_iterator() noexcept = default; - /// Copy an iterator. - const_result_iterator(const_result_iterator const &) noexcept = default; - /// Move an iterator. - const_result_iterator(const_result_iterator &&) noexcept = default; - - /// Begin iterating a @ref row. - const_result_iterator(row const &t) noexcept : row{t} {} -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /** - * @name Dereferencing operators - * - * An iterator "points to" its own row, which is also itself. This makes it - * easy to address a @ref result as a two-dimensional container, without - * going through the intermediate step of dereferencing the iterator. It - * makes the interface similar to C pointer/array semantics. - * - * IIRC Alex Stepanov, the inventor of the STL, once remarked that having - * this as standard behaviour for pointers would be useful in some - * algorithms. So even if this makes me look foolish, I would seem to be in - * distinguished company. - */ - //@{ - /// Dereference the iterator. - [[nodiscard]] pointer operator->() const { return this; } - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Dereference the iterator. - [[nodiscard]] reference operator*() const { return *this; } -#include "pqxx/internal/ignore-deprecated-post.hxx" - //@} - - /** - * @name Field access - */ - //@{ - using row::back; - using row::front; - using row::operator[]; - using row::at; - using row::rownumber; - //@} - - /** - * @name Manipulations - */ - //@{ - const_result_iterator &operator=(const_result_iterator const &rhs) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::operator=(rhs); -#include "pqxx/internal/ignore-deprecated-post.hxx" - return *this; - } - - const_result_iterator &operator=(const_result_iterator &&rhs) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::operator=(std::move(rhs)); -#include "pqxx/internal/ignore-deprecated-post.hxx" - return *this; - } - - const_result_iterator operator++(int); - const_result_iterator &operator++() - { - ++m_index; - return *this; - } - const_result_iterator operator--(int); - const_result_iterator &operator--() - { - --m_index; - return *this; - } - - const_result_iterator &operator+=(difference_type i) - { - m_index += i; - return *this; - } - const_result_iterator &operator-=(difference_type i) - { - m_index -= i; - return *this; - } - - /// Interchange two iterators in an exception-safe manner. - void swap(const_result_iterator &other) noexcept - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::swap(other); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool operator==(const_result_iterator const &i) const - { - return m_index == i.m_index; - } - [[nodiscard]] bool operator!=(const_result_iterator const &i) const - { - return m_index != i.m_index; - } - [[nodiscard]] bool operator<(const_result_iterator const &i) const - { - return m_index < i.m_index; - } - [[nodiscard]] bool operator<=(const_result_iterator const &i) const - { - return m_index <= i.m_index; - } - [[nodiscard]] bool operator>(const_result_iterator const &i) const - { - return m_index > i.m_index; - } - [[nodiscard]] bool operator>=(const_result_iterator const &i) const - { - return m_index >= i.m_index; - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] inline const_result_iterator operator+(difference_type) const; - friend const_result_iterator - operator+(difference_type, const_result_iterator const &); - [[nodiscard]] inline const_result_iterator operator-(difference_type) const; - [[nodiscard]] inline difference_type - operator-(const_result_iterator const &) const; - //@} - -private: - friend class pqxx::result; - const_result_iterator(pqxx::result const *r, result_size_type i) noexcept : - row{*r, i, r->columns()} - {} -}; - - -/// Reverse iterator for result. Use as result::const_reverse_iterator. -class PQXX_LIBEXPORT const_reverse_result_iterator - : private const_result_iterator -{ -public: - using super = const_result_iterator; - using iterator_type = const_result_iterator; - using iterator_type::difference_type; - using iterator_type::iterator_category; - using iterator_type::pointer; - using value_type = iterator_type::value_type; - using reference = iterator_type::reference; - - /// Create an iterator, but in an unusable state. - const_reverse_result_iterator() = default; - /// Copy an iterator. - const_reverse_result_iterator(const_reverse_result_iterator const &rhs) = - default; - /// Copy a reverse iterator from a regular iterator. - explicit const_reverse_result_iterator(const_result_iterator const &rhs) : - const_result_iterator{rhs} - { - super::operator--(); - } - - /// Move a regular iterator into a reverse iterator. - explicit const_reverse_result_iterator(const_result_iterator const &&rhs) : - const_result_iterator{std::move(rhs)} - { - super::operator--(); - } - - /// Return the underlying "regular" iterator (as per standard library). - [[nodiscard]] PQXX_PURE const_result_iterator base() const noexcept; - - /** - * @name Dereferencing operators - */ - //@{ - /// Dereference iterator. - using const_result_iterator::operator->; - /// Dereference iterator. - using const_result_iterator::operator*; - //@} - - /** - * @name Field access - */ - //@{ - using const_result_iterator::back; - using const_result_iterator::front; - using const_result_iterator::operator[]; - using const_result_iterator::at; - using const_result_iterator::rownumber; - //@} - - /** - * @name Manipulations - */ - //@{ - const_reverse_result_iterator & - operator=(const_reverse_result_iterator const &r) - { - iterator_type::operator=(r); - return *this; - } - const_reverse_result_iterator &operator=(const_reverse_result_iterator &&r) - { - iterator_type::operator=(std::move(r)); - return *this; - } - const_reverse_result_iterator &operator++() - { - iterator_type::operator--(); - return *this; - } - const_reverse_result_iterator operator++(int); - const_reverse_result_iterator &operator--() - { - iterator_type::operator++(); - return *this; - } - const_reverse_result_iterator operator--(int); - const_reverse_result_iterator &operator+=(difference_type i) - { - iterator_type::operator-=(i); - return *this; - } - const_reverse_result_iterator &operator-=(difference_type i) - { - iterator_type::operator+=(i); - return *this; - } - - void swap(const_reverse_result_iterator &other) noexcept - { - const_result_iterator::swap(other); - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] const_reverse_result_iterator - operator+(difference_type i) const - { - return const_reverse_result_iterator(base() - i); - } - [[nodiscard]] const_reverse_result_iterator operator-(difference_type i) - { - return const_reverse_result_iterator(base() + i); - } - [[nodiscard]] difference_type - operator-(const_reverse_result_iterator const &rhs) const - { - return rhs.const_result_iterator::operator-(*this); - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool - operator==(const_reverse_result_iterator const &rhs) const noexcept - { - return iterator_type::operator==(rhs); - } - [[nodiscard]] bool - operator!=(const_reverse_result_iterator const &rhs) const noexcept - { - return not operator==(rhs); - } - - [[nodiscard]] bool operator<(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator>(rhs); - } - [[nodiscard]] bool operator<=(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator>=(rhs); - } - [[nodiscard]] bool operator>(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator<(rhs); - } - [[nodiscard]] bool operator>=(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator<=(rhs); - } - //@} -}; - - -inline const_result_iterator -const_result_iterator::operator+(result::difference_type o) const -{ - return {&m_result, size_type(result::difference_type(m_index) + o)}; -} - -inline const_result_iterator -operator+(result::difference_type o, const_result_iterator const &i) -{ - return i + o; -} - -inline const_result_iterator -const_result_iterator::operator-(result::difference_type o) const -{ - return {&m_result, result_size_type(result::difference_type(m_index) - o)}; -} - -inline result::difference_type -const_result_iterator::operator-(const const_result_iterator &i) const -{ - return result::difference_type(num() - i.num()); -} - -inline const_result_iterator result::end() const noexcept -{ - return {this, size()}; -} - - -inline const_result_iterator result::cend() const noexcept -{ - return end(); -} - - -inline const_reverse_result_iterator -operator+(result::difference_type n, const_reverse_result_iterator const &i) -{ - return const_reverse_result_iterator{i.base() - n}; -} - -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/sql_cursor.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/sql_cursor.hxx deleted file mode 100644 index a26d06306..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/sql_cursor.hxx +++ /dev/null @@ -1,118 +0,0 @@ -/** Internal wrapper for SQL cursors. Supports higher-level cursor classes. - * - * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SQL_CURSOR -#define PQXX_H_SQL_CURSOR - -namespace pqxx::internal -{ -/// Cursor with SQL positioning semantics. -/** Thin wrapper around an SQL cursor, with SQL's ideas of positioning. - * - * SQL cursors have pre-increment/pre-decrement semantics, with on either end - * of the result set a special position that does not repesent a row. This - * class models SQL cursors for the purpose of implementing more C++-like - * semantics on top. - * - * Positions of actual rows are numbered starting at 1. Position 0 exists but - * does not refer to a row. There is a similar non-row position at the end of - * the result set. - * - * Don't use this at home. You deserve better. Use the stateles_cursor - * instead. - */ -class PQXX_LIBEXPORT sql_cursor : public cursor_base -{ -public: - sql_cursor( - transaction_base &t, std::string_view query, std::string_view cname, - cursor_base::access_policy ap, cursor_base::update_policy up, - cursor_base::ownership_policy op, bool hold); - - sql_cursor( - transaction_base &t, std::string_view cname, - cursor_base::ownership_policy op); - - ~sql_cursor() noexcept { close(); } - - result fetch(difference_type rows, difference_type &displacement); - result fetch(difference_type rows) - { - difference_type d = 0; - return fetch(rows, d); - } - difference_type move(difference_type rows, difference_type &displacement); - difference_type move(difference_type rows) - { - difference_type d = 0; - return move(rows, d); - } - - /// Current position, or -1 for unknown - /** - * The starting position, just before the first row, counts as position zero. - * - * Position may be unknown if (and only if) this cursor was adopted, and has - * never hit its starting position (position zero). - */ - difference_type pos() const noexcept { return m_pos; } - - /// End position, or -1 for unknown - /** - * Returns the final position, just after the last row in the result set. The - * starting position, just before the first row, counts as position zero. - * - * End position is unknown until it is encountered during use. - */ - difference_type endpos() const noexcept { return m_endpos; } - - /// Return zero-row result for this cursor. - result const &empty_result() const noexcept { return m_empty_result; } - - void close() noexcept; - -private: - difference_type adjust(difference_type hoped, difference_type actual); - static std::string stridestring(difference_type); - /// Initialize cached empty result. Call only at beginning or end! - void init_empty_result(transaction_base &); - - /// Connection in which this cursor lives. - connection &m_home; - - /// Zero-row result from this cursor (or plain empty one if cursor is - /// adopted) - result m_empty_result; - - result m_cached_current_row; - - /// Is this cursor adopted (as opposed to created by this cursor object)? - bool m_adopted; - - /// Will this cursor object destroy its SQL cursor when it dies? - cursor_base::ownership_policy m_ownership; - - /// At starting position (-1), somewhere in the middle (0), or past end (1) - int m_at_end; - - /// Position, or -1 for unknown - difference_type m_pos; - - /// End position, or -1 for unknown - difference_type m_endpos = -1; -}; - - -PQXX_LIBEXPORT result_size_type obtain_stateless_cursor_size(sql_cursor &); -PQXX_LIBEXPORT result stateless_cursor_retrieve( - sql_cursor &, result::difference_type size, - result::difference_type begin_pos, result::difference_type end_pos); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/statement_parameters.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/statement_parameters.hxx deleted file mode 100644 index b078bf6e0..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/statement_parameters.hxx +++ /dev/null @@ -1,131 +0,0 @@ -/** Common implementation for statement parameter lists. - * - * These are used for both prepared statements and parameterized statements. - * - * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STATEMENT_PARAMETER -#define PQXX_H_STATEMENT_PARAMETER - -#include -#include -#include -#include -#include - -#include "pqxx/binarystring.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/util.hxx" - - -namespace pqxx::internal -{ -template -constexpr inline auto const iterator_identity{ - [](decltype(*std::declval()) x) { return x; }}; - - -/// Marker type: pass a dynamically-determined number of statement parameters. -/** @deprecated Use @ref params instead. - * - * Normally when invoking a prepared or parameterised statement, the number - * of parameters is known at compile time. For instance, - * `t.exec_prepared("foo", 1, "x");` executes statement `foo` with two - * parameters, an `int` and a C string. - * - * But sometimes you may want to pass a number of parameters known only at run - * time. In those cases, a @ref dynamic_params encodes a dynamically - * determined number of parameters. You can mix these with regular, static - * parameter lists, and you can re-use them for multiple statement invocations. - * - * A dynamic_params object does not store copies of its parameters, so make - * sure they remain accessible until you've executed the statement. - * - * The ACCESSOR is an optional callable (such as a lambda). If you pass an - * accessor `a`, then each parameter `p` goes into your statement as `a(p)`. - */ -template)> -class dynamic_params -{ -public: - /// Wrap a sequence of pointers or iterators. - constexpr dynamic_params(IT begin, IT end) : - m_begin(begin), m_end(end), m_accessor(iterator_identity) - {} - - /// Wrap a sequence of pointers or iterators. - /** This version takes an accessor callable. If you pass an accessor `acc`, - * then any parameter `p` will go into the statement's parameter list as - * `acc(p)`. - */ - constexpr dynamic_params(IT begin, IT end, ACCESSOR &acc) : - m_begin(begin), m_end(end), m_accessor(acc) - {} - - /// Wrap a container. - template - explicit constexpr dynamic_params(C &container) : - dynamic_params(std::begin(container), std::end(container)) - {} - - /// Wrap a container. - /** This version takes an accessor callable. If you pass an accessor `acc`, - * then any parameter `p` will go into the statement's parameter list as - * `acc(p)`. - */ - template - explicit constexpr dynamic_params(C &container, ACCESSOR &acc) : - dynamic_params(std::begin(container), std::end(container), acc) - {} - - constexpr IT begin() const noexcept { return m_begin; } - constexpr IT end() const noexcept { return m_end; } - - constexpr auto access(decltype(*std::declval()) value) const - -> decltype(std::declval()(value)) - { - return m_accessor(value); - } - -private: - IT const m_begin, m_end; - ACCESSOR m_accessor = iterator_identity; -}; - - -/// Internal type: encode statement parameters. -/** Compiles arguments for prepared statements and parameterised queries into - * a format that can be passed into libpq. - * - * Objects of this type are meant to be short-lived: a `c_params` lives and - * dies entirely within the call to execute. So, for example, if you pass in a - * non-null pointer as a parameter, @ref params may simply use that pointer as - * a parameter value, without arranging longer-term storage for the data to - * which it points. All values referenced by parameters must remain "live" - * until the parameterised or prepared statement has been executed. - */ -struct PQXX_LIBEXPORT c_params -{ - c_params() = default; - /// Copying these objects is pointless and expensive. Don't do it. - c_params(c_params const &) = delete; - c_params(c_params &&) = default; - - /// Pre-allocate storage for `n` parameters. - void reserve(std::size_t n) &; - - /// As used by libpq: pointers to parameter values. - std::vector values; - /// As used by libpq: lengths of non-null arguments, in bytes. - std::vector lengths; - /// As used by libpq: effectively boolean "is this a binary parameter?" - std::vector formats; -}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/stream_iterator.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/stream_iterator.hxx deleted file mode 100644 index f240dcfa7..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/stream_iterator.hxx +++ /dev/null @@ -1,105 +0,0 @@ -/** Stream iterators. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_ITERATOR -#define PQXX_H_STREAM_ITERATOR - -#include - -namespace pqxx -{ -class stream_from; -} - - -namespace pqxx::internal -{ -// C++20: Replace with generator? -/// Input iterator for stream_from. -/** Just barely enough to support range-based "for" loops. Don't assume that - * any of the usual behaviour works beyond that. - */ -template class stream_input_iterator -{ -public: - using value_type = std::tuple; - - /// Construct an "end" iterator. - stream_input_iterator() = default; - - explicit stream_input_iterator(stream_from &home) : m_home(&home) - { - advance(); - } - stream_input_iterator(stream_input_iterator const &) = default; - - stream_input_iterator &operator++() - { - advance(); - return *this; - } - - value_type const &operator*() const { return m_value; } - - /// Comparison only works for comparing to end(). - bool operator==(stream_input_iterator const &rhs) const - { - return m_home == rhs.m_home; - } - /// Comparison only works for comparing to end(). - bool operator!=(stream_input_iterator const &rhs) const - { - return not(*this == rhs); - } - -private: - void advance() - { - if (m_home == nullptr) - throw usage_error{"Moving stream_from iterator beyond end()."}; - if (not((*m_home) >> m_value)) - m_home = nullptr; - } - - stream_from *m_home{nullptr}; - value_type m_value; -}; - - -// C++20: Replace with generator? -/// Iteration over a @ref stream_from. -template class stream_input_iteration -{ -public: - using iterator = stream_input_iterator; - explicit stream_input_iteration(stream_from &home) : m_home{home} {} - iterator begin() const { return iterator{m_home}; } - iterator end() const { return {}; } - -private: - stream_from &m_home; -}; - - -// C++20: Replace with generator? -/// Iteration over a @ref stream_from, deleting it once done. -template class owning_stream_input_iteration -{ -public: - using iterator = stream_input_iterator; - explicit owning_stream_input_iteration(std::unique_ptr &&home) : - m_home{std::move(home)} - {} - iterator begin() const { return iterator{*m_home.get()}; } - iterator end() const { return {}; } - -private: - std::unique_ptr m_home; -}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/internal/wait.hxx b/ext/libpqxx-7.7.3/include/pqxx/internal/wait.hxx deleted file mode 100644 index 7a82e6553..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/internal/wait.hxx +++ /dev/null @@ -1,18 +0,0 @@ -#if !defined(PQXX_WAIT_HXX) -# define PQXX_WAIT_HXX - -namespace pqxx::internal -{ -/// Wait. -/** This is normally `std::this_thread::sleep_for()`. But MinGW's `thread` - * header doesn't work, so we must be careful about including it. - */ -void PQXX_LIBEXPORT wait_for(unsigned int microseconds); - - -/// Wait for a socket to be ready for reading/writing, or timeout. -PQXX_LIBEXPORT void wait_fd( - int fd, bool for_read, bool for_write, unsigned seconds = 1, - unsigned microseconds = 0); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/isolation b/ext/libpqxx-7.7.3/include/pqxx/isolation deleted file mode 100644 index 1b801329b..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/isolation +++ /dev/null @@ -1,8 +0,0 @@ -/** Transaction isolation levels. - * - * Policies and traits describing SQL transaction isolation levels - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/isolation.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/isolation.hxx b/ext/libpqxx-7.7.3/include/pqxx/isolation.hxx deleted file mode 100644 index 0698c6ab4..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/isolation.hxx +++ /dev/null @@ -1,75 +0,0 @@ -/* Definitions for transaction isolation levels, and such. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ISOLATION -#define PQXX_H_ISOLATION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Should a transaction be read-only, or read-write? -/** No, this is not an isolation level. So it really doesn't belong here. - * But it's not really worth a separate header. - */ -enum class write_policy -{ - read_only, - read_write -}; - - -/// Transaction isolation levels. -/** These are as defined in the SQL standard. But there are a few notes - * specific to PostgreSQL. - * - * First, postgres does not support "read uncommitted." The lowest level you - * can get is "read committed," which is better. PostgreSQL is built on the - * MVCC paradigm, which guarantees "read committed" isolation without any - * additional performance overhead, so there was no point in providing the - * lower level. - * - * Second, "repeatable read" also makes more isolation guarantees than the - * standard requires. According to the standard, this level prevents "dirty - * reads" and "nonrepeatable reads," but not "phantom reads." In postgres, - * it actually prevents all three. - * - * Third, "serializable" is only properly supported starting at postgres 9.1. - * If you request "serializable" isolation on an older backend, you will get - * the same isolation as in "repeatable read." It's better than the - * "repeatable read" defined in the SQL standard, but not a complete - * implementation of the standard's "serializable" isolation level. - * - * In general, a lower isolation level will allow more surprising interactions - * between ongoing transactions, but improve performance. A higher level - * gives you more protection from subtle concurrency bugs, but sometimes it - * may not be possible to complete your transaction without avoiding paradoxes - * in the data. In that case a transaction may fail, and the application will - * have to re-do the whole thing based on the latest state of the database. - * (If you want to retry your code in that situation, have a look at the - * transactor framework.) - * - * Study the levels and design your application with the right level in mind. - */ -enum isolation_level -{ - // PostgreSQL only has the better isolation levels. - // read_uncommitted, - - read_committed, - repeatable_read, - serializable, -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/largeobject b/ext/libpqxx-7.7.3/include/pqxx/largeobject deleted file mode 100644 index 1f2f94790..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/largeobject +++ /dev/null @@ -1,8 +0,0 @@ -/** Large Objects interface. - * - * Supports direct access to large objects, as well as through I/O streams - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/largeobject.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/largeobject.hxx b/ext/libpqxx-7.7.3/include/pqxx/largeobject.hxx deleted file mode 100644 index ebafc51d8..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/largeobject.hxx +++ /dev/null @@ -1,735 +0,0 @@ -/* Large Objects interface. Deprecated; use blob instead. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_LARGEOBJECT -#define PQXX_H_LARGEOBJECT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/dbtransaction.hxx" - - -namespace pqxx -{ -/// Identity of a large object. -/** @deprecated Use the @ref blob class instead. - * - * Encapsulates the identity of a large object. - * - * A largeobject must be accessed only from within a backend transaction, but - * the object's identity remains valid as long as the object exists. - */ -class PQXX_LIBEXPORT largeobject -{ -public: - using size_type = large_object_size_type; - - /// Refer to a nonexistent large object (similar to what a null pointer - /// does). - [[deprecated("Use blob instead.")]] largeobject() noexcept = default; - - /// Create new large object. - /** @param t Backend transaction in which the object is to be created. - */ - [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t); - - /// Wrap object with given oid. - /** Convert combination of a transaction and object identifier into a - * large object identity. Does not affect the database. - * @param o Object identifier for the given object. - */ - [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept : - m_id{o} - {} - - /// Import large object from a local file. - /** Creates a large object containing the data found in the given file. - * @param t Backend transaction in which the large object is to be created. - * @param file A filename on the client program's filesystem. - */ - [[deprecated("Use blob instead.")]] largeobject( - dbtransaction &t, std::string_view file); - - /// Take identity of an opened large object. - /** Copy identity of already opened large object. Note that this may be done - * as an implicit conversion. - * @param o Already opened large object to copy identity from. - */ - [[deprecated("Use blob instead.")]] largeobject( - largeobjectaccess const &o) noexcept; - - /// Object identifier. - /** The number returned by this function identifies the large object in the - * database we're connected to (or oid_none is returned if we refer to the - * null object). - */ - [[nodiscard]] oid id() const noexcept { return m_id; } - - /** - * @name Identity comparisons - * - * These operators compare the object identifiers of large objects. This has - * nothing to do with the objects' actual contents; use them only for keeping - * track of containers of references to large objects and such. - */ - //@{ - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator==(largeobject const &other) const - { - return m_id == other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator!=(largeobject const &other) const - { - return m_id != other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator<=(largeobject const &other) const - { - return m_id <= other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator>=(largeobject const &other) const - { - return m_id >= other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator<(largeobject const &other) const - { - return m_id < other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator>(largeobject const &other) const - { - return m_id > other.m_id; - } - //@} - - /// Export large object's contents to a local file - /** Writes the data stored in the large object to the given file. - * @param t Transaction in which the object is to be accessed - * @param file A filename on the client's filesystem - */ - void to_file(dbtransaction &t, std::string_view file) const; - - /// Delete large object from database - /** Unlike its low-level equivalent cunlink, this will throw an exception if - * deletion fails. - * @param t Transaction in which the object is to be deleted - */ - void remove(dbtransaction &t) const; - -protected: - PQXX_PURE static internal::pq::PGconn * - raw_connection(dbtransaction const &T); - - PQXX_PRIVATE std::string reason(connection const &, int err) const; - -private: - oid m_id = oid_none; -}; - - -/// Accessor for large object's contents. -/** @deprecated Use the `blob` class instead. - */ -class PQXX_LIBEXPORT largeobjectaccess : private largeobject -{ -public: - using largeobject::size_type; - using off_type = size_type; - using pos_type = size_type; - - /// Open mode: `in`, `out` (can be combined using "bitwise or"). - /** According to the C++ standard, these should be in `std::ios_base`. We - * take them from derived class `std::ios` instead, which is easier on the - * eyes. - * - * Historical note: taking it from std::ios was originally a workaround for a - * problem with gcc 2.95. - */ - using openmode = std::ios::openmode; - - /// Default open mode: in, out, binary. - static constexpr auto default_mode{ - std::ios::in | std::ios::out | std::ios::binary}; - - /// Seek direction: `beg`, `cur`, `end`. - using seekdir = std::ios::seekdir; - - /// Create new large object and open it. - /** - * @param t Backend transaction in which the object is to be created. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] explicit largeobjectaccess( - dbtransaction &t, openmode mode = default_mode); - - /// Open large object with given oid. - /** Convert combination of a transaction and object identifier into a - * large object identity. Does not affect the database. - * @param t Transaction in which the object is to be accessed. - * @param o Object identifier for the given object. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, oid o, openmode mode = default_mode); - - /// Open given large object. - /** Open a large object with the given identity for reading and/or writing. - * @param t Transaction in which the object is to be accessed. - * @param o Identity for the large object to be accessed. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, largeobject o, openmode mode = default_mode); - - /// Import large object from a local file and open it. - /** Creates a large object containing the data found in the given file. - * @param t Backend transaction in which the large object is to be created. - * @param file A filename on the client program's filesystem. - * @param mode Access mode, defaults to ios_base::in | ios_base::out. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, std::string_view file, openmode mode = default_mode); - - ~largeobjectaccess() noexcept { close(); } - - /// Object identifier. - /** The number returned by this function uniquely identifies the large object - * in the context of the database we're connected to. - */ - using largeobject::id; - - /// Export large object's contents to a local file. - /** Writes the data stored in the large object to the given file. - * @param file A filename on the client's filesystem. - */ - void to_file(std::string_view file) const - { - largeobject::to_file(m_trans, file); - } - - using largeobject::to_file; - - /** - * @name High-level access to object contents. - */ - //@{ - /// Write data to large object. - /** @warning The size of a write is currently limited to 2GB. - * - * @param buf Data to write. - * @param len Number of bytes from Buf to write. - */ - void write(char const buf[], std::size_t len); - - /// Write string to large object. - /** If not all bytes could be written, an exception is thrown. - * @param buf Data to write; no terminating zero is written. - */ - void write(std::string_view buf) { write(std::data(buf), std::size(buf)); } - - /// Read data from large object. - /** Throws an exception if an error occurs while reading. - * @param buf Location to store the read data in. - * @param len Number of bytes to try and read. - * @return Number of bytes read, which may be less than the number requested - * if the end of the large object is reached. - */ - size_type read(char buf[], std::size_t len); - - /// Seek in large object's data stream. - /** Throws an exception if an error occurs. - * @return The new position in the large object - */ - size_type seek(size_type dest, seekdir dir); - - /// Report current position in large object's data stream. - /** Throws an exception if an error occurs. - * @return The current position in the large object. - */ - [[nodiscard]] size_type tell() const; - //@} - - /** - * @name Low-level access to object contents. - * - * These functions provide a more "C-like" access interface, returning - * special values instead of throwing exceptions on error. These functions - * are generally best avoided in favour of the high-level access functions, - * which behave more like C++ functions should. - * - * Due to libpq's underlying API, some operations are limited to "int" - * sizes, typically 2 GB, even though a large object can grow much larger. - */ - //@{ - /// Seek in large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param dest Offset to go to. - * @param dir Origin to which dest is relative: ios_base::beg (from beginning - * of the object), ios_base::cur (from current access position), or - * ios_base;:end (from end of object). - * @return New position in large object, or -1 if an error occurred. - */ - pos_type cseek(off_type dest, seekdir dir) noexcept; - - /// Write to large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param buf Data to write. - * @param len Number of bytes to write. - * @return Number of bytes actually written, or -1 if an error occurred. - */ - off_type cwrite(char const buf[], std::size_t len) noexcept; - - /// Read from large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param buf Area where incoming bytes should be stored. - * @param len Number of bytes to read. - * @return Number of bytes actually read, or -1 if an error occurred.. - */ - off_type cread(char buf[], std::size_t len) noexcept; - - /// Report current position in large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @return Current position in large object, of -1 if an error occurred. - */ - [[nodiscard]] pos_type ctell() const noexcept; - //@} - - /** - * @name Error/warning output - */ - //@{ - /// Issue message to transaction's notice processor. - void process_notice(zview) noexcept; - //@} - - using largeobject::remove; - - using largeobject::operator==; - using largeobject::operator!=; - using largeobject::operator<; - using largeobject::operator<=; - using largeobject::operator>; - using largeobject::operator>=; - - largeobjectaccess() = delete; - largeobjectaccess(largeobjectaccess const &) = delete; - largeobjectaccess operator=(largeobjectaccess const &) = delete; - -private: - PQXX_PRIVATE std::string reason(int err) const; - internal::pq::PGconn *raw_connection() const - { - return largeobject::raw_connection(m_trans); - } - - PQXX_PRIVATE void open(openmode mode); - void close() noexcept; - - dbtransaction &m_trans; - int m_fd = -1; -}; - - -/// Streambuf to use large objects in standard I/O streams. -/** @deprecated Access large objects directly using the @ref blob class. - * - * The standard streambuf classes provide uniform access to data storage such - * as files or string buffers, so they can be accessed using standard input or - * output streams. This streambuf implementation provided similar access to - * large objects, so they could be read and written using the same stream - * classes. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class largeobject_streambuf : public std::basic_streambuf -{ - using size_type = largeobject::size_type; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - using openmode = largeobjectaccess::openmode; - using seekdir = largeobjectaccess::seekdir; - - /// Default open mode: in, out, binary. - static constexpr auto default_mode{ - std::ios::in | std::ios::out | std::ios::binary}; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - [[deprecated("Use blob instead.")]] largeobject_streambuf( - dbtransaction &t, largeobject o, openmode mode = default_mode, - size_type buf_size = 512) : - m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr} - { - initialize(mode); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - [[deprecated("Use blob instead.")]] largeobject_streambuf( - dbtransaction &t, oid o, openmode mode = default_mode, - size_type buf_size = 512) : - m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr} - { - initialize(mode); - } - - virtual ~largeobject_streambuf() noexcept - { - delete[] m_p; - delete[] m_g; - } - - /// For use by large object stream classes. - void process_notice(zview const &s) { m_obj.process_notice(s); } - -protected: - virtual int sync() override - { - // setg() sets eback, gptr, egptr. - this->setg(this->eback(), this->eback(), this->egptr()); - return overflow(eof()); - } - - virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override - { - return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir)); - } - - virtual pos_type seekpos(pos_type pos, openmode) override - { - largeobjectaccess::pos_type const newpos{ - m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)}; - return adjust_eof(newpos); - } - - virtual int_type overflow(int_type ch) override - { - auto *const pp{this->pptr()}; - if (pp == nullptr) - return eof(); - auto *const pb{this->pbase()}; - int_type res{0}; - - if (pp > pb) - { - auto const write_sz{pp - pb}; - auto const written_sz{ - m_obj.cwrite(pb, static_cast(pp - pb))}; - if (internal::cmp_less_equal(written_sz, 0)) - throw internal_error{ - "pqxx::largeobject: write failed " - "(is transaction still valid on write or flush?), " - "libpq reports error"}; - else if (write_sz != written_sz) - throw internal_error{ - "pqxx::largeobject: write failed " - "(is transaction still valid on write or flush?), " + - std::to_string(written_sz) + "/" + std::to_string(write_sz) + - " bytes written"}; - auto const out{adjust_eof(written_sz)}; - - if constexpr (std::is_arithmetic_v) - res = check_cast(out, "largeobject position"sv); - else - res = int_type(out); - } - this->setp(m_p, m_p + m_bufsize); - - // Write that one more character, if it's there. - if (ch != eof()) - { - *this->pptr() = static_cast(ch); - this->pbump(1); - } - return res; - } - - virtual int_type overflow() { return overflow(eof()); } - - virtual int_type underflow() override - { - if (this->gptr() == nullptr) - return eof(); - auto *const eb{this->eback()}; - auto const res{adjust_eof( - m_obj.cread(this->eback(), static_cast(m_bufsize)))}; - this->setg( - eb, eb, eb + (res == eof() ? 0 : static_cast(res))); - return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb); - } - -private: - /// Shortcut for traits_type::eof(). - static int_type eof() { return traits_type::eof(); } - - /// Helper: change error position of -1 to EOF (probably a no-op). - template static std::streampos adjust_eof(INTYPE pos) - { - bool const at_eof{pos == -1}; - if constexpr (std::is_arithmetic_v) - { - return check_cast( - (at_eof ? eof() : pos), "large object seek"sv); - } - else - { - return std::streampos(at_eof ? eof() : pos); - } - } - - void initialize(openmode mode) - { - if ((mode & std::ios::in) != 0) - { - m_g = new char_type[unsigned(m_bufsize)]; - this->setg(m_g, m_g, m_g); - } - if ((mode & std::ios::out) != 0) - { - m_p = new char_type[unsigned(m_bufsize)]; - this->setp(m_p, m_p + m_bufsize); - } - } - - size_type const m_bufsize; - largeobjectaccess m_obj; - - /// Get & put buffers. - char_type *m_g, *m_p; -}; - - -/// Input stream that gets its data from a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This class worked like any other istream, but to read data from a large - * object. It supported all formatting and streaming operations of - * `std::istream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_ilostream : public std::basic_istream -{ - using super = std::basic_istream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create a basic_ilostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_ilostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::in | std::ios::binary, buf_size} - { - super::init(&m_buf); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// Create a basic_ilostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Identifier of a large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_ilostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::in | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - -private: - largeobject_streambuf m_buf; -}; - -using ilostream = basic_ilostream; - - -/// Output stream that writes data back to a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This worked like any other ostream, but to write data to a large object. - * It supported all formatting and streaming operations of `std::ostream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_olostream : public std::basic_ostream -{ - using super = std::basic_ostream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create a basic_olostream. - /** - * @param t transaction in which this stream is to exist. - * @param o a large object to access. - * @param buf_size size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_olostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// Create a basic_olostream. - /** - * @param t transaction in which this stream is to exist. - * @param o a large object to access. - * @param buf_size size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_olostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - ~basic_olostream() - { - try - { - m_buf.pubsync(); - m_buf.pubsync(); - } - catch (std::exception const &e) - { - m_buf.process_notice(e.what()); - } - } - -private: - largeobject_streambuf m_buf; -}; - -using olostream = basic_olostream; - - -/// Stream that reads and writes a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This worked like a std::iostream, but to read data from, or write data to, a - * large object. It supported all formatting and streaming operations of - * `std::iostream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_lostream : public std::basic_iostream -{ - using super = std::basic_iostream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - - /// Create a basic_lostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_lostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{ - t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - /// Create a basic_lostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_lostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{ - t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - ~basic_lostream() - { - try - { - m_buf.pubsync(); - m_buf.pubsync(); - } - catch (std::exception const &e) - { - m_buf.process_notice(e.what()); - } - } - -private: - largeobject_streambuf m_buf; -}; - -using lostream = basic_lostream; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/nontransaction b/ext/libpqxx-7.7.3/include/pqxx/nontransaction deleted file mode 100644 index bb5b79724..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/nontransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::nontransaction class. - * - * pqxx::nontransaction provides nontransactional database access. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/nontransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/nontransaction.hxx b/ext/libpqxx-7.7.3/include/pqxx/nontransaction.hxx deleted file mode 100644 index c50715594..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/nontransaction.hxx +++ /dev/null @@ -1,76 +0,0 @@ -/* Definition of the pqxx::nontransaction class. - * - * pqxx::nontransaction provides nontransactional database access - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_NONTRANSACTION -#define PQXX_H_NONTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/connection.hxx" -#include "pqxx/result.hxx" -#include "pqxx/transaction.hxx" - -namespace pqxx -{ -using namespace std::literals; - -/// Simple "transaction" class offering no transactional integrity. -/** - * @ingroup transactions - * - * nontransaction, like transaction or any other transaction_base-derived - * class, provides access to a database through a connection. Unlike its - * siblings, however, nontransaction does not maintain any kind of - * transactional integrity. This may be useful eg. for read-only access to the - * database that does not require a consistent, atomic view on its data; or for - * operations that are not allowed within a backend transaction, such as - * creating tables. - * - * For queries that update the database, however, a real transaction is likely - * to be faster unless the transaction consists of only a single record update. - * - * Also, you can keep a nontransaction open for as long as you like. Actual - * back-end transactions are limited in lifespan, and will sometimes fail just - * because they took too long to execute or were left idle for too long. This - * will not happen with a nontransaction (although the connection may still - * time out, e.g. when the network is unavailable for a very long time). - * - * Any query executed in a nontransaction is committed immediately, and neither - * commit() nor abort() has any effect. - * - * Database features that require a backend transaction, such as cursors or - * large objects, will not work in a nontransaction. - */ -class PQXX_LIBEXPORT nontransaction final : public transaction_base -{ -public: - /// Constructor. - /** Create a "dummy" transaction. - * @param c Connection in which this "transaction" will operate. - * @param tname Optional tname for the transaction, beginning with a letter - * and containing only letters and digits. - */ - nontransaction(connection &c, std::string_view tname = ""sv) : - transaction_base{c, tname, std::shared_ptr{}} - { - register_transaction(); - } - - virtual ~nontransaction() override { close(); } - -private: - virtual void do_commit() override {} -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/notification b/ext/libpqxx-7.7.3/include/pqxx/notification deleted file mode 100644 index a0bd1c73e..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/notification +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::notification_receiver functor interface. - * - * pqxx::notification_receiver handles incoming notifications. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/notification.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/notification.hxx b/ext/libpqxx-7.7.3/include/pqxx/notification.hxx deleted file mode 100644 index b59b8567a..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/notification.hxx +++ /dev/null @@ -1,94 +0,0 @@ -/* Definition of the pqxx::notification_receiver functor interface. - * - * pqxx::notification_receiver handles incoming notifications. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_NOTIFICATION -#define PQXX_H_NOTIFICATION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/types.hxx" - - -namespace pqxx -{ -/// "Observer" base class for notifications. -/** @addtogroup notification Notifications and Receivers - * - * To listen on a notification issued using the NOTIFY command, derive your own - * class from notification_receiver and define its function-call operator to - * perform whatever action you wish to take when the given notification - * arrives. Then create an object of that class and pass it to your connection. - * DO NOT use raw SQL to listen for notifications, or your attempts to listen - * won't be resumed when a connection fails--and you'll have no way to notice. - * - * Notifications never arrive inside a transaction, not even in a - * nontransaction. Therefore, you are free to open a transaction of your own - * inside your receiver's function invocation operator. - * - * Notifications you are listening for may arrive anywhere within libpqxx code, - * but be aware that **PostgreSQL defers notifications occurring inside - * transactions.** (This was done for excellent reasons; just think about what - * happens if the transaction where you happen to handle an incoming - * notification is later rolled back for other reasons). So if you're keeping - * a transaction open, don't expect any of your receivers on the same - * connection to be notified. - * - * (For very similar reasons, outgoing notifications are also not sent until - * the transaction that sends them commits.) - * - * Multiple receivers on the same connection may listen on a notification of - * the same name. An incoming notification is processed by invoking all - * receivers (zero or more) of the same name. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver -{ -public: - /// Register the receiver with a connection. - /** - * @param c Connnection to operate on. - * @param channel Name of the notification to listen for. - */ - notification_receiver(connection &c, std::string_view channel); - /// Register the receiver with a connection. - notification_receiver(notification_receiver const &) = delete; - /// Register the receiver with a connection. - notification_receiver &operator=(notification_receiver const &) = delete; - /// Deregister the receiver. - virtual ~notification_receiver(); - - /// The channel that this receiver listens on. - [[nodiscard]] std::string const &channel() const & { return m_channel; } - - // TODO: Change API to take payload as zview instead of string ref. - /// Overridable: action to invoke when notification arrives. - /** - * @param payload An optional string that may have been passed to the NOTIFY - * command. - * @param backend_pid Process ID of the database backend process that served - * our connection when the notification arrived. The actual process ID - * behind the connection may have changed by the time this method is called. - */ - virtual void operator()(std::string const &payload, int backend_pid) = 0; - -protected: - connection &conn() const noexcept { return m_conn; } - -private: - connection &m_conn; - std::string m_channel; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/params b/ext/libpqxx-7.7.3/include/pqxx/params deleted file mode 100644 index 4098782aa..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/params +++ /dev/null @@ -1,8 +0,0 @@ -/** Helper classes for passing statement parameters. - * - * Use these for prepared statements and parameterised statements. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/params.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/params.hxx b/ext/libpqxx-7.7.3/include/pqxx/params.hxx deleted file mode 100644 index 2d29cdfed..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/params.hxx +++ /dev/null @@ -1,383 +0,0 @@ -/* Helpers for prepared statements and parameterised statements. - * - * See the connection class for more about such statements. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_PARAMS -#define PQXX_H_PARAMS - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/statement_parameters.hxx" -#include "pqxx/types.hxx" - - -/// @deprecated The new @ref params class replaces all of this. -namespace pqxx::prepare -{ -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * sequence ranging from `begin` to `end` exclusively. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic sequences. - * - * @param begin A pointer or iterator for iterating parameters. - * @param end A pointer or iterator for iterating parameters. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(IT begin, IT end) -{ - return pqxx::internal::dynamic_params(begin, end); -} - - -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * container of parameter values. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic containers. - * - * @param container A container of parameter values. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(C const &container) -{ - using IT = typename C::const_iterator; -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return pqxx::internal::dynamic_params{container}; -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * container of parameter values. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic containers. - * - * @param container A container of parameter values. - * @param accessor For each parameter `p`, pass `accessor(p)`. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(C &container, ACCESSOR accessor) -{ - using IT = decltype(std::begin(container)); -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return pqxx::internal::dynamic_params{container, accessor}; -#include "pqxx/internal/ignore-deprecated-post.hxx" -} -} // namespace pqxx::prepare - - -namespace pqxx -{ -/// Generate parameter placeholders for use in an SQL statement. -/** When you want to pass parameters to a prepared statement or a parameterised - * statement, you insert placeholders into the SQL. During invocation, the - * database replaces those with the respective parameter values you passed. - * - * The placeholders look like `$1` (for the first parameter value), `$2` (for - * the second), and so on. You can just write those directly in your - * statement. But for those rare cases where it becomes difficult to track - * which number a placeholder should have, you can use a `placeholders` object - * to count and generate them in order. - */ -template class placeholders -{ -public: - /// Maximum number of parameters we support. - static inline constexpr unsigned int max_params{ - (std::numeric_limits::max)()}; - - placeholders() - { - static constexpr auto initial{"$1\0"sv}; - initial.copy(std::data(m_buf), std::size(initial)); - } - - /// Read an ephemeral version of the current placeholder text. - /** @warning Changing the current placeholder number will overwrite this. - * Use the view immediately, or lose it. - */ - constexpr zview view() const &noexcept - { - return zview{std::data(m_buf), m_len}; - } - - /// Read the current placeholder text, as a `std::string`. - /** This will be slightly slower than converting to a `zview`. With most - * C++ implementations however, until you get into ridiculous numbers of - * parameters, the string will benefit from the Short String Optimization, or - * SSO. - */ - std::string get() const { return std::string(std::data(m_buf), m_len); } - - /// Move on to the next parameter. - void next() & - { - if (m_current >= max_params) - throw range_error{pqxx::internal::concat( - "Too many parameters in one statement: limit is ", max_params, ".")}; - ++m_current; - if (m_current % 10 == 0) - { - // Carry the 1. Don't get too clever for this relatively rare - // case, just rewrite the entire number. Leave the $ in place - // though. - char *const data{std::data(m_buf)}; - char *const end{string_traits::into_buf( - data + 1, data + std::size(m_buf), m_current)}; - // (Subtract because we don't include the trailing zero.) - m_len = check_cast(end - data, "placeholders counter") - 1; - } - else - { - PQXX_LIKELY - // Shortcut for the common case: just increment that last digit. - ++m_buf[m_len - 1]; - } - } - - /// Return the current placeholder number. The initial placeholder is 1. - COUNTER count() const noexcept { return m_current; } - -private: - /// Current placeholder number. Starts at 1. - COUNTER m_current = 1; - - /// Length of the current placeholder string, not including trailing zero. - COUNTER m_len = 2; - - /// Text buffer where we render the placeholders, with a trailing zero. - /** We keep reusing this for every subsequent placeholder, just because we - * don't like string allocations. - * - * Maximum length is the maximum base-10 digits that COUNTER can fully - * represent, plus 1 more for the extra digit that it can only partially - * fill up, plus room for the dollar sign and the trailing zero. - */ - std::array::digits10 + 3> m_buf; -}; - - -/// Build a parameter list for a parameterised or prepared statement. -/** When calling a parameterised statement or a prepared statement, you can - * pass parameters into the statement directly in the invocation, as - * additional arguments to `exec_prepared` or `exec_params`. But in - * complex cases, sometimes that's just not convenient. - * - * In those situations, you can create a `params` and append your parameters - * into that, one by one. Then you pass the `params` to `exec_prepared` or - * `exec_params`. - * - * Combinations also work: if you have a `params` containing a string - * parameter, and you call `exec_params` with an `int` argument followed by - * your `params`, you'll be passing the `int` as the first parameter and - * the string as the second. You can even insert a `params` in a `params`, - * or pass two `params` objects to a statement. - */ -class PQXX_LIBEXPORT params -{ -public: - params() = default; - - /// Pre-populate a `params` with `args`. Feel free to add more later. - template constexpr params(Args &&...args) - { - reserve(sizeof...(args)); - append_pack(std::forward(args)...); - } - - /// Pre-allocate room for at least `n` parameters. - /** This is not needed, but it may improve efficiency. - * - * Reserve space if you're going to add parameters individually, and you've - * got some idea of how many there are going to be. It may save some - * memory re-allocations. - */ - void reserve(std::size_t n) &; - - // C++20: constexpr. - /// Get the number of parameters currently in this `params`. - [[nodiscard]] auto size() const noexcept { return m_params.size(); } - - // C++20: Use the vector's ssize() directly and go noexcept+constexpr. - /// Get the number of parameters (signed). - /** Unlike `size()`, this is not yet `noexcept`. That's because C++17's - * `std::vector` does not have a `ssize()` member function. These member - * functions are `noexcept`, but `std::size()` and `std::ssize()` are - * not. - */ - [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params); } - - /// Append a null value. - void append() &; - - /// Append a non-null zview parameter. - /** The underlying data must stay valid for as long as the `params` - * remains active. - */ - void append(zview) &; - - /// Append a non-null string parameter. - /** Copies the underlying data into internal storage. For best efficiency, - * use the @ref zview variant if you can, or `std::move()` - */ - void append(std::string const &) &; - - /// Append a non-null string parameter. - void append(std::string &&) &; - - /// Append a non-null binary parameter. - /** The underlying data must stay valid for as long as the `params` - * remains active. - */ - void append(std::basic_string_view) &; - - /// Append a non-null binary parameter. - /** Copies the underlying data into internal storage. For best efficiency, - * use the `std::basic_string_view` variant if you can, or - * `std::move()`. - */ - void append(std::basic_string const &) &; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Append a non-null binary parameter. - /** The `data` object must stay in place and unchanged, for as long as the - * `params` remains active. - */ - template void append(DATA const &data) & - { - append( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif // PQXX_HAVE_CONCEPTS - - /// Append a non-null binary parameter. - void append(std::basic_string &&) &; - - /// @deprecated Append binarystring parameter. - /** The binarystring must stay valid for as long as the `params` remains - * active. - */ - void append(binarystring const &value) &; - - /// Append all parameters from value. - template - void append(pqxx::internal::dynamic_params const &value) & - { - for (auto ¶m : value) append(value.access(param)); - } - - void append(params const &value) &; - - void append(params &&value) &; - - /// Append a non-null parameter, converting it to its string - /// representation. - template void append(TYPE const &value) & - { - // TODO: Pool storage for multiple string conversions in one buffer? - if constexpr (nullness>::always_null) - { - ignore_unused(value); - m_params.emplace_back(); - } - else if (is_null(value)) - { - m_params.emplace_back(); - } - else - { - m_params.emplace_back(entry{to_string(value)}); - } - } - - /// Append all elements of `range` as parameters. - template void append_multi(RANGE const &range) & - { -#if defined(PQXX_HAVE_CONCEPTS) - if constexpr (std::ranges::sized_range) - reserve(std::size(*this) + std::size(range)); -#endif - for (auto &value : range) append(value); - } - - /// For internal use: Generate a `params` object for use in calls. - /** The params object encapsulates the pointers which we will need to pass - * to libpq when calling a parameterised or prepared statement. - * - * The pointers in the params will refer to storage owned by either the - * params object, or the caller. This is not a problem because a - * `c_params` object is guaranteed to live only while the call is going on. - * As soon as we climb back out of that call tree, we're done with that - * data. - */ - pqxx::internal::c_params make_c_params() const; - -private: - /// Recursively append a pack of params. - template - void append_pack(Arg &&arg, More &&...args) - { - this->append(std::forward(arg)); - // Recurse for remaining args. - append_pack(std::forward(args)...); - } - - /// Terminating case: append an empty parameter pack. It's not hard BTW. - constexpr void append_pack() noexcept {} - - // The way we store a parameter depends on whether it's binary or text - // (most types are text), and whether we're responsible for storing the - // contents. - using entry = std::variant< - std::nullptr_t, zview, std::string, std::basic_string_view, - std::basic_string>; - std::vector m_params; - - static constexpr std::string_view s_overflow{ - "Statement parameter length overflow."sv}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/pipeline b/ext/libpqxx-7.7.3/include/pqxx/pipeline deleted file mode 100644 index bf828843a..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/pipeline +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::pipeline class. - * - * Throughput-optimized query interface. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/pipeline.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/pipeline.hxx b/ext/libpqxx-7.7.3/include/pqxx/pipeline.hxx deleted file mode 100644 index 049dcdd58..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/pipeline.hxx +++ /dev/null @@ -1,237 +0,0 @@ -/* Definition of the pqxx::pipeline class. - * - * Throughput-optimized mechanism for executing queries. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_PIPELINE -#define PQXX_H_PIPELINE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -// TODO: libpq 14 introduced a similar "pipeline mode." Can we use that? - -/// Processes several queries in FIFO manner, optimized for high throughput. -/** Use a pipeline if you want to keep doing useful work while your queries are - * executing. Result retrieval is decoupled from execution request; queries - * "go in at the front" and results "come out the back." - * - * Actually, you can retrieve the results in any order if you want, but it may - * lead to surprising "time travel" effects if any of the queries fails. In - * particular, syntax errors in the queries can confuse things and show up too - * early in the stream of results. - * - * Generally, if any of the queries fails, it will throw an exception at the - * point where you request its result. But it may happen earlier, especially - * if you request results out of chronological order. - * - * @warning While a pipeline is active, you cannot execute queries, open - * streams, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT pipeline : public transaction_focus -{ -public: - /// Identifying numbers for queries. - using query_id = long; - - pipeline(pipeline const &) = delete; - pipeline &operator=(pipeline const &) = delete; - - /// Start a pipeline. - explicit pipeline(transaction_base &t) : transaction_focus{t, s_classname} - { - init(); - } - /// Start a pipeline. Assign it a name, for more helpful error messages. - pipeline(transaction_base &t, std::string_view tname) : - transaction_focus{t, s_classname, tname} - { - init(); - } - - /// Close the pipeline. - ~pipeline() noexcept; - - /// Add query to the pipeline. - /** Queries accumulate in the pipeline, which sends them to the backend in a - * batch separated by semicolons. The queries you insert must not use this - * trick themselves, or the pipeline will get hopelessly confused! - * - * @return Identifier for this query, unique only within this pipeline. - */ - query_id insert(std::string_view) &; - - /// Wait for all ongoing or pending operations to complete, and detach. - /** Detaches from the transaction when done. - * - * This does not produce the queries' results, so it may not report any - * errors which may have occurred in their execution. To be sure that your - * statements succeeded, call @ref retrieve until the pipeline is empty. - */ - void complete(); - - /// Forget all ongoing or pending operations and retrieved results. - /** Queries already sent to the backend may still be completed, depending - * on implementation and timing. - * - * Any error state (unless caused by an internal error) will also be cleared. - * This is mostly useful in a nontransaction, since a backend transaction is - * aborted automatically when an error occurs. - * - * Detaches from the transaction when done. - */ - void flush(); - - /// Cancel ongoing query, if any. - /** May cancel any or all of the queries that have been inserted at this - * point whose results have not yet been retrieved. If the pipeline lives in - * a backend transaction, that transaction may be left in a nonfunctional - * state in which it can only be aborted. - * - * Therefore, either use this function in a nontransaction, or abort the - * transaction after calling it. - */ - void cancel(); - - /// Is result for given query available? - [[nodiscard]] bool is_finished(query_id) const; - - /// Retrieve result for given query. - /** If the query failed for whatever reason, this will throw an exception. - * The function will block if the query has not finished yet. - * @warning If results are retrieved out-of-order, i.e. in a different order - * than the one in which their queries were inserted, errors may "propagate" - * to subsequent queries. - */ - result retrieve(query_id qid) - { - return retrieve(m_queries.find(qid)).second; - } - - /// Retrieve oldest unretrieved result (possibly wait for one). - /** @return The query's identifier and its result set. */ - std::pair retrieve(); - - [[nodiscard]] bool empty() const noexcept { return std::empty(m_queries); } - - /// Set maximum number of queries to retain before issuing them to the - /// backend. - /** The pipeline will perform better if multiple queries are issued at once, - * but retaining queries until the results are needed (as opposed to issuing - * them to the backend immediately) may negate any performance benefits the - * pipeline can offer. - * - * Recommended practice is to set this value no higher than the number of - * queries you intend to insert at a time. - * @param retain_max A nonnegative "retention capacity;" passing zero will - * cause queries to be issued immediately - * @return Old retention capacity - */ - int retain(int retain_max = 2) &; - - - /// Resume retained query emission. Harmless when not needed. - void resume() &; - -private: - struct PQXX_PRIVATE Query - { - explicit Query(std::string_view q) : - query{std::make_shared(q)} - {} - - std::shared_ptr query; - result res; - }; - - using QueryMap = std::map; - - void init(); - void attach(); - void detach(); - - /// Upper bound to query id's. - static constexpr query_id qid_limit() noexcept - { - // Parenthesise this to work around an eternal Visual C++ problem: - // Without the extra parentheses, unless NOMINMAX is defined, the - // preprocessor will mistake this "max" for its annoying built-in macro - // of the same name. - return (std::numeric_limits::max)(); - } - - /// Create new query_id. - PQXX_PRIVATE query_id generate_id(); - - bool have_pending() const noexcept - { - return m_issuedrange.second != m_issuedrange.first; - } - - PQXX_PRIVATE void issue(); - - /// The given query failed; never issue anything beyond that. - void set_error_at(query_id qid) noexcept - { - PQXX_UNLIKELY - if (qid < m_error) - m_error = qid; - } - - /// Throw pqxx::internal_error. - [[noreturn]] PQXX_PRIVATE void internal_error(std::string const &err); - - PQXX_PRIVATE bool obtain_result(bool expect_none = false); - - PQXX_PRIVATE void obtain_dummy(); - PQXX_PRIVATE void get_further_available_results(); - PQXX_PRIVATE void check_end_results(); - - /// Receive any results that happen to be available; it's not urgent. - PQXX_PRIVATE void receive_if_available(); - - /// Receive results, up to stop if possible. - PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop); - std::pair retrieve(pipeline::QueryMap::iterator); - - QueryMap m_queries; - std::pair m_issuedrange; - int m_retain = 0; - int m_num_waiting = 0; - query_id m_q_id = 0; - - /// Is there a "dummy query" pending? - bool m_dummy_pending = false; - - /// Point at which an error occurred; no results beyond it will be available - query_id m_error = qid_limit(); - - /// Encoding. - /** We store this in the object to avoid the risk of exceptions at awkward - * moments. - */ - internal::encoding_group m_encoding; - - static constexpr std::string_view s_classname{"pipeline"}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/pqxx b/ext/libpqxx-7.7.3/include/pqxx/pqxx deleted file mode 100644 index 17a8eaa9c..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/pqxx +++ /dev/null @@ -1,28 +0,0 @@ -/// Convenience header: include all libpqxx definitions. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/array.hxx" -#include "pqxx/binarystring.hxx" -#include "pqxx/blob.hxx" -#include "pqxx/connection.hxx" -#include "pqxx/cursor.hxx" -#include "pqxx/errorhandler.hxx" -#include "pqxx/except.hxx" -#include "pqxx/largeobject.hxx" -#include "pqxx/nontransaction.hxx" -#include "pqxx/notification.hxx" -#include "pqxx/params.hxx" -#include "pqxx/pipeline.hxx" -#include "pqxx/prepared_statement.hxx" -#include "pqxx/result.hxx" -#include "pqxx/internal/result_iterator.hxx" -#include "pqxx/internal/result_iter.hxx" -#include "pqxx/robusttransaction.hxx" -#include "pqxx/row.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/stream_to.hxx" -#include "pqxx/subtransaction.hxx" -#include "pqxx/transaction.hxx" -#include "pqxx/transactor.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/prepared_statement b/ext/libpqxx-7.7.3/include/pqxx/prepared_statement deleted file mode 100644 index 674be7090..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/prepared_statement +++ /dev/null @@ -1,3 +0,0 @@ -/// @deprecated Include @c instead. - -#include "params.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/prepared_statement.hxx b/ext/libpqxx-7.7.3/include/pqxx/prepared_statement.hxx deleted file mode 100644 index 674be7090..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/prepared_statement.hxx +++ /dev/null @@ -1,3 +0,0 @@ -/// @deprecated Include @c instead. - -#include "params.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/range b/ext/libpqxx-7.7.3/include/pqxx/range deleted file mode 100644 index 11985eca4..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/range +++ /dev/null @@ -1,6 +0,0 @@ -/** Client-side support for SQL range types. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/range.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/range.hxx b/ext/libpqxx-7.7.3/include/pqxx/range.hxx deleted file mode 100644 index dc480e4b7..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/range.hxx +++ /dev/null @@ -1,515 +0,0 @@ -#ifndef PQXX_H_RANGE -#define PQXX_H_RANGE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/internal/array-composite.hxx" -#include "pqxx/internal/concat.hxx" - -namespace pqxx -{ -/// An _unlimited_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should extend - * to infinity on that side. - * - * An unlimited boundary is always inclusive of "infinity" values, if the - * range's value type supports them. - */ -struct no_bound -{ - template constexpr bool extends_down_to(TYPE const &) const - { - return true; - } - template constexpr bool extends_up_to(TYPE const &) const - { - return true; - } -}; - - -/// An _inclusive_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should include - * the value. - */ -template class inclusive_bound -{ -public: - inclusive_bound() = delete; - explicit inclusive_bound(TYPE const &value) : m_value{value} - { - if (is_null(value)) - throw argument_error{"Got null value as an inclusive range bound."}; - } - - [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as a lower bound, include value? - [[nodiscard]] bool extends_down_to(TYPE const &value) const - { - return not(value < m_value); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as an upper bound, include value? - [[nodiscard]] bool extends_up_to(TYPE const &value) const - { - return not(m_value < value); - } - -private: - TYPE m_value; -}; - - -/// An _exclusive_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should _not_ - * include the value. - */ -template class exclusive_bound -{ -public: - exclusive_bound() = delete; - explicit exclusive_bound(TYPE const &value) : m_value{value} - { - if (is_null(value)) - throw argument_error{"Got null value as an exclusive range bound."}; - } - - [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as a lower bound, include value? - [[nodiscard]] bool extends_down_to(TYPE const &value) const - { - return m_value < value; - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as an upper bound, include value? - [[nodiscard]] bool extends_up_to(TYPE const &value) const - { - return value < m_value; - } - -private: - TYPE m_value; -}; - - -/// A range boundary value. -/** A range bound is either no bound at all; or an inclusive bound; or an - * exclusive bound. Pass one of the three to the constructor. - */ -template class range_bound -{ -public: - range_bound() = delete; - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(no_bound) : m_bound{} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(inclusive_bound const &bound) : m_bound{bound} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(exclusive_bound const &bound) : m_bound{bound} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(range_bound const &) = default; - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(range_bound &&) = default; - - // TODO: constexpr and/or noexcept if underlying operators support it. - bool operator==(range_bound const &rhs) const - { - if (this->is_limited()) - return ( - rhs.is_limited() and (this->is_inclusive() == rhs.is_inclusive()) and - (*this->value() == *rhs.value())); - else - return not rhs.is_limited(); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - bool operator!=(range_bound const &rhs) const { return not(*this == rhs); } - range_bound &operator=(range_bound const &) = default; - range_bound &operator=(range_bound &&) = default; - - /// Is this a finite bound? - constexpr bool is_limited() const noexcept - { - return not std::holds_alternative(m_bound); - } - - /// Is this boundary an inclusive one? - constexpr bool is_inclusive() const noexcept - { - return std::holds_alternative>(m_bound); - } - - /// Is this boundary an exclusive one? - constexpr bool is_exclusive() const noexcept - { - return std::holds_alternative>(m_bound); - } - - // TODO: constexpr/noexcept if underlying function supports it. - /// Would this bound, as a lower bound, include `value`? - bool extends_down_to(TYPE const &value) const - { - return std::visit( - [&value](auto const &bound) { return bound.extends_down_to(value); }, - m_bound); - } - - // TODO: constexpr/noexcept if underlying function supports it. - /// Would this bound, as an upper bound, include `value`? - bool extends_up_to(TYPE const &value) const - { - return std::visit( - [&value](auto const &bound) { return bound.extends_up_to(value); }, - m_bound); - } - - /// Return bound value, or `nullptr` if it's not limited. - [[nodiscard]] constexpr TYPE const *value() const &noexcept - { - return std::visit( - [](auto const &bound) noexcept { - using bound_t = std::decay_t; - if constexpr (std::is_same_v) - return static_cast(nullptr); - else - return &bound.get(); - }, - m_bound); - } - -private: - std::variant, exclusive_bound> m_bound; -}; - - -// C++20: Concepts for comparisons, construction, etc. -/// A C++ equivalent to PostgreSQL's range types. -/** You can use this as a client-side representation of a "range" in SQL. - * - * PostgreSQL defines several range types, differing in the data type over - * which they range. You can also define your own range types. - * - * Usually you'll want the server to deal with ranges. But on occasions where - * you need to work with them client-side, you may want to use @ref - * pqxx::range. (In cases where all you do is pass them along to the server - * though, it's not worth the complexity. In that case you might as well treat - * ranges as just strings.) - * - * For documentation on PostgreSQL's range types, see: - * https://www.postgresql.org/docs/current/rangetypes.html - * - * The value type must be copyable and default-constructible, and support the - * less-than (`<`) and equals (`==`) comparisons. Value initialisation must - * produce a consistent value. - */ -template class range -{ -public: - /// Create a range. - /** For each of the two bounds, pass a @ref no_bound, @ref inclusive_bound, - * or - * @ref exclusive_bound. - */ - range(range_bound lower, range_bound upper) : - m_lower{lower}, m_upper{upper} - { - if ( - lower.is_limited() and upper.is_limited() and - (*upper.value() < *lower.value())) - throw range_error{internal::concat( - "Range's lower bound (", *lower.value(), - ") is greater than its upper bound (", *upper.value(), ").")}; - } - - // TODO: constexpr and/or noexcept if underlying constructor supports it. - /// Create an empty range. - /** SQL has a separate literal to denote an empty range, but any range which - * encompasses no values is an empty range. - */ - range() : - m_lower{exclusive_bound{TYPE{}}}, - m_upper{exclusive_bound{TYPE{}}} - {} - - // TODO: constexpr and/or noexcept if underlying operators support it. - bool operator==(range const &rhs) const - { - return (this->lower_bound() == rhs.lower_bound() and - this->upper_bound() == rhs.upper_bound()) or - (this->empty() and rhs.empty()); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - bool operator!=(range const &rhs) const { return !(*this == rhs); } - - range(range const &) = default; - range(range &&) = default; - range &operator=(range const &) = default; - range &operator=(range &&) = default; - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Is this range clearly empty? - /** An empty range encompasses no values. - * - * It is possible to "fool" this. For example, if your range is of an - * integer type and has exclusive bounds of 0 and 1, it encompasses no values - * but its `empty()` will return false. The PostgreSQL implementation, by - * contrast, will notice that it is empty. Similar things can happen for - * floating-point types, but with more subtleties and edge cases. - */ - bool empty() const - { - return (m_lower.is_exclusive() or m_upper.is_exclusive()) and - m_lower.is_limited() and m_upper.is_limited() and - not(*m_lower.value() < *m_upper.value()); - } - - // TODO: constexpr and/or noexcept if underlying functions support it. - /// Does this range encompass `value`? - bool contains(TYPE value) const - { - return m_lower.extends_down_to(value) and m_upper.extends_up_to(value); - } - - // TODO: constexpr and/or noexcept if underlying operators support it. - /// Does this range encompass all of `other`? - /** This function is not particularly smart. It does not know, for example, - * that integer ranges `[0,9]` and `[0,10)` contain the same values. - */ - bool contains(range const &other) const - { - return (*this & other) == other; - } - - [[nodiscard]] constexpr range_bound const & - lower_bound() const &noexcept - { - return m_lower; - } - [[nodiscard]] constexpr range_bound const & - upper_bound() const &noexcept - { - return m_upper; - } - - // TODO: constexpr and/or noexcept if underlying operators support it. - /// Intersection of two ranges. - /** Returns a range describing those values which are in both ranges. - */ - range operator&(range const &other) const - { - range_bound lower{no_bound{}}; - if (not this->lower_bound().is_limited()) - lower = other.lower_bound(); - else if (not other.lower_bound().is_limited()) - lower = this->lower_bound(); - else if (*this->lower_bound().value() < *other.lower_bound().value()) - lower = other.lower_bound(); - else if (*other.lower_bound().value() < *this->lower_bound().value()) - lower = this->lower_bound(); - else if (this->lower_bound().is_exclusive()) - lower = this->lower_bound(); - else - lower = other.lower_bound(); - - range_bound upper{no_bound{}}; - if (not this->upper_bound().is_limited()) - upper = other.upper_bound(); - else if (not other.upper_bound().is_limited()) - upper = this->upper_bound(); - else if (*other.upper_bound().value() < *this->upper_bound().value()) - upper = other.upper_bound(); - else if (*this->upper_bound().value() < *other.upper_bound().value()) - upper = this->upper_bound(); - else if (this->upper_bound().is_exclusive()) - upper = this->upper_bound(); - else - upper = other.upper_bound(); - - if ( - lower.is_limited() and upper.is_limited() and - (*upper.value() < *lower.value())) - return {}; - else - return {lower, upper}; - } - - /// Convert to another base type. - template operator range() const - { - range_bound lower{no_bound{}}, upper{no_bound{}}; - if (lower_bound().is_inclusive()) - lower = inclusive_bound{*lower_bound().value()}; - else if (lower_bound().is_exclusive()) - lower = exclusive_bound{*lower_bound().value()}; - - if (upper_bound().is_inclusive()) - upper = inclusive_bound{*upper_bound().value()}; - else if (upper_bound().is_exclusive()) - upper = exclusive_bound{*upper_bound().value()}; - - return {lower, upper}; - } - -private: - range_bound m_lower, m_upper; -}; - - -/// String conversions for a @ref range type. -/** Conversion assumes that either your client encoding is UTF-8, or the values - * are pure ASCII. - */ -template struct string_traits> -{ - [[nodiscard]] static inline zview - to_buf(char *begin, char *end, range const &value) - { - return generic_to_buf(begin, end, value); - } - - static inline char * - into_buf(char *begin, char *end, range const &value) - { - if (value.empty()) - { - if ((end - begin) <= internal::ssize(s_empty)) - throw conversion_overrun{s_overrun.c_str()}; - char *here = begin + s_empty.copy(begin, std::size(s_empty)); - *here++ = '\0'; - return here; - } - else - { - if (end - begin < 4) - throw conversion_overrun{s_overrun.c_str()}; - char *here = begin; - *here++ = - (static_cast(value.lower_bound().is_inclusive() ? '[' : '(')); - TYPE const *lower{value.lower_bound().value()}; - // Convert bound (but go back to overwrite that trailing zero). - if (lower != nullptr) - here = string_traits::into_buf(here, end, *lower) - 1; - *here++ = ','; - TYPE const *upper{value.upper_bound().value()}; - // Convert bound (but go back to overwrite that trailing zero). - if (upper != nullptr) - here = string_traits::into_buf(here, end, *upper) - 1; - if ((end - here) < 2) - throw conversion_overrun{s_overrun.c_str()}; - *here++ = - static_cast(value.upper_bound().is_inclusive() ? ']' : ')'); - *here++ = '\0'; - return here; - } - } - - [[nodiscard]] static inline range from_string(std::string_view text) - { - if (std::size(text) < 3) - throw pqxx::conversion_error{err_bad_input(text)}; - bool left_inc{false}; - switch (text[0]) - { - case '[': left_inc = true; break; - - case '(': break; - - case 'e': - case 'E': - if ( - (std::size(text) != std::size(s_empty)) or - (text[1] != 'm' and text[1] != 'M') or - (text[2] != 'p' and text[2] != 'P') or - (text[3] != 't' and text[3] != 'T') or - (text[4] != 'y' and text[4] != 'Y')) - throw pqxx::conversion_error{err_bad_input(text)}; - return {}; - break; - - default: throw pqxx::conversion_error{err_bad_input(text)}; - } - - auto scan{internal::get_glyph_scanner(internal::encoding_group::UTF8)}; - // The field parser uses this to track which field it's parsing, and - // when not to expect a field separator. - std::size_t index{0}; - // The last field we expect to see. - static constexpr std::size_t last{1}; - // Current parsing position. We skip the opening parenthesis or bracket. - std::size_t pos{1}; - // The string may leave out either bound to indicate that it's unlimited. - std::optional lower, upper; - // We reuse the same field parser we use for composite values and arrays. - internal::parse_composite_field(index, text, pos, lower, scan, last); - internal::parse_composite_field(index, text, pos, upper, scan, last); - - // We need one more character: the closing parenthesis or bracket. - if (pos != std::size(text)) - throw pqxx::conversion_error{err_bad_input(text)}; - char const closing{text[pos - 1]}; - if (closing != ')' and closing != ']') - throw pqxx::conversion_error{err_bad_input(text)}; - bool const right_inc{closing == ']'}; - - range_bound lower_bound{no_bound{}}, upper_bound{no_bound{}}; - if (lower) - { - if (left_inc) - lower_bound = inclusive_bound{*lower}; - else - lower_bound = exclusive_bound{*lower}; - } - if (upper) - { - if (right_inc) - upper_bound = inclusive_bound{*upper}; - else - upper_bound = exclusive_bound{*upper}; - } - - return {lower_bound, upper_bound}; - } - - [[nodiscard]] static inline constexpr std::size_t - size_buffer(range const &value) noexcept - { - TYPE const *lower{value.lower_bound().value()}, - *upper{value.upper_bound().value()}; - std::size_t const lsz{ - lower == nullptr ? 0 : string_traits::size_buffer(*lower) - 1}, - usz{upper == nullptr ? 0 : string_traits::size_buffer(*upper) - 1}; - - if (value.empty()) - return std::size(s_empty) + 1; - else - return 1 + lsz + 1 + usz + 2; - } - -private: - static constexpr zview s_empty{"empty"_zv}; - static constexpr auto s_overrun{"Not enough space in buffer for range."_zv}; - - /// Compose error message for invalid range input. - static std::string err_bad_input(std::string_view text) - { - return internal::concat("Invalid range input: '", text, "'"); - } -}; - - -/// A range type does not have an innate null value. -template struct nullness> : no_null> -{}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/result b/ext/libpqxx-7.7.3/include/pqxx/result deleted file mode 100644 index 523394b72..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/result +++ /dev/null @@ -1,16 +0,0 @@ -/** pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/result.hxx" - -// Now include some types which depend on result, but which the user will -// expect to see defined after including this header. -#include "pqxx/internal/result_iterator.hxx" -#include "pqxx/field.hxx" -#include "pqxx/internal/result_iter.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/result.hxx b/ext/libpqxx-7.7.3/include/pqxx/result.hxx deleted file mode 100644 index 6c41cc096..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/result.hxx +++ /dev/null @@ -1,335 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT -#define PQXX_H_RESULT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include - -#include "pqxx/except.hxx" -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - -#include "pqxx/internal/encodings.hxx" - - -namespace pqxx::internal -{ -// TODO: Make noexcept (but breaks ABI). -PQXX_LIBEXPORT void clear_result(pq::PGresult const *); -} // namespace pqxx::internal - - -namespace pqxx::internal::gate -{ -class result_connection; -class result_creation; -class result_pipeline; -class result_row; -class result_sql_cursor; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Result set containing data returned by a query or command. -/** This behaves as a container (as defined by the C++ standard library) and - * provides random access const iterators to iterate over its rows. You can - * also access a row by indexing a `result R` by the row's zero-based - * number: - * - * - * for (result::size_type i=0; i < std::size(R); ++i) Process(R[i]); - * - * - * Result sets in libpqxx are lightweight, reference-counted wrapper objects - * which are relatively small and cheap to copy. Think of a result object as - * a "smart pointer" to an underlying result set. - * - * @warning The result set that a result object points to is not thread-safe. - * If you copy a result object, it still refers to the same underlying result - * set. So never copy, destroy, query, or otherwise access a result while - * another thread may be copying, destroying, querying, or otherwise accessing - * the same result set--even if it is doing so through a different result - * object! - */ -class PQXX_LIBEXPORT result -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - using reference = row; - using const_iterator = const_result_iterator; - using pointer = const_iterator; - using iterator = const_iterator; - using const_reverse_iterator = const_reverse_result_iterator; - using reverse_iterator = const_reverse_iterator; - - result() noexcept : - m_data{make_data_pointer()}, - m_query{}, - m_encoding{internal::encoding_group::MONOBYTE} - {} - - result(result const &rhs) noexcept = default; - result(result &&rhs) noexcept = default; - - /// Assign one result to another. - /** Copying results is cheap: it copies only smart pointers, but the actual - * data stays in the same place. - */ - result &operator=(result const &rhs) noexcept = default; - - /// Assign one result to another, invaliding the old one. - result &operator=(result &&rhs) noexcept = default; - - /** - * @name Comparisons - * - * You can compare results for equality. Beware: this is a very strict, - * dumb comparison. The smallest difference between two results (such as a - * string "Foo" versus a string "foo") will make them unequal. - */ - //@{ - /// Compare two results for equality. - [[nodiscard]] bool operator==(result const &) const noexcept; - /// Compare two results for inequality. - [[nodiscard]] bool operator!=(result const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - /// Iterate rows, reading them directly into a tuple of "TYPE...". - /** Converts the fields to values of the given respective types. - * - * Use this only with a ranged "for" loop. The iteration produces - * std::tuple which you can "unpack" to a series of `auto` - * variables. - */ - template auto iter() const; - - [[nodiscard]] const_reverse_iterator rbegin() const; - [[nodiscard]] const_reverse_iterator crbegin() const; - [[nodiscard]] const_reverse_iterator rend() const; - [[nodiscard]] const_reverse_iterator crend() const; - - [[nodiscard]] const_iterator begin() const noexcept; - [[nodiscard]] const_iterator cbegin() const noexcept; - [[nodiscard]] inline const_iterator end() const noexcept; - [[nodiscard]] inline const_iterator cend() const noexcept; - - [[nodiscard]] reference front() const noexcept; - [[nodiscard]] reference back() const noexcept; - - [[nodiscard]] PQXX_PURE size_type size() const noexcept; - [[nodiscard]] PQXX_PURE bool empty() const noexcept; - [[nodiscard]] size_type capacity() const noexcept { return size(); } - - /// Exchange two `result` values in an exception-safe manner. - /** If the swap fails, the two values will be exactly as they were before. - * - * The swap is not necessarily thread-safe. - */ - void swap(result &) noexcept; - - /// Index a row by number. - /** This returns a @ref row object. Generally you should not keep the row - * around as a variable, but if you do, make sure that your variable is a - * `row`, not a `row&`. - */ - [[nodiscard]] row operator[](size_type i) const noexcept; - -#if defined(PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT) - // TODO: If C++23 will let us, also accept string for the column. - [[nodiscard]] field - operator[](size_type row_num, row_size_type col_num) const noexcept; -#endif - - /// Index a row by number, but check that the row number is valid. - row at(size_type) const; - - /// Index a field by row number and column number. - field at(size_type, row_size_type) const; - - /// Let go of the result's data. - /** Use this if you need to deallocate the result data earlier than you can - * destroy the `result` object itself. - * - * Multiple `result` objects can refer to the same set of underlying data. - * The underlying data will be deallocated once all `result` objects that - * refer to it are cleared or destroyed. - */ - void clear() noexcept - { - m_data.reset(); - m_query = nullptr; - } - - /** - * @name Column information - */ - //@{ - /// Number of columns in result. - [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept; - - /// Number of given column (throws exception if it doesn't exist). - [[nodiscard]] row_size_type column_number(zview name) const; - - /// Name of column with this number (throws exception if it doesn't exist) - [[nodiscard]] char const *column_name(row_size_type number) const &; - - /// Return column's type, as an OID from the system catalogue. - [[nodiscard]] oid column_type(row_size_type col_num) const; - - /// Return column's type, as an OID from the system catalogue. - [[nodiscard]] oid column_type(zview col_name) const - { - return column_type(column_number(col_name)); - } - - /// What table did this column come from? - [[nodiscard]] oid column_table(row_size_type col_num) const; - - /// What table did this column come from? - [[nodiscard]] oid column_table(zview col_name) const - { - return column_table(column_number(col_name)); - } - - /// What column in its table did this column come from? - [[nodiscard]] row_size_type table_column(row_size_type col_num) const; - - /// What column in its table did this column come from? - [[nodiscard]] row_size_type table_column(zview col_name) const - { - return table_column(column_number(col_name)); - } - //@} - - /// Query that produced this result, if available (empty string otherwise) - [[nodiscard]] PQXX_PURE std::string const &query() const &noexcept; - - /// If command was an `INSERT` of 1 row, return oid of the inserted row. - /** @return Identifier of inserted row if exactly one row was inserted, or - * @ref oid_none otherwise. - */ - [[nodiscard]] PQXX_PURE oid inserted_oid() const; - - /// If command was `INSERT`, `UPDATE`, or `DELETE`: number of affected rows. - /** @return Number of affected rows if last command was `INSERT`, `UPDATE`, - * or `DELETE`; zero for all other commands. - */ - [[nodiscard]] PQXX_PURE size_type affected_rows() const; - - // C++20: Concept like std::invocable, but without specifying param types. - /// Run `func` on each row, passing the row's fields as parameters. - /** Goes through the rows from first to last. You provide a callable `func`. - * - * For each row in the `result`, `for_each` will call `func`. It converts - * the row's fields to the types of `func`'s parameters, and pass them to - * `func`. - * - * (Therefore `func` must have a _single_ signature. It can't be a generic - * lambda, or an object of a class with multiple overloaded function call - * operators. Otherwise, `for_each` will have no way to detect a parameter - * list without ambiguity.) - * - * If any of your parameter types is `std::string_view`, it refers to the - * underlying storage of this `result`. - * - * If any of your parameter types is a reference type, its argument will - * refer to a temporary value which only lives for the duration of that - * single invocation to `func`. If the reference is an lvalue reference, it - * must be `const`. - * - * For example, this queries employee names and salaries from the database - * and prints how much each would like to earn instead: - * ```cxx - * tx.exec("SELECT name, salary FROM employee").for_each( - * [](std::string_view name, float salary){ - * std::cout << name << " would like " << salary * 2 << ".\n"; - * }) - * ``` - * - * If `func` throws an exception, processing stops at that point and - * propagates the exception. - * - * @throws usage_error if `func`'s number of parameters does not match the - * number of columns in this result. - */ - template inline void for_each(CALLABLE &&func) const; - -private: - using data_pointer = std::shared_ptr; - - /// Underlying libpq result set. - data_pointer m_data; - - /// Factory for data_pointer. - static data_pointer - make_data_pointer(internal::pq::PGresult const *res = nullptr) noexcept - { - return {res, internal::clear_result}; - } - - friend class pqxx::internal::gate::result_pipeline; - PQXX_PURE std::shared_ptr query_ptr() const noexcept - { - return m_query; - } - - /// Query string. - std::shared_ptr m_query; - - internal::encoding_group m_encoding; - - static std::string const s_empty_string; - - friend class pqxx::field; - // TODO: noexcept. Breaks ABI. - PQXX_PURE char const *get_value(size_type row, row_size_type col) const; - // TODO: noexcept. Breaks ABI. - PQXX_PURE bool get_is_null(size_type row, row_size_type col) const; - PQXX_PURE - field_size_type get_length(size_type, row_size_type) const noexcept; - - friend class pqxx::internal::gate::result_creation; - result( - internal::pq::PGresult *rhs, std::shared_ptr query, - internal::encoding_group enc); - - PQXX_PRIVATE void check_status(std::string_view desc = ""sv) const; - - friend class pqxx::internal::gate::result_connection; - friend class pqxx::internal::gate::result_row; - bool operator!() const noexcept { return m_data.get() == nullptr; } - operator bool() const noexcept { return m_data.get() != nullptr; } - - [[noreturn]] PQXX_PRIVATE void - throw_sql_error(std::string const &Err, std::string const &Query) const; - PQXX_PRIVATE PQXX_PURE int errorposition() const; - PQXX_PRIVATE std::string status_error() const; - - friend class pqxx::internal::gate::result_sql_cursor; - PQXX_PURE char const *cmd_status() const noexcept; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/robusttransaction b/ext/libpqxx-7.7.3/include/pqxx/robusttransaction deleted file mode 100644 index 04b71d7cc..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/robusttransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::robusttransaction class. - * - * pqxx::robusttransaction is a slower but safer transaction class. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/robusttransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/robusttransaction.hxx b/ext/libpqxx-7.7.3/include/pqxx/robusttransaction.hxx deleted file mode 100644 index faf6dbf5e..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/robusttransaction.hxx +++ /dev/null @@ -1,120 +0,0 @@ -/* Definition of the pqxx::robusttransaction class. - * - * pqxx::robusttransaction is a slower but safer transaction class. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ROBUSTTRANSACTION -#define PQXX_H_ROBUSTTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx::internal -{ -/// Helper base class for the @ref robusttransaction class template. -class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction - : public dbtransaction -{ -public: - virtual ~basic_robusttransaction() override = 0; - -protected: - basic_robusttransaction( - connection &c, zview begin_command, std::string_view tname); - basic_robusttransaction(connection &c, zview begin_command); - -private: - using IDType = unsigned long; - - std::string m_conn_string; - std::string m_xid; - int m_backendpid = -1; - - void init(zview begin_command); - - // @warning This function will become `final`. - virtual void do_commit() override; -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @ingroup transactions - * - * @{ - */ - -/// Slightly slower, better-fortified version of transaction. -/** Requires PostgreSQL 10 or better. - * - * robusttransaction is similar to transaction, but spends more time and effort - * to deal with the hopefully rare case that the connection to the backend is - * lost just while it's trying to commit. In such cases, the client does not - * know whether the backend (on the other side of the broken connection) - * managed to commit the transaction. - * - * When this happens, robusttransaction tries to reconnect to the database and - * figure out what happened. - * - * This service level was made optional since you may not want to pay the - * overhead where it is not necessary. Certainly the use of this class makes - * no sense for local connections, or for transactions that read the database - * but never modify it, or for noncritical database manipulations. - * - * Besides being slower, it's also more complex. Which means that in practice - * a robusttransaction could actually fail more instead of less often than a - * normal transaction. What robusttransaction tries to achieve is to give you - * certainty, not just be more successful per se. - */ -template -class robusttransaction final : public internal::basic_robusttransaction -{ -public: - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - * @param tname optional human-readable name for this transaction. - */ - robusttransaction(connection &c, std::string_view tname) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd, - tname} - {} - - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - * @param tname optional human-readable name for this transaction. - */ - robusttransaction(connection &c, std::string &&tname) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd, - std::move(tname)} - {} - - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - */ - explicit robusttransaction(connection &c) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd} - {} - - virtual ~robusttransaction() noexcept override { close(); } -}; - -/** - * @} - */ -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/row b/ext/libpqxx-7.7.3/include/pqxx/row deleted file mode 100644 index 62a950ac8..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/row +++ /dev/null @@ -1,11 +0,0 @@ -/** pqxx::row class. - * - * pqxx::row refers to a row in a result. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/row.hxx b/ext/libpqxx-7.7.3/include/pqxx/row.hxx deleted file mode 100644 index 5be5132e3..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/row.hxx +++ /dev/null @@ -1,561 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ROW -#define PQXX_H_ROW - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/except.hxx" -#include "pqxx/field.hxx" -#include "pqxx/result.hxx" - -#include "pqxx/internal/concat.hxx" - -namespace pqxx::internal -{ -template class result_iter; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// Reference to one row in a result. -/** A row represents one row (also called a row) in a query result set. - * It also acts as a container mapping column numbers or names to field - * values (see below): - * - * ```cxx - * cout << row["date"].c_str() << ": " << row["name"].c_str() << endl; - * ``` - * - * The row itself acts like a (non-modifyable) container, complete with its - * own const_iterator and const_reverse_iterator. - */ -class PQXX_LIBEXPORT row -{ -public: - using size_type = row_size_type; - using difference_type = row_difference_type; - using const_iterator = const_row_iterator; - using iterator = const_iterator; - using reference = field; - using pointer = const_row_iterator; - using const_reverse_iterator = const_reverse_row_iterator; - using reverse_iterator = const_reverse_iterator; - - row() noexcept = default; - row(row &&) noexcept = default; - row(row const &) noexcept = default; - row &operator=(row const &) noexcept = default; - row &operator=(row &&) noexcept = default; - - /** - * @name Comparison - */ - //@{ - [[nodiscard]] PQXX_PURE bool operator==(row const &) const noexcept; - [[nodiscard]] bool operator!=(row const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - [[nodiscard]] const_iterator begin() const noexcept; - [[nodiscard]] const_iterator cbegin() const noexcept; - [[nodiscard]] const_iterator end() const noexcept; - [[nodiscard]] const_iterator cend() const noexcept; - - /** - * @name Field access - */ - //@{ - [[nodiscard]] reference front() const noexcept; - [[nodiscard]] reference back() const noexcept; - - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator rbegin() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator crbegin() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator rend() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator crend() const; - - [[nodiscard]] reference operator[](size_type) const noexcept; - /** Address field by name. - * @warning This is much slower than indexing by number, or iterating. - */ - [[nodiscard]] reference operator[](zview col_name) const; - - reference at(size_type) const; - /** Address field by name. - * @warning This is much slower than indexing by number, or iterating. - */ - reference at(zview col_name) const; - - [[nodiscard]] constexpr size_type size() const noexcept - { - return m_end - m_begin; - } - - [[deprecated("Swap iterators, not rows.")]] void swap(row &) noexcept; - - /// Row number, assuming this is a real row and not end()/rend(). - [[nodiscard]] constexpr result::size_type rownumber() const noexcept - { - return m_index; - } - - /** - * @name Column information - */ - //@{ - /// Number of given column (throws exception if it doesn't exist). - [[nodiscard]] size_type column_number(zview col_name) const; - - /// Return a column's type. - [[nodiscard]] oid column_type(size_type) const; - - /// Return a column's type. - [[nodiscard]] oid column_type(zview col_name) const - { - return column_type(column_number(col_name)); - } - - /// What table did this column come from? - [[nodiscard]] oid column_table(size_type col_num) const; - - /// What table did this column come from? - [[nodiscard]] oid column_table(zview col_name) const - { - return column_table(column_number(col_name)); - } - - /// What column number in its table did this result column come from? - /** A meaningful answer can be given only if the column in question comes - * directly from a column in a table. If the column is computed in any - * other way, a logic_error will be thrown. - * - * @param col_num a zero-based column number in this result set - * @return a zero-based column number in originating table - */ - [[nodiscard]] size_type table_column(size_type) const; - - /// What column number in its table did this result column come from? - [[nodiscard]] size_type table_column(zview col_name) const - { - return table_column(column_number(col_name)); - } - //@} - - [[nodiscard]] constexpr result::size_type num() const noexcept - { - return rownumber(); - } - - /** Produce a slice of this row, containing the given range of columns. - * - * @deprecated I haven't heard of anyone caring about row slicing at all in - * at least the last 15 years. Yet it adds complexity, so unless anyone - * files a bug explaining why they really need this feature, I'm going to - * remove it. Even if they do, the feature may need an update. - * - * The slice runs from the range's starting column to the range's end - * column, exclusive. It looks just like a normal result row, except - * slices can be empty. - */ - [[deprecated("Row slicing is going away. File a bug if you need it.")]] row - slice(size_type sbegin, size_type send) const; - - /// Is this a row without fields? Can only happen to a slice. - [[nodiscard, deprecated("Row slicing is going away.")]] PQXX_PURE bool - empty() const noexcept; - - /// Extract entire row's values into a tuple. - /** Converts to the types of the tuple's respective fields. - */ - template void to(Tuple &t) const - { - check_size(std::tuple_size_v); - convert(t); - } - - template std::tuple as() const - { - check_size(sizeof...(TYPE)); - using seq = std::make_index_sequence; - return get_tuple>(seq{}); - } - -protected: - friend class const_row_iterator; - friend class result; - row(result const &r, result_size_type index, size_type cols) noexcept; - - /// Throw @ref usage_error if row size is not `expected`. - void check_size(size_type expected) const - { - if (size() != expected) - throw usage_error{internal::concat( - "Tried to extract ", expected, " field(s) from a row of ", size(), - ".")}; - } - - /// Convert to a given tuple of values, don't check sizes. - /** We need this for cases where we have a full tuple of field types, but - * not a parameter pack. - */ - template TUPLE as_tuple() const - { - using seq = std::make_index_sequence>; - return get_tuple(seq{}); - } - - template friend class pqxx::internal::result_iter; - /// Convert entire row to tuple fields, without checking row size. - template void convert(Tuple &t) const - { - extract_fields(t, std::make_index_sequence>{}); - } - - friend class field; - - /// Result set of which this is one row. - result m_result; - - /// Row number. - /** - * You'd expect this to be unsigned, but due to the way reverse iterators - * are related to regular iterators, it must be allowed to underflow to -1. - */ - result::size_type m_index = 0; - - // TODO: Remove m_begin and (if possible) m_end when we remove slice(). - /// First column in slice. This row ignores lower-numbered columns. - size_type m_begin = 0; - /// End column in slice. This row only sees lower-numbered columns. - size_type m_end = 0; - -private: - template - void extract_fields(Tuple &t, std::index_sequence) const - { - (extract_value(t), ...); - } - - template - void extract_value(Tuple &t) const; - - /// Convert row's values as a new tuple. - template - auto get_tuple(std::index_sequence) const - { - return std::make_tuple(get_field()...); - } - - /// Extract and convert a field. - template auto get_field() const - { - return (*this)[index].as>(); - } -}; - - -/// Iterator for fields in a row. Use as row::const_iterator. -class PQXX_LIBEXPORT const_row_iterator : public field -{ -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = field const; - using pointer = field const *; - using size_type = row_size_type; - using difference_type = row_difference_type; - using reference = field; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - const_row_iterator() = default; -#include "pqxx/internal/ignore-deprecated-post.hxx" - const_row_iterator(row const &t, row_size_type c) noexcept : - field{t.m_result, t.m_index, c} - {} - const_row_iterator(field const &F) noexcept : field{F} {} - const_row_iterator(const_row_iterator const &) noexcept = default; - const_row_iterator(const_row_iterator &&) noexcept = default; - - /** - * @name Dereferencing operators - */ - //@{ - [[nodiscard]] constexpr pointer operator->() const noexcept { return this; } - [[nodiscard]] reference operator*() const noexcept { return {*this}; } - //@} - - /** - * @name Manipulations - */ - //@{ - const_row_iterator &operator=(const_row_iterator const &) noexcept = default; - const_row_iterator &operator=(const_row_iterator &&) noexcept = default; - - // TODO: noexcept. Breaks ABI. - const_row_iterator operator++(int); - const_row_iterator &operator++() noexcept - { - ++m_col; - return *this; - } - // TODO: noexcept. Breaks ABI. - const_row_iterator operator--(int); - const_row_iterator &operator--() noexcept - { - --m_col; - return *this; - } - - const_row_iterator &operator+=(difference_type i) noexcept - { - m_col = size_type(difference_type(m_col) + i); - return *this; - } - const_row_iterator &operator-=(difference_type i) noexcept - { - m_col = size_type(difference_type(m_col) - i); - return *this; - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] constexpr bool - operator==(const_row_iterator const &i) const noexcept - { - return col() == i.col(); - } - [[nodiscard]] constexpr bool - operator!=(const_row_iterator const &i) const noexcept - { - return col() != i.col(); - } - [[nodiscard]] constexpr bool - operator<(const_row_iterator const &i) const noexcept - { - return col() < i.col(); - } - [[nodiscard]] constexpr bool - operator<=(const_row_iterator const &i) const noexcept - { - return col() <= i.col(); - } - [[nodiscard]] constexpr bool - operator>(const_row_iterator const &i) const noexcept - { - return col() > i.col(); - } - [[nodiscard]] constexpr bool - operator>=(const_row_iterator const &i) const noexcept - { - return col() >= i.col(); - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] inline const_row_iterator - operator+(difference_type) const noexcept; - - friend const_row_iterator - operator+(difference_type, const_row_iterator const &) noexcept; - - [[nodiscard]] inline const_row_iterator - operator-(difference_type) const noexcept; - [[nodiscard]] inline difference_type - operator-(const_row_iterator const &) const noexcept; - //@} -}; - - -/// Reverse iterator for a row. Use as row::const_reverse_iterator. -class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator -{ -public: - using super = const_row_iterator; - using iterator_type = const_row_iterator; - using iterator_type::difference_type; - using iterator_type::iterator_category; - using iterator_type::pointer; - using value_type = iterator_type::value_type; - using reference = iterator_type::reference; - - const_reverse_row_iterator() noexcept = default; - const_reverse_row_iterator(const_reverse_row_iterator const &) noexcept = - default; - const_reverse_row_iterator(const_reverse_row_iterator &&) noexcept = default; - - explicit const_reverse_row_iterator(super const &rhs) noexcept : - const_row_iterator{rhs} - { - super::operator--(); - } - - [[nodiscard]] PQXX_PURE iterator_type base() const noexcept; - - /** - * @name Dereferencing operators - */ - //@{ - using iterator_type::operator->; - using iterator_type::operator*; - //@} - - /** - * @name Manipulations - */ - //@{ - const_reverse_row_iterator & - operator=(const_reverse_row_iterator const &r) noexcept - { - iterator_type::operator=(r); - return *this; - } - const_reverse_row_iterator operator++() noexcept - { - iterator_type::operator--(); - return *this; - } - // TODO: noexcept. Breaks ABI. - const_reverse_row_iterator operator++(int); - const_reverse_row_iterator &operator--() noexcept - { - iterator_type::operator++(); - return *this; - } - const_reverse_row_iterator operator--(int); - // TODO: noexcept. Breaks ABI. - const_reverse_row_iterator &operator+=(difference_type i) noexcept - { - iterator_type::operator-=(i); - return *this; - } - const_reverse_row_iterator &operator-=(difference_type i) noexcept - { - iterator_type::operator+=(i); - return *this; - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] const_reverse_row_iterator - operator+(difference_type i) const noexcept - { - return const_reverse_row_iterator{base() - i}; - } - [[nodiscard]] const_reverse_row_iterator - operator-(difference_type i) noexcept - { - return const_reverse_row_iterator{base() + i}; - } - [[nodiscard]] difference_type - operator-(const_reverse_row_iterator const &rhs) const noexcept - { - return rhs.const_row_iterator::operator-(*this); - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool - operator==(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator==(rhs); - } - [[nodiscard]] bool - operator!=(const_reverse_row_iterator const &rhs) const noexcept - { - return !operator==(rhs); - } - - [[nodiscard]] constexpr bool - operator<(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator>(rhs); - } - [[nodiscard]] constexpr bool - operator<=(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator>=(rhs); - } - [[nodiscard]] constexpr bool - operator>(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator<(rhs); - } - [[nodiscard]] constexpr bool - operator>=(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator<=(rhs); - } - //@} -}; - - -const_row_iterator -const_row_iterator::operator+(difference_type o) const noexcept -{ - // TODO:: More direct route to home().columns()? - return { - row{home(), idx(), home().columns()}, - size_type(difference_type(col()) + o)}; -} - -inline const_row_iterator operator+( - const_row_iterator::difference_type o, const_row_iterator const &i) noexcept -{ - return i + o; -} - -inline const_row_iterator -const_row_iterator::operator-(difference_type o) const noexcept -{ - // TODO:: More direct route to home().columns()? - return { - row{home(), idx(), home().columns()}, - size_type(difference_type(col()) - o)}; -} - -inline const_row_iterator::difference_type -const_row_iterator::operator-(const_row_iterator const &i) const noexcept -{ - return difference_type(num() - i.num()); -} - - -template -inline void row::extract_value(Tuple &t) const -{ - using field_type = strip_t(t))>; - field const f{m_result, m_index, index}; - std::get(t) = from_string(f); -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/separated_list b/ext/libpqxx-7.7.3/include/pqxx/separated_list deleted file mode 100644 index 1bdf51c6a..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/separated_list +++ /dev/null @@ -1,6 +0,0 @@ -/** Helper similar to Python's @c str.join(). - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/separated_list.hxx b/ext/libpqxx-7.7.3/include/pqxx/separated_list.hxx deleted file mode 100644 index d4230ea08..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/separated_list.hxx +++ /dev/null @@ -1,142 +0,0 @@ -/* Helper similar to Python's `str.join()`. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SEPARATED_LIST -#define PQXX_H_SEPARATED_LIST - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/strconv.hxx" - -// C++20: Simplify using std::ranges::range. -// C++20: Optimise buffer allocation using random_access_range/iterator. -namespace pqxx -{ -/** - * @defgroup utility Utility functions - */ -//@{ - -/// Represent sequence of values as a string, joined by a given separator. -/** - * Use this to turn e.g. the numbers 1, 2, and 3 into a string "1, 2, 3". - * - * @param sep separator string (to be placed between items) - * @param begin beginning of items sequence - * @param end end of items sequence - * @param access functor defining how to dereference sequence elements - */ -template -[[nodiscard]] inline std::string -separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access) -{ - if (end == begin) - return {}; - auto next{begin}; - ++next; - if (next == end) - return to_string(access(begin)); - - // From here on, we've got at least 2 elements -- meaning that we need sep. - using elt_type = strip_t; - using traits = string_traits; - - std::size_t budget{0}; - for (ITER cnt{begin}; cnt != end; ++cnt) - budget += traits::size_buffer(access(cnt)); - budget += - static_cast(std::distance(begin, end)) * std::size(sep); - - std::string result; - result.resize(budget); - - char *const data{result.data()}; - char *here{data}; - char *stop{data + budget}; - here = traits::into_buf(here, stop, access(begin)) - 1; - for (++begin; begin != end; ++begin) - { - here += sep.copy(here, std::size(sep)); - here = traits::into_buf(here, stop, access(begin)) - 1; - } - result.resize(static_cast(here - data)); - return result; -} - - -/// Render sequence as a string, using given separator between items. -template -[[nodiscard]] inline std::string -separated_list(std::string_view sep, ITER begin, ITER end) -{ - return separated_list(sep, begin, end, [](ITER i) { return *i; }); -} - - -/// Render items in a container as a string, using given separator. -template -[[nodiscard]] inline auto -separated_list(std::string_view sep, CONTAINER const &c) - /* - Always std::string; necessary because SFINAE doesn't work with the - contents of function bodies, so the check for iterability has to be in - the signature. - */ - -> typename std::enable_if< - (not std::is_void::value and - not std::is_void::value), - std::string>::type -{ - return separated_list(sep, std::begin(c), std::end(c)); -} - - -/// Render items in a tuple as a string, using given separator. -template< - typename TUPLE, std::size_t INDEX = 0, typename ACCESS, - typename std::enable_if< - (INDEX == std::tuple_size::value - 1), int>::type = 0> -[[nodiscard]] inline std::string separated_list( - std::string_view /* sep */, TUPLE const &t, ACCESS const &access) -{ - return to_string(access(&std::get(t))); -} - -template< - typename TUPLE, std::size_t INDEX = 0, typename ACCESS, - typename std::enable_if< - (INDEX < std::tuple_size::value - 1), int>::type = 0> -[[nodiscard]] inline std::string -separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access) -{ - std::string out{to_string(access(&std::get(t)))}; - out.append(sep); - out.append(separated_list(sep, t, access)); - return out; -} - -template< - typename TUPLE, std::size_t INDEX = 0, - typename std::enable_if< - (INDEX <= std::tuple_size::value), int>::type = 0> -[[nodiscard]] inline std::string -separated_list(std::string_view sep, TUPLE const &t) -{ - // TODO: Optimise allocation. - return separated_list(sep, t, [](TUPLE const &tup) { return *tup; }); -} -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/strconv b/ext/libpqxx-7.7.3/include/pqxx/strconv deleted file mode 100644 index aa2c40ed5..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/strconv +++ /dev/null @@ -1,6 +0,0 @@ -/** String conversion definitions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/strconv.hxx b/ext/libpqxx-7.7.3/include/pqxx/strconv.hxx deleted file mode 100644 index 863711228..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/strconv.hxx +++ /dev/null @@ -1,468 +0,0 @@ -/* String conversion definitions. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STRCONV -#define PQXX_H_STRCONV - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -#if defined(PQXX_HAVE_RANGES) && __has_include() -# include -#endif - -#include "pqxx/except.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - - -namespace pqxx::internal -{ -/// Attempt to demangle @c std::type_info::name() to something human-readable. -PQXX_LIBEXPORT std::string demangle_type_name(char const[]); -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @defgroup stringconversion String conversion - * - * The PostgreSQL server accepts and represents data in string form. It has - * its own formats for various data types. The string conversions define how - * various C++ types translate to and from their respective PostgreSQL text - * representations. - * - * Each conversion is defined by a specialisations of @c string_traits. It - * gets complicated if you want top performance, but until you do, all you - * really need to care about when converting values between C++ in-memory - * representations such as @c int and the postgres string representations is - * the @c pqxx::to_string and @c pqxx::from_string functions. - * - * If you need to convert a type which is not supported out of the box, you'll - * need to define your own specialisations for these templates, similar to the - * ones defined here and in `pqxx/conversions.hxx`. Any conversion code which - * "sees" your specialisation will now support your conversion. In particular, - * you'll be able to read result fields into a variable of the new type. - * - * There is a macro to help you define conversions for individual enumeration - * types. The conversion will represent enumeration values as numeric strings. - */ -//@{ - -/// A human-readable name for a type, used in error messages and such. -/** Actually this may not always be very user-friendly. It uses - * @c std::type_info::name(). On gcc-like compilers we try to demangle its - * output. Visual Studio produces human-friendly names out of the box. - * - * This variable is not inline. Inlining it gives rise to "memory leak" - * warnings from asan, the address sanitizer, possibly from use of - * @c std::type_info::name. - */ -template -std::string const type_name{internal::demangle_type_name(typeid(TYPE).name())}; - - -/// Traits describing a type's "null value," if any. -/** Some C++ types have a special value or state which correspond directly to - * SQL's NULL. - * - * The @c nullness traits describe whether it exists, and whether a particular - * value is null. - */ -template struct nullness -{ - /// Does this type have a null value? - static bool has_null; - - /// Is this type always null? - static bool always_null; - - /// Is @c value a null? - static bool is_null(TYPE const &value); - - /// Return a null value. - /** Don't use this in generic code to compare a value and see whether it is - * null. Some types may have multiple null values which do not compare as - * equal, or may define a null value which is not equal to anything including - * itself, like in SQL. - */ - [[nodiscard]] static TYPE null(); -}; - - -/// Nullness traits describing a type which does not have a null value. -template struct no_null -{ - /// Does @c TYPE have a "built-in null value"? - /** For example, a pointer can equal @c nullptr, which makes a very natural - * representation of an SQL null value. For such types, the code sometimes - * needs to make special allowances. - * - * for most types, such as @c int or @c std::string, there is no built-in - * null. If you want to represent an SQL null value for such a type, you - * would have to wrap it in something that does have a null value. For - * example, you could use @c std::optional for "either an @c int or a - * null value." - */ - static constexpr bool has_null = false; - - /// Are all values of this type null? - /** There are a few special C++ types which are always null - mainly - * @c std::nullptr_t. - */ - static constexpr bool always_null = false; - - /// Does a given value correspond to an SQL null value? - /** Most C++ types, such as @c int or @c std::string, have no inherent null - * value. But some types such as C-style string pointers do have a natural - * equivalent to an SQL null. - */ - [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept - { - return false; - } -}; - - -/// Traits class for use in string conversions. -/** Specialize this template for a type for which you wish to add to_string - * and from_string support. - * - * String conversions are not meant to work for nulls. Check for null before - * converting a value of @c TYPE to a string, or vice versa. - */ -template struct string_traits -{ - /// Return a @c string_view representing value, plus terminating zero. - /** Produces a @c string_view containing the PostgreSQL string representation - * for @c value. - * - * Uses the space from @c begin to @c end as a buffer, if needed. The - * returned string may lie somewhere in that buffer, or it may be a - * compile-time constant, or it may be null if value was a null value. Even - * if the string is stored in the buffer, its @c begin() may or may not be - * the same as @c begin. - * - * The @c string_view is guaranteed to be valid as long as the buffer from - * @c begin to @c end remains accessible and unmodified. - * - * @throws pqxx::conversion_overrun if the provided buffer space may not be - * enough. For maximum performance, this is a conservative estimate. It may - * complain about a buffer which is actually large enough for your value, if - * an exact check gets too expensive. - */ - [[nodiscard]] static inline zview - to_buf(char *begin, char *end, TYPE const &value); - - /// Write value's string representation into buffer at @c begin. - /** Assumes that value is non-null. - * - * Writes value's string representation into the buffer, starting exactly at - * @c begin, and ensuring a trailing zero. Returns the address just beyond - * the trailing zero, so the caller could use it as the @c begin for another - * call to @c into_buf writing a next value. - */ - static inline char *into_buf(char *begin, char *end, TYPE const &value); - - /// Parse a string representation of a @c TYPE value. - /** Throws @c conversion_error if @c value does not meet the expected format - * for a value of this type. - */ - [[nodiscard]] static inline TYPE from_string(std::string_view text); - - // C++20: Can we make these all constexpr? - /// Estimate how much buffer space is needed to represent value. - /** The estimate may be a little pessimistic, if it saves time. - * - * The estimate includes the terminating zero. - */ - [[nodiscard]] static inline std::size_t - size_buffer(TYPE const &value) noexcept; -}; - - -/// Nullness: Enums do not have an inherent null value. -template -struct nullness>> : no_null -{}; -} // namespace pqxx - - -namespace pqxx::internal -{ -/// Helper class for defining enum conversions. -/** The conversion will convert enum values to numeric strings, and vice versa. - * - * To define a string conversion for an enum type, derive a @c string_traits - * specialisation for the enum from this struct. - * - * There's usually an easier way though: the @c PQXX_DECLARE_ENUM_CONVERSION - * macro. Use @c enum_traits manually only if you need to customise your - * traits type in more detail. - */ -template struct enum_traits -{ - using impl_type = std::underlying_type_t; - using impl_traits = string_traits; - - [[nodiscard]] static constexpr zview - to_buf(char *begin, char *end, ENUM const &value) - { - return impl_traits::to_buf(begin, end, to_underlying(value)); - } - - static constexpr char *into_buf(char *begin, char *end, ENUM const &value) - { - return impl_traits::into_buf(begin, end, to_underlying(value)); - } - - [[nodiscard]] static ENUM from_string(std::string_view text) - { - return static_cast(impl_traits::from_string(text)); - } - - [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept - { - return impl_traits::size_buffer(to_underlying(value)); - } - -private: - // C++23: Replace with std::to_underlying. - static constexpr impl_type to_underlying(ENUM const &value) noexcept - { - return static_cast(value); - } -}; -} // namespace pqxx::internal - - -/// Macro: Define a string conversion for an enum type. -/** This specialises the @c pqxx::string_traits template, so use it in the - * @c ::pqxx namespace. - * - * For example: - * - * #include - * #include - * enum X { xa, xb }; - * namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(x); } - * int main() { std::cout << pqxx::to_string(xa) << std::endl; } - */ -#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \ - template<> struct string_traits : pqxx::internal::enum_traits \ - {}; \ - template<> inline std::string const type_name { #ENUM } - - -namespace pqxx -{ -/// Parse a value in postgres' text format as a TYPE. -/** If the form of the value found in the string does not match the expected - * type, e.g. if a decimal point is found when converting to an integer type, - * the conversion fails. Overflows (e.g. converting "9999999999" to a 16-bit - * C++ type) are also treated as errors. If in some cases this behaviour - * should be inappropriate, convert to something bigger such as @c long @c int - * first and then truncate the resulting value. - * - * Only the simplest possible conversions are supported. Fancy features like - * hexadecimal or octal, spurious signs, or exponent notation won't work. - * Whitespace is not stripped away. Only the kinds of strings that come out of - * PostgreSQL and out of to_string() can be converted. - */ -template -[[nodiscard]] inline TYPE from_string(std::string_view text) -{ - return string_traits::from_string(text); -} - - -/// "Convert" a std::string_view to a std::string_view. -/** Just returns its input. - * - * @warning Of course the result is only valid for as long as the original - * string remains valid! Never access the string referenced by the return - * value after the original has been destroyed. - */ -template<> -[[nodiscard]] inline std::string_view from_string(std::string_view text) -{ - return text; -} - - -/// Attempt to convert postgres-generated string to given built-in object. -/** This is like the single-argument form of the function, except instead of - * returning the value, it sets @c value. - * - * You may find this more convenient in that it infers the type you want from - * the argument you pass. But there are disadvantages: it requires an - * assignment operator, and it may be less efficient. - */ -template inline void from_string(std::string_view text, T &value) -{ - value = from_string(text); -} - - -/// Convert a value to a readable string that PostgreSQL will understand. -/** The conversion does no special formatting, and ignores any locale settings. - * The resulting string will be human-readable and in a format suitable for use - * in SQL queries. It won't have niceties such as "thousands separators" - * though. - */ -template inline std::string to_string(TYPE const &value); - - -/// Convert multiple values to strings inside a single buffer. -/** There must be enough room for all values, or this will throw - * @c conversion_overrun. You can obtain a conservative estimate of the buffer - * space required by calling @c size_buffer() on the values. - * - * The @c std::string_view results may point into the buffer, so don't assume - * that they will remain valid after you destruct or move the buffer. - */ -template -[[nodiscard]] inline std::vector -to_buf(char *here, char const *end, TYPE... value) -{ - return {[&here, end](auto v) { - auto begin = here; - here = string_traits::into_buf(begin, end, v); - // Exclude the trailing zero out of the string_view. - auto len{static_cast(here - begin) - 1}; - return std::string_view{begin, len}; - }(value)...}; -} - -/// Convert a value to a readable string that PostgreSQL will understand. -/** This variant of to_string can sometimes save a bit of time in loops, by - * re-using a std::string for multiple conversions. - */ -template -inline void into_string(TYPE const &value, std::string &out); - - -/// Is @c value null? -template -[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept -{ - return nullness>::is_null(value); -} - - -/// Estimate how much buffer space is needed to represent values as a string. -/** The estimate may be a little pessimistic, if it saves time. It also - * includes room for a terminating zero after each value. - */ -template -[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept -{ - return (string_traits>::size_buffer(value) + ...); -} - - -/// Does this type translate to an SQL array? -/** Specialisations may override this to be true for container types. - * - * This may not always be a black-and-white choice. For instance, a - * @c std::string is a container, but normally it translates to an SQL string, - * not an SQL array. - */ -template inline constexpr bool is_sql_array{false}; - - -/// Can we use this type in arrays and composite types without quoting them? -/** Define this as @c true only if values of @c TYPE can never contain any - * special characters that might need escaping or confuse the parsing of array - * or composite * types, such as commas, quotes, parentheses, braces, newlines, - * and so on. - * - * When converting a value of such a type to a string in an array or a field in - * a composite type, we do not need to add quotes, nor escape any special - * characters. - * - * This is just an optimisation, so it defaults to @c false to err on the side - * of slow correctness. - */ -template inline constexpr bool is_unquoted_safe{false}; - - -/// Element separator between SQL array elements of this type. -template inline constexpr char array_separator{','}; - - -/// What's the preferred format for passing non-null parameters of this type? -/** This affects how we pass parameters of @c TYPE when calling parameterised - * statements or prepared statements. - * - * Generally we pass parameters in text format, but binary strings are the - * exception. We also pass nulls in binary format, so this function need not - * handle null values. - */ -template inline constexpr format param_format(TYPE const &) -{ - return format::text; -} - - -/// Implement @c string_traits::to_buf by calling @c into_buf. -/** When you specialise @c string_traits for a new type, most of the time its - * @c to_buf implementation has no special optimisation tricks and just writes - * its text into the buffer it receives from the caller, starting at the - * beginning. - * - * In that common situation, you can implement @c to_buf as just a call to - * @c generic_to_buf. It will call @c into_buf and return the right result for - * @c to_buf. - */ -template -inline zview generic_to_buf(char *begin, char *end, TYPE const &value) -{ - using traits = string_traits; - // The trailing zero does not count towards the zview's size, so subtract 1 - // from the result we get from into_buf(). - if (is_null(value)) - return {}; - else - return {begin, traits::into_buf(begin, end, value) - begin - 1}; -} - - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: Binary string, akin to @c std::string for binary data. -/** Any type that satisfies this concept can represent an SQL BYTEA value. - * - * A @c binary has a @c begin(), @c end(), @c size(), and @data(). Each byte - * is a @c std::byte, and they must all be laid out contiguously in memory so - * we can reference them by a pointer. - */ -template -concept binary = std::ranges::contiguous_range and - std::is_same_v>, std::byte>; -#endif -//@} -} // namespace pqxx - - -#include "pqxx/internal/conversions.hxx" -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/stream_from b/ext/libpqxx-7.7.3/include/pqxx/stream_from deleted file mode 100644 index 972762443..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/stream_from +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::stream_from class. - * - * pqxx::stream_from enables optimized batch reads from a database table. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/stream_from.hxx b/ext/libpqxx-7.7.3/include/pqxx/stream_from.hxx deleted file mode 100644 index ff4a93d2e..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/stream_from.hxx +++ /dev/null @@ -1,361 +0,0 @@ -/* Definition of the pqxx::stream_from class. - * - * pqxx::stream_from enables optimized batch reads from a database table. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_FROM -#define PQXX_H_STREAM_FROM - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/connection.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/internal/stream_iterator.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/transaction_focus.hxx" - - -namespace pqxx -{ -class transaction_base; - - -/// Pass this to a `stream_from` constructor to stream table contents. -/** @deprecated Use @ref stream_from::table() instead. - */ -constexpr from_table_t from_table; -/// Pass this to a `stream_from` constructor to stream query results. -/** @deprecated Use stream_from::query() instead. - */ -constexpr from_query_t from_query; - - -/// Stream data from the database. -/** For larger data sets, retrieving data this way is likely to be faster than - * executing a query and then iterating and converting the rows fields. You - * will also be able to start processing before all of the data has come in. - * - * There are also downsides. Not all kinds of query will work in a stream. - * But straightforward `SELECT` and `UPDATE ... RETURNING` queries should work. - * This function makes use of @ref pqxx::stream_from, which in turn uses - * PostgreSQL's `COPY` command, so see the documentation for those to get the - * full details. - * - * There are other downsides. If there stream encounters an error, it may - * leave the entire connection in an unusable state, so you'll have to give the - * whole thing up. Finally, opening a stream puts the connection in a special - * state, so you won't be able to do many other things with the connection or - * the transaction while the stream is open. - * - * There are two ways of starting a stream: you stream either all rows in a - * table (using one of the factories, `table()` or `raw_table()`), or the - * results of a query (using the `query()` factory). - * - * Usually you'll want the `stream` convenience wrapper in - * @ref transaction_base, * so you don't need to deal with this class directly. - * - * @warning While a stream is active, you cannot execute queries, open a - * pipeline, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT stream_from : transaction_focus -{ -public: - using raw_line = - std::pair>, std::size_t>; - - /// Factory: Execute query, and stream the results. - /** The query can be a SELECT query or a VALUES query; or it can be an - * UPDATE, INSERT, or DELETE with a RETURNING clause. - * - * The query is executed as part of a COPY statement, so there are additional - * restrictions on what kind of query you can use here. See the PostgreSQL - * documentation for the COPY command: - * - * https://www.postgresql.org/docs/current/sql-copy.html - */ - static stream_from query(transaction_base &tx, std::string_view q) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return {tx, from_query, q}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /** - * @name Streaming data from tables - * - * You can use `stream_from` to read a table's contents. This is a quick - * and easy way to read a table, but it comes with limitations. It cannot - * stream from a view, only from a table. It does not support conditions. - * And there are no guarantees about ordering. If you need any of those - * things, consider streaming from a query instead. - */ - //@{ - - /// Factory: Stream data from a pre-quoted table and columns. - /** Use this factory if you need to create multiple streams using the same - * table path and/or columns list, and you want to save a bit of work on - * composing the internal SQL statement for starting the stream. It lets you - * compose the string representations for the table path and the columns - * list, so you can compute these once and then re-use them later. - * - * @param tx The transaction within which the stream will operate. - * @param path Name or path for the table upon which the stream will - * operate. If any part of the table path may contain special - * characters or be case-sensitive, quote the path using - * pqxx::connection::quote_table(). - * @param columns Columns which the stream will read. They should be - * comma-separated and, if needed, quoted. You can produce the string - * using pqxx::connection::quote_columns(). If you omit this argument, - * the stream will read all columns in the table, in schema order. - */ - static stream_from raw_table( - transaction_base &tx, std::string_view path, - std::string_view columns = ""sv); - - /// Factory: Stream data from a given table. - /** This is the convenient way to stream from a table. - */ - static stream_from table( - transaction_base &tx, table_path path, - std::initializer_list columns = {}); - //@} - - /// Execute query, and stream over the results. - /** @deprecated Use factory function @ref query instead. - */ - [[deprecated("Use query() factory instead.")]] stream_from( - transaction_base &, from_query_t, std::string_view query); - - /// Stream all rows in table, all columns. - /** @deprecated Use factories @ref table or @ref raw_table instead. - */ - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &, from_table_t, std::string_view table); - - /// Stream given columns from all rows in table. - /** @deprecated Use factories @ref table or @ref raw_table instead. - */ - template - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &, from_table_t, std::string_view table, - Iter columns_begin, Iter columns_end); - - /// Stream given columns from all rows in table. - /** @deprecated Use factory function @ref query instead. - */ - template - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &tx, from_table_t, std::string_view table, - Columns const &columns); - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// @deprecated Use factories @ref table or @ref raw_table instead. - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &tx, std::string_view table) : - stream_from{tx, from_table, table} - {} -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// @deprecated Use factories @ref table or @ref raw_table instead. - template - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &tx, std::string_view table, Columns const &columns) : - stream_from{tx, from_table, table, columns} - {} - - /// @deprecated Use factories @ref table or @ref raw_table instead. - template - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &, std::string_view table, Iter columns_begin, - Iter columns_end); - - ~stream_from() noexcept; - - /// May this stream still produce more data? - [[nodiscard]] constexpr operator bool() const noexcept - { - return not m_finished; - } - /// Has this stream produced all the data it is going to produce? - [[nodiscard]] constexpr bool operator!() const noexcept - { - return m_finished; - } - - /// Finish this stream. Call this before continuing to use the connection. - /** Consumes all remaining lines, and closes the stream. - * - * This may take a while if you're abandoning the stream before it's done, so - * skip it in error scenarios where you're not planning to use the connection - * again afterwards. - */ - void complete(); - - /// Read one row into a tuple. - /** Converts the row's fields into the fields making up the tuple. - * - * For a column which can contain nulls, be sure to give the corresponding - * tuple field a type which can be null. For example, to read a field as - * `int` when it may contain nulls, read it as `std::optional`. - * Using `std::shared_ptr` or `std::unique_ptr` will also work. - */ - template stream_from &operator>>(Tuple &); - - /// Doing this with a `std::variant` is going to be horrifically borked. - template - stream_from &operator>>(std::variant &) = delete; - - /// Iterate over this stream. Supports range-based "for" loops. - /** Produces an input iterator over the stream. - * - * Do not call this yourself. Use it like "for (auto data : stream.iter())". - */ - template [[nodiscard]] auto iter() & - { - return pqxx::internal::stream_input_iteration{*this}; - } - - /// Read a row. Return fields as views, valid until you read the next row. - /** Returns `nullptr` when there are no more rows to read. Do not attempt - * to read any further rows after that. - * - * Do not access the vector, or the storage referenced by the views, after - * closing or completing the stream, or after attempting to read a next row. - * - * A @ref pqxx::zview is like a `std::string_view`, but with the added - * guarantee that if its data pointer is non-null, the string is followed by - * a terminating zero (which falls just outside the view itself). - * - * If any of the views' data pointer is null, that means that the - * corresponding SQL field is null. - * - * @warning The return type may change in the future, to support C++20 - * coroutine-based usage. - */ - std::vector const *read_row() &; - - /// Read a raw line of text from the COPY command. - /** @warning Do not use this unless you really know what you're doing. */ - raw_line get_raw_line(); - -private: - // TODO: Clean up this signature once we cull the deprecated constructors. - /// @deprecated - stream_from( - transaction_base &tx, std::string_view table, std::string_view columns, - from_table_t); - - // TODO: Clean up this signature once we cull the deprecated constructors. - /// @deprecated - stream_from( - transaction_base &, std::string_view unquoted_table, - std::string_view columns, from_table_t, int); - - template - void extract_fields(Tuple &t, std::index_sequence) const - { - (extract_value(t), ...); - } - - pqxx::internal::glyph_scanner_func *m_glyph_scanner; - - /// Current row's fields' text, combined into one reusable string. - std::string m_row; - - /// The current row's fields. - std::vector m_fields; - - bool m_finished = false; - - void close(); - - template - void extract_value(Tuple &) const; - - /// Read a line of COPY data, write `m_row` and `m_fields`. - void parse_line(); -}; - - -template -inline stream_from::stream_from( - transaction_base &tx, from_table_t, std::string_view table_name, - Columns const &columns) : - stream_from{ - tx, from_table, table_name, std::begin(columns), std::end(columns)} -{} - - -template -inline stream_from::stream_from( - transaction_base &tx, from_table_t, std::string_view table, - Iter columns_begin, Iter columns_end) : - stream_from{ - tx, table, separated_list(",", columns_begin, columns_end), - from_table, 1} -{} - - -template inline stream_from &stream_from::operator>>(Tuple &t) -{ - if (m_finished) - return *this; - static constexpr auto tup_size{std::tuple_size_v}; - m_fields.reserve(tup_size); - parse_line(); - if (m_finished) - return *this; - - if (std::size(m_fields) != tup_size) - throw usage_error{internal::concat( - "Tried to extract ", tup_size, " field(s) from a stream of ", - std::size(m_fields), ".")}; - - extract_fields(t, std::make_index_sequence{}); - return *this; -} - - -template -inline void stream_from::extract_value(Tuple &t) const -{ - using field_type = strip_t(t))>; - using nullity = nullness; - assert(index < std::size(m_fields)); - if constexpr (nullity::always_null) - { - if (std::data(m_fields[index]) != nullptr) - throw conversion_error{"Streaming non-null value into null field."}; - } - else if (std::data(m_fields[index]) == nullptr) - { - if constexpr (nullity::has_null) - std::get(t) = nullity::null(); - else - internal::throw_null_conversion(type_name); - } - else - { - // Don't ever try to convert a non-null value to nullptr_t! - std::get(t) = from_string(m_fields[index]); - } -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/stream_to b/ext/libpqxx-7.7.3/include/pqxx/stream_to deleted file mode 100644 index 8760cf1f4..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/stream_to +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::stream_to class. - * - * pqxx::stream_to enables optimized batch updates to a database table. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/stream_to.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/stream_to.hxx b/ext/libpqxx-7.7.3/include/pqxx/stream_to.hxx deleted file mode 100644 index 2a49d8f85..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/stream_to.hxx +++ /dev/null @@ -1,455 +0,0 @@ -/* Definition of the pqxx::stream_to class. - * - * pqxx::stream_to enables optimized batch updates to a database table. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_TO -#define PQXX_H_STREAM_TO - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/separated_list.hxx" -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -/// Efficiently write data directly to a database table. -/** If you wish to insert rows of data into a table, you can compose INSERT - * statements and execute them. But it's slow and tedious, and you need to - * worry about quoting and escaping the data. - * - * If you're just inserting a single row, it probably won't matter much. You - * can use prepared or parameterised statements to take care of the escaping - * for you. But if you're inserting large numbers of rows you will want - * something better. - * - * Inserting rows one by one using INSERT statements involves a lot of - * pointless overhead, especially when you are working with a remote database - * server over the network. You may end up sending each row over the network - * as a separate query, and waiting for a reply. Do it "in bulk" using - * `stream_to`, and you may find that it goes many times faster. Sometimes - * you gain orders of magnitude in speed. - * - * Here's how it works: you create a `stream_to` stream to start writing to - * your table. You will probably want to specify the columns. Then, you - * feed your data into the stream one row at a time. And finally, you call the - * stream's @ref complete function to tell it to finalise the operation, wait - * for completion, and check for errors. - * - * (You _must_ complete the stream before committing or aborting the - * transaction. The connection is in a special state while the stream is - * active, where it can't process commands, and can't commit or abort a - * transaction.) - * - * So how do you feed a row of data into the stream? There's several ways, but - * the preferred one is to call its @ref write_values. Pass the field values - * as arguments. Doesn't matter what type they are, as long as libpqxx knows - * how to convert them to PostgreSQL's text format: `int`, `std::string` or - * `std:string_view`, `float` and `double`, `bool`... lots of basic types - * are supported. If some of the values are null, feel free to use - * `std::optional`, `std::shared_ptr`, or `std::unique_ptr`. - * - * The arguments' types don't even have to match the fields' SQL types. If you - * want to insert an `int` into a `DECIMAL` column, that's your choice -- it - * will produce a `DECIMAL` value which happens to be integral. Insert a - * `float` into a `VARCHAR` column? That's fine, you'll get a string whose - * contents happen to read like a number. And so on. You can even insert - * different types of value in the same column on different rows. If you have - * a code path where a particular field is always null, just insert `nullptr`. - * - * There is another way to insert rows: the `<<` ("shift-left") operator. - * It's not as fast and it doesn't support variable arguments: each row must be - * either a `std::tuple` or something iterable, such as a `std::vector`, or - * anything else with a `begin()` and `end()`. - * - * @warning While a stream is active, you cannot execute queries, open a - * pipeline, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT stream_to : transaction_focus -{ -public: - /// Stream data to a pre-quoted table and columns. - /** This factory can be useful when it's not convenient to provide the - * columns list in the form of a `std::initializer_list`, or when the list - * of columns is simply not known at compile time. - * - * Also use this if you need to create multiple streams using the same table - * path and/or columns list, and you want to save a bit of work on composing - * the internal SQL statement for starting the stream. It lets you compose - * the string representations for the table path and the columns list, so you - * can compute these once and then re-use them later. - * - * @param tx The transaction within which the stream will operate. - * @param path Name or path for the table upon which the stream will - * operate. If any part of the table path may contain special - * characters or be case-sensitive, quote the path using - * pqxx::connection::quote_table(). - * @param columns Columns to which the stream will write. They should be - * comma-separated and, if needed, quoted. You can produce the string - * using pqxx::connection::quote_columns(). If you omit this argument, - * the stream will write all columns in the table, in schema order. - */ - static stream_to raw_table( - transaction_base &tx, std::string_view path, std::string_view columns = "") - { - return {tx, path, columns}; - } - - /// Create a `stream_to` writing to a named table and columns. - /** Use this to stream data to a table, where the list of columns is known at - * compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns Optionally, the columns to which the stream should write. - * If you do not pass this, the stream will write to all columns in the - * table, in schema order. - */ - static stream_to table( - transaction_base &tx, table_path path, - std::initializer_list columns = {}) - { - auto const &conn{tx.conn()}; - return raw_table(tx, conn.quote_table(path), conn.quote_columns(columns)); - } - -#if defined(PQXX_HAVE_CONCEPTS) - /// Create a `stream_to` writing to a named table and columns. - /** Use this version to stream data to a table, when the list of columns is - * not known at compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns The columns to which the stream should write. - */ - template - static stream_to - table(transaction_base &tx, table_path path, COLUMNS const &columns) - { - auto const &conn{tx.conn()}; - return stream_to::raw_table( - tx, conn.quote_table(path), tx.conn().quote_columns(columns)); - } - - /// Create a `stream_to` writing to a named table and columns. - /** Use this version to stream data to a table, when the list of columns is - * not known at compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns The columns to which the stream should write. - */ - template - static stream_to - table(transaction_base &tx, std::string_view path, COLUMNS const &columns) - { - return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns)); - } -#endif // PQXX_HAVE_CONCEPTS - - /// Create a stream, without specifying columns. - /** @deprecated Use @ref table or @ref raw_table as a factory. - * - * Fields will be inserted in whatever order the columns have in the - * database. - * - * You'll probably want to specify the columns, so that the mapping between - * your data fields and the table is explicit in your code, and not hidden - * in an "implicit contract" between your code and your schema. - */ - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &tx, std::string_view table_name) : - stream_to{tx, table_name, ""sv} - {} - - /// Create a stream, specifying column names as a container of strings. - /** @deprecated Use @ref table or @ref raw_table as a factory. - */ - template - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &, std::string_view table_name, Columns const &columns); - - /// Create a stream, specifying column names as a sequence of strings. - /** @deprecated Use @ref table or @ref raw_table as a factory. - */ - template - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &, std::string_view table_name, Iter columns_begin, - Iter columns_end); - - ~stream_to() noexcept; - - /// Does this stream still need to @ref complete()? - [[nodiscard]] constexpr operator bool() const noexcept - { - return not m_finished; - } - /// Has this stream been through its concluding @c complete()? - [[nodiscard]] constexpr bool operator!() const noexcept - { - return m_finished; - } - - /// Complete the operation, and check for errors. - /** Always call this to close the stream in an orderly fashion, even after - * an error. (In the case of an error, abort the transaction afterwards.) - * - * The only circumstance where it's safe to skip this is after an error, if - * you're discarding the entire connection. - */ - void complete(); - - /// Insert a row of data. - /** Returns a reference to the stream, so you can chain the calls. - * - * The @c row can be a tuple, or any type that can be iterated. Each - * item becomes a field in the row, in the same order as the columns you - * specified when creating the stream. - * - * If you don't already happen to have your fields in the form of a tuple or - * container, prefer @c write_values. It's faster and more convenient. - */ - template stream_to &operator<<(Row const &row) - { - write_row(row); - return *this; - } - - /// Stream a `stream_from` straight into a `stream_to`. - /** This can be useful when copying between different databases. If the - * source and the destination are on the same database, you'll get better - * performance doing it all in a regular query. - */ - stream_to &operator<<(stream_from &); - - /// Insert a row of data, given in the form of a @c std::tuple or container. - /** The @c row can be a tuple, or any type that can be iterated. Each - * item becomes a field in the row, in the same order as the columns you - * specified when creating the stream. - * - * The preferred way to insert a row is @c write_values. - */ - template void write_row(Row const &row) - { - fill_buffer(row); - write_buffer(); - } - - /// Insert values as a row. - /** This is the recommended way of inserting data. Pass your field values, - * of any convertible type. - */ - template void write_values(Ts const &...fields) - { - fill_buffer(fields...); - write_buffer(); - } - -private: - /// Stream a pre-quoted table name and columns list. - stream_to( - transaction_base &tx, std::string_view path, std::string_view columns); - - bool m_finished = false; - - /// Reusable buffer for a row. Saves doing an allocation for each row. - std::string m_buffer; - - /// Reusable buffer for converting/escaping a field. - std::string m_field_buf; - - /// Glyph scanner, for parsing the client encoding. - internal::glyph_scanner_func *m_scanner; - - /// Write a row of raw text-format data into the destination table. - void write_raw_line(std::string_view); - - /// Write a row of data from @c m_buffer into the destination table. - /** Resets the buffer for the next row. - */ - void write_buffer(); - - /// COPY encoding for a null field, plus subsequent separator. - static constexpr std::string_view null_field{"\\N\t"}; - - /// Estimate buffer space needed for a field which is always null. - template - static std::enable_if_t::always_null, std::size_t> - estimate_buffer(T const &) - { - return std::size(null_field); - } - - /// Estimate buffer space needed for field f. - /** The estimate is not very precise. We don't actually know how much space - * we'll need once the escaping comes in. - */ - template - static std::enable_if_t::always_null, std::size_t> - estimate_buffer(T const &field) - { - return is_null(field) ? std::size(null_field) : size_buffer(field); - } - - /// Append escaped version of @c data to @c m_buffer, plus a tab. - void escape_field_to_buffer(std::string_view data); - - /// Append string representation for @c f to @c m_buffer. - /** This is for the general case, where the field may contain a value. - * - * Also appends a tab. The tab is meant to be a separator, not a terminator, - * so if you write any fields at all, you'll end up with one tab too many - * at the end of the buffer. - */ - template - std::enable_if_t::always_null> - append_to_buffer(Field const &f) - { - // We append each field, terminated by a tab. That will leave us with - // one tab too many, assuming we write any fields at all; we remove that - // at the end. - if (is_null(f)) - { - // Easy. Append null and tab in one go. - m_buffer.append(null_field); - } - else - { - // Convert f into m_buffer. - - using traits = string_traits; - auto const budget{estimate_buffer(f)}; - auto const offset{std::size(m_buffer)}; - - if constexpr (std::is_arithmetic_v) - { - // Specially optimised for "safe" types, which never need any - // escaping. Convert straight into m_buffer. - - // The budget we get from size_buffer() includes room for the trailing - // zero, which we must remove. But we're also inserting tabs between - // fields, so we re-purpose the extra byte for that. - auto const total{offset + budget}; - m_buffer.resize(total); - auto const data{m_buffer.data()}; - char *const end{traits::into_buf(data + offset, data + total, f)}; - *(end - 1) = '\t'; - // Shrink to fit. Keep the tab though. - m_buffer.resize(static_cast(end - data)); - } - else if constexpr ( - std::is_same_v or - std::is_same_v or - std::is_same_v) - { - // This string may need escaping. - m_field_buf.resize(budget); - escape_field_to_buffer(f); - } - else - { - // This field needs to be converted to a string, and after that, - // escaped as well. - m_field_buf.resize(budget); - auto const data{m_field_buf.data()}; - escape_field_to_buffer( - traits::to_buf(data, data + std::size(m_field_buf), f)); - } - } - } - - /// Append string representation for a null field to @c m_buffer. - /** This special case is for types which are always null. - * - * Also appends a tab. The tab is meant to be a separator, not a terminator, - * so if you write any fields at all, you'll end up with one tab too many - * at the end of the buffer. - */ - template - std::enable_if_t::always_null> - append_to_buffer(Field const &) - { - m_buffer.append(null_field); - } - - /// Write raw COPY line into @c m_buffer, based on a container of fields. - template - std::enable_if_t> - fill_buffer(Container const &c) - { - // To avoid unnecessary allocations and deallocations, we run through c - // twice: once to determine how much buffer space we may need, and once to - // actually write it into the buffer. - std::size_t budget{0}; - for (auto const &f : c) budget += estimate_buffer(f); - m_buffer.reserve(budget); - for (auto const &f : c) append_to_buffer(f); - } - - /// Estimate how many buffer bytes we need to write tuple. - template - static std::size_t - budget_tuple(Tuple const &t, std::index_sequence) - { - return (estimate_buffer(std::get(t)) + ...); - } - - /// Write tuple of fields to @c m_buffer. - template - void append_tuple(Tuple const &t, std::index_sequence) - { - (append_to_buffer(std::get(t)), ...); - } - - /// Write raw COPY line into @c m_buffer, based on a tuple of fields. - template void fill_buffer(std::tuple const &t) - { - using indexes = std::make_index_sequence; - - m_buffer.reserve(budget_tuple(t, indexes{})); - append_tuple(t, indexes{}); - } - - /// Write raw COPY line into @c m_buffer, based on varargs fields. - template void fill_buffer(const Ts &...fields) - { - (..., append_to_buffer(fields)); - } - - constexpr static std::string_view s_classname{"stream_to"}; -}; - - -template -inline stream_to::stream_to( - transaction_base &tx, std::string_view table_name, Columns const &columns) : - stream_to{tx, table_name, std::begin(columns), std::end(columns)} -{} - - -template -inline stream_to::stream_to( - transaction_base &tx, std::string_view table_name, Iter columns_begin, - Iter columns_end) : - stream_to{ - tx, - tx.quote_name( - table_name, - separated_list(",", columns_begin, columns_end, [&tx](auto col) { - return tx.quote_name(*col); - }))} -{} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/subtransaction b/ext/libpqxx-7.7.3/include/pqxx/subtransaction deleted file mode 100644 index e0d154903..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/subtransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::subtransaction class. - * - * pqxx::subtransaction is a nested transaction, i.e. one inside a transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/subtransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/subtransaction.hxx b/ext/libpqxx-7.7.3/include/pqxx/subtransaction.hxx deleted file mode 100644 index e66b7a7a8..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/subtransaction.hxx +++ /dev/null @@ -1,96 +0,0 @@ -/* Definition of the pqxx::subtransaction class. - * - * pqxx::subtransaction is a nested transaction, i.e. one within a transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SUBTRANSACTION -#define PQXX_H_SUBTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx -{ -/** - * @ingroup transactions - */ -/// "Transaction" nested within another transaction -/** A subtransaction can be executed inside a backend transaction, or inside - * another subtransaction. This can be useful when, for example, statements in - * a transaction may harmlessly fail and you don't want them to abort the - * entire transaction. Here's an example of how a temporary table may be - * dropped before re-creating it, without failing if the table did not exist: - * - * ```cxx - * void do_job(connection &C) - * { - * string const temptable = "fleetingtable"; - * - * work W(C, "do_job"); - * do_firstpart(W); - * - * // Attempt to delete our temporary table if it already existed. - * try - * { - * subtransaction S(W, "droptemp"); - * S.exec0("DROP TABLE " + temptable); - * S.commit(); - * } - * catch (undefined_table const &) - * { - * // Table did not exist. Which is what we were hoping to achieve anyway. - * // Carry on without regrets. - * } - * - * // S may have gone into a failed state and been destroyed, but the - * // upper-level transaction W is still fine. We can continue to use it. - * W.exec0("CREATE TEMP TABLE " + temptable + "(bar integer, splat - * varchar)"); - * - * do_lastpart(W); - * } - * ``` - * - * (This is just an example. If you really wanted to do drop a table without - * an error if it doesn't exist, you'd use DROP TABLE IF EXISTS.) - * - * There are no isolation levels inside a transaction. They are not needed - * because all actions within the same backend transaction are always performed - * sequentially anyway. - * - * @warning While the subtransaction is "live," you cannot execute queries or - * open streams etc. on its parent transaction. A transaction can have at most - * one object of a type derived from @ref pqxx::transaction_focus active on it - * at a time. - */ -class PQXX_LIBEXPORT subtransaction : public transaction_focus, - public dbtransaction -{ -public: - /// Nest a subtransaction nested in another transaction. - explicit subtransaction(dbtransaction &t, std::string_view tname = ""sv); - - /// Nest a subtransaction in another subtransaction. - explicit subtransaction(subtransaction &t, std::string_view name = ""sv); - - virtual ~subtransaction() noexcept override; - -private: - std::string quoted_name() const - { - return quote_name(transaction_focus::name()); - } - virtual void do_commit() override; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/time b/ext/libpqxx-7.7.3/include/pqxx/time deleted file mode 100644 index 85df05744..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/time +++ /dev/null @@ -1,6 +0,0 @@ -/** Date/time string conversions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/time.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/time.hxx b/ext/libpqxx-7.7.3/include/pqxx/time.hxx deleted file mode 100644 index effed05e0..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/time.hxx +++ /dev/null @@ -1,88 +0,0 @@ -/** Support for date/time values. - * - * At the moment this supports dates, but not times. - */ -#ifndef PQXX_H_TIME -#define PQXX_H_TIME - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/internal/concat.hxx" -#include "pqxx/strconv.hxx" - - -#if defined(PQXX_HAVE_YEAR_MONTH_DAY) - -namespace pqxx -{ -using namespace std::literals; - -template<> -struct nullness - : no_null -{}; - - -/// String representation for a Gregorian date in ISO-8601 format. -/** @warning Experimental. There may still be design problems, particularly - * when it comes to BC years. - * - * PostgreSQL supports a choice of date formats, but libpqxx does not. The - * other formats in turn support a choice of "month before day" versus "day - * before month," meaning that it's not necessarily known which format a given - * date is supposed to be. So I repeat: ISO-8601-style format only! - * - * Invalid dates will not convert. This includes February 29 on non-leap - * years, which is why it matters that `year_month_day` represents a - * _Gregorian_ date. - * - * The range of years is limited. At the time of writing, PostgreSQL 14 - * supports years from 4713 BC to 294276 AD inclusive, and C++20 supports - * a range of 32767 BC to 32767 AD inclusive. So in practice, years must fall - * between 4713 BC and 32767 AD, inclusive. - * - * @warning Support for BC (or BCE) years is still experimental. I still need - * confirmation on this issue: it looks as if C++ years are astronomical years, - * which means they have a Year Zero. Regular BC/AD years do not have a year - * zero, so the year 1 AD follows directly after 1 BC. - * - * So, what to our calendars (and to PostgreSQL) is the year "0001 BC" seems to - * count as year "0" in a `std::chrono::year_month_day`. The year 0001 AD is - * still equal to 1 as you'd expect, and all AD years work normally, but all - * years before then are shifted by one. For instance, the year 543 BC would - * be -542 in C++. - */ -template<> struct PQXX_LIBEXPORT string_traits -{ - [[nodiscard]] static zview - to_buf(char *begin, char *end, std::chrono::year_month_day const &value) - { - return generic_to_buf(begin, end, value); - } - - static char * - into_buf(char *begin, char *end, std::chrono::year_month_day const &value); - - [[nodiscard]] static std::chrono::year_month_day - from_string(std::string_view text); - - [[nodiscard]] static std::size_t - size_buffer(std::chrono::year_month_day const &) noexcept - { - static_assert(int{(std::chrono::year::min)()} >= -99999); - static_assert(int{(std::chrono::year::max)()} <= 99999); - return 5 + 1 + 2 + 1 + 2 + std::size(s_bc) + 1; - } - -private: - /// The "BC" suffix for years before 1 AD. - static constexpr std::string_view s_bc{" BC"sv}; -}; -} // namespace pqxx -#endif // PQXX_HAVE_YEAR_MONTH_DAY -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/transaction b/ext/libpqxx-7.7.3/include/pqxx/transaction deleted file mode 100644 index a7ae39d43..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/transaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::transaction class. - * - * pqxx::transaction represents a standard database transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/transaction.hxx b/ext/libpqxx-7.7.3/include/pqxx/transaction.hxx deleted file mode 100644 index e90917e38..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/transaction.hxx +++ /dev/null @@ -1,108 +0,0 @@ -/* Definition of the pqxx::transaction class. - * pqxx::transaction represents a standard database transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION -#define PQXX_H_TRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx::internal -{ -/// Helper base class for the @ref transaction class template. -class PQXX_LIBEXPORT basic_transaction : public dbtransaction -{ -protected: - basic_transaction( - connection &c, zview begin_command, std::string_view tname); - basic_transaction(connection &c, zview begin_command, std::string &&tname); - basic_transaction(connection &c, zview begin_command); - - virtual ~basic_transaction() noexcept override = 0; - -private: - virtual void do_commit() override; -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @ingroup transactions - */ -//@{ - -/// Standard back-end transaction, templatised on isolation level. -/** This is the type you'll normally want to use to represent a transaction on - * the database. - * - * Usage example: double all wages. - * - * ```cxx - * extern connection C; - * work T(C); - * try - * { - * T.exec0("UPDATE employees SET wage=wage*2"); - * T.commit(); // NOTE: do this inside try block - * } - * catch (exception const &e) - * { - * cerr << e.what() << endl; - * T.abort(); // Usually not needed; same happens when T's life ends. - * } - * ``` - */ -template< - isolation_level ISOLATION = isolation_level::read_committed, - write_policy READWRITE = write_policy::read_write> -class transaction final : public internal::basic_transaction -{ -public: - /// Begin a transaction. - /** - * @param c Connection for this transaction to operate on. - * @param tname Optional name for transaction. Must begin with a letter and - * may contain letters and digits only. - */ - transaction(connection &c, std::string_view tname) : - internal::basic_transaction{ - c, internal::begin_cmd, tname} - {} - - /// Begin a transaction. - /** - * @param c Connection for this transaction to operate on. - * may contain letters and digits only. - */ - explicit transaction(connection &c) : - internal::basic_transaction{ - c, internal::begin_cmd} - {} - - virtual ~transaction() noexcept override { close(); } -}; - - -/// The default transaction type. -using work = transaction<>; - -/// Read-only transaction. -using read_transaction = - transaction; - -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/transaction_base b/ext/libpqxx-7.7.3/include/pqxx/transaction_base deleted file mode 100644 index c39219aac..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/transaction_base +++ /dev/null @@ -1,9 +0,0 @@ -/** Base for the transaction classes. - * - * pqxx::transaction_base defines the interface for any abstract class that - * represents a database transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transaction_base.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/transaction_base.hxx b/ext/libpqxx-7.7.3/include/pqxx/transaction_base.hxx deleted file mode 100644 index 4363cc56a..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/transaction_base.hxx +++ /dev/null @@ -1,810 +0,0 @@ -/* Common code and definitions for the transaction classes. - * - * pqxx::transaction_base defines the interface for any abstract class that - * represents a database transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION_BASE -#define PQXX_H_TRANSACTION_BASE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -/* End-user programs need not include this file, unless they define their own - * transaction classes. This is not something the typical program should want - * to do. - * - * However, reading this file is worthwhile because it defines the public - * interface for the available transaction classes such as transaction and - * nontransaction. - */ - -#include "pqxx/connection.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/isolation.hxx" -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/util.hxx" - -namespace pqxx::internal::gate -{ -class transaction_subtransaction; -class transaction_sql_cursor; -class transaction_stream_to; -class transaction_transaction_focus; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -using namespace std::literals; - - -class transaction_focus; - - -/** - * @defgroup transactions Transaction classes - * - * All database access goes through instances of these classes. - * However, not all implementations of this interface need to provide full - * transactional integrity. - * - * Several implementations of this interface are shipped with libpqxx, - * including the plain transaction class, the entirely unprotected - * nontransaction, and the more cautious robusttransaction. - */ - -/// Interface definition (and common code) for "transaction" classes. -/** - * @ingroup transactions - * - * Abstract base class for all transaction types. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base -{ -public: - transaction_base() = delete; - transaction_base(transaction_base const &) = delete; - transaction_base(transaction_base &&) = delete; - transaction_base &operator=(transaction_base const &) = delete; - transaction_base &operator=(transaction_base &&) = delete; - - virtual ~transaction_base() = 0; - - /// Commit the transaction. - /** Make the effects of this transaction definite. If you destroy a - * transaction without invoking its @ref commit() first, that will implicitly - * abort it. (For the @ref nontransaction class though, "commit" and "abort" - * really don't do anything, hence its name.) - * - * There is, however, a minute risk that you might lose your connection to - * the database at just the wrong moment here. In that case, libpqxx may be - * unable to determine whether the database was able to complete the - * transaction, or had to roll it back. In that scenario, @ref commit() will - * throw an in_doubt_error. There is a different transaction class called - * @ref robusttransaction which takes some special precautions to reduce this - * risk. - */ - void commit(); - - /// Abort the transaction. - /** No special effort is required to call this function; it will be called - * implicitly when the transaction is destructed. - */ - void abort(); - - /** - * @ingroup escaping-functions - * - * Use these when writing SQL queries that incorporate C++ values as SQL - * constants. - * - * The functions you see here are just convenience shortcuts to the same - * functions on the connection object. - */ - //@{ - /// Escape string for use as SQL string literal in this transaction. - template [[nodiscard]] auto esc(ARGS &&...args) const - { - return conn().esc(std::forward(args)...); - } - - /// Escape binary data for use as SQL string literal in this transaction. - /** Raw, binary data is treated differently from regular strings. Binary - * strings are never interpreted as text, so they may safely include byte - * values or byte sequences that don't happen to represent valid characters - * in the character encoding being used. - * - * The binary string does not stop at the first zero byte, as is the case - * with textual strings. Instead, it may contain zero bytes anywhere. If - * it happens to contain bytes that look like quote characters, or other - * things that can disrupt their use in SQL queries, they will be replaced - * with special escape sequences. - */ - template [[nodiscard]] auto esc_raw(ARGS &&...args) const - { - return conn().esc_raw(std::forward(args)...); - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(zview text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return conn().unesc_raw(text); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard]] std::basic_string unesc_bin(zview text) - { - return conn().unesc_bin(text); - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(char const *text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return conn().unesc_raw(text); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard]] std::basic_string unesc_bin(char const text[]) - { - return conn().unesc_bin(text); - } - - /// Represent object as SQL string, including quoting & escaping. - /** Nulls are recognized and represented as SQL nulls. */ - template [[nodiscard]] std::string quote(T const &t) const - { - return conn().quote(t); - } - - [[deprecated( - "Use std::basic_string instead of binarystring.")]] std::string - quote(binarystring const &t) const - { - return conn().quote(t.bytes_view()); - } - - /// Binary-escape and quote a binary string for use as an SQL constant. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(unsigned char const bin[], std::size_t len) const - { - return quote(binary_cast(bin, len)); - } - - /// Binary-escape and quote a binary string for use as an SQL constant. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(zview bin) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Binary-escape and quote a binary string for use as an SQL constant. - /** For binary data you can also just use @ref quote(data). */ - template - [[nodiscard]] std::string quote_raw(DATA const &data) const - { - return conn().quote_raw(data); - } -#endif - - /// Escape an SQL identifier for use in a query. - [[nodiscard]] std::string quote_name(std::string_view identifier) const - { - return conn().quote_name(identifier); - } - - /// Escape string for literal LIKE match. - [[nodiscard]] std::string - esc_like(std::string_view bin, char escape_char = '\\') const - { - return conn().esc_like(bin, escape_char); - } - //@} - - /** - * @name Command execution - * - * There are many functions for executing (or "performing") a command (or - * "query"). This is the most fundamental thing you can do with the library, - * and you always do it from a transaction class. - * - * Command execution can throw many types of exception, including sql_error, - * broken_connection, and many sql_error subtypes such as - * feature_not_supported or insufficient_privilege. But any exception thrown - * by the C++ standard library may also occur here. All exceptions you will - * see libpqxx throw are derived from std::exception. - * - * One unusual feature in libpqxx is that you can give your query a name or - * description. This does not mean anything to the database, but sometimes - * it can help libpqxx produce more helpful error messages, making problems - * in your code easier to debug. - * - * Many of the execution functions used to accept a `desc` argument, a - * human-readable description of the statement for use in error messages. - * This could make failures easier to debug. Future versions will use - * C++20's `std::source_location` to identify the failing statement. - */ - //@{ - - /// Execute a command. - /** - * @param query Query or command to execute. - * @param desc Optional identifier for query, to help pinpoint SQL errors. - * @return A result set describing the query's or command's result. - */ - [[deprecated("The desc parameter is going away.")]] result - exec(std::string_view query, std::string_view desc); - - /// Execute a command. - /** - * @param query Query or command to execute. - * @return A result set describing the query's or command's result. - */ - result exec(std::string_view query) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec(query, std::string_view{}); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute a command. - /** - * @param query Query or command to execute. - * @param desc Optional identifier for query, to help pinpoint SQL errors. - * @return A result set describing the query's or command's result. - */ - [[deprecated( - "Pass your query as a std::string_view, not stringstream.")]] result - exec(std::stringstream const &query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec(query.str(), desc); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command, which should return zero rows of data. - /** Works like @ref exec, but fails if the result contains data. It still - * returns a result, however, which may contain useful metadata. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] result - exec0(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(0, query, desc); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command, which should return zero rows of data. - /** Works like @ref exec, but fails if the result contains data. It still - * returns a result, however, which may contain useful metadata. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - result exec0(zview query) { return exec_n(0, query); } - - /// Execute command returning a single row of data. - /** Works like @ref exec, but requires the result to contain exactly one row. - * The row can be addressed directly, without the need to find the first row - * in a result set. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] row - exec1(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(1, query, desc).front(); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command returning a single row of data. - /** Works like @ref exec, but requires the result to contain exactly one row. - * The row can be addressed directly, without the need to find the first row - * in a result set. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - row exec1(zview query) { return exec_n(1, query).front(); } - - /// Execute command, expect given number of rows. - /** Works like @ref exec, but checks that the result has exactly the expected - * number of rows. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] result - exec_n(result::size_type rows, zview query, std::string_view desc); - - /// Execute command, expect given number of rows. - /** Works like @ref exec, but checks that the result has exactly the expected - * number of rows. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - result exec_n(result::size_type rows, zview query) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(rows, query, std::string_view{}); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Perform query, expecting exactly 1 row with 1 field, and convert it. - /** This is convenience shorthand for querying exactly one value from the - * database. It returns that value, converted to the type you specify. - */ - template - [[deprecated("The desc parameter is going away.")]] TYPE - query_value(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row const r{exec1(query, desc)}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - if (std::size(r) != 1) - throw usage_error{internal::concat( - "Queried single value from result with ", std::size(r), " columns.")}; - return r[0].as(); - } - - /// Perform query, expecting exactly 1 row with 1 field, and convert it. - /** This is convenience shorthand for querying exactly one value from the - * database. It returns that value, converted to the type you specify. - */ - template TYPE query_value(zview query) - { - row const r{exec1(query)}; - if (std::size(r) != 1) - throw usage_error{internal::concat( - "Queried single value from result with ", std::size(r), " columns.")}; - return r[0].as(); - } - - /// Execute a query, and loop over the results row by row. - /** Converts the rows to `std::tuple`, of the column types you specify. - * - * Use this with a range-based "for" loop. It executes the query, and - * directly maps the resulting rows onto a `std::tuple` of the types you - * specify. It starts before all the data from the server is in, so if your - * network connection to the server breaks while you're iterating, you'll get - * an exception partway through. - * - * The stream lives entirely within the lifetime of the transaction. Make - * sure you destroy the stream before you destroy the transaction. Either - * iterate the stream all the way to the end, or destroy first the stream - * and then the transaction without touching either in any other way. Until - * the stream has finished, the transaction is in a special state where it - * cannot execute queries. - * - * As a special case, tuple may contain `std::string_view` fields, but the - * strings to which they point will only remain valid until you extract the - * next row. After that, the memory holding the string may be overwritten or - * deallocated. - * - * If any of the columns can be null, and the C++ type to which it translates - * does not have a null value, wrap the type in `std::optional` (or if - * you prefer, `std::shared_ptr` or `std::unique_ptr)`. These templates - * do recognise null values, and libpqxx will know how to convert to them. - * - * The connection is in a special state until the iteration finishes. So if - * it does not finish due to a `break` or a `return` or an exception, then - * the entire connection becomes effectively unusable. - * - * Querying in this way is faster than the `exec()` methods for larger - * results (but slower for small ones). You can start processing rows before - * the full result is in. Also, `stream()` scales better in terms of memory - * usage. Where @ref exec() reads the entire result into memory at once, - * `stream()` will read and process one row at at a time. - * - * Your query executes as part of a COPY command, not as a stand-alone query, - * so there are limitations to what you can do in the query. It can be - * either a SELECT or VALUES query; or an INSERT, UPDATE, or DELETE with a - * RETURNING clause. See the documentation for PostgreSQL's COPY command for - * the details: - * - * https://www.postgresql.org/docs/current/sql-copy.html - * - * Iterating in this way does require each of the field types you pass to be - * default-constructible, copy-constructible, and assignable. These - * requirements may be loosened once libpqxx moves on to C++20. - */ - template - [[nodiscard]] auto stream(std::string_view query) & - { - // Tricky: std::make_unique() supports constructors but not RVO functions. - return pqxx::internal::owning_stream_input_iteration{ - std::unique_ptr{ - new stream_from{stream_from::query(*this, query)}}}; - } - - // C++20: Concept like std::invocable, but without specifying param types. - /// Perform a streaming query, and for each result row, call `func`. - /** Here, `func` can be a function, a `std::function`, a lambda, or an - * object that supports the function call operator. Of course `func` must - * have an unambiguous signature; it can't be overloaded or generic. - * - * The `for_each` function executes `query` in a stream using - * @ref pqxx::stream_from. Every time a row of data comes in from the - * server, it converts the row's fields to the types of `func`'s respective - * parameters, and calls `func` with those values. - * - * This will not work for all queries, but straightforward `SELECT` and - * `UPDATE ... RETURNING` queries should work. Consult the documentation for - * @ref pqxx::stream_from and PostgreSQL's underlying `COPY` command for the - * full details. - * - * Streaming a query like this is likely to be slower than the @ref exec() - * functions for small result sets, but faster for large result sets. So if - * performance matters, you'll want to use `for_each` if you query large - * amounts of data, but not if you do lots of queries with small outputs. - */ - template - inline auto for_each(std::string_view query, CALLABLE &&func) - { - using param_types = - pqxx::internal::strip_types_t>; - param_types const *const sample{nullptr}; - auto data_stream{stream_like(query, sample)}; - for (auto const &fields : data_stream) std::apply(func, fields); - } - - /** - * @name Parameterized statements - * - * You'll often need parameters in the queries you execute: "select the - * car with this licence plate." If the parameter is a string, you need to - * quote it and escape any special characters inside it, or it may become a - * target for an SQL injection attack. If it's an integer (for example), - * you need to convert it to a string, but in the database's format, without - * locale-specific niceties like "," separators between the thousands. - * - * Parameterised statements are an easier and safer way to do this. They're - * like prepared statements, but for a single use. You don't need to name - * them, and you don't need to prepare them first. - * - * Your query will include placeholders like `$1` and `$2` etc. in the places - * where you want the arguments to go. Then, you pass the argument values - * and the actual query is constructed for you. - * - * Pass the exact right number of parameters, and in the right order. The - * parameters in the query don't have to be neatly ordered from `$1` to - * `$2` to `$3` - but you must pass the argument for `$1` first, the one - * for `$2` second, etc. - * - * @warning Beware of "nul" bytes. Any string you pass as a parameter will - * end at the first char with value zero. If you pass a string that contains - * a zero byte, the last byte in the value will be the one just before the - * zero. - */ - //@{ - /// Execute an SQL statement with parameters. - template result exec_params(zview query, Args &&...args) - { - params pp(args...); - return internal_exec_params(query, pp.make_c_params()); - } - - // Execute parameterised statement, expect a single-row result. - /** @throw unexpected_rows if the result does not consist of exactly one row. - */ - template row exec_params1(zview query, Args &&...args) - { - return exec_params_n(1, query, std::forward(args)...).front(); - } - - // Execute parameterised statement, expect a result with zero rows. - /** @throw unexpected_rows if the result contains rows. - */ - template result exec_params0(zview query, Args &&...args) - { - return exec_params_n(0, query, std::forward(args)...); - } - - // Execute parameterised statement, expect exactly a given number of rows. - /** @throw unexpected_rows if the result contains the wrong number of rows. - */ - template - result exec_params_n(std::size_t rows, zview query, Args &&...args) - { - auto const r{exec_params(query, std::forward(args)...)}; - check_rowcount_params(rows, std::size(r)); - return r; - } - //@} - - /** - * @name Prepared statements - * - * These are very similar to parameterised statements. The difference is - * that you prepare them in advance, giving them identifying names. You can - * then call them by these names, passing in the argument values appropriate - * for that call. - * - * You prepare a statement on the connection, using - * @ref pqxx::connection::prepare(). But you then call the statement in a - * transaction, using the functions you see here. - * - * Never try to prepare, execute, or unprepare a prepared statement manually - * using direct SQL queries when you also use the libpqxx equivalents. For - * any given statement, either prepare, manage, and execute it through the - * dedicated libpqxx functions; or do it all directly in SQL. Don't mix the - * two, or the code may get confused. - * - * See \ref prepared for a full discussion. - * - * @warning Beware of "nul" bytes. Any string you pass as a parameter will - * end at the first char with value zero. If you pass a string that contains - * a zero byte, the last byte in the value will be the one just before the - * zero. If you need a zero byte, you're dealing with binary strings, not - * regular strings. Represent binary strings on the SQL side as `BYTEA` - * (or as large objects). On the C++ side, use types like - * `std::basic_string` or `std::basic_string_view` - * or (in C++20) `std::vector`. Also, consider large objects on - * the SQL side and @ref blob on the C++ side. - */ - //@{ - - /// Execute a prepared statement, with optional arguments. - template - result exec_prepared(zview statement, Args &&...args) - { - params pp(args...); - return internal_exec_prepared(statement, pp.make_c_params()); - } - - /// Execute a prepared statement, and expect a single-row result. - /** @throw pqxx::unexpected_rows if the result was not exactly 1 row. - */ - template - row exec_prepared1(zview statement, Args &&...args) - { - return exec_prepared_n(1, statement, std::forward(args)...).front(); - } - - /// Execute a prepared statement, and expect a result with zero rows. - /** @throw pqxx::unexpected_rows if the result contained rows. - */ - template - result exec_prepared0(zview statement, Args &&...args) - { - return exec_prepared_n(0, statement, std::forward(args)...); - } - - /// Execute a prepared statement, expect a result with given number of rows. - /** @throw pqxx::unexpected_rows if the result did not contain exactly the - * given number of rows. - */ - template - result - exec_prepared_n(result::size_type rows, zview statement, Args &&...args) - { - auto const r{exec_prepared(statement, std::forward(args)...)}; - check_rowcount_prepared(statement, rows, std::size(r)); - return r; - } - - //@} - - /** - * @name Error/warning output - */ - //@{ - /// Have connection process a warning message. - void process_notice(char const msg[]) const { m_conn.process_notice(msg); } - /// Have connection process a warning message. - void process_notice(zview msg) const { m_conn.process_notice(msg); } - //@} - - /// The connection in which this transaction lives. - [[nodiscard]] constexpr connection &conn() const noexcept { return m_conn; } - - /// Set session variable using SQL "SET" command. - /** @deprecated To set a transaction-local variable, execute an SQL `SET` - * command. To set a session variable, use the connection's - * @ref set_session_var function. - * - * @warning When setting a string value, you must make sure that the string - * is "safe." If you call @ref quote() on the string, it will return a - * safely escaped and quoted version for use as an SQL literal. - * - * @warning This function executes SQL. Do not try to set or get variables - * while a pipeline or table stream is active. - * - * @param var The variable to set. - * @param value The new value to store in the variable. This can be any SQL - * expression. - */ - [[deprecated( - "Set transaction-local variables using SQL SET statements.")]] void - set_variable(std::string_view var, std::string_view value); - - /// Read session variable using SQL "SHOW" command. - /** @warning This executes SQL. Do not try to set or get variables while a - * pipeline or table stream is active. - */ - [[deprecated("Read variables using SQL SHOW statements.")]] std::string - get_variable(std::string_view); - - // C++20: constexpr. - /// Transaction name, if you passed one to the constructor; or empty string. - [[nodiscard]] std::string_view name() const &noexcept { return m_name; } - -protected: - /// Create a transaction (to be called by implementation classes only). - /** The name, if nonempty, must begin with a letter and may contain letters - * and digits only. - */ - transaction_base( - connection &c, std::string_view tname, - std::shared_ptr rollback_cmd) : - m_conn{c}, m_name{tname}, m_rollback_cmd{rollback_cmd} - {} - - /// Create a transaction (to be called by implementation classes only). - /** Its rollback command will be "ROLLBACK". - * - * The name, if nonempty, must begin with a letter and may contain letters - * and digits only. - */ - transaction_base(connection &c, std::string_view tname); - - /// Create a transaction (to be called by implementation classes only). - explicit transaction_base(connection &c); - - /// Register this transaction with the connection. - void register_transaction(); - - /// End transaction. To be called by implementing class' destructor. - void close() noexcept; - - /// To be implemented by derived implementation class: commit transaction. - virtual void do_commit() = 0; - - /// Transaction type-specific way of aborting a transaction. - /** @warning This will become "final", since this function can be called - * from the implementing class destructor. - */ - virtual void do_abort(); - - /// Set the rollback command. - void set_rollback_cmd(std::shared_ptr cmd) - { - m_rollback_cmd = cmd; - } - - /// Execute query on connection directly. - result direct_exec(std::string_view, std::string_view desc = ""sv); - result - direct_exec(std::shared_ptr, std::string_view desc = ""sv); - -private: - enum class status - { - active, - aborted, - committed, - in_doubt - }; - - PQXX_PRIVATE void check_pending_error(); - - result - internal_exec_prepared(zview statement, internal::c_params const &args); - - result internal_exec_params(zview query, internal::c_params const &args); - - /// Throw unexpected_rows if prepared statement returned wrong no. of rows. - void check_rowcount_prepared( - zview statement, result::size_type expected_rows, - result::size_type actual_rows); - - /// Throw unexpected_rows if wrong row count from parameterised statement. - void - check_rowcount_params(std::size_t expected_rows, std::size_t actual_rows); - - /// Describe this transaction to humans, e.g. "transaction 'foo'". - [[nodiscard]] std::string description() const; - - friend class pqxx::internal::gate::transaction_transaction_focus; - PQXX_PRIVATE void register_focus(transaction_focus *); - PQXX_PRIVATE void unregister_focus(transaction_focus *) noexcept; - PQXX_PRIVATE void register_pending_error(zview) noexcept; - PQXX_PRIVATE void register_pending_error(std::string &&) noexcept; - - /// Like @ref stream(), but takes a tuple rather than a parameter pack. - template - auto stream_like(std::string_view query, std::tuple const *) - { - return stream(query); - } - - connection &m_conn; - - /// Current "focus": a pipeline, a nested transaction, a stream... - /** This pointer is used for only one purpose: sanity checks against mistakes - * such as opening one while another is still active. - */ - transaction_focus const *m_focus = nullptr; - - status m_status = status::active; - bool m_registered = false; - std::string m_name; - std::string m_pending_error; - - /// SQL command for aborting this type of transaction. - std::shared_ptr m_rollback_cmd; - - static constexpr std::string_view s_type_name{"transaction"sv}; -}; - - -// C++20: Can borrowed_range help? -/// Forbidden specialisation: underlying buffer immediately goes out of scope. -template<> -std::string_view transaction_base::query_value( - zview query, std::string_view desc) = delete; -/// Forbidden specialisation: underlying buffer immediately goes out of scope. -template<> -zview transaction_base::query_value( - zview query, std::string_view desc) = delete; - -} // namespace pqxx - - -namespace pqxx::internal -{ -/// The SQL command for starting a given type of transaction. -template -extern const zview begin_cmd; - -// These are not static members, so "constexpr" does not imply "inline". -template<> -inline constexpr zview begin_cmd{ - "BEGIN"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN READ ONLY"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL REPEATABLE READ"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL SERIALIZABLE"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY"_zv}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/transaction_focus b/ext/libpqxx-7.7.3/include/pqxx/transaction_focus deleted file mode 100644 index fe78a9bcc..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/transaction_focus +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Transaction focus: types which monopolise a transaction's attention. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/types.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/transaction_focus.hxx b/ext/libpqxx-7.7.3/include/pqxx/transaction_focus.hxx deleted file mode 100644 index 0707e3cc4..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/transaction_focus.hxx +++ /dev/null @@ -1,89 +0,0 @@ -/** Transaction focus: types which monopolise a transaction's attention. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION_FOCUS -#define PQXX_H_TRANSACTION_FOCUS - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Base class for things that monopolise a transaction's attention. -/** You probably won't need to use this class. But it can be useful to _know_ - * that a given libpqxx class is derived from it. - * - * Pipelines, SQL statements, and data streams are examples of classes derived - * from `transaction_focus`. For any given transaction, only one object of - * such a class can be active at any given time. - */ -class PQXX_LIBEXPORT transaction_focus -{ -public: - transaction_focus( - transaction_base &t, std::string_view cname, std::string_view oname) : - m_trans{t}, m_classname{cname}, m_name{oname} - {} - - transaction_focus( - transaction_base &t, std::string_view cname, std::string &&oname) : - m_trans{t}, m_classname{cname}, m_name{std::move(oname)} - {} - - transaction_focus(transaction_base &t, std::string_view cname) : - m_trans{t}, m_classname{cname} - {} - - transaction_focus() = delete; - transaction_focus(transaction_focus const &) = delete; - transaction_focus &operator=(transaction_focus const &) = delete; - - /// Class name, for human consumption. - [[nodiscard]] constexpr std::string_view classname() const noexcept - { - return m_classname; - } - - /// Name for this object, if the caller passed one; empty string otherwise. - [[nodiscard]] std::string_view name() const &noexcept { return m_name; } - - [[nodiscard]] std::string description() const - { - return pqxx::internal::describe_object(m_classname, m_name); - } - - /// Can't move a transaction_focus. - /** Moving the transaction_focus would break the transaction's reference back - * to the object. - */ - transaction_focus(transaction_focus &&) = delete; - - /// Can't move a transaction_focus. - /** Moving the transaction_focus would break the transaction's reference back - * to the object. - */ - transaction_focus &operator=(transaction_focus &&) = delete; - -protected: - void register_me(); - void unregister_me() noexcept; - void reg_pending_error(std::string const &) noexcept; - bool registered() const noexcept { return m_registered; } - - transaction_base &m_trans; - -private: - bool m_registered = false; - std::string_view m_classname; - std::string m_name; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/transactor b/ext/libpqxx-7.7.3/include/pqxx/transactor deleted file mode 100644 index 29d1b9640..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/transactor +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::transactor class. - * - * pqxx::transactor is a framework-style wrapper for safe transactions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transactor.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/transactor.hxx b/ext/libpqxx-7.7.3/include/pqxx/transactor.hxx deleted file mode 100644 index eefd04ba1..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/transactor.hxx +++ /dev/null @@ -1,147 +0,0 @@ -/* Transactor framework, a wrapper for safely retryable transactions. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTOR -#define PQXX_H_TRANSACTOR - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/connection.hxx" -#include "pqxx/transaction.hxx" - -namespace pqxx -{ -/** - * @defgroup transactor Transactor framework - * - * Sometimes a transaction can fail for completely transient reasons, such as a - * conflict with another transaction in SERIALIZABLE isolation. The right way - * to handle those failures is often just to re-run the transaction from - * scratch. - * - * For example, your REST API might be handling each HTTP request in its own - * database transaction, and if this kind of transient failure happens, you - * simply want to "replay" the whole request, in a fresh transaction. - * - * You won't necessarily want to execute the exact same SQL commands with the - * exact same data. Some of your SQL statements may depend on state that can - * vary between retries. Data in the database may already have changed, for - * instance. So instead of dumbly replaying the SQL, you re-run the same - * application code that produced those SQL commands, from the start. - * - * The transactor framework makes it a little easier for you to do this safely, - * and avoid typical pitfalls. You encapsulate the work that you want to do - * into a callable that you pass to the @ref perform function. - * - * Here's how it works. You write your transaction code as a lambda or - * function, which creates its own transaction object, does its work, and - * commits at the end. You pass that callback to @ref pqxx::perform, which - * runs it for you. - * - * If there's a failure inside your callback, there will be an exception. Your - * transaction object goes out of scope and gets destroyed, so that it aborts - * implicitly. Seeing this, @ref perform tries running your callback again. It - * stops doing that when the callback succeeds, or when it has failed too many - * times, or when there's an error that leaves the database in an unknown - * state, such as a lost connection just while we're waiting for the database - * to confirm a commit. It all depends on the type of exception. - * - * The callback takes no arguments. If you're using lambdas, the easy way to - * pass arguments is for the lambda to "capture" them from your variables. Or, - * if you're using functions, you may want to use `std::bind`. - * - * Once your callback succeeds, it can return a result, and @ref perform will - * return that result back to you. - */ -//@{ - -/// Simple way to execute a transaction with automatic retry. -/** - * Executes your transaction code as a callback. Repeats it until it completes - * normally, or it throws an error other than the few libpqxx-generated - * exceptions that the framework understands, or after a given number of failed - * attempts, or if the transaction ends in an "in-doubt" state. - * - * (An in-doubt state is one where libpqxx cannot determine whether the server - * finally committed a transaction or not. This can happen if the network - * connection to the server is lost just while we're waiting for its reply to - * a "commit" statement. The server may have completed the commit, or not, but - * it can't tell you because there's no longer a connection. - * - * Using this still takes a bit of care. If your callback makes use of data - * from the database, you'll probably have to query that data within your - * callback. If the attempt to perform your callback fails, and the framework - * tries again, you'll be in a new transaction and the data in the database may - * have changed under your feet. - * - * Also be careful about changing variables or data structures from within - * your callback. The run may still fail, and perhaps get run again. The - * ideal way to do it (in most cases) is to return your result from your - * callback, and change your program's data state only after @ref perform - * completes successfully. - * - * @param callback Transaction code that can be called with no arguments. - * @param attempts Maximum number of times to attempt performing callback. - * Must be greater than zero. - * @return Whatever your callback returns. - */ -template -inline auto perform(TRANSACTION_CALLBACK &&callback, int attempts = 3) - -> std::invoke_result_t -{ - if (attempts <= 0) - throw std::invalid_argument{ - "Zero or negative number of attempts passed to pqxx::perform()."}; - - for (; attempts > 0; --attempts) - { - try - { - return std::invoke(callback); - } - catch (in_doubt_error const &) - { - // Not sure whether transaction went through or not. The last thing in - // the world that we should do now is try again! - throw; - } - catch (statement_completion_unknown const &) - { - // Not sure whether our last statement succeeded. Don't risk running it - // again. - throw; - } - catch (broken_connection const &) - { - // Connection failed. May be worth retrying, if the transactor opens its - // own connection. - if (attempts <= 1) - throw; - continue; - } - catch (transaction_rollback const &) - { - // Some error that may well be transient, such as serialization failure - // or deadlock. Worth retrying. - if (attempts <= 1) - throw; - continue; - } - } - throw pqxx::internal_error{"No outcome reached on perform()."}; -} -} // namespace pqxx -//@} -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/types b/ext/libpqxx-7.7.3/include/pqxx/types deleted file mode 100644 index 23a5caae1..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/types +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Basic typedefs and forward declarations. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/types.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/types.hxx b/ext/libpqxx-7.7.3/include/pqxx/types.hxx deleted file mode 100644 index f95b598f8..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/types.hxx +++ /dev/null @@ -1,173 +0,0 @@ -/* Basic type aliases and forward declarations. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TYPES -#define PQXX_H_TYPES - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#if defined(PQXX_HAVE_CONCEPTS) && __has_include() -# include -#endif - - -namespace pqxx -{ -/// Number of rows in a result set. -using result_size_type = int; - -/// Difference between result sizes. -using result_difference_type = int; - -/// Number of fields in a row of database data. -using row_size_type = int; - -/// Difference between row sizes. -using row_difference_type = int; - -/// Number of bytes in a field of database data. -using field_size_type = std::size_t; - -/// Number of bytes in a large object. -using large_object_size_type = int64_t; - - -// Forward declarations, to help break compilation dependencies. -// These won't necessarily include all classes in libpqxx. -class binarystring; -class connection; -class const_result_iterator; -class const_reverse_result_iterator; -class const_reverse_row_iterator; -class const_row_iterator; -class dbtransaction; -class field; -class largeobjectaccess; -class notification_receiver; -struct range_error; -class result; -class row; -class stream_from; -class transaction_base; - -/// Marker for @ref stream_from constructors: "stream from table." -/** @deprecated Use @ref stream_from::table() instead. - */ -struct from_table_t -{}; - -/// Marker for @ref stream_from constructors: "stream from query." -/** @deprecated Use @ref stream_from::query() instead. - */ -struct from_query_t -{}; - - -/// Format code: is data text or binary? -/** Binary-compatible with libpq's format codes. - */ -enum class format : int -{ - text = 0, - binary = 1, -}; - - -/// Remove any constness, volatile, and reference-ness from a type. -/** @deprecated In C++20 we'll replace this with std::remove_cvref. - */ -template -using strip_t = std::remove_cv_t>; - - -#if defined(PQXX_HAVE_CONCEPTS) -/// The type of a container's elements. -/** At the time of writing there's a similar thing in `std::experimental`, - * which we may or may not end up using for this. - */ -template -using value_type = strip_t()))>; -#else // PQXX_HAVE_CONCEPTS -/// The type of a container's elements. -/** At the time of writing there's a similar thing in `std::experimental`, - * which we may or may not end up using for this. - */ -template -using value_type = strip_t()))>; -#endif // PQXX_HAVE_CONCEPTS - - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: Any type that we can read as a string of `char`. -template -concept char_string = std::ranges::contiguous_range and - std::same_as < strip_t>, -char > ; - -/// Concept: Anything we can iterate to get things we can read as strings. -template -concept char_strings = - std::ranges::range and char_string>>; - -/// Concept: Anything we might want to treat as binary data. -template -concept potential_binary = std::ranges::contiguous_range and - (sizeof(value_type) == 1); -#endif // PQXX_HAVE_CONCEPTS - - -// C++20: Retire these compatibility definitions. -#if defined(PQXX_HAVE_CONCEPTS) - -/// Template argument type for a range. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_RANGE_ARG std::ranges::range - -/// Template argument type for @ref char_string. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRING_ARG pqxx::char_string - -/// Template argument type for @ref char_strings -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRINGS_ARG pqxx::char_strings - -#else // PQXX_HAVE_CONCEPTS - -/// Template argument type for a range. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_RANGE_ARG typename - -/// Template argument type for @ref char_string. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRING_ARG typename - -/// Template argument type for @ref char_strings -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRINGS_ARG typename - -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/util b/ext/libpqxx-7.7.3/include/pqxx/util deleted file mode 100644 index 6d85ab611..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/util +++ /dev/null @@ -1,6 +0,0 @@ -/** Various utility definitions for libpqxx. - */ -// Actual definitions in .hxx file so editors and such recognize file type -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/util.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/util.hxx b/ext/libpqxx-7.7.3/include/pqxx/util.hxx deleted file mode 100644 index 4aa5ecf57..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/util.hxx +++ /dev/null @@ -1,521 +0,0 @@ -/* Various utility definitions for libpqxx. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_UTIL -#define PQXX_H_UTIL - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -#include "pqxx/except.hxx" -#include "pqxx/internal/encodings.hxx" -#include "pqxx/types.hxx" -#include "pqxx/version.hxx" - - -/// The home of all libpqxx classes, functions, templates, etc. -namespace pqxx -{} - -#include - - -/// Internal items for libpqxx' own use. Do not use these yourself. -namespace pqxx::internal -{ - -// C++20: Retire wrapper. -/// Same as `std::cmp_less`, or a workaround where that's not available. -template -inline constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_less(lhs, rhs); -#else - // We need a variable just because lgtm.com gives off a false positive - // warning when we compare the values directly. It considers that a - // "self-comparison." - constexpr bool left_signed{std::is_signed_v}; - if constexpr (left_signed == std::is_signed_v) - return lhs < rhs; - else if constexpr (std::is_signed_v) - return (lhs <= 0) ? true : (std::make_unsigned_t(lhs) < rhs); - else - return (rhs <= 0) ? false : (lhs < std::make_unsigned_t(rhs)); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_greater, or workaround if not available. -template -inline constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_greater(lhs, rhs); -#else - return cmp_less(rhs, lhs); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_less_equal, or workaround if not available. -template -inline constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_less_equal(lhs, rhs); -#else - return not cmp_less(rhs, lhs); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_greater_equal, or workaround if not available. -template -inline constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_greater_equal(lhs, rhs); -#else - return not cmp_less(lhs, rhs); -#endif -} - - -/// Efficiently concatenate two strings. -/** This is a special case of concatenate(), needed because dependency - * management does not let us use that function here. - */ -[[nodiscard]] inline std::string cat2(std::string_view x, std::string_view y) -{ - std::string buf; - auto const xs{std::size(x)}, ys{std::size(y)}; - buf.resize(xs + ys); - x.copy(std::data(buf), xs); - y.copy(std::data(buf) + xs, ys); - return buf; -} -} // namespace pqxx::internal - - -namespace pqxx -{ -using namespace std::literals; - -/// Suppress compiler warning about an unused item. -template inline constexpr void ignore_unused(T &&...) noexcept -{} - - -/// Cast a numeric value to another type, or throw if it underflows/overflows. -/** Both types must be arithmetic types, and they must either be both integral - * or both floating-point types. - */ -template -inline TO check_cast(FROM value, std::string_view description) -{ - static_assert(std::is_arithmetic_v); - static_assert(std::is_arithmetic_v); - static_assert(std::is_integral_v == std::is_integral_v); - - // The rest of this code won't quite work for bool, but bool is trivially - // convertible to other arithmetic types as far as I can see. - if constexpr (std::is_same_v) - return static_cast(value); - - // Depending on our "if constexpr" conditions, this parameter may not be - // needed. Some compilers will warn. - ignore_unused(description); - - using from_limits = std::numeric_limits; - using to_limits = std::numeric_limits; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_signed_v) - { - if (value < to_limits::lowest()) - throw range_error{internal::cat2("Cast underflow: "sv, description)}; - } - else - { - // FROM is signed, but TO is not. Treat this as a special case, because - // there may not be a good broader type in which the compiler can even - // perform our check. - if (value < 0) - throw range_error{internal::cat2( - "Casting negative value to unsigned type: "sv, description)}; - } - } - else - { - // No need to check: the value is unsigned so can't fall below the range - // of the TO type. - } - - if constexpr (std::is_integral_v) - { - using unsigned_from = std::make_unsigned_t; - using unsigned_to = std::make_unsigned_t; - constexpr auto from_max{static_cast((from_limits::max)())}; - constexpr auto to_max{static_cast((to_limits::max)())}; - if constexpr (from_max > to_max) - { - if (internal::cmp_greater(value, to_max)) - throw range_error{internal::cat2("Cast overflow: "sv, description)}; - } - } - else if constexpr ((from_limits::max)() > (to_limits::max)()) - { - if (value > (to_limits::max)()) - throw range_error{internal::cat2("Cast overflow: ", description)}; - } - - return static_cast(value); -} - - -/** Check library version at link time. - * - * Ensures a failure when linking an application against a radically - * different libpqxx version than the one against which it was compiled. - * - * Sometimes application builds fail in unclear ways because they compile - * using headers from libpqxx version X, but then link against libpqxx - * binary version Y. A typical scenario would be one where you're building - * against a libpqxx which you have built yourself, but a different version - * is installed on the system. - * - * The check_library_version template is declared for any library version, - * but only actually defined for the version of the libpqxx binary against - * which the code is linked. - * - * If the library binary is a different version than the one declared in - * these headers, then this call will fail to link: there will be no - * definition for the function with these exact template parameter values. - * There will be a definition, but the version in the parameter values will - * be different. - */ -inline PQXX_PRIVATE void check_version() noexcept -{ - // There is no particular reason to do this here in @ref connection, except - // to ensure that every meaningful libpqxx client will execute it. The call - // must be in the execution path somewhere or the compiler won't try to link - // it. We can't use it to initialise a global or class-static variable, - // because a smart compiler might resolve it at compile time. - // - // On the other hand, we don't want to make a useless function call too - // often for performance reasons. A local static variable is initialised - // only on the definition's first execution. Compilers will be well - // optimised for this behaviour, so there's a minimal one-time cost. - static auto const version_ok{internal::PQXX_VERSION_CHECK()}; - ignore_unused(version_ok); -} - - -/// Descriptor of library's thread-safety model. -/** This describes what the library knows about various risks to thread-safety. - */ -struct PQXX_LIBEXPORT thread_safety_model -{ - /// Is the underlying libpq build thread-safe? - bool safe_libpq = false; - - /// Is Kerberos thread-safe? - /** @warning Is currently always `false`. - * - * If your application uses Kerberos, all accesses to libpqxx or Kerberos - * must be serialized. Confine their use to a single thread, or protect it - * with a global lock. - */ - bool safe_kerberos = false; - - /// A human-readable description of any thread-safety issues. - std::string description; -}; - - -/// Describe thread safety available in this build. -[[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety(); - - -#if defined(PQXX_HAVE_CONCEPTS) -# define PQXX_POTENTIAL_BINARY_ARG pqxx::potential_binary -#else -# define PQXX_POTENTIAL_BINARY_ARG typename -#endif - - -/// Cast binary data to a type that libpqxx will recognise as binary. -/** There are many different formats for storing binary data in memory. You - * may have yours as a `std::string`, or a `std::vector`, or one of - * many other types. - * - * But for libpqxx to recognise your data as binary, it needs to be a - * `std::basic_string`, or a `std::basic_string_view`; - * or in C++20 or better, any contiguous block of `std::byte`. - * - * Use `binary_cast` as a convenience helper to cast your data as a - * `std::basic_string_view`. - * - * @warning There are two things you should be aware of! First, the data must - * be contiguous in memory. In C++20 the compiler will enforce this, but in - * C++17 it's your own problem. Second, you must keep the object where you - * store the actual data alive for as long as you might use this function's - * return value. - */ -template -std::basic_string_view binary_cast(TYPE const &data) -{ - static_assert(sizeof(value_type) == 1); - return { - reinterpret_cast( - const_cast const *>( - std::data(data))), - std::size(data)}; -} - - -#if defined(PQXX_HAVE_CONCEPTS) -template -concept char_sized = (sizeof(CHAR) == 1); -# define PQXX_CHAR_SIZED_ARG char_sized -#else -# define PQXX_CHAR_SIZED_ARG typename -#endif - -/// Construct a type that libpqxx will recognise as binary. -/** Takes a data pointer and a size, without being too strict about their - * types, and constructs a `std::basic_string_view` pointing to - * the same data. - * - * This makes it a little easier to turn binary data, in whatever form you - * happen to have it, into binary data as libpqxx understands it. - */ -template -std::basic_string_view binary_cast(CHAR const *data, SIZE size) -{ - static_assert(sizeof(CHAR) == 1); - return { - reinterpret_cast(data), - check_cast(size, "binary data size")}; -} - - -/// The "null" oid. -constexpr oid oid_none{0}; -} // namespace pqxx - - -/// Private namespace for libpqxx's internal use; do not access. -/** This namespace hides definitions internal to libpqxx. These are not - * supposed to be used by client programs, and they may change at any time - * without notice. - * - * Conversely, if you find something in this namespace tremendously useful, by - * all means do lodge a request for its publication. - * - * @warning Here be dragons! - */ -namespace pqxx::internal -{ -using namespace std::literals; - - -/// A safer and more generic replacement for `std::isdigit`. -/** Turns out `std::isdigit` isn't as easy to use as it sounds. It takes an - * `int`, but requires it to be nonnegative. Which means it's an outright - * liability on systems where `char` is signed. - */ -template inline constexpr bool is_digit(CHAR c) noexcept -{ - return (c >= '0') and (c <= '9'); -} - - -/// Describe an object for humans, based on class name and optional name. -/** Interprets an empty name as "no name given." - */ -[[nodiscard]] std::string -describe_object(std::string_view class_name, std::string_view name); - - -/// Check validity of registering a new "guest" in a "host." -/** The host might be e.g. a connection, and the guest a transaction. The - * host can only have one guest at a time, so it is an error to register a new - * guest while the host already has a guest. - * - * If the new registration is an error, this function throws a descriptive - * exception. - * - * Pass the old guest (if any) and the new guest (if any), for both, a type - * name (at least if the guest is not null), and optionally an object name - * (but which may be omitted if the caller did not assign one). - */ -void check_unique_register( - void const *old_guest, std::string_view old_class, std::string_view old_name, - void const *new_guest, std::string_view new_class, - std::string_view new_name); - - -/// Like @ref check_unique_register, but for un-registering a guest. -/** Pass the guest which was registered, as well as the guest which is being - * unregistered, so that the function can check that they are the same one. - */ -void check_unique_unregister( - void const *old_guest, std::string_view old_class, std::string_view old_name, - void const *new_guest, std::string_view new_class, - std::string_view new_name); - - -/// Compute buffer size needed to escape binary data for use as a BYTEA. -/** This uses the hex-escaping format. The return value includes room for the - * "\x" prefix. - */ -inline constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept -{ - return 2 + (2 * binary_bytes) + 1; -} - - -/// Compute binary size from the size of its escaped version. -/** Do not include a terminating zero in `escaped_bytes`. - */ -inline constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept -{ - return (escaped_bytes - 2) / 2; -} - - -// TODO: Use actual binary type for "data". -/// Hex-escape binary data into a buffer. -/** The buffer must be able to accommodate - * `size_esc_bin(std::size(binary_data))` bytes, and the function will write - * exactly that number of bytes into the buffer. This includes a trailing - * zero. - */ -void PQXX_LIBEXPORT -esc_bin(std::basic_string_view binary_data, char buffer[]) noexcept; - - -/// Hex-escape binary data into a std::string. -std::string PQXX_LIBEXPORT -esc_bin(std::basic_string_view binary_data); - - -/// Reconstitute binary data from its escaped version. -void PQXX_LIBEXPORT -unesc_bin(std::string_view escaped_data, std::byte buffer[]); - - -/// Reconstitute binary data from its escaped version. -std::basic_string - PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data); - - -/// Transitional: std::ssize(), or custom implementation if not available. -template auto ssize(T const &c) -{ -#if defined(__cpp_lib_ssize) && __cplusplus >= __cpp_lib_ssize - return std::ssize(c); -#else - using signed_t = std::make_signed_t; - return static_cast(std::size(c)); -#endif // __cpp_lib_ssize -} - - -/// Helper for determining a function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple args_f(RETURN (&func)(ARGS...)); - - -/// Helper for determining a `std::function`'s parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple args_f(std::function const &); - - -/// Helper for determining a member function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple member_args_f(RETURN (CLASS::*)(ARGS...)); - - -/// Helper for determining a const member function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple member_args_f(RETURN (CLASS::*)(ARGS...) const); - - -/// Helper for determining a callable type's parameter types. -/** This specialisation should work for lambdas. - * - * This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -auto args_f(CALLABLE const &f) - -> decltype(member_args_f(&CALLABLE::operator())); - - -/// A callable's parameter types, as a tuple. -template -using args_t = decltype(args_f(std::declval())); - - -/// Helper: Apply `strip_t` to each of a tuple type's component types. -/** This function has no definition. It is not meant to be called, only to be - * used to deduce the right types. - */ -template -std::tuple...> strip_types(std::tuple const &); - - -/// Take a tuple type and apply @ref strip_t to its component types. -template -using strip_types_t = decltype(strip_types(std::declval())); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/version b/ext/libpqxx-7.7.3/include/pqxx/version deleted file mode 100644 index 8dd5e48d4..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/version +++ /dev/null @@ -1,7 +0,0 @@ -/** libpqxx version info. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/version.hxx" -#include "pqxx/internal/header-post.hxx" - diff --git a/ext/libpqxx-7.7.3/include/pqxx/version.hxx b/ext/libpqxx-7.7.3/include/pqxx/version.hxx deleted file mode 100644 index a159f1bed..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/version.hxx +++ /dev/null @@ -1,55 +0,0 @@ -/* Version info for libpqxx. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_VERSION - -# if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -# endif - -/// Full libpqxx version string. -# define PQXX_VERSION "7.7.3" -/// Library ABI version. -# define PQXX_ABI "7.7" - -/// Major version number. -# define PQXX_VERSION_MAJOR 7 -/// Minor version number. -# define PQXX_VERSION_MINOR 7 - -# define PQXX_VERSION_CHECK check_pqxx_version_7_7 - -namespace pqxx::internal -{ -/// Library version check stub. -/** Helps detect version mismatches between libpqxx headers and the libpqxx - * library binary. - * - * Sometimes users run into trouble linking their code against libpqxx because - * they build their own libpqxx, but the system also has a different version - * installed. The declarations in the headers against which they compile their - * code will differ from the ones used to build the libpqxx version they're - * using, leading to confusing link errors. The solution is to generate a link - * error when the libpqxx binary is not the same version as the libpqxx headers - * used to compile the code. - * - * This function's definition is in the libpqxx binary, so it's based on the - * version as found in the binary. The headers contain a call to the function, - * whose name contains the libpqxx version as found in the headers. (The - * library build process will use its own local headers even if another version - * of the headers is installed on the system.) - * - * If the libpqxx binary was compiled for a different version than the user's - * code, linking will fail with an error: `check_pqxx_version_*_*` will not - * exist for the given version number. - */ -PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/version.hxx.template b/ext/libpqxx-7.7.3/include/pqxx/version.hxx.template deleted file mode 100644 index 40837f16a..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/version.hxx.template +++ /dev/null @@ -1,55 +0,0 @@ -/* Version info for libpqxx. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_VERSION - -#if !defined(PQXX_HEADER_PRE) -#error "Include libpqxx headers as , not ." -#endif - -/// Full libpqxx version string. -# define PQXX_VERSION "@PQXXVERSION@" -/// Library ABI version. -# define PQXX_ABI "@PQXX_ABI@" - -/// Major version number. -# define PQXX_VERSION_MAJOR @PQXX_MAJOR@ -/// Minor version number. -# define PQXX_VERSION_MINOR @PQXX_MINOR@ - -# define PQXX_VERSION_CHECK check_pqxx_version_@PQXX_MAJOR@_@PQXX_MINOR@ - -namespace pqxx::internal -{ -/// Library version check stub. -/** Helps detect version mismatches between libpqxx headers and the libpqxx - * library binary. - * - * Sometimes users run into trouble linking their code against libpqxx because - * they build their own libpqxx, but the system also has a different version - * installed. The declarations in the headers against which they compile their - * code will differ from the ones used to build the libpqxx version they're - * using, leading to confusing link errors. The solution is to generate a link - * error when the libpqxx binary is not the same version as the libpqxx headers - * used to compile the code. - * - * This function's definition is in the libpqxx binary, so it's based on the - * version as found in the binary. The headers contain a call to the function, - * whose name contains the libpqxx version as found in the headers. (The - * library build process will use its own local headers even if another version - * of the headers is installed on the system.) - * - * If the libpqxx binary was compiled for a different version than the user's - * code, linking will fail with an error: `check_pqxx_version_*_*` will not - * exist for the given version number. - */ -PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/include/pqxx/zview b/ext/libpqxx-7.7.3/include/pqxx/zview deleted file mode 100644 index 66ea2a625..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/zview +++ /dev/null @@ -1,6 +0,0 @@ -/** Zero-terminated string view class. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/zview.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/include/pqxx/zview.hxx b/ext/libpqxx-7.7.3/include/pqxx/zview.hxx deleted file mode 100644 index 36a779f51..000000000 --- a/ext/libpqxx-7.7.3/include/pqxx/zview.hxx +++ /dev/null @@ -1,163 +0,0 @@ -/* Zero-terminated string view. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/zview instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ZVIEW -#define PQXX_H_ZVIEW - -#include -#include -#include - -#include "pqxx/types.hxx" - - -namespace pqxx -{ -/// Marker-type wrapper: zero-terminated `std::string_view`. -/** @warning Use this only if the underlying string is zero-terminated. - * - * When you construct a zview, you are promising that if the data pointer is - * non-null, the underlying string is zero-terminated. It otherwise behaves - * exactly like a std::string_view. - * - * The terminating zero is not "in" the string, so it does not count as part of - * the view's length. - * - * The added guarantee lets the view be used as a C-style string, which often - * matters since libpqxx builds on top of a C library. For this reason, zview - * also adds a @ref c_str method. - */ -class zview : public std::string_view -{ -public: - constexpr zview() noexcept = default; - - /// Convenience overload: construct using pointer and signed length. - constexpr zview(char const text[], std::ptrdiff_t len) : - std::string_view{text, static_cast(len)} - {} - - /// Convenience overload: construct using pointer and signed length. - constexpr zview(char text[], std::ptrdiff_t len) : - std::string_view{text, static_cast(len)} - {} - - /// Explicitly promote a `string_view` to a `zview`. - explicit constexpr zview(std::string_view other) noexcept : - std::string_view{other} - {} - - /// Construct from any initialiser you might use for `std::string_view`. - /** @warning Only do this if you are sure that the string is zero-terminated. - */ - template - explicit constexpr zview(Args &&...args) : - std::string_view(std::forward(args)...) - {} - - // C++20: constexpr. - /// @warning There's an implicit conversion from `std::string`. - zview(std::string const &str) noexcept : - std::string_view{str.c_str(), str.size()} - {} - - /// Construct a `zview` from a C-style string. - /** @warning This scans the string to discover its length. So if you need to - * do it many times, it's probably better to create the `zview` once and - * re-use it. - */ - constexpr zview(char const str[]) : std::string_view{str} {} - - /// Construct a `zview` from a string literal. - /** A C++ string literal ("foo") normally looks a lot like a pointer to - * char const, but that's not really true. It's actually an array of char, - * which _devolves_ to a pointer when you pass it. - * - * For the purpose of creating a `zview` there is one big difference: if we - * know the array's size, we don't need to scan through the string in order - * to find out its length. - */ - template - constexpr zview(char const (&literal)[size]) : zview(literal, size - 1) - {} - - /// Either a null pointer, or a zero-terminated text buffer. - [[nodiscard]] constexpr char const *c_str() const &noexcept - { - return data(); - } -}; - - -/// Support @ref zview literals. -/** You can "import" this selectively into your namespace, without pulling in - * all of the @ref pqxx namespace: - * - * ```cxx - * using pqxx::operator"" _zv; - * ``` - */ -constexpr zview operator"" _zv(char const str[], std::size_t len) noexcept -{ - return zview{str, len}; -} -} // namespace pqxx - - -#if defined(PQXX_HAVE_CONCEPTS) -/// A zview is a view. -template<> inline constexpr bool std::ranges::enable_view{true}; - - -/// A zview is a borrowed range. -template<> -inline constexpr bool std::ranges::enable_borrowed_range{true}; - -namespace pqxx::internal -{ -/// Concept: T is a known zero-terminated string type. -/** There's no unified API for these string types. It's just a check for some - * known types. Any code that makes use of the concept will still have to - * support each of these individually. - */ -template -concept ZString = std::is_convertible_v < strip_t, -char const * > or std::is_convertible_v, zview> or - std::is_convertible_v; -} // namespace pqxx::internal -#endif // PQXX_HAVE_CONCEPTS - - -namespace pqxx::internal -{ -/// Get a raw C string pointer. -inline constexpr char const *as_c_string(char const str[]) noexcept -{ - return str; -} -/// Get a raw C string pointer. -template -inline constexpr char const *as_c_string(char (&str)[N]) noexcept -{ - return str; -} -/// Get a raw C string pointer. -inline constexpr char const *as_c_string(pqxx::zview str) noexcept -{ - return str.c_str(); -} -// C++20: Make this constexpr. -/// Get a raw C string pointer. -inline char const *as_c_string(std::string const &str) noexcept -{ - return str.c_str(); -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/array b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/array deleted file mode 100644 index 689f5b27b..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/array +++ /dev/null @@ -1,6 +0,0 @@ -/** Handling of SQL arrays. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/array.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/array.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/array.hxx deleted file mode 100644 index 8440a244f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/array.hxx +++ /dev/null @@ -1,103 +0,0 @@ -/* Handling of SQL arrays. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ARRAY -#define PQXX_H_ARRAY - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/internal/encodings.hxx" - - -namespace pqxx -{ -/// Low-level array parser. -/** Use this to read an array field retrieved from the database. - * - * This parser will only work reliably if your client encoding is UTF-8, ASCII, - * or a single-byte encoding which is a superset of ASCII (such as Latin-1). - * - * Also, the parser only supports array element types which use either a comma - * or a semicolon ("," or ";") as the separator between array elements. All - * built-in types use comma, except for one which uses semicolon, but some - * custom types may not work. - * - * The input is a C-style string containing the textual representation of an - * array, as returned by the database. The parser reads this representation - * on the fly. The string must remain in memory until parsing is done. - * - * Parse the array by making calls to @ref get_next until it returns a - * @ref juncture of "done". The @ref juncture tells you what the parser found - * in that step: did the array "nest" to a deeper level, or "un-nest" back up? - */ -class PQXX_LIBEXPORT array_parser -{ -public: - /// What's the latest thing found in the array? - enum class juncture - { - /// Starting a new row. - row_start, - /// Ending the current row. - row_end, - /// Found a NULL value. - null_value, - /// Found a string value. - string_value, - /// Parsing has completed. - done, - }; - - // TODO: constexpr noexcept. Breaks ABI. - /// Constructor. You don't need this; use @ref field::as_array instead. - /** The parser only remains valid while the data underlying the @ref result - * remains valid. Once all `result` objects referring to that data have been - * destroyed, the parser will no longer refer to valid memory. - */ - explicit array_parser( - std::string_view input, - internal::encoding_group = internal::encoding_group::MONOBYTE); - - /// Parse the next step in the array. - /** Returns what it found. If the juncture is @ref juncture::string_value, - * the string will contain the value. Otherwise, it will be empty. - * - * Call this until the @ref array_parser::juncture it returns is - * @ref juncture::done. - */ - std::pair get_next(); - -private: - std::string_view m_input; - internal::glyph_scanner_func *const m_scan; - - /// Current parsing position in the input. - std::string::size_type m_pos = 0u; - - std::string::size_type scan_single_quoted_string() const; - std::string parse_single_quoted_string(std::string::size_type end) const; - std::string::size_type scan_double_quoted_string() const; - std::string parse_double_quoted_string(std::string::size_type end) const; - std::string::size_type scan_unquoted_string() const; - std::string parse_unquoted_string(std::string::size_type end) const; - - std::string::size_type scan_glyph(std::string::size_type pos) const; - std::string::size_type - scan_glyph(std::string::size_type pos, std::string::size_type end) const; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/binarystring b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/binarystring deleted file mode 100644 index 77551d9f7..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/binarystring +++ /dev/null @@ -1,6 +0,0 @@ -/** BYTEA (binary string) conversions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/binarystring.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/binarystring.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/binarystring.hxx deleted file mode 100644 index 47c82a035..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/binarystring.hxx +++ /dev/null @@ -1,236 +0,0 @@ -/* Deprecated representation for raw, binary data. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_BINARYSTRING -#define PQXX_H_BINARYSTRING - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/result.hxx" -#include "pqxx/strconv.hxx" - -namespace pqxx -{ -class binarystring; -template<> struct string_traits; - - -/// Binary data corresponding to PostgreSQL's "BYTEA" binary-string type. -/** @ingroup escaping-functions - * @deprecated Use @c std::basic_string and - * @c std::basic_string_view for binary data. In C++20 or better, - * any @c contiguous_range of @c std::byte will do. - * - * This class represents a binary string as stored in a field of type @c bytea. - * - * Internally a binarystring is zero-terminated, but it may also contain null - * bytes, they're just like any other byte value. So don't assume that it's - * safe to treat the contents as a C-style string. - * - * The binarystring retains its value even if the result it was obtained from - * is destroyed, but it cannot be copied or assigned. - * - * \relatesalso transaction_base::quote_raw - * - * To include a @c binarystring value in an SQL query, escape and quote it - * using the transaction's @c quote_raw function. - * - * @warning This class is implemented as a reference-counting smart pointer. - * Copying, swapping, and destroying binarystring objects that refer to the - * same underlying data block is not thread-safe. If you wish to pass - * binarystrings around between threads, make sure that each of these - * operations is protected against concurrency with similar operations on the - * same object, or other objects pointing to the same data block. - */ -class PQXX_LIBEXPORT binarystring -{ -public: - using char_type = unsigned char; - using value_type = std::char_traits::char_type; - using size_type = std::size_t; - using difference_type = long; - using const_reference = value_type const &; - using const_pointer = value_type const *; - using const_iterator = const_pointer; - using const_reverse_iterator = std::reverse_iterator; - - [[deprecated("Use std::byte for binary data.")]] binarystring( - binarystring const &) = default; - - /// Read and unescape bytea field. - /** The field will be zero-terminated, even if the original bytea field - * isn't. - * @param F the field to read; must be a bytea field - */ - [[deprecated("Use std::byte for binary data.")]] explicit binarystring( - field const &); - - /// Copy binary data from std::string_view on binary data. - /** This is inefficient in that it copies the data to a buffer allocated on - * the heap. - */ - [[deprecated("Use std::byte for binary data.")]] explicit binarystring( - std::string_view); - - /// Copy binary data of given length straight out of memory. - [[deprecated("Use std::byte for binary data.")]] binarystring( - void const *, std::size_t); - - /// Efficiently wrap a buffer of binary data in a @c binarystring. - [[deprecated("Use std::byte for binary data.")]] binarystring( - std::shared_ptr ptr, size_type size) : - m_buf{std::move(ptr)}, m_size{size} - {} - - /// Size of converted string in bytes. - [[nodiscard]] size_type size() const noexcept { return m_size; } - /// Size of converted string in bytes. - [[nodiscard]] size_type length() const noexcept { return size(); } - [[nodiscard]] bool empty() const noexcept { return size() == 0; } - - [[nodiscard]] const_iterator begin() const noexcept { return data(); } - [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); } - [[nodiscard]] const_iterator end() const noexcept { return data() + m_size; } - [[nodiscard]] const_iterator cend() const noexcept { return end(); } - - [[nodiscard]] const_reference front() const noexcept { return *begin(); } - [[nodiscard]] const_reference back() const noexcept - { - return *(data() + m_size - 1); - } - - [[nodiscard]] const_reverse_iterator rbegin() const - { - return const_reverse_iterator{end()}; - } - [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); } - [[nodiscard]] const_reverse_iterator rend() const - { - return const_reverse_iterator{begin()}; - } - [[nodiscard]] const_reverse_iterator crend() const { return rend(); } - - /// Unescaped field contents. - [[nodiscard]] value_type const *data() const noexcept { return m_buf.get(); } - - [[nodiscard]] const_reference operator[](size_type i) const noexcept - { - return data()[i]; - } - - [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const noexcept; - [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept - { - return not operator==(rhs); - } - - binarystring &operator=(binarystring const &); - - /// Index contained string, checking for valid index. - const_reference at(size_type) const; - - /// Swap contents with other binarystring. - void swap(binarystring &); - - /// Raw character buffer (no terminating zero is added). - /** @warning No terminating zero is added! If the binary data did not end in - * a null character, you will not find one here. - */ - [[nodiscard]] char const *get() const noexcept - { - return reinterpret_cast(m_buf.get()); - } - - /// Read contents as a std::string_view. - [[nodiscard]] std::string_view view() const noexcept - { - return std::string_view(get(), size()); - } - - /// Read as regular C++ string (may include null characters). - /** This creates and returns a new string object. Don't call this - * repeatedly; retrieve your string once and keep it in a local variable. - * Also, do not expect to be able to compare the string's address to that of - * an earlier invocation. - */ - [[nodiscard]] std::string str() const; - - /// Access data as a pointer to @c std::byte. - [[nodiscard]] std::byte const *bytes() const - { - return reinterpret_cast(get()); - } - - /// Read data as a @c std::basic_string_view. - [[nodiscard]] std::basic_string_view bytes_view() const - { - return std::basic_string_view{bytes(), size()}; - } - -private: - std::shared_ptr m_buf; - size_type m_size{0}; -}; - - -template<> struct nullness : no_null -{}; - - -/// String conversion traits for @c binarystring. -/** Defines the conversions between a @c binarystring and its PostgreSQL - * textual format, for communication with the database. - * - * These conversions rely on the "hex" format which was introduced in - * PostgreSQL 9.0. Both your libpq and the server must be recent enough to - * speak this format. - */ -template<> struct string_traits -{ - static std::size_t size_buffer(binarystring const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf(char *begin, char *end, binarystring const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, binarystring const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - std::string_view text{value.view()}; - internal::esc_bin(binary_cast(text), begin); - return begin + budget; - } - - static binarystring from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::shared_ptr buf{ - new unsigned char[size], [](unsigned char const *x) { delete[] x; }}; - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.get())); -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return binarystring{std::move(buf), size}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - } -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/blob b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/blob deleted file mode 100644 index 3fd0afac9..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/blob +++ /dev/null @@ -1,6 +0,0 @@ -/** Binary Large Objects interface. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/blob.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/blob.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/blob.hxx deleted file mode 100644 index 6d77be724..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/blob.hxx +++ /dev/null @@ -1,351 +0,0 @@ -/* Binary Large Objects interface. - * - * Read or write large objects, stored in their own storage on the server. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_BLOB -#define PQXX_H_BLOB - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#if defined(PQXX_HAVE_PATH) -# include -#endif - -#if defined(PQXX_HAVE_RANGES) && __has_include() -# include -#endif - -#if defined(PQXX_HAVE_SPAN) && __has_include() -# include -#endif - -#include "pqxx/dbtransaction.hxx" - - -namespace pqxx -{ -/** Binary large object. - * - * This is how you store data that may be too large for the `BYTEA` type. - * Access operations are similar to those for a file: you can read, write, - * query or set the current reading/writing position, and so on. - * - * These large objects live in their own storage on the server, indexed by an - * integer object identifier ("oid"). - * - * Two `blob` objects may refer to the same actual large object in the - * database at the same time. Each will have its own reading/writing position, - * but writes to the one will of course affect what the other sees. - */ -class PQXX_LIBEXPORT blob -{ -public: - /// Create a new, empty large object. - /** You may optionally specify an oid for the new blob. If you do, then - * the new object will have that oid -- or creation will fail if there - * already is an object with that oid. - */ - [[nodiscard]] static oid create(dbtransaction &, oid = 0); - - /// Delete a large object, or fail if it does not exist. - static void remove(dbtransaction &, oid); - - /// Open blob for reading. Any attempt to write to it will fail. - [[nodiscard]] static blob open_r(dbtransaction &, oid); - // Open blob for writing. Any attempt to read from it will fail. - [[nodiscard]] static blob open_w(dbtransaction &, oid); - // Open blob for reading and/or writing. - [[nodiscard]] static blob open_rw(dbtransaction &, oid); - - /// You can default-construct a blob, but it won't do anything useful. - /** Most operations on a default-constructed blob will throw @ref - * usage_error. - */ - blob() = default; - - /// You can move a blob, but not copy it. The original becomes unusable. - blob(blob &&); - /// You can move a blob, but not copy it. The original becomes unusable. - blob &operator=(blob &&); - - blob(blob const &) = delete; - blob &operator=(blob const &) = delete; - ~blob(); - - /// Maximum number of bytes that can be read or written at a time. - /** The underlying protocol only supports reads and writes up to 2 GB - * exclusive. - * - * If you need to read or write more data to or from a binary large object, - * you'll have to break it up into chunks. - */ - static constexpr std::size_t chunk_limit = 0x7fffffff; - - /// Read up to `size` bytes of the object into `buf`. - /** Uses a buffer that you provide, resizing it as needed. If it suits you, - * this lets you allocate the buffer once and then re-use it multiple times. - * - * Resizes `buf` as needed. - * - * @warning The underlying protocol only supports reads up to 2GB at a time. - * If you need to read more, try making repeated calls to @ref append_to_buf. - */ - std::size_t read(std::basic_string &buf, std::size_t size); - -#if defined(PQXX_HAVE_SPAN) - /// Read up to `std::size(buf)` bytes from the object. - /** Retrieves bytes from the blob, at the current position, until `buf` is - * full or there are no more bytes to read, whichever comes first. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template - std::span read(std::span buf) - { - return buf.subspan(0, raw_read(std::data(buf), std::size(buf))); - } -#endif // PQXX_HAVE_SPAN - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Read up to `std::size(buf)` bytes from the object. - /** Retrieves bytes from the blob, at the current position, until `buf` is - * full or there are no more bytes to read, whichever comes first. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template std::span read(DATA &buf) - { - return {std::data(buf), raw_read(std::data(buf), std::size(buf))}; - } -#else // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN - /// Read up to `std::size(buf)` bytes from the object. - /** @deprecated As libpqxx moves to C++20 as its baseline language version, - * this will take and return `std::span`. - * - * Retrieves bytes from the blob, at the current position, until `buf` is - * full (i.e. its current size is reached), or there are no more bytes to - * read, whichever comes first. - * - * This function will not change either the size or the capacity of `buf`, - * only its contents. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template - std::basic_string_view read(std::vector &buf) - { - return {std::data(buf), raw_read(std::data(buf), std::size(buf))}; - } -#endif // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN - -#if defined(PQXX_HAVE_CONCEPTS) - /// Write `data` to large object, at the current position. - /** If the writing position is at the end of the object, this will append - * `data` to the object's contents and move the writing position so that - * it's still at the end. - * - * If the writing position was not at the end, writing will overwrite the - * prior data, but it will not remove data that follows the part where you - * wrote your new data. - * - * @warning This is a big difference from writing to a file. You can - * overwrite some data in a large object, but this does not truncate the - * data that was already there. For example, if the object contained binary - * data "abc", and you write "12" at the starting position, the object will - * contain "12c". - * - * @warning The underlying protocol only supports writes up to 2 GB at a - * time. If you need to write more, try making repeated calls to - * @ref append_from_buf. - */ - template void write(DATA const &data) - { - raw_write(std::data(data), std::size(data)); - } -#else - /// Write `data` large object, at the current position. - /** If the writing position is at the end of the object, this will append - * `data` to the object's contents and move the writing position so that - * it's still at the end. - * - * If the writing position was not at the end, writing will overwrite the - * prior data, but it will not remove data that follows the part where you - * wrote your new data. - * - * @warning This is a big difference from writing to a file. You can - * overwrite some data in a large object, but this does not truncate the - * data that was already there. For example, if the object contained binary - * data "abc", and you write "12" at the starting position, the object will - * contain "12c". - * - * @warning The underlying protocol only supports writes up to 2 GB at a - * time. If you need to write more, try making repeated calls to - * @ref append_from_buf. - */ - template void write(DATA const &data) - { - raw_write(std::data(data), std::size(data)); - } -#endif - - /// Resize large object to `size` bytes. - /** If the blob is more than `size` bytes long, this removes the end so as - * to make the blob the desired length. - * - * If the blob is less than `size` bytes long, it adds enough zero bytes to - * make it the desired length. - */ - void resize(std::int64_t size); - - /// Return the current reading/writing position in the large object. - [[nodiscard]] std::int64_t tell() const; - - /// Set the current reading/writing position to an absolute offset. - /** Returns the new file offset. */ - std::int64_t seek_abs(std::int64_t offset = 0); - /// Move the current reading/writing position forwards by an offset. - /** To move backwards, pass a negative offset. - * - * Returns the new file offset. - */ - std::int64_t seek_rel(std::int64_t offset = 0); - /// Set the current position to an offset relative to the end of the blob. - /** You'll probably want an offset of zero or less. - * - * Returns the new file offset. - */ - std::int64_t seek_end(std::int64_t offset = 0); - - /// Create a binary large object containing given `data`. - /** You may optionally specify an oid for the new object. If you do, and an - * object with that oid already exists, creation will fail. - */ - static oid from_buf( - dbtransaction &tx, std::basic_string_view data, oid id = 0); - - /// Append `data` to binary large object. - /** The underlying protocol only supports appending blocks up to 2 GB. - */ - static void append_from_buf( - dbtransaction &tx, std::basic_string_view data, oid id); - - /// Read client-side file and store it server-side as a binary large object. - [[nodiscard]] static oid from_file(dbtransaction &, char const path[]); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Read client-side file and store it server-side as a binary large object. - /** This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - [[nodiscard]] static oid - from_file(dbtransaction &tx, std::filesystem::path const &path) - { - return from_file(tx, path.c_str()); - } -#endif - - /// Read client-side file and store it server-side as a binary large object. - /** In this version, you specify the binary large object's oid. If that oid - * is already in use, the operation will fail. - */ - static oid from_file(dbtransaction &, char const path[], oid); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Read client-side file and store it server-side as a binary large object. - /** In this version, you specify the binary large object's oid. If that oid - * is already in use, the operation will fail. - * - * This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - static oid - from_file(dbtransaction &tx, std::filesystem::path const &path, oid id) - { - return from_file(tx, path.c_str(), id); - } -#endif - - /// Convenience function: Read up to `max_size` bytes from blob with `id`. - /** You could easily do this yourself using the @ref open_r and @ref read - * functions, but it can save you a bit of code to do it this way. - */ - static void to_buf( - dbtransaction &, oid, std::basic_string &, - std::size_t max_size); - - /// Read part of the binary large object with `id`, and append it to `buf`. - /** Use this to break up a large read from one binary large object into one - * massive buffer. Just keep calling this function until it returns zero. - * - * The `offset` is how far into the large object your desired chunk is, and - * `append_max` says how much to try and read in one go. - */ - static std::size_t append_to_buf( - dbtransaction &tx, oid id, std::int64_t offset, - std::basic_string &buf, std::size_t append_max); - - /// Write a binary large object's contents to a client-side file. - static void to_file(dbtransaction &, oid, char const path[]); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Write a binary large object's contents to a client-side file. - /** This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - static void - to_file(dbtransaction &tx, oid id, std::filesystem::path const &path) - { - to_file(tx, id, path.c_str()); - } -#endif - - /// Close this blob. - /** This does not delete the blob from the database; it only terminates your - * local object for accessing the blob. - * - * Resets the blob to a useless state similar to one that was - * default-constructed. - * - * The destructor will do this for you automatically. Still, there is a - * reason to `close()` objects explicitly where possible: if an error should - * occur while closing, `close()` can throw an exception. A destructor - * cannot. - */ - void close(); - -private: - PQXX_PRIVATE blob(connection &conn, int fd) noexcept : - m_conn{&conn}, m_fd{fd} - {} - static PQXX_PRIVATE blob open_internal(dbtransaction &, oid, int); - static PQXX_PRIVATE pqxx::internal::pq::PGconn * - raw_conn(pqxx::connection *) noexcept; - static PQXX_PRIVATE pqxx::internal::pq::PGconn * - raw_conn(pqxx::dbtransaction const &) noexcept; - static PQXX_PRIVATE std::string errmsg(connection const *); - static PQXX_PRIVATE std::string errmsg(dbtransaction const &tx) - { - return errmsg(&tx.conn()); - } - PQXX_PRIVATE std::string errmsg() const { return errmsg(m_conn); } - PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence); - std::size_t raw_read(std::byte buf[], std::size_t size); - void raw_write(std::byte const buf[], std::size_t size); - - connection *m_conn = nullptr; - int m_fd = -1; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/composite b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/composite deleted file mode 100644 index 2bfa7ade9..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/composite +++ /dev/null @@ -1,6 +0,0 @@ -/** Handling of SQL "composite types." - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/composite.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/composite.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/composite.hxx deleted file mode 100644 index 439b133a8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/composite.hxx +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef PQXX_H_COMPOSITE -#define PQXX_H_COMPOSITE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/internal/array-composite.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Parse a string representation of a value of a composite type. -/** @warning This code is still experimental. Use with care. - * - * You may use this as a helper while implementing your own @ref string_traits - * for a composite type. - * - * This function interprets `text` as the string representation of a value of - * some composite type, and sets each of `fields` to the respective values of - * its fields. The field types must be copy-assignable. - * - * The number of fields must match the number of fields in the composite type, - * and there must not be any other text in the input. The function is meant to - * handle any value string that the backend can produce, but not necessarily - * every valid alternative spelling. - * - * Fields in composite types can be null. When this happens, the C++ type of - * the corresponding field reference must be of a type that can handle nulls. - * If you are working with a type that does not have an inherent null value, - * such as e.g. `int`, consider using `std::optional`. - */ -template -inline void parse_composite( - pqxx::internal::encoding_group enc, std::string_view text, T &...fields) -{ - static_assert(sizeof...(fields) > 0); - - auto const scan{pqxx::internal::get_glyph_scanner(enc)}; - auto const data{std::data(text)}; - auto const size{std::size(text)}; - if (size == 0) - throw conversion_error{"Cannot parse composite value from empty string."}; - - std::size_t here{0}, next{scan(data, size, here)}; - if (next != 1 or data[here] != '(') - throw conversion_error{ - internal::concat("Invalid composite value string: ", text)}; - - here = next; - - constexpr auto num_fields{sizeof...(fields)}; - std::size_t index{0}; - (pqxx::internal::parse_composite_field( - index, text, here, fields, scan, num_fields - 1), - ...); - if (here != std::size(text)) - throw conversion_error{internal::concat( - "Composite value did not end at the closing parenthesis: '", text, - "'.")}; - if (text[here - 1] != ')') - throw conversion_error{internal::concat( - "Composive value did not end in parenthesis: '", text, "'")}; -} - - -/// Parse a string representation of a value of a composite type. -/** @warning This version only works for UTF-8 and single-byte encodings. - * - * For proper encoding support, use the composite-type support in the - * `field` class. - */ -template -inline void parse_composite(std::string_view text, T &...fields) -{ - parse_composite(pqxx::internal::encoding_group::MONOBYTE, text, fields...); -} -} // namespace pqxx - - -namespace pqxx::internal -{ -constexpr char empty_composite_str[]{"()"}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// Estimate the buffer size needed to represent a value of a composite type. -/** Returns a conservative estimate. - */ -template -[[nodiscard]] inline std::size_t -composite_size_buffer(T const &...fields) noexcept -{ - constexpr auto num{sizeof...(fields)}; - - // Size for a multi-field composite includes room for... - // + opening parenthesis - // + field budgets - // + separating comma per field - // - comma after final field - // + closing parenthesis - // + terminating zero - - if constexpr (num == 0) - return std::size(pqxx::internal::empty_composite_str); - else - return 1 + (pqxx::internal::size_composite_field_buffer(fields) + ...) + - num + 1; -} - - -/// Render a series of values as a single composite SQL value. -/** @warning This code is still experimental. Use with care. - * - * You may use this as a helper while implementing your own `string_traits` - * for a composite type. - */ -template -inline char *composite_into_buf(char *begin, char *end, T const &...fields) -{ - if (std::size_t(end - begin) < composite_size_buffer(fields...)) - throw conversion_error{ - "Buffer space may not be enough to represent composite value."}; - - constexpr auto num_fields{sizeof...(fields)}; - if constexpr (num_fields == 0) - { - constexpr char empty[]{"()"}; - std::memcpy(begin, empty, std::size(empty)); - return begin + std::size(empty); - } - - char *pos{begin}; - *pos++ = '('; - - (pqxx::internal::write_composite_field(pos, end, fields), ...); - - // If we've got multiple fields, "backspace" that last comma. - if constexpr (num_fields > 1) - --pos; - *pos++ = ')'; - *pos++ = '\0'; - return pos; -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/config-public-compiler.h b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/config-public-compiler.h deleted file mode 100644 index 3668a10f8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/config-public-compiler.h +++ /dev/null @@ -1,81 +0,0 @@ -/* include/pqxx/config.h.in. Generated from configure.ac by autoheader. */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ -/* Define to 1 if you have the `pq' library (-lpq). */ -/* #undef HAVE_LIBPQ */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MEMORY_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDINT_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDLIB_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRING_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_STAT_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TYPES_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -/* #undef LT_OBJDIR */ -/* Name of package */ -/* #undef PACKAGE */ -/* Define to the address where bug reports for this package should be sent. */ -/* #undef PACKAGE_BUGREPORT */ -/* Define to the full name of this package. */ -/* #undef PACKAGE_NAME */ -/* Define to the full name and version of this package. */ -/* #undef PACKAGE_STRING */ -/* Define to the one symbol short name of this package. */ -/* #undef PACKAGE_TARNAME */ -/* Define to the home page for this package. */ -/* #undef PACKAGE_URL */ -/* Define to the version of this package. */ -/* #undef PACKAGE_VERSION */ -/* Define if supports floating-point conversion. */ -#define PQXX_HAVE_CHARCONV_FLOAT -/* Define if supports integer conversion. */ -#define PQXX_HAVE_CHARCONV_INT -/* Define if compiler has C++20 std::cmp_greater etc. */ -/* #undef PQXX_HAVE_CMP */ -/* Define if compiler supports Concepts and header. */ -/* #undef PQXX_HAVE_CONCEPTS */ -/* Define if compiler supports __cxa_demangle */ -#define PQXX_HAVE_CXA_DEMANGLE -/* Define if g++ supports pure attribute */ -#define PQXX_HAVE_GCC_PURE -/* Define if g++ supports visibility attribute. */ -#define PQXX_HAVE_GCC_VISIBILITY -/* Define if likely & unlikely work. */ -/* #undef PQXX_HAVE_LIKELY */ -/* Define if operator[] can take multiple arguments. */ -/* #undef PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT */ -/* Define if compiler has usable std::filesystem::path. */ -#define PQXX_HAVE_PATH -/* Define if poll() is available. */ -#define PQXX_HAVE_POLL -/* Define if libpq has PQencryptPasswordConn (since pg 10). */ -#define PQXX_HAVE_PQENCRYPTPASSWORDCONN -/* Define if libpq has pipeline mode (since pg 14). */ -#define PQXX_HAVE_PQ_PIPELINE -/* Define if std::this_thread::sleep_for works. */ -#define PQXX_HAVE_SLEEP_FOR -/* Define if compiler has std::span. */ -/* #undef PQXX_HAVE_SPAN */ -/* Define if strerror_r() is available. */ -#define PQXX_HAVE_STRERROR_R -/* Define if strerror_s() is available. */ -/* #undef PQXX_HAVE_STRERROR_S */ -/* Define if thread_local is fully supported. */ -#define PQXX_HAVE_THREAD_LOCAL -/* Define if std::chrono has year_month_day etc. */ -/* #undef PQXX_HAVE_YEAR_MONTH_DAY */ -/* Define to 1 if you have the ANSI C header files. */ -/* #undef STDC_HEADERS */ -/* Version number of package */ -/* #undef VERSION */ diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/connection b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/connection deleted file mode 100644 index 82ff43aa5..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/connection +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::connection class. - * - * pqxx::connection encapsulates a connection to a database. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/connection.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/connection.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/connection.hxx deleted file mode 100644 index 92454bb47..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/connection.hxx +++ /dev/null @@ -1,1261 +0,0 @@ -/* Definition of the connection class. - * - * pqxx::connection encapsulates a connection to a database. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_CONNECTION -#define PQXX_H_CONNECTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Double-check in order to suppress an overzealous Visual C++ warning (#418). -#if defined(PQXX_HAVE_CONCEPTS) && __has_include() -# include -#endif - -#include "pqxx/errorhandler.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/params.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - - -/** - * @addtogroup connections - * - * Use of the libpqxx library starts here. - * - * Everything that can be done with a database through libpqxx must go through - * a @ref pqxx::connection object. It connects to a database when you create - * it, and it terminates that communication during destruction. - * - * Many things come together in this class. Handling of error and warning - * messages, for example, is defined by @ref pqxx::errorhandler objects in the - * context of a connection. Prepared statements are also defined here. - * - * When you connect to a database, you pass a connection string containing any - * parameters and options, such as the server address and the database name. - * - * These are identical to the ones in libpq, the C language binding upon which - * libpqxx itself is built: - * - * https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING - * - * There are also environment variables you can set to provide defaults, again - * as defined by libpq: - * - * https://www.postgresql.org/docs/current/libpq-envars.html - * - * You can also create a database connection _asynchronously_ using an - * intermediate @ref pqxx::connecting object. - */ - -namespace pqxx::internal -{ -class sql_cursor; - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: T is a range of pairs of zero-terminated strings. -template -concept ZKey_ZValues = std::ranges::input_range and requires(T t) -{ - {std::cbegin(t)}; - { - std::get<0>(*std::cbegin(t)) - } -> ZString; - { - std::get<1>(*std::cbegin(t)) - } -> ZString; -} and std::tuple_size_v::value_type> -== 2; -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx::internal - - -namespace pqxx::internal::gate -{ -class connection_dbtransaction; -class connection_errorhandler; -class connection_largeobject; -class connection_notification_receiver; -class connection_pipeline; -class connection_sql_cursor; -class connection_stream_from; -class connection_stream_to; -class connection_transaction; -class const_connection_largeobject; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Representation of a PostgreSQL table path. -/** A "table path" consists of a table name, optionally prefixed by a schema - * name, which in turn is optionally prefixed by a database name. - * - * A minimal example of a table path would be `{mytable}`. But a table path - * may also take the forms `{myschema,mytable}` or - * `{mydb,myschema,mytable}`. - */ -using table_path = std::initializer_list; - - -/// Encrypt a password. @deprecated Use connection::encrypt_password instead. -[[nodiscard, - deprecated("Use connection::encrypt_password instead.")]] std::string - PQXX_LIBEXPORT - encrypt_password(char const user[], char const password[]); - -/// Encrypt password. @deprecated Use connection::encrypt_password instead. -[[nodiscard, - deprecated("Use connection::encrypt_password instead.")]] inline std::string -encrypt_password(zview user, zview password) -{ -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return encrypt_password(user.c_str(), password.c_str()); -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -/// Error verbosity levels. -enum class error_verbosity : int -{ - // These values must match those in libpq's PGVerbosity enum. - terse = 0, - normal = 1, - verbose = 2 -}; - - -/// Connection to a database. -/** This is the first class to look at when you wish to work with a database - * through libpqxx. The connection opens during construction, and closes upon - * destruction. - * - * When creating a connection, you can pass a connection URI or a postgres - * connection string, to specify the database server's address, a login - * username, and so on. If you don't, the connection will try to obtain them - * from certain environment variables. If those are not set either, the - * default is to try and connect to the local system's port 5432. - * - * Find more about connection strings here: - * - * https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING - * - * The variables are documented here: - * - * https://www.postgresql.org/docs/current/libpq-envars.html - * - * To query or manipulate the database once connected, use one of the - * transaction classes (see pqxx/transaction_base.hxx) and perhaps also the - * transactor framework (see pqxx/transactor.hxx). - * - * When a connection breaks, you will typically get a @ref broken_connection - * exception. This can happen at almost any point. - * - * @warning On Unix-like systems, including GNU and BSD systems, your program - * may receive the SIGPIPE signal when the connection to the backend breaks. By - * default this signal will abort your program. Use "signal(SIGPIPE, SIG_IGN)" - * if you want your program to continue running after a connection fails. - */ -class PQXX_LIBEXPORT connection -{ -public: - connection() : connection{""} {} - - /// Connect to a database, using `options` string. - explicit connection(char const options[]) - { - check_version(); - init(options); - } - - /// Connect to a database, using `options` string. - explicit connection(zview options) : connection{options.c_str()} - { - // (Delegates to other constructor which calls check_version for us.) - } - - /// Move constructor. - /** Moving a connection is not allowed if it has an open transaction, or has - * error handlers or notification receivers registered on it. In those - * situations, other objects may hold references to the old object which - * would become invalid and might produce hard-to-diagnose bugs. - */ - connection(connection &&rhs); - -#if defined(PQXX_HAVE_CONCEPTS) - /// Connect to a database, passing options as a range of key/value pairs. - /** @warning Experimental. Requires C++20 "concepts" support. Define - * `PQXX_HAVE_CONCEPTS` to enable it. - * - * There's no need to escape the parameter values. - * - * See the PostgreSQL libpq documentation for the full list of possible - * options: - * - * https://postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS - * - * The options can be anything that can be iterated as a series of pairs of - * zero-terminated strings: `std::pair`, or - * `std::tuple`, or - * `std::map`, and so on. - */ - template - inline connection(MAPPING const ¶ms); -#endif // PQXX_HAVE_CONCEPTS - - ~connection() - { - try - { - close(); - } - catch (std::exception const &) - {} - } - - /// Move assignment. - /** Neither connection can have an open transaction, registered error - * handlers, or registered notification receivers. - */ - connection &operator=(connection &&rhs); - - connection(connection const &) = delete; - connection &operator=(connection const &) = delete; - - /// Is this connection open at the moment? - /** @warning This function is **not** needed in most code. Resist the - * temptation to check it after opening a connection. The `connection` - * constructor will throw a @ref broken_connection exception if can't connect - * to the database. - */ - [[nodiscard]] bool PQXX_PURE is_open() const noexcept; - - /// Invoke notice processor function. The message should end in newline. - void process_notice(char const[]) noexcept; - /// Invoke notice processor function. Newline at end is recommended. - /** The zview variant, with a message ending in newline, is the most - * efficient way to call process_notice. - */ - void process_notice(zview) noexcept; - - /// Enable tracing to a given output stream, or nullptr to disable. - void trace(std::FILE *) noexcept; - - /** - * @name Connection properties - * - * These are probably not of great interest, since most are derived from - * information supplied by the client program itself, but they are included - * for completeness. - * - * The connection needs to be currently active for these to work. - */ - //@{ - /// Name of database we're connected to, if any. - [[nodiscard]] char const *dbname() const; - - /// Database user ID we're connected under, if any. - [[nodiscard]] char const *username() const; - - /// Address of server, or nullptr if none specified (i.e. default or local) - [[nodiscard]] char const *hostname() const; - - /// Server port number we're connected to. - [[nodiscard]] char const *port() const; - - /// Process ID for backend process, or 0 if inactive. - [[nodiscard]] int PQXX_PURE backendpid() const &noexcept; - - /// Socket currently used for connection, or -1 for none. Use with care! - /** Query the current socket number. This is intended for event loops based - * on functions such as select() or poll(), where you're waiting for any of - * multiple file descriptors to become ready for communication. - * - * Please try to stay away from this function. It is really only meant for - * event loops that need to wait on more than one file descriptor. If all - * you need is to block until a notification arrives, for instance, use - * await_notification(). If you want to issue queries and retrieve results - * in nonblocking fashion, check out the pipeline class. - */ - [[nodiscard]] int PQXX_PURE sock() const &noexcept; - - /// What version of the PostgreSQL protocol is this connection using? - /** The answer can be 0 (when there is no connection); 3 for protocol 3.0; or - * possibly higher values as newer protocol versions come into use. - */ - [[nodiscard]] int PQXX_PURE protocol_version() const noexcept; - - /// What version of the PostgreSQL server are we connected to? - /** The result is a bit complicated: each of the major, medium, and minor - * release numbers is written as a two-digit decimal number, and the three - * are then concatenated. Thus server version 9.4.2 will be returned as the - * decimal number 90402. If there is no connection to the server, this - * returns zero. - * - * @warning When writing version numbers in your code, don't add zero at the - * beginning! Numbers beginning with zero are interpreted as octal (base-8) - * in C++. Thus, 070402 is not the same as 70402, and 080000 is not a number - * at all because there is no digit "8" in octal notation. Use strictly - * decimal notation when it comes to these version numbers. - */ - [[nodiscard]] int PQXX_PURE server_version() const noexcept; - //@} - - /// @name Text encoding - /** - * Each connection is governed by a "client encoding," which dictates how - * strings and other text is represented in bytes. The database server will - * send text data to you in this encoding, and you should use it for the - * queries and data which you send to the server. - * - * Search the PostgreSQL documentation for "character set encodings" to find - * out more about the available encodings, how to extend them, and how to use - * them. Not all server-side encodings are compatible with all client-side - * encodings or vice versa. - * - * Encoding names are case-insensitive, so e.g. "UTF8" is equivalent to - * "utf8". - * - * You can change the client encoding, but this may not work when the - * connection is in a special state, such as when streaming a table. It's - * not clear what happens if you change the encoding during a transaction, - * and then abort the transaction. - */ - //@{ - /// Get client-side character encoding, by name. - [[nodiscard]] std::string get_client_encoding() const; - - /// Set client-side character encoding, by name. - /** - * @param encoding Name of the character set encoding to use. - */ - void set_client_encoding(zview encoding) & - { - set_client_encoding(encoding.c_str()); - } - - /// Set client-side character encoding, by name. - /** - * @param encoding Name of the character set encoding to use. - */ - void set_client_encoding(char const encoding[]) &; - - /// Get the connection's encoding, as a PostgreSQL-defined code. - [[nodiscard]] int PQXX_PRIVATE encoding_id() const; - - //@} - - /// Set session variable, using SQL's `SET` command. - /** @deprecated To set a session variable, use @ref set_session_var. To set - * a transaction-local variable, execute an SQL `SET` command. - * - * @warning When setting a string value, you must escape and quote it first. - * Use the @ref quote() function to do that. - * - * @warning This executes an SQL query, so do not get or set variables while - * a table stream or pipeline is active on the same connection. - * - * @param var Variable to set. - * @param value New value for Var. This can be any SQL expression. If it's - * a string, be sure that it's properly escaped and quoted. - */ - [[deprecated("To set session variables, use set_session_var.")]] void - set_variable(std::string_view var, std::string_view value) &; - - /// Set one of the session variables to a new value. - /** This executes SQL, so do not do it while a pipeline or stream is active - * on the connection. - * - * The value you set here will last for the rest of the connection's - * duration, or until you set a new value. - * - * If you set the value while in a @ref dbtransaction (i.e. any transaction - * that is not a @ref nontransaction), then rolling back the transaction will - * undo the change. - * - * All applies to setting _session_ variables. You can also set the same - * variables as _local_ variables, in which case they will always revert to - * their previous value when the transaction ends (or when you overwrite them - * of course). To set a local variable, simply execute an SQL statement - * along the lines of "`SET LOCAL var = 'value'`" inside your transaction. - * - * @param var The variable to set. - * @param value The new value for the variable. - * @throw @ref variable_set_to_null if the value is null; this is not - * allowed. - */ - template - void set_session_var(std::string_view var, TYPE const &value) & - { - if constexpr (nullness::has_null) - { - if (nullness::is_null(value)) - throw variable_set_to_null{ - internal::concat("Attempted to set variable ", var, " to null.")}; - } - exec(internal::concat("SET ", quote_name(var), "=", quote(value))); - } - - /// Read session variable, using SQL's `SHOW` command. - /** @warning This executes an SQL query, so do not get or set variables while - * a table stream or pipeline is active on the same connection. - */ - [[deprecated("Use get_var instead.")]] std::string - get_variable(std::string_view); - - /// Read currently applicable value of a variable. - /** This function executes an SQL statement, so it won't work while a - * @ref pipeline or query stream is active on the connection. - * - * @return a blank `std::optional` if the variable's value is null, or its - * string value otherwise. - */ - std::string get_var(std::string_view var); - - /// Read currently applicable value of a variable. - /** This function executes an SQL statement, so it won't work while a - * @ref pipeline or query stream is active on the connection. - * - * If there is any possibility that the variable is null, ensure that `TYPE` - * can represent null values. - */ - template TYPE get_var_as(std::string_view var) - { - return from_string(get_var(var)); - } - - /** - * @name Notifications and Receivers - */ - //@{ - /// Check for pending notifications and take appropriate action. - /** This does not block. To wait for incoming notifications, either call - * await_notification() (it calls this function); or wait for incoming data - * on the connection's socket (i.e. wait to read), and then call this - * function repeatedly until it returns zero. After that, there are no more - * pending notifications so you may want to wait again. - * - * If any notifications are pending when you call this function, it - * processes them by finding any receivers that match the notification string - * and invoking those. If no receivers match, there is nothing to invoke but - * we do consider the notification processed. - * - * If any of the client-registered receivers throws an exception, the - * function will report it using the connection's errorhandlers. It does not - * re-throw the exceptions. - * - * @return Number of notifications processed. - */ - int get_notifs(); - - /// Wait for a notification to come in. - /** There are other events that will also terminate the wait, such as the - * backend failing. It will also wake up periodically. - * - * If a notification comes in, the call will process it, along with any other - * notifications that may have been pending. - * - * To wait for notifications into your own event loop instead, wait until - * there is incoming data on the connection's socket to be read, then call - * @ref get_notifs() repeatedly until it returns zero. - * - * @return Number of notifications processed. - */ - int await_notification(); - - /// Wait for a notification to come in, or for given timeout to pass. - /** There are other events that will also terminate the wait, such as the - * backend failing, or timeout expiring. - * - * If a notification comes in, the call will process it, along with any other - * notifications that may have been pending. - * - * To wait for notifications into your own event loop instead, wait until - * there is incoming data on the connection's socket to be read, then call - * @ref get_notifs repeatedly until it returns zero. - * - * @return Number of notifications processed - */ - int await_notification(std::time_t seconds, long microseconds); - //@} - - /** - * @name Password encryption - * - * Use this when setting a new password for the user if password encryption - * is enabled. Inputs are the SQL name for the user for whom you with to - * encrypt a password; the plaintext password; and the hash algorithm. - * - * The algorithm must be one of "md5", "scram-sha-256" (introduced in - * PostgreSQL 10), or `nullptr`. If the pointer is null, this will query - * the `password_encryption setting` from the server, and use the default - * algorithm as defined there. - * - * @return encrypted version of the password, suitable for encrypted - * PostgreSQL authentication. - * - * Thus you can change a user's password with: - * ```cxx - * void setpw(transaction_base &t, string const &user, string const &pw) - * { - * t.exec0("ALTER USER " + user + " " - * "PASSWORD '" + t.conn().encrypt_password(user,pw) + "'"); - * } - * ``` - * - * When building this against a libpq older than version 10, this will use - * an older function which only supports md5. In that case, requesting a - * different algorithm than md5 will result in a @ref feature_not_supported - * exception. - */ - //@{ - /// Encrypt a password for a given user. - [[nodiscard]] std::string - encrypt_password(zview user, zview password, zview algorithm) - { - return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str()); - } - /// Encrypt a password for a given user. - [[nodiscard]] std::string encrypt_password( - char const user[], char const password[], char const *algorithm = nullptr); - //@} - - /** - * @name Prepared statements - * - * PostgreSQL supports prepared SQL statements, i.e. statements that you can - * register under a name you choose, optimized once by the backend, and - * executed any number of times under the given name. - * - * Prepared statement definitions are not sensitive to transaction - * boundaries. A statement defined inside a transaction will remain defined - * outside that transaction, even if the transaction itself is subsequently - * aborted. Once a statement has been prepared, it will only go away if you - * close the connection or explicitly "unprepare" the statement. - * - * Use the `pqxx::transaction_base::exec_prepared` functions to execute a - * prepared statement. See @ref prepared for a full discussion. - * - * @warning Using prepared statements can save time, but if your statement - * takes parameters, it may also make your application significantly slower! - * The reason is that the server works out a plan for executing the query - * when you prepare it. At that time, of course it does not know the values - * for the parameters that you will pass. If you execute a query without - * preparing it, then the server works out the plan on the spot, with full - * knowledge of the parameter values. - * - * A statement's definition can refer to its parameters as `$1`, `$2`, etc. - * The first parameter you pass to the call provides a value for `$1`, and - * so on. - * - * Here's an example of how to use prepared statements. - * - * ```cxx - * using namespace pqxx; - * void foo(connection &c) - * { - * c.prepare("findtable", "select * from pg_tables where name=$1"); - * work tx{c}; - * result r = tx.exec_prepared("findtable", "mytable"); - * if (std::empty(r)) throw runtime_error{"mytable not found!"}; - * } - * ``` - */ - //@{ - - /// Define a prepared statement. - /** - * @param name unique name for the new prepared statement. - * @param definition SQL statement to prepare. - */ - void prepare(zview name, zview definition) & - { - prepare(name.c_str(), definition.c_str()); - } - - /** - * @param name unique name for the new prepared statement. - * @param definition SQL statement to prepare. - */ - void prepare(char const name[], char const definition[]) &; - - /// Define a nameless prepared statement. - /** - * This can be useful if you merely want to pass large binary parameters to a - * statement without otherwise wishing to prepare it. If you use this - * feature, always keep the definition and the use close together to avoid - * the nameless statement being redefined unexpectedly by code somewhere - * else. - */ - void prepare(char const definition[]) &; - void prepare(zview definition) & { return prepare(definition.c_str()); } - - /// Drop prepared statement. - void unprepare(std::string_view name); - - //@} - - // C++20: constexpr. Breaks ABI. - /// Suffix unique number to name to make it unique within session context. - /** Used internally to generate identifiers for SQL objects (such as cursors - * and nested transactions) based on a given human-readable base name. - */ - [[nodiscard]] std::string adorn_name(std::string_view); - - /** - * @defgroup escaping-functions String-escaping functions - */ - //@{ - - /// Escape string for use as SQL string literal on this connection. - /** @warning This accepts a length, and it does not require a terminating - * zero byte. But if there is a zero byte, escaping stops there even if - * it's not at the end of the string! - */ - [[deprecated("Use std::string_view or pqxx:zview.")]] std::string - esc(char const text[], std::size_t maxlen) const - { - return esc(std::string_view{text, maxlen}); - } - - /// Escape string for use as SQL string literal on this connection. - [[nodiscard]] std::string esc(char const text[]) const - { - return esc(std::string_view{text}); - } - -#if defined(PQXX_HAVE_SPAN) - /// Escape string for use as SQL string literal, into `buffer`. - /** Use this variant when you want to re-use the same buffer across multiple - * calls. If that's not the case, or convenience and simplicity are more - * important, use the single-argument variant. - * - * For every byte in `text`, there must be at least 2 bytes of space in - * `buffer`; plus there must be one byte of space for a trailing zero. - * Throws @ref range_error if this space is not available. - * - * Returns a reference to the escaped string, which is actually stored in - * `buffer`. - */ - [[nodiscard]] std::string_view - esc(std::string_view text, std::span buffer) - { - auto const size{std::size(text)}, space{std::size(buffer)}; - auto const needed{2 * size + 1}; - if (space < needed) - throw range_error{internal::concat( - "Not enough room to escape string of ", size, " byte(s): need ", - needed, " bytes of buffer space, but buffer size is ", space, ".")}; - auto const data{buffer.data()}; - return {data, esc_to_buf(text, data)}; - } -#endif - - /// Escape string for use as SQL string literal on this connection. - /** @warning This is meant for text strings only. It cannot contain bytes - * whose value is zero ("nul bytes"). - */ - [[nodiscard]] std::string esc(std::string_view text) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape binary string for use as SQL string literal on this connection. - /** This is identical to `esc_raw(data)`. */ - template [[nodiscard]] std::string esc(DATA const &data) const - { - return esc_raw(data); - } -#endif - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - /** Use this variant when you want to re-use the same buffer across multiple - * calls. If that's not the case, or convenience and simplicity are more - * important, use the single-argument variant. - * - * For every byte in `data`, there must be at least two bytes of space in - * `buffer`; plus there must be two bytes of space for a header and one for - * a trailing zero. Throws @ref range_error if this space is not available. - * - * Returns a reference to the escaped string, which is actually stored in - * `buffer`. - */ - template - [[nodiscard]] zview esc(DATA const &data, std::span buffer) const - { - auto const size{std::size(data)}, space{std::size(buffer)}; - auto const needed{internal::size_esc_bin(std::size(data))}; - if (space < needed) - throw range_error{internal::concat( - "Not enough room to escape binary string of ", size, " byte(s): need ", - needed, " bytes of buffer space, but buffer size is ", space, ".")}; - - std::basic_string_view view{std::data(data), std::size(data)}; - auto const out{std::data(buffer)}; - // Actually, in the modern format, we know beforehand exactly how many - // bytes we're going to fill. Just leave out the trailing zero. - internal::esc_bin(view, out); - return zview{out, needed - 1}; - } -#endif - - /// Escape binary string for use as SQL string literal on this connection. - [[deprecated("Use std::byte for binary data.")]] std::string - esc_raw(unsigned char const bin[], std::size_t len) const; - - /// Escape binary string for use as SQL string literal on this connection. - /** You can also just use @ref esc with a binary string. */ - [[nodiscard]] std::string esc_raw(std::basic_string_view) const; - -#if defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - /** You can also just use @ref esc with a binary string. */ - [[nodiscard]] std::string - esc_raw(std::basic_string_view, std::span buffer) const; -#endif - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape binary string for use as SQL string literal on this connection. - /** You can also just use @ref esc with a binary string. */ - template - [[nodiscard]] std::string esc_raw(DATA const &data) const - { - return esc_raw( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - template - [[nodiscard]] zview esc_raw(DATA const &data, std::span buffer) const - { - return this->esc(binary_cast(data), buffer); - } -#endif - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(zview text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return unesc_raw(text.c_str()); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(char const text[]) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - * - * (The data must be encoded in PostgreSQL's "hex" format. The legacy - * "bytea" escape format, used prior to PostgreSQL 9.0, is no longer - * supported.) - */ - [[nodiscard]] std::basic_string - unesc_bin(std::string_view text) const - { - std::basic_string buf; - buf.resize(pqxx::internal::size_unesc_bin(std::size(text))); - pqxx::internal::unesc_bin(text, buf.data()); - return buf; - } - - /// Escape and quote a string of binary data. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(unsigned char const bin[], std::size_t len) const; - - /// Escape and quote a string of binary data. - std::string quote_raw(std::basic_string_view) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape and quote a string of binary data. - /** You can also just use @ref quote with binary data. */ - template - [[nodiscard]] std::string quote_raw(DATA const &data) const - { - return quote_raw( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote an SQL identifier for use in a query. - [[nodiscard]] std::string quote_name(std::string_view identifier) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote a table name. - /** When passing just a table name, this is just another name for - * @ref quote_name. - */ - [[nodiscard]] std::string quote_table(std::string_view name) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote a table path. - /** A table path consists of a table name, optionally prefixed by a schema - * name; and if both are given, they are in turn optionally prefixed by a - * database name. - * - * Each portion of the path (database name, schema name, table name) will be - * quoted separately, and they will be joined together by dots. So for - * example, `myschema.mytable` will become `"myschema"."mytable"`. - */ - [[nodiscard]] std::string quote_table(table_path) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Quote and comma-separate a series of column names. - /** Use this to save a bit of work in cases where you repeatedly need to pass - * the same list of column names, e.g. with @ref stream_to and @ref - * stream_from. Some functions that need to quote the columns list - * internally, will have a "raw" alternative which let you do the quoting - * yourself. It's a bit of extra work, but it can in rare cases let you - * eliminate some duplicate work in quoting them repeatedly. - */ - template - inline std::string quote_columns(STRINGS const &columns) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Represent object as SQL string, including quoting & escaping. - /** - * Recognises nulls and represents them as SQL nulls. They get no quotes. - */ - template - [[nodiscard]] inline std::string quote(T const &t) const; - - [[deprecated("Use std::byte for binary data.")]] std::string - quote(binarystring const &) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote binary data for use as a BYTEA value in SQL statement. - [[nodiscard]] std::string - quote(std::basic_string_view bytes) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape string for literal LIKE match. - /** Use this when part of an SQL "LIKE" pattern should match only as a - * literal string, not as a pattern, even if it contains "%" or "_" - * characters that would normally act as wildcards. - * - * The string does not get string-escaped or quoted. You do that later. - * - * For instance, let's say you have a string `name` entered by the user, - * and you're searching a `file` column for items that match `name` - * followed by a dot and three letters. Even if `name` contains wildcard - * characters "%" or "_", you only want those to match literally, so "_" - * only matches "_" and "%" only matches a single "%". - * - * You do that by "like-escaping" `name`, appending the wildcard pattern - * `".___"`, and finally, escaping and quoting the result for inclusion in - * your query: - * - * ```cxx - * tx.exec( - * "SELECT file FROM item WHERE file LIKE " + - * tx.quote(tx.esc_like(name) + ".___")); - * ``` - * - * The SQL "LIKE" operator also lets you choose your own escape character. - * This is supported, but must be a single-byte character. - */ - [[nodiscard]] std::string - esc_like(std::string_view text, char escape_char = '\\') const; - //@} - - /// Attempt to cancel the ongoing query, if any. - /** You can use this from another thread, and/or while a query is executing - * in a pipeline, but it's up to you to ensure that you're not canceling the - * wrong query. This may involve locking. - */ - void cancel_query(); - -#if defined(_WIN32) || __has_include() - /// Set socket to blocking (true) or nonblocking (false). - /** @warning Do not use this unless you _really_ know what you're doing. - * @warning This function is available on most systems, but not necessarily - * all. - */ - void set_blocking(bool block) &; -#endif // defined(_WIN32) || __has_include() - - /// Set session verbosity. - /** Set the verbosity of error messages to "terse", "normal" (the default), - * or "verbose." - * - * If "terse", returned messages include severity, primary text, and - * position only; this will normally fit on a single line. "normal" produces - * messages that include the above plus any detail, hint, or context fields - * (these might span multiple lines). "verbose" includes all available - * fields. - */ - void set_verbosity(error_verbosity verbosity) &noexcept; - - /// Return pointers to the active errorhandlers. - /** The entries are ordered from oldest to newest handler. - * - * You may use this to find errorhandlers that your application wants to - * delete when destroying the connection. Be aware, however, that libpqxx - * may also add errorhandlers of its own, and those will be included in the - * list. If this is a problem for you, derive your errorhandlers from a - * custom base class derived from pqxx::errorhandler. Then use dynamic_cast - * to find which of the error handlers are yours. - * - * The pointers point to the real errorhandlers. The container it returns - * however is a copy of the one internal to the connection, not a reference. - */ - [[nodiscard]] std::vector get_errorhandlers() const; - - /// Return a connection string encapsulating this connection's options. - /** The connection must be currently open for this to work. - * - * Returns a reconstruction of this connection's connection string. It may - * not exactly match the connection string you passed in when creating this - * connection. - */ - [[nodiscard]] std::string connection_string() const; - - /// Explicitly close the connection. - /** The destructor will do this for you automatically. Still, there is a - * reason to `close()` objects explicitly where possible: if an error should - * occur while closing, `close()` can throw an exception. A destructor - * cannot. - * - * Closing a connection is idempotent. Closing a connection that's already - * closed does nothing. - */ - void close(); - - /// Seize control of a raw libpq connection. - /** @warning Do not do this. Please. It's for very rare, very specific - * use-cases. The mechanism may change (or break) in unexpected ways in - * future versions. - * - * @param raw_conn a raw libpq `PQconn` pointer. - */ - static connection seize_raw_connection(internal::pq::PGconn *raw_conn) - { - return connection{raw_conn}; - } - - /// Release the raw connection without closing it. - /** @warning Do not do this. It's for very rare, very specific use-cases. - * The mechanism may change (or break) in unexpected ways in future versions. - * - * The `connection` object becomes unusable after this. - */ - internal::pq::PGconn *release_raw_connection() && - { - return std::exchange(m_conn, nullptr); - } - -private: - friend class connecting; - enum connect_mode - { - connect_nonblocking - }; - connection(connect_mode, zview connection_string); - - /// For use by @ref seize_raw_connection. - explicit connection(internal::pq::PGconn *raw_conn) : m_conn{raw_conn} {} - - /// Poll for ongoing connection, try to progress towards completion. - /** Returns a pair of "now please wait to read data from socket" and "now - * please wait to write data to socket." Both will be false when done. - * - * Throws an exception if polling indicates that the connection has failed. - */ - std::pair poll_connect(); - - // Initialise based on connection string. - void init(char const options[]); - // Initialise based on parameter names and values. - void init(char const *params[], char const *values[]); - void complete_init(); - - result make_result( - internal::pq::PGresult *pgr, std::shared_ptr const &query, - std::string_view desc = ""sv); - - void PQXX_PRIVATE set_up_state(); - - int PQXX_PRIVATE PQXX_PURE status() const noexcept; - - /// Escape a string, into a buffer allocated by the caller. - /** The buffer must have room for at least `2*std::size(text) + 1` bytes. - * - * Returns the number of bytes written, including the trailing zero. - */ - std::size_t esc_to_buf(std::string_view text, char *buf) const; - - friend class internal::gate::const_connection_largeobject; - char const *PQXX_PURE err_msg() const noexcept; - - void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept; - - result exec_prepared(std::string_view statement, internal::c_params const &); - - /// Throw @ref usage_error if this connection is not in a movable state. - void check_movable() const; - /// Throw @ref usage_error if not in a state where it can be move-assigned. - void check_overwritable() const; - - friend class internal::gate::connection_errorhandler; - void PQXX_PRIVATE register_errorhandler(errorhandler *); - void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept; - - friend class internal::gate::connection_transaction; - result exec(std::string_view, std::string_view = ""sv); - result - PQXX_PRIVATE exec(std::shared_ptr, std::string_view = ""sv); - void PQXX_PRIVATE register_transaction(transaction_base *); - void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept; - - friend class internal::gate::connection_stream_from; - std::pair>, std::size_t> - PQXX_PRIVATE read_copy_line(); - - friend class internal::gate::connection_stream_to; - void PQXX_PRIVATE write_copy_line(std::string_view); - void PQXX_PRIVATE end_copy_write(); - - friend class internal::gate::connection_largeobject; - internal::pq::PGconn *raw_connection() const { return m_conn; } - - friend class internal::gate::connection_notification_receiver; - void add_receiver(notification_receiver *); - void remove_receiver(notification_receiver *) noexcept; - - friend class internal::gate::connection_pipeline; - void PQXX_PRIVATE start_exec(char const query[]); - bool PQXX_PRIVATE consume_input() noexcept; - bool PQXX_PRIVATE is_busy() const noexcept; - internal::pq::PGresult *get_result(); - - friend class internal::gate::connection_dbtransaction; - friend class internal::gate::connection_sql_cursor; - - result exec_params(std::string_view query, internal::c_params const &args); - - /// Connection handle. - internal::pq::PGconn *m_conn = nullptr; - - /// Active transaction on connection, if any. - /** We don't use this for anything, except to check for open transactions - * when we close the connection or start a new transaction. - * - * We also don't allow move construction or move assignment while there's a - * transaction, since moving the connection in that case would leave one or - * more pointers back from the transaction to the connection dangling. - */ - transaction_base const *m_trans = nullptr; - - std::list m_errorhandlers; - - using receiver_list = - std::multimap; - /// Notification receivers. - receiver_list m_receivers; - - /// Unique number to use as suffix for identifiers (see adorn_name()). - int m_unique_id = 0; -}; - - -/// @deprecated Old base class for connection. They are now the same class. -using connection_base = connection; - - -/// An ongoing, non-blocking stepping stone to a connection. -/** Use this when you want to create a connection to the database, but without - * blocking your whole thread. It is only available on systems that have - * the `` header, and Windows. - * - * Connecting in this way is probably not "faster" (it's more complicated and - * has some extra overhead), but in some situations you can use it to make your - * application as a whole faster. It all depends on having other useful work - * to do in the same thread, and being able to wait on a socket. If you have - * other I/O going on at the same time, your event loop can wait for both the - * libpqxx socket and your own sockets, and wake up whenever any of them is - * ready to do work. - * - * Connecting in this way is not properly "asynchronous;" it's merely - * "nonblocking." This means it's not a super-high-performance mechanism like - * you might get with e.g. `io_uring`. In particular, if we need to look up - * the database hostname in DNS, that will happen synchronously. - * - * To use this, create the `connecting` object, passing a connection string. - * Then loop: If @ref wait_to_read returns true, wait for the socket to have - * incoming data on it. If @ref wait_to_write returns true, wait for the - * socket to be ready for writing. Then call @ref process to process any - * incoming or outgoing data. Do all of this until @ref done returns true (or - * there is an exception). Finally, call @ref produce to get the completed - * connection. - * - * For example: - * - * ```cxx - * pqxx::connecting cg{}; - * - * // Loop until we're done connecting. - * while (!cg.done()) - * { - * wait_for_fd(cg.sock(), cg.wait_to_read(), cg.wait_to_write()); - * cg.process(); - * } - * - * pqxx::connection conn = std::move(cg).produce(); - * - * // At this point, conn is a working connection. You can no longer use - * // cg at all. - * ``` - */ -class PQXX_LIBEXPORT connecting -{ -public: - /// Start connecting. - connecting(zview connection_string = ""_zv); - - connecting(connecting const &) = delete; - connecting(connecting &&) = default; - connecting &operator=(connecting const &) = delete; - connecting &operator=(connecting &&) = default; - - /// Get the socket. The socket may change during the connection process. - [[nodiscard]] int sock() const &noexcept { return m_conn.sock(); } - - /// Should we currently wait to be able to _read_ from the socket? - [[nodiscard]] constexpr bool wait_to_read() const &noexcept - { - return m_reading; - } - - /// Should we currently wait to be able to _write_ to the socket? - [[nodiscard]] constexpr bool wait_to_write() const &noexcept - { - return m_writing; - } - - /// Progress towards completion (but don't block). - void process() &; - - /// Is our connection finished? - [[nodiscard]] constexpr bool done() const &noexcept - { - return not m_reading and not m_writing; - } - - /// Produce the completed connection object. - /** Use this only once, after @ref done returned `true`. Once you have - * called this, the `connecting` instance has no more use or meaning. You - * can't call any of its member functions afterwards. - * - * This member function is rvalue-qualified, meaning that you can only call - * it on an rvalue instance of the class. If what you have is not an rvalue, - * turn it into one by wrapping it in `std::move()`. - */ - [[nodiscard]] connection produce() &&; - -private: - connection m_conn; - bool m_reading{false}; - bool m_writing{true}; -}; - - -template inline std::string connection::quote(T const &t) const -{ - if constexpr (nullness::always_null) - { - return "NULL"; - } - else - { - if (is_null(t)) - return "NULL"; - auto const text{to_string(t)}; - - // Okay, there's an easy way to do this and there's a hard way. The easy - // way was "quote, esc(to_string(t)), quote". I'm going with the hard way - // because it's going to save some string manipulation that will probably - // incur some unnecessary memory allocations and deallocations. - std::string buf{'\''}; - buf.resize(2 + 2 * std::size(text) + 1); - auto const content_bytes{esc_to_buf(text, buf.data() + 1)}; - auto const closing_quote{1 + content_bytes}; - buf[closing_quote] = '\''; - auto const end{closing_quote + 1}; - buf.resize(end); - return buf; - } -} - - -template -inline std::string connection::quote_columns(STRINGS const &columns) const -{ - return separated_list( - ","sv, std::cbegin(columns), std::cend(columns), - [this](auto col) { return this->quote_name(*col); }); -} - - -#if defined(PQXX_HAVE_CONCEPTS) -template -inline connection::connection(MAPPING const ¶ms) -{ - check_version(); - - std::vector keys, values; - if constexpr (std::ranges::sized_range) - { - auto const size{std::ranges::size(params) + 1}; - keys.reserve(size); - values.reserve(size); - } - for (auto const &[key, value] : params) - { - keys.push_back(internal::as_c_string(key)); - values.push_back(internal::as_c_string(value)); - } - keys.push_back(nullptr); - values.push_back(nullptr); - init(std::data(keys), std::data(values)); -} -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/cursor b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/cursor deleted file mode 100644 index e20b3a4fa..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/cursor +++ /dev/null @@ -1,8 +0,0 @@ -/** Definition of the iterator/container-style cursor classes. - * - * C++-style wrappers for SQL cursors - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/cursor.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/cursor.hxx deleted file mode 100644 index b392e2407..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/cursor.hxx +++ /dev/null @@ -1,483 +0,0 @@ -/* Definition of the iterator/container-style cursor classes. - * - * C++-style wrappers for SQL cursors. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_CURSOR -#define PQXX_H_CURSOR - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/result.hxx" -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -/// Common definitions for cursor types -/** In C++ terms, fetches are always done in pre-increment or pre-decrement - * fashion--i.e. the result does not include the row the cursor is on at the - * beginning of the fetch, and the cursor ends up being positioned on the last - * row in the result. - * - * There are singular positions akin to `end()` at both the beginning and the - * end of the cursor's range of movement, although these fit in so naturally - * with the semantics that one rarely notices them. The cursor begins at the - * first of these, but any fetch in the forward direction will move the cursor - * off this position and onto the first row before returning anything. - */ -class PQXX_LIBEXPORT cursor_base -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - - /// Cursor access-pattern policy - /** Allowing a cursor to move forward only can result in better performance, - * so use this access policy whenever possible. - */ - enum access_policy - { - /// Cursor can move forward only - forward_only, - /// Cursor can move back and forth - random_access - }; - - /// Cursor update policy - /** - * @warning Not all PostgreSQL versions support updatable cursors. - */ - enum update_policy - { - /// Cursor can be used to read data but not to write - read_only, - /// Cursor can be used to update data as well as read it - update - }; - - /// Cursor destruction policy - /** The normal thing to do is to make a cursor object the owner of the SQL - * cursor it represents. There may be cases, however, where a cursor needs - * to persist beyond the end of the current transaction (and thus also beyond - * the lifetime of the cursor object that created it!), where it can be - * "adopted" into a new cursor object. See the basic_cursor documentation - * for an explanation of cursor adoption. - * - * If a cursor is created with "loose" ownership policy, the object - * representing the underlying SQL cursor will not take the latter with it - * when its own lifetime ends, nor will its originating transaction. - * - * @warning Use this feature with care and moderation. Only one cursor - * object should be responsible for any one underlying SQL cursor at any - * given time. - */ - enum ownership_policy - { - /// Destroy SQL cursor when cursor object is closed at end of transaction - owned, - /// Leave SQL cursor in existence after close of object and transaction - loose - }; - - cursor_base() = delete; - cursor_base(cursor_base const &) = delete; - cursor_base &operator=(cursor_base const &) = delete; - - /** - * @name Special movement distances. - */ - //@{ - - // TODO: Make constexpr inline (but breaks ABI). - /// Special value: read until end. - /** @return Maximum value for result::difference_type, so the cursor will - * attempt to read the largest possible result set. - */ - [[nodiscard]] static difference_type all() noexcept; - - /// Special value: read one row only. - /** @return Unsurprisingly, 1. - */ - [[nodiscard]] static constexpr difference_type next() noexcept { return 1; } - - /// Special value: read backwards, one row only. - /** @return Unsurprisingly, -1. - */ - [[nodiscard]] static constexpr difference_type prior() noexcept - { - return -1; - } - - // TODO: Make constexpr inline (but breaks ABI). - /// Special value: read backwards from current position back to origin. - /** @return Minimum value for result::difference_type. - */ - [[nodiscard]] static difference_type backward_all() noexcept; - - //@} - - /// Name of underlying SQL cursor - /** - * @returns Name of SQL cursor, which may differ from original given name. - * @warning Don't use this to access the SQL cursor directly without going - * through the provided wrapper classes! - */ - [[nodiscard]] constexpr std::string const &name() const noexcept - { - return m_name; - } - -protected: - cursor_base(connection &, std::string_view Name, bool embellish_name = true); - - std::string const m_name; -}; -} // namespace pqxx - - -#include - - -namespace pqxx -{ -/// "Stateless cursor" class: easy API for retrieving parts of result sets -/** This is a front-end for SQL cursors, but with a more C++-like API. - * - * Actually, stateless_cursor feels entirely different from SQL cursors. You - * don't keep track of positions, fetches, and moves; you just say which rows - * you want. See the retrieve() member function. - */ -template -class stateless_cursor -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - - /// Create cursor. - /** - * @param tx The transaction within which you want to create the cursor. - * @param query The SQL query whose results the cursor should traverse. - * @param cname A hint for the cursor's name. The actual SQL cursor's name - * will be based on this (though not necessarily identical). - * @param hold Create a `WITH HOLD` cursor? Such cursors stay alive after - * the transaction has ended, so you can continue to use it. - */ - stateless_cursor( - transaction_base &tx, std::string_view query, std::string_view cname, - bool hold) : - m_cur{tx, query, cname, cursor_base::random_access, up, op, hold} - {} - - /// Adopt an existing scrolling SQL cursor. - /** This lets you define a cursor yourself, and then wrap it in a - * libpqxx-managed `stateless_cursor` object. - * - * @param tx The transaction within which you want to manage the cursor. - * @param adopted_cursor Your cursor's SQL name. - */ - stateless_cursor(transaction_base &tx, std::string_view adopted_cursor) : - m_cur{tx, adopted_cursor, op} - { - // Put cursor in known position - m_cur.move(cursor_base::backward_all()); - } - - /// Close this cursor. - /** The destructor will do this for you automatically. - * - * Closing a cursor is idempotent. Closing a cursor that's already closed - * does nothing. - */ - void close() noexcept { m_cur.close(); } - - /// Number of rows in cursor's result set - /** @note This function is not const; it may need to scroll to find the size - * of the result set. - */ - [[nodiscard]] size_type size() - { - return internal::obtain_stateless_cursor_size(m_cur); - } - - /// Retrieve rows from begin_pos (inclusive) to end_pos (exclusive) - /** Rows are numbered starting from 0 to size()-1. - * - * @param begin_pos First row to retrieve. May be one row beyond the end of - * the result set, to avoid errors for empty result sets. Otherwise, must be - * a valid row number in the result set. - * @param end_pos Row up to which to fetch. Rows are returned ordered from - * begin_pos to end_pos, i.e. in ascending order if begin_pos < end_pos but - * in descending order if begin_pos > end_pos. The end_pos may be - * arbitrarily inside or outside the result set; only existing rows are - * included in the result. - */ - result retrieve(difference_type begin_pos, difference_type end_pos) - { - return internal::stateless_cursor_retrieve( - m_cur, result::difference_type(size()), begin_pos, end_pos); - } - - /// Return this cursor's name. - [[nodiscard]] constexpr std::string const &name() const noexcept - { - return m_cur.name(); - } - -private: - internal::sql_cursor m_cur; -}; - - -class icursor_iterator; -} // namespace pqxx - - -namespace pqxx::internal::gate -{ -class icursor_iterator_icursorstream; -class icursorstream_icursor_iterator; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Simple read-only cursor represented as a stream of results -/** SQL cursors can be tricky, especially in C++ since the two languages seem - * to have been designed on different planets. An SQL cursor has two singular - * positions akin to `end()` on either side of the underlying result set. - * - * These cultural differences are hidden from view somewhat by libpqxx, which - * tries to make SQL cursors behave more like familiar C++ entities such as - * iterators, sequences, streams, and containers. - * - * Data is fetched from the cursor as a sequence of result objects. Each of - * these will contain the number of rows defined as the stream's stride, except - * of course the last block of data which may contain fewer rows. - * - * This class can create or adopt cursors that live outside any backend - * transaction, which your backend version may not support. - */ -class PQXX_LIBEXPORT icursorstream -{ -public: - using size_type = cursor_base::size_type; - using difference_type = cursor_base::difference_type; - - /// Set up a read-only, forward-only cursor. - /** Roughly equivalent to a C++ Standard Library istream, this cursor type - * supports only two operations: reading a block of rows while moving - * forward, and moving forward without reading any data. - * - * @param context Transaction context in which this cursor will be active. - * @param query SQL query whose results this cursor shall iterate. - * @param basename Suggested name for the SQL cursor; the library will append - * a unique code to ensure its uniqueness. - * @param sstride Number of rows to fetch per read operation; must be a - * positive number. - */ - icursorstream( - transaction_base &context, std::string_view query, - std::string_view basename, difference_type sstride = 1); - - /// Adopt existing SQL cursor. Use with care. - /** Forms a cursor stream around an existing SQL cursor, as returned by e.g. - * a server-side function. The SQL cursor will be cleaned up by the stream's - * destructor as if it had been created by the stream; cleaning it up by hand - * or adopting the same cursor twice is an error. - * - * Passing the name of the cursor as a string is not allowed, both to avoid - * confusion with the other constructor and to discourage unnecessary use of - * adopted cursors. - * - * @warning It is technically possible to adopt a "WITH HOLD" cursor, i.e. a - * cursor that stays alive outside its creating transaction. However, any - * cursor stream (including the underlying SQL cursor, naturally) must be - * destroyed before its transaction context object is destroyed. Therefore - * the only way to use SQL's WITH HOLD feature is to adopt the cursor, but - * defer doing so until after entering the transaction context that will - * eventually destroy it. - * - * @param context Transaction context in which this cursor will be active. - * @param cname Result field containing the name of the SQL cursor to adopt. - * @param sstride Number of rows to fetch per read operation; must be a - * positive number. - * @param op Ownership policy. Determines whether the cursor underlying this - * stream will be destroyed when the stream is closed. - */ - icursorstream( - transaction_base &context, field const &cname, difference_type sstride = 1, - cursor_base::ownership_policy op = cursor_base::owned); - - /// Return `true` if this stream may still return more data. - constexpr operator bool() const &noexcept { return not m_done; } - - /// Read new value into given result object; same as operator `>>`. - /** The result set may continue any number of rows from zero to the chosen - * stride, inclusive. An empty result will only be returned if there are no - * more rows to retrieve. - * - * @param res Write the retrieved data into this result object. - * @return Reference to this very stream, to facilitate "chained" invocations - * ("C.get(r1).get(r2);") - */ - icursorstream &get(result &res) - { - res = fetchblock(); - return *this; - } - /// Read new value into given result object; same as `get(result&)`. - /** The result set may continue any number of rows from zero to the chosen - * stride, inclusive. An empty result will only be returned if there are no - * more rows to retrieve. - * - * @param res Write the retrieved data into this result object. - * @return Reference to this very stream, to facilitate "chained" invocations - * ("C >> r1 >> r2;") - */ - icursorstream &operator>>(result &res) { return get(res); } - - /// Move given number of rows forward without reading data. - /** Ignores any stride that you may have set. It moves by a given number of - * rows, not a number of strides. - * - * @return Reference to this stream itself, to facilitate "chained" - * invocations. - */ - icursorstream &ignore(std::streamsize n = 1) &; - - /// Change stride, i.e. the number of rows to fetch per read operation. - /** - * @param stride Must be a positive number. - */ - void set_stride(difference_type stride) &; - [[nodiscard]] constexpr difference_type stride() const noexcept - { - return m_stride; - } - -private: - result fetchblock(); - - friend class internal::gate::icursorstream_icursor_iterator; - size_type forward(size_type n = 1); - void insert_iterator(icursor_iterator *) noexcept; - void remove_iterator(icursor_iterator *) const noexcept; - - void service_iterators(difference_type); - - internal::sql_cursor m_cur; - - difference_type m_stride; - difference_type m_realpos, m_reqpos; - - mutable icursor_iterator *m_iterators; - - bool m_done; -}; - - -/// Approximate istream_iterator for icursorstream. -/** Intended as an implementation of an input_iterator (as defined by the C++ - * Standard Library), this class supports only two basic operations: reading - * the current element, and moving forward. In addition to the minimal - * guarantees for istream_iterators, this class supports multiple successive - * reads of the same position (the current result set is cached in the - * iterator) even after copying and even after new data have been read from the - * stream. This appears to be a requirement for input_iterators. Comparisons - * are also supported in the general case. - * - * The iterator does not care about its own position, however. Moving an - * iterator forward moves the underlying stream forward and reads the data from - * the new stream position, regardless of the iterator's old position in the - * stream. - * - * The stream's stride defines the granularity for all iterator movement or - * access operations, i.e. "ici += 1" advances the stream by one stride's worth - * of rows, and "*ici++" reads one stride's worth of rows from the stream. - * - * @warning Do not read from the underlying stream or its cursor, move its read - * position, or change its stride, between the time the first icursor_iterator - * on it is created and the time its last icursor_iterator is destroyed. - * - * @warning Manipulating these iterators within the context of a single cursor - * stream is not thread-safe. Creating a new iterator, copying one, - * or destroying one affects the stream as a whole. - */ -class PQXX_LIBEXPORT icursor_iterator -{ -public: - using iterator_category = std::input_iterator_tag; - using value_type = result; - using pointer = result const *; - using reference = result const &; - using istream_type = icursorstream; - using size_type = istream_type::size_type; - using difference_type = istream_type::difference_type; - - icursor_iterator() noexcept; - explicit icursor_iterator(istream_type &) noexcept; - icursor_iterator(icursor_iterator const &) noexcept; - ~icursor_iterator() noexcept; - - result const &operator*() const - { - refresh(); - return m_here; - } - result const *operator->() const - { - refresh(); - return &m_here; - } - icursor_iterator &operator++(); - icursor_iterator operator++(int); - icursor_iterator &operator+=(difference_type); - icursor_iterator &operator=(icursor_iterator const &) noexcept; - - [[nodiscard]] bool operator==(icursor_iterator const &rhs) const; - [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept - { - return not operator==(rhs); - } - [[nodiscard]] bool operator<(icursor_iterator const &rhs) const; - [[nodiscard]] bool operator>(icursor_iterator const &rhs) const - { - return rhs < *this; - } - [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const - { - return not(*this > rhs); - } - [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const - { - return not(*this < rhs); - } - -private: - void refresh() const; - - friend class internal::gate::icursor_iterator_icursorstream; - difference_type pos() const noexcept { return m_pos; } - void fill(result const &); - - icursorstream *m_stream{nullptr}; - result m_here; - difference_type m_pos; - icursor_iterator *m_prev{nullptr}, *m_next{nullptr}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/dbtransaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/dbtransaction deleted file mode 100644 index fa8d26476..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/dbtransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::dbtransaction abstract base class. - * - * pqxx::dbransaction defines a real transaction on the database. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/dbtransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/dbtransaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/dbtransaction.hxx deleted file mode 100644 index d85cb170f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/dbtransaction.hxx +++ /dev/null @@ -1,70 +0,0 @@ -/* Definition of the pqxx::dbtransaction abstract base class. - * - * pqxx::dbransaction defines a real transaction on the database. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_DBTRANSACTION -#define PQXX_H_DBTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/transaction_base.hxx" - -namespace pqxx -{ -/// Abstract transaction base class: bracket transactions on the database. -/** - * @ingroup transactions - * - * Use a dbtransaction-derived object such as "work" (transaction<>) to enclose - * operations on a database in a single "unit of work." This ensures that the - * whole series of operations either succeeds as a whole or fails completely. - * In no case will it leave half-finished work behind in the database. - * - * Once processing on a transaction has succeeded and any changes should be - * allowed to become permanent in the database, call commit(). If something - * has gone wrong and the changes should be forgotten, call abort() instead. - * If you do neither, an implicit abort() is executed at destruction time. - * - * It is an error to abort a transaction that has already been committed, or to - * commit a transaction that has already been aborted. Aborting an already - * aborted transaction or committing an already committed one is allowed, to - * make error handling easier. Repeated aborts or commits have no effect after - * the first one. - * - * Database transactions are not suitable for guarding long-running processes. - * If your transaction code becomes too long or too complex, consider ways to - * break it up into smaller ones. Unfortunately there is no universal recipe - * for this. - * - * The actual operations for committing/aborting the backend transaction are - * implemented by a derived class. The implementing concrete class must also - * call @ref close from its destructor. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base -{ -protected: - /// Begin transaction. - explicit dbtransaction(connection &c) : transaction_base{c} {} - /// Begin transaction. - dbtransaction(connection &c, std::string_view tname) : - transaction_base{c, tname} - {} - /// Begin transaction. - dbtransaction( - connection &c, std::string_view tname, - std::shared_ptr rollback_cmd) : - transaction_base{c, tname, rollback_cmd} - {} -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/errorhandler b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/errorhandler deleted file mode 100644 index ea572ee79..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/errorhandler +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::errorhandler class. - * - * Callbacks for handling errors and warnings. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/errorhandler.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/errorhandler.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/errorhandler.hxx deleted file mode 100644 index 2ffb5703c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/errorhandler.hxx +++ /dev/null @@ -1,92 +0,0 @@ -/* Definition of the pqxx::errorhandler class. - * - * pqxx::errorhandler handlers errors and warnings in a database session. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/errorhandler instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ERRORHANDLER -#define PQXX_H_ERRORHANDLER - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/types.hxx" - - -namespace pqxx::internal::gate -{ -class errorhandler_connection; -} - - -namespace pqxx -{ -/** - * @addtogroup errorhandler - */ -//@{ - -/// Base class for error-handler callbacks. -/** To receive errors and warnings from a connection, subclass this with your - * own error-handler functor, and instantiate it for the connection. Destroying - * the handler un-registers it. - * - * A connection can have multiple error handlers at the same time. When the - * database connection emits an error or warning message, it passes the message - * to each error handler, starting with the most recently registered one and - * progressing towards the oldest one. However an error handler may also - * instruct the connection not to pass the message to further handlers by - * returning "false." - * - * @warning Strange things happen when a result object outlives its parent - * connection. If you register an error handler on a connection, then you must - * not access the result after destroying the connection. This applies even if - * you destroy the error handler first! - */ -class PQXX_LIBEXPORT errorhandler -{ -public: - explicit errorhandler(connection &); - virtual ~errorhandler(); - - /// Define in subclass: receive an error or warning message from the - /// database. - /** - * @return Whether the same error message should also be passed to the - * remaining, older errorhandlers. - */ - virtual bool operator()(char const msg[]) noexcept = 0; - - errorhandler() = delete; - errorhandler(errorhandler const &) = delete; - errorhandler &operator=(errorhandler const &) = delete; - -private: - connection *m_home; - - friend class internal::gate::errorhandler_connection; - void unregister() noexcept; -}; - - -/// An error handler that suppresses any previously registered error handlers. -class quiet_errorhandler : public errorhandler -{ -public: - /// Suppress error notices. - quiet_errorhandler(connection &conn) : errorhandler{conn} {} - - /// Revert to previous handling of error notices. - virtual bool operator()(char const[]) noexcept override { return false; } -}; - -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/except b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/except deleted file mode 100644 index e5dd508bf..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/except +++ /dev/null @@ -1,8 +0,0 @@ -/** libpqxx exception classes. - * - * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/except.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/except.hxx deleted file mode 100644 index 24f959437..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/except.hxx +++ /dev/null @@ -1,447 +0,0 @@ -/* Definition of libpqxx exception classes. - * - * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_EXCEPT -#define PQXX_H_EXCEPT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - - -namespace pqxx -{ -/** - * @addtogroup exception Exception classes - * - * These exception classes follow, roughly, the two-level hierarchy defined by - * the PostgreSQL SQLSTATE error codes (see Appendix A of the PostgreSQL - * documentation corresponding to your server version). This is not a complete - * mapping though. There are other differences as well, e.g. the error code - * for `statement_completion_unknown` has a separate status in libpqxx as - * @ref in_doubt_error, and `too_many_connections` is classified as a - * `broken_connection` rather than a subtype of `insufficient_resources`. - * - * @see http://www.postgresql.org/docs/9.4/interactive/errcodes-appendix.html - * - * @{ - */ - -/// Run-time failure encountered by libpqxx, similar to std::runtime_error. -struct PQXX_LIBEXPORT failure : std::runtime_error -{ - explicit failure(std::string const &); -}; - - -/// Exception class for lost or failed backend connection. -/** - * @warning When this happens on Unix-like systems, you may also get a SIGPIPE - * signal. That signal aborts the program by default, so if you wish to be - * able to continue after a connection breaks, be sure to disarm this signal. - * - * If you're working on a Unix-like system, see the manual page for - * `signal` (2) on how to deal with SIGPIPE. The easiest way to make this - * signal harmless is to make your program ignore it: - * - * ```cxx - * #include - * - * int main() - * { - * signal(SIGPIPE, SIG_IGN); - * // ... - * ``` - */ -struct PQXX_LIBEXPORT broken_connection : failure -{ - broken_connection(); - explicit broken_connection(std::string const &); -}; - - -/// The caller attempted to set a variable to null, which is not allowed. -struct PQXX_LIBEXPORT variable_set_to_null : failure -{ - variable_set_to_null(); - explicit variable_set_to_null(std::string const &); -}; - - -/// Exception class for failed queries. -/** Carries, in addition to a regular error message, a copy of the failed query - * and (if available) the SQLSTATE value accompanying the error. - */ -class PQXX_LIBEXPORT sql_error : public failure -{ - /// Query string. Empty if unknown. - std::string const m_query; - /// SQLSTATE string describing the error type, if known; or empty string. - std::string const m_sqlstate; - -public: - explicit sql_error( - std::string const &whatarg = "", std::string const &Q = "", - char const sqlstate[] = nullptr); - virtual ~sql_error() noexcept override; - - /// The query whose execution triggered the exception - [[nodiscard]] PQXX_PURE std::string const &query() const noexcept; - - /// SQLSTATE error code if known, or empty string otherwise. - [[nodiscard]] PQXX_PURE std::string const &sqlstate() const noexcept; -}; - - -/// "Help, I don't know whether transaction was committed successfully!" -/** Exception that might be thrown in rare cases where the connection to the - * database is lost while finishing a database transaction, and there's no way - * of telling whether it was actually executed by the backend. In this case - * the database is left in an indeterminate (but consistent) state, and only - * manual inspection will tell which is the case. - */ -struct PQXX_LIBEXPORT in_doubt_error : failure -{ - explicit in_doubt_error(std::string const &); -}; - - -/// The backend saw itself forced to roll back the ongoing transaction. -struct PQXX_LIBEXPORT transaction_rollback : sql_error -{ - explicit transaction_rollback( - std::string const &whatarg, std::string const &q = "", - char const sqlstate[] = nullptr); -}; - - -/// Transaction failed to serialize. Please retry it. -/** Can only happen at transaction isolation levels REPEATABLE READ and - * SERIALIZABLE. - * - * The current transaction cannot be committed without violating the guarantees - * made by its isolation level. This is the effect of a conflict with another - * ongoing transaction. The transaction may still succeed if you try to - * perform it again. - */ -struct PQXX_LIBEXPORT serialization_failure : transaction_rollback -{ - explicit serialization_failure( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// We can't tell whether our last statement succeeded. -struct PQXX_LIBEXPORT statement_completion_unknown : transaction_rollback -{ - explicit statement_completion_unknown( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// The ongoing transaction has deadlocked. Retrying it may help. -struct PQXX_LIBEXPORT deadlock_detected : transaction_rollback -{ - explicit deadlock_detected( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// Internal error in libpqxx library -struct PQXX_LIBEXPORT internal_error : std::logic_error -{ - explicit internal_error(std::string const &); -}; - - -/// Error in usage of libpqxx library, similar to std::logic_error -struct PQXX_LIBEXPORT usage_error : std::logic_error -{ - explicit usage_error(std::string const &); -}; - - -/// Invalid argument passed to libpqxx, similar to std::invalid_argument -struct PQXX_LIBEXPORT argument_error : std::invalid_argument -{ - explicit argument_error(std::string const &); -}; - - -/// Value conversion failed, e.g. when converting "Hello" to int. -struct PQXX_LIBEXPORT conversion_error : std::domain_error -{ - explicit conversion_error(std::string const &); -}; - - -/// Could not convert value to string: not enough buffer space. -struct PQXX_LIBEXPORT conversion_overrun : conversion_error -{ - explicit conversion_overrun(std::string const &); -}; - - -/// Something is out of range, similar to std::out_of_range -struct PQXX_LIBEXPORT range_error : std::out_of_range -{ - explicit range_error(std::string const &); -}; - - -/// Query returned an unexpected number of rows. -struct PQXX_LIBEXPORT unexpected_rows : public range_error -{ - explicit unexpected_rows(std::string const &msg) : range_error{msg} {} -}; - - -/// Database feature not supported in current setup. -struct PQXX_LIBEXPORT feature_not_supported : sql_error -{ - explicit feature_not_supported( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Error in data provided to SQL statement. -struct PQXX_LIBEXPORT data_exception : sql_error -{ - explicit data_exception( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT integrity_constraint_violation : sql_error -{ - explicit integrity_constraint_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT restrict_violation : integrity_constraint_violation -{ - explicit restrict_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT not_null_violation : integrity_constraint_violation -{ - explicit not_null_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT foreign_key_violation : integrity_constraint_violation -{ - explicit foreign_key_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT unique_violation : integrity_constraint_violation -{ - explicit unique_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT check_violation : integrity_constraint_violation -{ - explicit check_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_cursor_state : sql_error -{ - explicit invalid_cursor_state( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_sql_statement_name : sql_error -{ - explicit invalid_sql_statement_name( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_cursor_name : sql_error -{ - explicit invalid_cursor_name( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT syntax_error : sql_error -{ - /// Approximate position in string where error occurred, or -1 if unknown. - int const error_position; - - explicit syntax_error( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr, int pos = -1) : - sql_error{err, Q, sqlstate}, error_position{pos} - {} -}; - -struct PQXX_LIBEXPORT undefined_column : syntax_error -{ - explicit undefined_column( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT undefined_function : syntax_error -{ - explicit undefined_function( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT undefined_table : syntax_error -{ - explicit undefined_table( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT insufficient_privilege : sql_error -{ - explicit insufficient_privilege( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Resource shortage on the server -struct PQXX_LIBEXPORT insufficient_resources : sql_error -{ - explicit insufficient_resources( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT disk_full : insufficient_resources -{ - explicit disk_full( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - insufficient_resources{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT out_of_memory : insufficient_resources -{ - explicit out_of_memory( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - insufficient_resources{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT too_many_connections : broken_connection -{ - explicit too_many_connections(std::string const &err) : - broken_connection{err} - {} -}; - -/// PL/pgSQL error -/** Exceptions derived from this class are errors from PL/pgSQL procedures. - */ -struct PQXX_LIBEXPORT plpgsql_error : sql_error -{ - explicit plpgsql_error( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Exception raised in PL/pgSQL procedure -struct PQXX_LIBEXPORT plpgsql_raise : plpgsql_error -{ - explicit plpgsql_raise( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT plpgsql_no_data_found : plpgsql_error -{ - explicit plpgsql_no_data_found( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT plpgsql_too_many_rows : plpgsql_error -{ - explicit plpgsql_too_many_rows( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT blob_already_exists : failure -{ - explicit blob_already_exists(std::string const &); -}; - -/** - * @} - */ -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/field b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/field deleted file mode 100644 index 37cb69e84..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/field +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::field class. - * - * pqxx::field refers to a field in a query result. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/field.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/field.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/field.hxx deleted file mode 100644 index b8b869fe4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/field.hxx +++ /dev/null @@ -1,542 +0,0 @@ -/* Definitions for the pqxx::field class. - * - * pqxx::field refers to a field in a query result. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_FIELD -#define PQXX_H_FIELD - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/array.hxx" -#include "pqxx/composite.hxx" -#include "pqxx/result.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/types.hxx" - -namespace pqxx -{ -/// Reference to a field in a result set. -/** A field represents one entry in a row. It represents an actual value - * in the result set, and can be converted to various types. - */ -class PQXX_LIBEXPORT field -{ -public: - using size_type = field_size_type; - - /// Constructor. Do not call this yourself; libpqxx will do it for you. - /** Create field as reference to a field in a result set. - * @param r Row that this field is part of. - * @param c Column number of this field. - */ - [[deprecated( - "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept; - - /// Constructor. Do not call this yourself; libpqxx will do it for you. - [[deprecated( - "Do not construct fields yourself. Get them from the " - "row.")]] field() noexcept = default; - - /** - * @name Comparison - */ - //@{ - // TODO: noexcept. Breaks ABI. - /// Byte-by-byte comparison of two fields (all nulls are considered equal) - /** @warning null handling is still open to discussion and change! - * - * Handling of null values differs from that in SQL where a comparison - * involving a null value yields null, so nulls are never considered equal - * to one another or even to themselves. - * - * Null handling also probably differs from the closest equivalent in C++, - * which is the NaN (Not-a-Number) value, a singularity comparable to - * SQL's null. This is because the builtin == operator demands that a == a. - * - * The usefulness of this operator is questionable. No interpretation - * whatsoever is imposed on the data; 0 and 0.0 are considered different, - * as are null vs. the empty string, or even different (but possibly - * equivalent and equally valid) encodings of the same Unicode character - * etc. - */ - [[nodiscard]] PQXX_PURE bool operator==(field const &) const; - - /// Byte-by-byte comparison (all nulls are considered equal) - /** @warning See operator==() for important information about this operator - */ - [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - /** - * @name Column information - */ - //@{ - /// Column name. - [[nodiscard]] PQXX_PURE char const *name() const &; - - /// Column type. - [[nodiscard]] oid PQXX_PURE type() const; - - /// What table did this column come from? - [[nodiscard]] PQXX_PURE oid table() const; - - /// Return row number. The first row is row 0, the second is row 1, etc. - PQXX_PURE constexpr row_size_type num() const noexcept { return col(); } - - /// What column number in its originating table did this column come from? - [[nodiscard]] PQXX_PURE row_size_type table_column() const; - //@} - - /** - * @name Content access - */ - //@{ - /// Read as `string_view`, or an empty one if null. - /** The result only remains usable while the data for the underlying - * @ref result exists. Once all `result` objects referring to that data have - * been destroyed, the `string_view` will no longer point to valid memory. - */ - [[nodiscard]] PQXX_PURE std::string_view view() const & - { - return std::string_view(c_str(), size()); - } - - /// Read as plain C string. - /** Since the field's data is stored internally in the form of a - * zero-terminated C string, this is the fastest way to read it. Use the - * to() or as() functions to convert the string to other types such as - * `int`, or to C++ strings. - * - * Do not use this for BYTEA values, or other binary values. To read those, - * convert the value to your desired type using `to()` or `as()`. For - * example: `f.as>()`. - */ - [[nodiscard]] PQXX_PURE char const *c_str() const &; - - /// Is this field's value null? - [[nodiscard]] PQXX_PURE bool is_null() const noexcept; - - /// Return number of bytes taken up by the field's value. - [[nodiscard]] PQXX_PURE size_type size() const noexcept; - - /// Read value into obj; or if null, leave obj untouched and return `false`. - /** This can be used with optional types (except pointers other than C-style - * strings). - */ - template - auto to(T &obj) const -> typename std::enable_if_t< - (not std::is_pointer::value or std::is_same::value), - bool> - { - if (is_null()) - { - return false; - } - else - { - auto const bytes{c_str()}; - from_string(bytes, obj); - return true; - } - } - - /// Read field as a composite value, write its components into `fields`. - /** @warning This is still experimental. It may change or be replaced. - * - * Returns whether the field was null. If it was, it will not touch the - * values in `fields`. - */ - template bool composite_to(T &...fields) const - { - if (is_null()) - { - return false; - } - else - { - parse_composite(m_home.m_encoding, view(), fields...); - return true; - } - } - - /// Read value into obj; or leave obj untouched and return `false` if null. - template bool operator>>(T &obj) const { return to(obj); } - - /// Read value into obj; or if null, use default value and return `false`. - /** This can be used with `std::optional`, as well as with standard smart - * pointer types, but not with raw pointers. If the conversion from a - * PostgreSQL string representation allocates a pointer (e.g. using `new`), - * then the object's later deallocation should be baked in as well, right - * from the point where the object is created. So if you want a pointer, use - * a smart pointer, not a raw pointer. - * - * There is one exception, of course: C-style strings. Those are just - * pointers to the field's internal text data. - */ - template - auto to(T &obj, T const &default_value) const -> typename std::enable_if_t< - (not std::is_pointer::value or std::is_same::value), - bool> - { - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = from_string(this->view()); - return not null; - } - - /// Return value as object of given type, or default value if null. - /** Note that unless the function is instantiated with an explicit template - * argument, the Default value's type also determines the result type. - */ - template T as(T const &default_value) const - { - if (is_null()) - return default_value; - else - return from_string(this->view()); - } - - /// Return value as object of given type, or throw exception if null. - /** Use as `as>()` or `as()` as - * an alternative to `get()`; this is disabled for use with raw pointers - * (other than C-strings) because storage for the value can't safely be - * allocated here - */ - template T as() const - { - if (is_null()) - { - if constexpr (not nullness::has_null) - internal::throw_null_conversion(type_name); - else - return nullness::null(); - } - else - { - return from_string(this->view()); - } - } - - /// Return value wrapped in some optional type (empty for nulls). - /** Use as `get()` as before to obtain previous behavior, or specify - * container type with `get()` - */ - template class O = std::optional> - constexpr O get() const - { - return as>(); - } - - // TODO: constexpr noexcept, once array_parser constructor gets those. - /// Parse the field as an SQL array. - /** Call the parser to retrieve values (and structure) from the array. - * - * Make sure the @ref result object stays alive until parsing is finished. If - * you keep the @ref row of `field` object alive, it will keep the @ref - * result object alive as well. - */ - array_parser as_array() const & - { - return array_parser{c_str(), m_home.m_encoding}; - } - //@} - - -protected: - constexpr result const &home() const noexcept { return m_home; } - constexpr result::size_type idx() const noexcept { return m_row; } - constexpr row_size_type col() const noexcept { return m_col; } - - // TODO: Create gates. - friend class pqxx::result; - friend class pqxx::row; - field( - result const &r, result_size_type row_num, row_size_type col_num) noexcept - : - m_col{col_num}, m_home{r}, m_row{row_num} - {} - - /** - * You'd expect this to be unsigned, but due to the way reverse iterators - * are related to regular iterators, it must be allowed to underflow to -1. - */ - row_size_type m_col; - -private: - result m_home; - result::size_type m_row; -}; - - -template<> inline bool field::to(std::string &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = std::string{view()}; - return not null; -} - - -template<> -inline bool field::to( - std::string &obj, std::string const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = std::string{view()}; - return not null; -} - - -/// Specialization: `to(char const *&)`. -/** The buffer has the same lifetime as the data in this result (i.e. of this - * result object, or the last remaining one copied from it etc.), so take care - * not to use it after the last result object referring to this query result is - * destroyed. - */ -template<> inline bool field::to(char const *&obj) const -{ - bool const null{is_null()}; - if (not null) - obj = c_str(); - return not null; -} - - -template<> inline bool field::to(std::string_view &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = view(); - return not null; -} - - -template<> -inline bool field::to( - std::string_view &obj, std::string_view const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = view(); - return not null; -} - - -template<> inline std::string_view field::as() const -{ - if (is_null()) - PQXX_UNLIKELY - internal::throw_null_conversion(type_name); - return view(); -} - - -template<> -inline std::string_view -field::as(std::string_view const &default_value) const -{ - return is_null() ? default_value : view(); -} - - -template<> inline bool field::to(zview &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = zview{c_str(), size()}; - return not null; -} - - -template<> -inline bool field::to(zview &obj, zview const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = zview{c_str(), size()}; - return not null; -} - - -template<> inline zview field::as() const -{ - if (is_null()) - PQXX_UNLIKELY - internal::throw_null_conversion(type_name); - return zview{c_str(), size()}; -} - - -template<> inline zview field::as(zview const &default_value) const -{ - return is_null() ? default_value : zview{c_str(), size()}; -} - - -template> -class field_streambuf : public std::basic_streambuf -{ -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - using openmode = std::ios::openmode; - using seekdir = std::ios::seekdir; - - explicit field_streambuf(field const &f) : m_field{f} { initialize(); } - -protected: - virtual int sync() override { return traits_type::eof(); } - - virtual pos_type seekoff(off_type, seekdir, openmode) override - { - return traits_type::eof(); - } - virtual pos_type seekpos(pos_type, openmode) override - { - return traits_type::eof(); - } - virtual int_type overflow(int_type) override { return traits_type::eof(); } - virtual int_type underflow() override { return traits_type::eof(); } - -private: - field const &m_field; - - int_type initialize() - { - auto g{static_cast(const_cast(m_field.c_str()))}; - this->setg(g, g, g + std::size(m_field)); - return int_type(std::size(m_field)); - } -}; - - -/// Input stream that gets its data from a result field -/** Use this class exactly as you would any other istream to read data from a - * field. All formatting and streaming operations of `std::istream` are - * supported. What you'll typically want to use, however, is the fieldstream - * alias (which defines a @ref basic_fieldstream for `char`). This is similar - * to how e.g. `std::ifstream` relates to `std::basic_ifstream`. - * - * This class has only been tested for the char type (and its default traits). - */ -template> -class basic_fieldstream : public std::basic_istream -{ - using super = std::basic_istream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - - basic_fieldstream(field const &f) : super{nullptr}, m_buf{f} - { - super::init(&m_buf); - } - -private: - field_streambuf m_buf; -}; - -using fieldstream = basic_fieldstream; - -/// Write a result field to any type of stream -/** This can be convenient when writing a field to an output stream. More - * importantly, it lets you write a field to e.g. a `stringstream` which you - * can then use to read, format and convert the field in ways that to() does - * not support. - * - * Example: parse a field into a variable of the nonstandard - * "long long" type. - * - * ```cxx - * extern result R; - * long long L; - * stringstream S; - * - * // Write field's string into S - * S << R[0][0]; - * - * // Parse contents of S into L - * S >> L; - * ``` - */ -template -inline std::basic_ostream & -operator<<(std::basic_ostream &s, field const &value) -{ - s.write(value.c_str(), std::streamsize(std::size(value))); - return s; -} - - -/// Convert a field's value to type `T`. -/** Unlike the "regular" `from_string`, this knows how to deal with null - * values. - */ -template inline T from_string(field const &value) -{ - if (value.is_null()) - { - if constexpr (nullness::has_null) - return nullness::null(); - else - internal::throw_null_conversion(type_name); - } - else - { - return from_string(value.view()); - } -} - - -/// Convert a field's value to `nullptr_t`. -/** Yes, you read that right. This conversion does nothing useful. It always - * returns `nullptr`. - * - * Except... what if the field is not null? In that case, this throws - * @ref conversion_error. - */ -template<> -inline std::nullptr_t from_string(field const &value) -{ - if (not value.is_null()) - throw conversion_error{ - "Extracting non-null field into nullptr_t variable."}; - return nullptr; -} - - -/// Convert a field to a string. -template<> PQXX_LIBEXPORT std::string to_string(field const &value); -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/array-composite.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/array-composite.hxx deleted file mode 100644 index d2b6603e5..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/array-composite.hxx +++ /dev/null @@ -1,305 +0,0 @@ -#if !defined(PQXX_ARRAY_COMPOSITE_HXX) -# define PQXX_ARRAY_COMPOSITE_HXX - -# include - -# include "pqxx/strconv.hxx" - -namespace pqxx::internal -{ -// Find the end of a double-quoted string. -/** `input[pos]` must be the opening double quote. - * - * Returns the offset of the first position after the closing quote. - */ -inline std::size_t scan_double_quoted_string( - char const input[], std::size_t size, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - // XXX: find_char<'"', '\\'>(). - auto next{scan(input, size, pos)}; - bool at_quote{false}; - for (pos = next, next = scan(input, size, pos); pos < size; - pos = next, next = scan(input, size, pos)) - { - if (at_quote) - { - if (next - pos == 1 and input[pos] == '"') - { - // We just read a pair of double quotes. Carry on. - at_quote = false; - } - else - { - // We just read one double quote, and now we're at a character that's - // not a second double quote. Ergo, that last character was the - // closing double quote and this is the position right after it. - return pos; - } - } - else if (next - pos == 1) - { - switch (input[pos]) - { - case '\\': - // Backslash escape. Skip ahead by one more character. - pos = next; - next = scan(input, size, pos); - break; - - case '"': - // This is either the closing double quote, or the first of a pair of - // double quotes. - at_quote = true; - break; - } - } - else - { - // Multibyte character. Carry on. - } - } - if (not at_quote) - throw argument_error{ - "Missing closing double-quote: " + std::string{input}}; - return pos; -} - - -/// Un-quote and un-escape a double-quoted SQL string. -inline std::string parse_double_quoted_string( - char const input[], std::size_t end, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - std::string output; - // Maximum output size is same as the input size, minus the opening and - // closing quotes. Or in the extreme opposite case, the real number could be - // half that. Usually it'll be a pretty close estimate. - output.reserve(std::size_t(end - pos - 2)); - - for (auto here{scan(input, end, pos)}, next{scan(input, end, here)}; - here < end - 1; here = next, next = scan(input, end, here)) - { - // A backslash here is always an escape. So is a double-quote, since we're - // inside the double-quoted string. In either case, we can just ignore the - // escape character and use the next character. This is the one redeeming - // feature of SQL's escaping system. - if ((next - here == 1) and (input[here] == '\\' or input[here] == '"')) - { - // Skip escape. - here = next; - next = scan(input, end, here); - } - output.append(input + here, input + next); - } - return output; -} - - -/// Find the end of an unquoted string in an array or composite-type value. -/** Stops when it gets to the end of the input; or when it sees any of the - * characters in STOP which has not been escaped. - * - * For array values, STOP is a comma, a semicolon, or a closing brace. For - * a value of a composite type, STOP is a comma or a closing parenthesis. - */ -template -inline std::size_t scan_unquoted_string( - char const input[], std::size_t size, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - bool at_backslash{false}; - auto next{scan(input, size, pos)}; - while ((pos < size) and - ((next - pos) > 1 or at_backslash or ((input[pos] != STOP) and ...))) - { - pos = next; - next = scan(input, size, pos); - at_backslash = - ((not at_backslash) and ((next - pos) == 1) and (input[pos] == '\\')); - } - return pos; -} - - -/// Parse an unquoted array entry or cfield of a composite-type field. -inline std::string parse_unquoted_string( - char const input[], std::size_t end, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - std::string output; - bool at_backslash{false}; - output.reserve(end - pos); - for (auto next{scan(input, end, pos)}; pos < end; - pos = next, next = scan(input, end, pos)) - { - at_backslash = - ((not at_backslash) and ((next - pos) == 1) and (input[pos] == '\\')); - if (not at_backslash) - output.append(input + pos, next - pos); - } - return output; -} - - -/// Parse a field of a composite-type value. -/** `T` is the C++ type of the field we're parsing, and `index` is its - * zero-based number. - * - * Strip off the leading parenthesis or bracket yourself before parsing. - * However, this function will parse the lcosing parenthesis or bracket. - * - * After a successful parse, `pos` will point at `std::end(text)`. - * - * For the purposes of parsing, ranges and arrays count as compositve values, - * so this function supports parsing those. If you specifically need a closing - * parenthesis, check afterwards that `text` did not end in a bracket instead. - * - * @param index Index of the current field, zero-based. It will increment for - * the next field. - * @param input Full input text for the entire composite-type value. - * @param pos Starting position (in `input`) of the field that we're parsing. - * After parsing, this will point at the beginning of the next field if - * there is one, or one position past the last character otherwise. - * @param field Destination for the parsed value. - * @param scan Glyph scanning function for the relevant encoding type. - * @param last_field Number of the last field in the value (zero-based). When - * parsing the last field, this will equal `index`. - */ -template -inline void parse_composite_field( - std::size_t &index, std::string_view input, std::size_t &pos, T &field, - glyph_scanner_func *scan, std::size_t last_field) -{ - assert(index <= last_field); - auto next{scan(std::data(input), std::size(input), pos)}; - if ((next - pos) != 1) - throw conversion_error{"Non-ASCII character in composite-type syntax."}; - - // Expect a field. - switch (input[pos]) - { - case ',': - case ')': - case ']': - // The field is empty, i.e, null. - if constexpr (nullness::has_null) - field = nullness::null(); - else - throw conversion_error{ - "Can't read composite field " + to_string(index) + ": C++ type " + - type_name + " does not support nulls."}; - break; - - case '"': { - auto const stop{scan_double_quoted_string( - std::data(input), std::size(input), pos, scan)}; - auto const text{ - parse_double_quoted_string(std::data(input), stop, pos, scan)}; - field = from_string(text); - pos = stop; - } - break; - - default: { - auto const stop{scan_unquoted_string<',', ')', ']'>( - std::data(input), std::size(input), pos, scan)}; - auto const text{parse_unquoted_string(std::data(input), stop, pos, scan)}; - field = from_string(text); - pos = stop; - } - break; - } - - // Expect a comma or a closing parenthesis. - next = scan(std::data(input), std::size(input), pos); - - if ((next - pos) != 1) - throw conversion_error{ - "Unexpected non-ASCII character after composite field: " + - std::string{input}}; - - if (index < last_field) - { - if (input[pos] != ',') - throw conversion_error{ - "Found '" + std::string{input[pos]} + - "' in composite value where comma was expected: " + std::data(input)}; - } - else - { - if (input[pos] == ',') - throw conversion_error{ - "Composite value contained more fields than the expected " + - to_string(last_field) + ": " + std::data(input)}; - if (input[pos] != ')' and input[pos] != ']') - throw conversion_error{ - "Composite value has unexpected characters where closing parenthesis " - "was expected: " + - std::string{input}}; - if (next != std::size(input)) - throw conversion_error{ - "Composite value has unexpected text after closing parenthesis: " + - std::string{input}}; - } - - pos = next; - ++index; -} - - -/// Conservatively estimate buffer size needed for a composite field. -template -inline std::size_t size_composite_field_buffer(T const &field) -{ - if constexpr (is_unquoted_safe) - { - // Safe to copy, without quotes or escaping. Drop the terminating zero. - return size_buffer(field) - 1; - } - else - { - // + Opening quote. - // + Field budget. - // - Terminating zero. - // + Escaping for each byte in the field's string representation. - // - Escaping for terminating zero. - // + Closing quote. - return 1 + 2 * (size_buffer(field) - 1) + 1; - } -} - - -template -inline void write_composite_field(char *&pos, char *end, T const &field) -{ - if constexpr (is_unquoted_safe) - { - // No need for quoting or escaping. Convert it straight into its final - // place in the buffer, and "backspace" the trailing zero. - pos = string_traits::into_buf(pos, end, field) - 1; - } - else - { - // The field may need escaping, which means we need an intermediate buffer. - // To avoid allocating that at run time, we use the end of the buffer that - // we have. - auto const budget{size_buffer(field)}; - *pos++ = '"'; - - // Now escape buf into its final position. - for (char const c : string_traits::to_buf(end - budget, end, field)) - { - if ((c == '"') or (c == '\\')) - *pos++ = '\\'; - - *pos++ = c; - } - - *pos++ = '"'; - } - - *pos++ = ','; -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/callgate.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/callgate.hxx deleted file mode 100644 index 42f7703e3..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/callgate.hxx +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef PQXX_H_CALLGATE -#define PQXX_H_CALLGATE - -/* -Here's what a typical gate class definition looks like: - -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE @gateclass@ : callgate<@host@> -{ - friend class @client@; - - @gateclass@(reference x) : super(x) {} - - // Methods here. Use home() to access the host-class object. -}; -} // namespace pqxx::internal::gate -*/ - -namespace pqxx::internal -{ -/// Base class for call gates. -/** - * A call gate defines a limited, private interface on the host class that - * specified client classes can access. - * - * The metaphor works as follows: the gate stands in front of a "home," which - * is really a class, and only lets specific friends in. - * - * To implement a call gate that gives client C access to host H, - * * derive a gate class from callgate; - * * make the gate class a friend of H; - * * make C a friend of the gate class; and - * * implement "stuff C can do with H" as private members in the gate class. - * - * This special kind of "gated" friendship gives C private access to H, but - * only through an expressly limited interface. The gate class can access its - * host object as home(). - * - * Keep gate classes entirely stateless. They should be ultra-lightweight - * wrappers for their host classes, and be optimized away as much as possible - * by the compiler. Once you start adding state, you're on a slippery slope - * away from the pure, clean, limited interface pattern that gate classes are - * meant to implement. - * - * Ideally, all member functions of the gate class should be one-liners passing - * calls straight on to the host class. It can be useful however to break this - * rule temporarily during inter-class refactoring. - */ -template class PQXX_PRIVATE callgate -{ -protected: - /// This class, to keep constructors easy. - using super = callgate; - /// A reference to the host class. Helps keep constructors easy. - using reference = HOME &; - - callgate(reference x) : m_home(x) {} - - /// The home object. The gate class has full "private" access. - reference home() const noexcept { return m_home; } - -private: - reference m_home; -}; -} // namespace pqxx::internal - -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/concat.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/concat.hxx deleted file mode 100644 index cd28bde7c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/concat.hxx +++ /dev/null @@ -1,45 +0,0 @@ -#if !defined(PQXX_CONCAT_HXX) -# define PQXX_CONCAT_HXX - -# include -# include - -# include "pqxx/strconv.hxx" - -namespace pqxx::internal -{ -/// Convert item to a string, write it into [here, end). -template -void render_item(TYPE const &item, char *&here, char *end) -{ - here = string_traits::into_buf(here, end, item) - 1; -} - - -// C++20: Support non-random_access_range ranges. -/// Efficiently combine a bunch of items into one big string. -/** Use this as an optimised version of string concatentation. It takes just - * about any type; it will represent each item as a string according to its - * @ref string_traits. - * - * This is a simpler, more specialised version of @ref separated_list for a - * statically known series of items, possibly of different types. - */ -template -[[nodiscard]] inline std::string concat(TYPE... item) -{ - std::string buf; - // Size to accommodate string representations of all inputs, minus their - // terminating zero bytes. - buf.resize(size_buffer(item...)); - - char *const data{buf.data()}; - char *here = data; - char *end = data + std::size(buf); - (render_item(item, here, end), ...); - - buf.resize(static_cast(here - data)); - return buf; -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/conversions.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/conversions.hxx deleted file mode 100644 index 1df4fdead..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/conversions.hxx +++ /dev/null @@ -1,1188 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#if defined(PQXX_HAVE_SPAN) && __has_include() -# include -#endif - -#include -#include -#include - -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" - - -/* Internal helpers for string conversion, and conversion implementations. - * - * Do not include this header directly. The libpqxx headers do it for you. - */ -namespace pqxx::internal -{ -/// Convert a number in [0, 9] to its ASCII digit. -inline constexpr char number_to_digit(int i) noexcept -{ - return static_cast(i + '0'); -} - - -/// Compute numeric value of given textual digit (assuming that it is a digit). -constexpr int digit_to_number(char c) noexcept -{ - return c - '0'; -} - - -/// Summarize buffer overrun. -/** Don't worry about the exact parameter types: the sizes will be reasonably - * small, and nonnegative. - */ -std::string PQXX_LIBEXPORT -state_buffer_overrun(int have_bytes, int need_bytes); - - -template -inline std::string state_buffer_overrun(HAVE have_bytes, NEED need_bytes) -{ - return state_buffer_overrun( - static_cast(have_bytes), static_cast(need_bytes)); -} - - -/// Throw exception for attempt to convert null to given type. -[[noreturn]] PQXX_LIBEXPORT void -throw_null_conversion(std::string const &type); - - -/// Deliberately nonfunctional conversion traits for `char` types. -/** There are no string conversions for `char` and its signed and unsigned - * variants. Such a conversion would be dangerously ambiguous: should we treat - * it as text, or as a small integer? It'd be an open invitation for bugs. - * - * But the error message when you get this wrong is very cryptic. So, we - * derive dummy @ref string_traits implementations from this dummy type, and - * ensure that the compiler disallows their use. The compiler error message - * will at least contain a hint of the root of the problem. - */ -template struct disallowed_ambiguous_char_conversion -{ - static char *into_buf(char *, char *, CHAR_TYPE) = delete; - static constexpr zview - to_buf(char *, char *, CHAR_TYPE const &) noexcept = delete; - - static constexpr std::size_t - size_buffer(CHAR_TYPE const &) noexcept = delete; - static CHAR_TYPE from_string(std::string_view) = delete; -}; - - -template PQXX_LIBEXPORT extern std::string to_string_float(T); - - -/// Generic implementation for into_buf, on top of to_buf. -template -inline char *generic_into_buf(char *begin, char *end, T const &value) -{ - zview const text{string_traits::to_buf(begin, end, value)}; - auto const space{end - begin}; - // Include the trailing zero. - auto const len = std::size(text) + 1; - if (internal::cmp_greater(len, space)) - throw conversion_overrun{ - "Not enough buffer space to insert " + type_name + ". " + - state_buffer_overrun(space, len)}; - std::memmove(begin, text.data(), len); - return begin + len; -} - - -/// String traits for builtin integral types (though not bool). -template struct integral_traits -{ - static PQXX_LIBEXPORT T from_string(std::string_view text); - static PQXX_LIBEXPORT zview to_buf(char *begin, char *end, T const &value); - static PQXX_LIBEXPORT char *into_buf(char *begin, char *end, T const &value); - - static constexpr std::size_t size_buffer(T const &) noexcept - { - /** Includes a sign if needed; the number of base-10 digits which the type - * can reliably represent; the one extra base-10 digit which the type can - * only partially represent; and the terminating zero. - */ - return std::is_signed_v + std::numeric_limits::digits10 + 1 + 1; - } -}; - - -/// String traits for builtin floating-point types. -template struct float_traits -{ - static PQXX_LIBEXPORT T from_string(std::string_view text); - static PQXX_LIBEXPORT zview to_buf(char *begin, char *end, T const &value); - static PQXX_LIBEXPORT char *into_buf(char *begin, char *end, T const &value); - - // Return a nonnegative integral value's number of decimal digits. - static constexpr std::size_t digits10(std::size_t value) noexcept - { - if (value < 10) - return 1; - else - return 1 + digits10(value / 10); - } - - static constexpr std::size_t size_buffer(T const &) noexcept - { - using lims = std::numeric_limits; - // See #328 for a detailed discussion on the maximum number of digits. - // - // In a nutshell: for the big cases, the scientific notation is always - // the shortest one, and therefore the one that to_chars will pick. - // - // So... How long can the scientific notation get? 1 (for sign) + 1 (for - // decimal point) + 1 (for 'e') + 1 (for exponent sign) + max_digits10 + - // max number of digits in the exponent + 1 (terminating zero). - // - // What's the max number of digits in the exponent? It's the max number of - // digits out of the most negative exponent and the most positive one. - // - // The longest positive exponent is easy: 1 + ceil(log10(max_exponent10)). - // (The extra 1 is because 10^n takes up 1 + n digits, not n.) - // - // The longest negative exponent is a bit harder: min_exponent10 gives us - // the smallest power of 10 which a normalised version of T can represent. - // But the smallest denormalised power of 10 that T can represent is - // another max_digits10 powers of 10 below that. - // needs a minus sign. - // - // All this stuff messes with my head a bit because it's on the order of - // log10(log10(n)). It's easy to get the number of logs wrong. - auto const max_pos_exp{digits10(lims::max_exponent10)}; - // Really want std::abs(lims::min_exponent10), but MSVC 2017 apparently has - // problems with std::abs. So we use -lims::min_exponent10 instead. - auto const max_neg_exp{ - digits10(lims::max_digits10 - lims::min_exponent10)}; - return 1 + // Sign. - 1 + // Decimal point. - std::numeric_limits::max_digits10 + // Mantissa digits. - 1 + // Exponent "e". - 1 + // Exponent sign. - // Spell this weirdly to stop Windows compilers from reading this as - // a call to their "max" macro when NOMINMAX is not defined. - (std::max)(max_pos_exp, max_neg_exp) + // Exponent digits. - 1; // Terminating zero. - } -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// The built-in arithmetic types do not have inherent null values. -template -struct nullness>> : no_null -{}; - - -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits - : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits - : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; - - -template<> struct string_traits -{ - static PQXX_LIBEXPORT bool from_string(std::string_view text); - - static constexpr zview to_buf(char *, char *, bool const &value) noexcept - { - return value ? "true"_zv : "false"_zv; - } - - static char *into_buf(char *begin, char *end, bool const &value) - { - return pqxx::internal::generic_into_buf(begin, end, value); - } - - static constexpr std::size_t size_buffer(bool const &) noexcept { return 6; } -}; - - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - - -template<> inline constexpr bool is_unquoted_safe{true}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - /// Technically, you could have an optional of an always-null type. - static constexpr bool always_null = nullness::always_null; - static constexpr bool is_null(std::optional const &v) noexcept - { - return ((not v.has_value()) or pqxx::is_null(*v)); - } - static constexpr std::optional null() { return {}; } -}; - - -template -inline constexpr format param_format(std::optional const &value) -{ - return param_format(*value); -} - - -template struct string_traits> -{ - static char *into_buf(char *begin, char *end, std::optional const &value) - { - return string_traits::into_buf(begin, end, *value); - } - - static zview to_buf(char *begin, char *end, std::optional const &value) - { - if (value.has_value()) - return string_traits::to_buf(begin, end, *value); - else - return {}; - } - - static std::optional from_string(std::string_view text) - { - return std::optional{ - std::in_place, string_traits::from_string(text)}; - } - - static std::size_t size_buffer(std::optional const &value) noexcept - { - return pqxx::size_buffer(value.value()); - } -}; - - -template -inline constexpr bool is_unquoted_safe>{is_unquoted_safe}; - - -template struct nullness> -{ - static constexpr bool has_null = (nullness::has_null or ...); - static constexpr bool always_null = (nullness::always_null and ...); - static constexpr bool is_null(std::variant const &value) noexcept - { - return std::visit( - [](auto const &i) noexcept { - return nullness>::is_null(i); - }, - value); - } - - // We don't support `null()` for `std::variant`. - /** It would be technically possible to have a `null` in the case where just - * one of the types has a null, but it gets complicated and arbitrary. - */ - static constexpr std::variant null() = delete; -}; - - -template struct string_traits> -{ - static char * - into_buf(char *begin, char *end, std::variant const &value) - { - return std::visit( - [begin, end](auto const &i) { - return string_traits>::into_buf(begin, end, i); - }, - value); - } - static zview to_buf(char *begin, char *end, std::variant const &value) - { - return std::visit( - [begin, end](auto const &i) { - return string_traits>::to_buf(begin, end, i); - }, - value); - } - static std::size_t size_buffer(std::variant const &value) noexcept - { - return std::visit( - [](auto const &i) noexcept { return pqxx::size_buffer(i); }, value); - } - - /** There's no from_string for std::variant. We could have one with a rule - * like "pick the first type which fits the value," but we'd have to look - * into how natural that API feels to users. - */ - static std::variant from_string(std::string_view) = delete; -}; - - -template -inline constexpr format param_format(std::variant const &value) -{ - return std::visit([](auto &v) { return param_format(v); }, value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - (is_unquoted_safe and ...)}; - - -template inline T from_string(std::stringstream const &text) -{ - return from_string(text.str()); -} - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::nullptr_t) = delete; - - static constexpr zview - to_buf(char *, char *, std::nullptr_t const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::nullptr_t = nullptr) noexcept - { - return 0; - } - static std::nullptr_t from_string(std::string_view) = delete; -}; - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::nullopt_t) = delete; - - static constexpr zview - to_buf(char *, char *, std::nullopt_t const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::nullopt_t) noexcept - { - return 0; - } - static std::nullopt_t from_string(std::string_view) = delete; -}; - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::monostate) = delete; - - static constexpr zview - to_buf(char *, char *, std::monostate const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::monostate) noexcept - { - return 0; - } - static std::monostate from_string(std::string_view) = delete; -}; - - -template<> inline constexpr bool is_unquoted_safe{true}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(char const *t) noexcept - { - return t == nullptr; - } - static constexpr char const *null() noexcept { return nullptr; } -}; - - -/// String traits for C-style string ("pointer to char const"). -template<> struct string_traits -{ - static char const *from_string(std::string_view text) { return text.data(); } - - static zview to_buf(char *begin, char *end, char const *const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, char const *const &value) - { - auto const space{end - begin}; - // Count the trailing zero, even though std::strlen() and friends don't. - auto const len{std::strlen(value) + 1}; - if (space < ptrdiff_t(len)) - throw conversion_overrun{ - "Could not copy string: buffer too small. " + - pqxx::internal::state_buffer_overrun(space, len)}; - std::memmove(begin, value, len); - return begin + len; - } - - static std::size_t size_buffer(char const *const &value) noexcept - { - return std::strlen(value) + 1; - } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(char const *t) noexcept - { - return t == nullptr; - } - static constexpr char const *null() { return nullptr; } -}; - - -/// String traits for non-const C-style string ("pointer to char"). -template<> struct string_traits -{ - static char *into_buf(char *begin, char *end, char *const &value) - { - return string_traits::into_buf(begin, end, value); - } - static zview to_buf(char *begin, char *end, char *const &value) - { - return string_traits::to_buf(begin, end, value); - } - static std::size_t size_buffer(char *const &value) noexcept - { - return string_traits::size_buffer(value); - } - - /// Don't allow conversion to this type since it breaks const-safety. - static char *from_string(std::string_view) = delete; -}; - - -template struct nullness : no_null -{}; - - -/// String traits for C-style string constant ("array of char"). -/** @warning This assumes that every array-of-char is a C-style string literal. - * So, it must include a trailing zero. and it must have static duration. - */ -template struct string_traits -{ - static constexpr zview - to_buf(char *, char *, char const (&value)[N]) noexcept - { - return zview{value, N - 1}; - } - - static char *into_buf(char *begin, char *end, char const (&value)[N]) - { - if (internal::cmp_less(end - begin, size_buffer(value))) - throw conversion_overrun{ - "Could not convert char[] to string: too long for buffer."}; - std::memcpy(begin, value, N); - return begin + N; - } - static constexpr std::size_t size_buffer(char const (&)[N]) noexcept - { - return N; - } - - /// Don't allow conversion to this type. - static void from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -template<> struct string_traits -{ - static std::string from_string(std::string_view text) - { - return std::string{text}; - } - - static char *into_buf(char *begin, char *end, std::string const &value) - { - if (internal::cmp_greater_equal(std::size(value), end - begin)) - throw conversion_overrun{ - "Could not convert string to string: too long for buffer."}; - // Include the trailing zero. - value.copy(begin, std::size(value)); - begin[std::size(value)] = '\0'; - return begin + std::size(value) + 1; - } - - static zview to_buf(char *begin, char *end, std::string const &value) - { - return generic_to_buf(begin, end, value); - } - - static std::size_t size_buffer(std::string const &value) noexcept - { - return std::size(value) + 1; - } -}; - - -/// There's no real null for `std::string_view`. -/** I'm not sure how clear-cut this is: a `string_view` may have a null - * data pointer, which is analogous to a null `char` pointer. - */ -template<> struct nullness : no_null -{}; - - -/// String traits for `string_view`. -template<> struct string_traits -{ - static constexpr std::size_t - size_buffer(std::string_view const &value) noexcept - { - return std::size(value) + 1; - } - - static char *into_buf(char *begin, char *end, std::string_view const &value) - { - if (internal::cmp_greater_equal(std::size(value), end - begin)) - throw conversion_overrun{ - "Could not store string_view: too long for buffer."}; - value.copy(begin, std::size(value)); - begin[std::size(value)] = '\0'; - return begin + std::size(value) + 1; - } - - /// Don't convert to this type; it has nowhere to store its contents. - static std::string_view from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -/// String traits for `zview`. -template<> struct string_traits -{ - static constexpr std::size_t - size_buffer(std::string_view const &value) noexcept - { - return std::size(value) + 1; - } - - static char *into_buf(char *begin, char *end, zview const &value) - { - auto const size{std::size(value)}; - if (internal::cmp_less_equal(end - begin, std::size(value))) - throw conversion_overrun{"Not enough buffer space to store this zview."}; - value.copy(begin, size); - begin[size] = '\0'; - return begin + size + 1; - } - - static std::string_view to_buf(char *begin, char *end, zview const &value) - { - return {into_buf(begin, end, value), std::size(value)}; - } - - /// Don't convert to this type; it has nowhere to store its contents. - static zview from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -template<> struct string_traits -{ - static std::size_t size_buffer(std::stringstream const &) = delete; - - static std::stringstream from_string(std::string_view text) - { - std::stringstream stream; - stream.write(text.data(), std::streamsize(std::size(text))); - return stream; - } - - static char *into_buf(char *, char *, std::stringstream const &) = delete; - static std::string_view - to_buf(char *, char *, std::stringstream const &) = delete; -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::nullptr_t const &) noexcept - { - return true; - } - static constexpr std::nullptr_t null() noexcept { return nullptr; } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::nullopt_t const &) noexcept - { - return true; - } - static constexpr std::nullopt_t null() noexcept { return std::nullopt; } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::monostate const &) noexcept - { - return true; - } - static constexpr std::monostate null() noexcept { return {}; } -}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(std::unique_ptr const &t) noexcept - { - return not t or pqxx::is_null(*t); - } - static constexpr std::unique_ptr null() { return {}; } -}; - - -template -struct string_traits> -{ - static std::unique_ptr from_string(std::string_view text) - { - return std::make_unique(string_traits::from_string(text)); - } - - static char * - into_buf(char *begin, char *end, std::unique_ptr const &value) - { - return string_traits::into_buf(begin, end, *value); - } - - static zview - to_buf(char *begin, char *end, std::unique_ptr const &value) - { - if (value) - return string_traits::to_buf(begin, end, *value); - else - return {}; - } - - static std::size_t - size_buffer(std::unique_ptr const &value) noexcept - { - return pqxx::size_buffer(*value.get()); - } -}; - - -template -inline format param_format(std::unique_ptr const &value) -{ - return param_format(*value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - is_unquoted_safe}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(std::shared_ptr const &t) noexcept - { - return not t or pqxx::is_null(*t); - } - static constexpr std::shared_ptr null() { return {}; } -}; - - -template struct string_traits> -{ - static std::shared_ptr from_string(std::string_view text) - { - return std::make_shared(string_traits::from_string(text)); - } - - static zview to_buf(char *begin, char *end, std::shared_ptr const &value) - { - return string_traits::to_buf(begin, end, *value); - } - static char * - into_buf(char *begin, char *end, std::shared_ptr const &value) - { - return string_traits::into_buf(begin, end, *value); - } - static std::size_t size_buffer(std::shared_ptr const &value) noexcept - { - return pqxx::size_buffer(*value); - } -}; - - -template format param_format(std::shared_ptr const &value) -{ - return param_format(*value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - is_unquoted_safe}; - - -template<> -struct nullness> - : no_null> -{}; - - -#if defined(PQXX_HAVE_CONCEPTS) -template struct nullness : no_null -{}; - - -template inline constexpr format param_format(DATA const &) -{ - return format::binary; -} - - -template struct string_traits -{ - static std::size_t size_buffer(DATA const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf(char *begin, char *end, DATA const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, DATA const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - static DATA from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::basic_string buf; - buf.resize(size); - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.data())); - return buf; - } -}; -#endif // PQXX_HAVE_CONCEPTS - - -template<> struct string_traits> -{ - static std::size_t - size_buffer(std::basic_string const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview - to_buf(char *begin, char *end, std::basic_string const &value) - { - return generic_to_buf(begin, end, value); - } - - static char * - into_buf(char *begin, char *end, std::basic_string const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - static std::basic_string from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::basic_string buf; - buf.resize(size); - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.data())); - return buf; - } -}; - - -template<> -inline constexpr format param_format(std::basic_string const &) -{ - return format::binary; -} - - -template<> -struct nullness> - : no_null> -{}; - - -template<> struct string_traits> -{ - static std::size_t - size_buffer(std::basic_string_view const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf( - char *begin, char *end, std::basic_string_view const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf( - char *begin, char *end, std::basic_string_view const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - // There's no from_string, because there's nobody to hold the data. -}; - -template<> -inline constexpr format param_format(std::basic_string_view const &) -{ - return format::binary; -} -} // namespace pqxx - - -namespace pqxx::internal -{ -/// String traits for SQL arrays. -template struct array_string_traits -{ -private: - using elt_type = strip_t>; - using elt_traits = string_traits; - static constexpr zview s_null{"NULL"}; - -public: - static zview to_buf(char *begin, char *end, Container const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, Container const &value) - { - std::size_t const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to convert array to string."}; - - char *here = begin; - *here++ = '{'; - - bool nonempty{false}; - for (auto const &elt : value) - { - if (is_null(elt)) - { - s_null.copy(here, std::size(s_null)); - here += std::size(s_null); - } - else if constexpr (is_sql_array) - { - // Render nested array in-place. Then erase the trailing zero. - here = elt_traits::into_buf(here, end, elt) - 1; - } - else if constexpr (is_unquoted_safe) - { - // No need to quote or escape. Just convert the value straight into - // its place in the array, and "backspace" the trailing zero. - here = elt_traits::into_buf(here, end, elt) - 1; - } - else - { - *here++ = '"'; - - // Use the tail end of the destination buffer as an intermediate - // buffer. - auto const elt_budget{pqxx::size_buffer(elt)}; - for (char const c : elt_traits::to_buf(end - elt_budget, end, elt)) - { - if (c == '\\' or c == '"') - *here++ = '\\'; - *here++ = c; - } - *here++ = '"'; - } - *here++ = array_separator; - nonempty = true; - } - - // Erase that last comma, if present. - if (nonempty) - here--; - - *here++ = '}'; - *here++ = '\0'; - - return here; - } - - static std::size_t size_buffer(Container const &value) noexcept - { - if constexpr (is_unquoted_safe) - return 3 + std::accumulate( - std::begin(value), std::end(value), std::size_t{}, - [](std::size_t acc, elt_type const &elt) { - return acc + - (pqxx::is_null(elt) ? - std::size(s_null) : - elt_traits::size_buffer(elt)) - - 1; - }); - else - return 3 + std::accumulate( - std::begin(value), std::end(value), std::size_t{}, - [](std::size_t acc, elt_type const &elt) { - // Opening and closing quotes, plus worst-case escaping, - // but don't count the trailing zeroes. - std::size_t const elt_size{ - pqxx::is_null(elt) ? std::size(s_null) : - elt_traits::size_buffer(elt) - 1}; - return acc + 2 * elt_size + 2; - }); - } - - // We don't yet support parsing of array types using from_string. Doing so - // would require a reference to the connection. -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -template -struct nullness> : no_null> -{}; - - -template -struct string_traits> - : internal::array_string_traits> -{}; - - -/// We don't know how to pass array params in binary format, so pass as text. -template -inline constexpr format param_format(std::vector const &) -{ - return format::text; -} - - -/// A `std::vector` is a binary string. Other vectors are not. -template -inline constexpr format param_format(std::vector const &) -{ - return format::binary; -} - - -template inline constexpr bool is_sql_array>{true}; - - -template -struct nullness> : no_null> -{}; - - -template -struct string_traits> - : internal::array_string_traits> -{}; - - -/// We don't know how to pass array params in binary format, so pass as text. -template -inline constexpr format param_format(std::array const &) -{ - return format::text; -} - - -/// An array of `std::byte` is a binary string. -template -inline constexpr format param_format(std::array const &) -{ - return format::binary; -} - - -template -inline constexpr bool is_sql_array>{true}; -} // namespace pqxx - - -namespace pqxx -{ -template inline std::string to_string(T const &value) -{ - if (is_null(value)) - throw conversion_error{ - "Attempt to convert null " + type_name + " to a string."}; - - std::string buf; - // We can't just reserve() space; modifying the terminating zero leads to - // undefined behaviour. - buf.resize(size_buffer(value)); - auto const data{buf.data()}; - auto const end{ - string_traits::into_buf(data, data + std::size(buf), value)}; - buf.resize(static_cast(end - data - 1)); - return buf; -} - - -template<> inline std::string to_string(float const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(double const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(long double const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(std::stringstream const &value) -{ - return value.str(); -} - - -template inline void into_string(T const &value, std::string &out) -{ - if (is_null(value)) - throw conversion_error{ - "Attempt to convert null " + type_name + " to a string."}; - - // We can't just reserve() data; modifying the terminating zero leads to - // undefined behaviour. - out.resize(size_buffer(value) + 1); - auto const data{out.data()}; - auto const end{ - string_traits::into_buf(data, data + std::size(out), value)}; - out.resize(static_cast(end - data - 1)); -} -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/encoding_group.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/encoding_group.hxx deleted file mode 100644 index e17736e5b..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/encoding_group.hxx +++ /dev/null @@ -1,60 +0,0 @@ -/** Enum type for supporting encodings in libpqxx - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ENCODING_GROUP -#define PQXX_H_ENCODING_GROUP - -#include - -namespace pqxx::internal -{ -// Types of encodings supported by PostgreSQL, see -// https://www.postgresql.org/docs/current/static/multibyte.html#CHARSET-TABLE -enum class encoding_group -{ - // Handles all single-byte fixed-width encodings - MONOBYTE, - - // Multibyte encodings. - // Many of these can embed ASCII-like bytes inside multibyte characters, - // notably Big5, SJIS, SHIFT_JIS_2004, GP18030, GBK, JOHAB, UHC. - BIG5, - EUC_CN, - // TODO: Merge EUC_JP and EUC_JIS_2004? - EUC_JP, - EUC_JIS_2004, - EUC_KR, - EUC_TW, - GB18030, - GBK, - JOHAB, - MULE_INTERNAL, - // TODO: Merge SJIS and SHIFT_JIS_2004? - SJIS, - SHIFT_JIS_2004, - UHC, - UTF8, -}; - - -// TODO:: Can we just use string_view now? -/// Function type: "find the end of the current glyph." -/** This type of function takes a text buffer, and a location in that buffer, - * and returns the location one byte past the end of the current glyph. - * - * The start offset marks the beginning of the current glyph. It must fall - * within the buffer. - * - * There are multiple different glyph scanner implementations, for different - * kinds of encodings. - */ -using glyph_scanner_func = - std::size_t(char const buffer[], std::size_t buffer_len, std::size_t start); -} // namespace pqxx::internal - -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/encodings.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/encodings.hxx deleted file mode 100644 index ba7fecc70..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/encodings.hxx +++ /dev/null @@ -1,90 +0,0 @@ -/** Internal string encodings support for libpqxx - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ENCODINGS -#define PQXX_H_ENCODINGS - -#include "pqxx/internal/encoding_group.hxx" - -#include -#include - - -namespace pqxx::internal -{ -char const *name_encoding(int encoding_id); - -/// Convert libpq encoding enum or encoding name to its libpqxx group. -encoding_group enc_group(int /* libpq encoding ID */); -encoding_group enc_group(std::string_view); - - -/// Look up the glyph scanner function for a given encoding group. -/** To identify the glyph boundaries in a buffer, call this to obtain the - * scanner function appropriate for the buffer's encoding. Then, repeatedly - * call the scanner function to find the glyphs. - */ -PQXX_LIBEXPORT glyph_scanner_func *get_glyph_scanner(encoding_group); - - -// TODO: For ASCII search, treat UTF8/EUC_*/MULE_INTERNAL as MONOBYTE. - -/// Find any of the ASCII characters `NEEDLE` in `haystack`. -/** Scans through `haystack` until it finds a single-byte character that - * matches any value in `NEEDLE`. - * - * If it finds one, returns its offset. If not, returns the end of the - * haystack. - */ -template -inline std::size_t find_char( - glyph_scanner_func *scanner, std::string_view haystack, - std::size_t here = 0u) -{ - auto const sz{std::size(haystack)}; - auto const data{std::data(haystack)}; - while (here < sz) - { - auto next{scanner(data, sz, here)}; - // (For some reason gcc had a problem with a right-fold here. But clang - // was fine.) - if ((... or (data[here] == NEEDLE))) - { - // Also check against a multibyte character starting with a bytes which - // just happens to match one of the ASCII bytes we're looking for. It'd - // be cleaner to check that first, but either works. So, let's apply the - // most selective filter first and skip this check in almost all cases. - if (next == here + 1) - return here; - } - - // Nope, no hit. Move on. - here = next; - } - return sz; -} - - -/// Iterate over the glyphs in a buffer. -/** Scans the glyphs in the buffer, and for each, passes its begin and its - * one-past-end pointers to `callback`. - */ -template -inline void for_glyphs( - encoding_group enc, CALLABLE callback, char const buffer[], - std::size_t buffer_len, std::size_t start = 0) -{ - auto const scan{get_glyph_scanner(enc)}; - for (std::size_t here = start, next; here < buffer_len; here = next) - { - next = scan(buffer, buffer_len, here); - callback(buffer + here, buffer + next); - } -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-errorhandler.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-errorhandler.hxx deleted file mode 100644 index ffc12a6cf..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-errorhandler.hxx +++ /dev/null @@ -1,26 +0,0 @@ -#include - -namespace pqxx -{ -class connection; -class errorhandler; -} // namespace pqxx - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_errorhandler : callgate -{ - friend class pqxx::errorhandler; - - connection_errorhandler(reference x) : super(x) {} - - void register_errorhandler(errorhandler *h) - { - home().register_errorhandler(h); - } - void unregister_errorhandler(errorhandler *h) - { - home().unregister_errorhandler(h); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-largeobject.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-largeobject.hxx deleted file mode 100644 index 49feaf9e6..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-largeobject.hxx +++ /dev/null @@ -1,35 +0,0 @@ -#include - -#include -#include - -namespace pqxx -{ -class blob; -class largeobject; -} // namespace pqxx - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_largeobject : callgate -{ - friend class pqxx::blob; - friend class pqxx::largeobject; - - connection_largeobject(reference x) : super(x) {} - - pq::PGconn *raw_connection() const { return home().raw_connection(); } -}; - - -class PQXX_PRIVATE const_connection_largeobject : callgate -{ - friend class pqxx::blob; - friend class pqxx::largeobject; - - const_connection_largeobject(reference x) : super(x) {} - - std::string error_message() const { return home().err_msg(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-notification_receiver.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-notification_receiver.hxx deleted file mode 100644 index 0bcb2db17..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-notification_receiver.hxx +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#include "pqxx/connection.hxx" - - -namespace pqxx -{ -class notification_receiver; -} - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_notification_receiver : callgate -{ - friend class pqxx::notification_receiver; - - connection_notification_receiver(reference x) : super(x) {} - - void add_receiver(notification_receiver *receiver) - { - home().add_receiver(receiver); - } - void remove_receiver(notification_receiver *receiver) noexcept - { - home().remove_receiver(receiver); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-pipeline.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-pipeline.hxx deleted file mode 100644 index c6ae6e17a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-pipeline.hxx +++ /dev/null @@ -1,23 +0,0 @@ -#include "pqxx/internal/libpq-forward.hxx" -#include - -#include "pqxx/pipeline.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_pipeline : callgate -{ - friend class pqxx::pipeline; - - connection_pipeline(reference x) : super(x) {} - - void start_exec(char const query[]) { home().start_exec(query); } - pqxx::internal::pq::PGresult *get_result() { return home().get_result(); } - void cancel_query() { home().cancel_query(); } - - bool consume_input() noexcept { return home().consume_input(); } - bool is_busy() const noexcept { return home().is_busy(); } - - int encoding_id() { return home().encoding_id(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-sql_cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-sql_cursor.hxx deleted file mode 100644 index 51a889844..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-sql_cursor.hxx +++ /dev/null @@ -1,19 +0,0 @@ -#include - -namespace pqxx::internal -{ -class sql_cursor; -} - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - - connection_sql_cursor(reference x) : super(x) {} - - result exec(char const query[]) { return home().exec(query); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-stream_from.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-stream_from.hxx deleted file mode 100644 index 8961e7146..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-stream_from.hxx +++ /dev/null @@ -1,15 +0,0 @@ -#include - -#include "pqxx/connection.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_stream_from : callgate -{ - friend class pqxx::stream_from; - - connection_stream_from(reference x) : super{x} {} - - auto read_copy_line() { return home().read_copy_line(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-stream_to.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-stream_to.hxx deleted file mode 100644 index a6974fb21..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-stream_to.hxx +++ /dev/null @@ -1,17 +0,0 @@ -#include - -#include "pqxx/stream_to.hxx" - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_stream_to : callgate -{ - friend class pqxx::stream_to; - - connection_stream_to(reference x) : super(x) {} - - void write_copy_line(std::string_view line) { home().write_copy_line(line); } - void end_copy_write() { home().end_copy_write(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-transaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-transaction.hxx deleted file mode 100644 index 74d659253..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/connection-transaction.hxx +++ /dev/null @@ -1,44 +0,0 @@ -#include - -namespace pqxx -{ -class connection; -} - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_transaction : callgate -{ - friend class pqxx::transaction_base; - - connection_transaction(reference x) : super(x) {} - - template result exec(STRING query, std::string_view desc) - { - return home().exec(query, desc); - } - - void register_transaction(transaction_base *t) - { - home().register_transaction(t); - } - void unregister_transaction(transaction_base *t) noexcept - { - home().unregister_transaction(t); - } - - auto read_copy_line() { return home().read_copy_line(); } - void write_copy_line(std::string_view line) { home().write_copy_line(line); } - void end_copy_write() { home().end_copy_write(); } - - result exec_prepared(zview statement, internal::c_params const &args) - { - return home().exec_prepared(statement, args); - } - - result exec_params(zview query, internal::c_params const &args) - { - return home().exec_params(query, args); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/errorhandler-connection.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/errorhandler-connection.hxx deleted file mode 100644 index 5560cedec..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/errorhandler-connection.hxx +++ /dev/null @@ -1,13 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE errorhandler_connection : callgate -{ - friend class pqxx::connection; - - errorhandler_connection(reference x) : super(x) {} - - void unregister() noexcept { home().unregister(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx deleted file mode 100644 index 296d22145..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx +++ /dev/null @@ -1,24 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE icursor_iterator_icursorstream : callgate -{ - friend class pqxx::icursorstream; - - icursor_iterator_icursorstream(reference x) : super(x) {} - - icursor_iterator::difference_type pos() const noexcept - { - return home().pos(); - } - - icursor_iterator *get_prev() { return home().m_prev; } - void set_prev(icursor_iterator *i) { home().m_prev = i; } - - icursor_iterator *get_next() { return home().m_next; } - void set_next(icursor_iterator *i) { home().m_next = i; } - - void fill(result const &r) { home().fill(r); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx deleted file mode 100644 index 56056d5ef..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx +++ /dev/null @@ -1,32 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE icursorstream_icursor_iterator : callgate -{ - friend class pqxx::icursor_iterator; - - icursorstream_icursor_iterator(reference x) : super(x) {} - - void insert_iterator(icursor_iterator *i) noexcept - { - home().insert_iterator(i); - } - - void remove_iterator(icursor_iterator *i) const noexcept - { - home().remove_iterator(i); - } - - icursorstream::size_type forward() { return home().forward(); } - icursorstream::size_type forward(icursorstream::size_type n) - { - return home().forward(n); - } - - void service_iterators(icursorstream::difference_type p) - { - home().service_iterators(p); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-connection.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-connection.hxx deleted file mode 100644 index daa0808c0..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-connection.hxx +++ /dev/null @@ -1,14 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_connection : callgate -{ - friend class pqxx::connection; - - result_connection(reference x) : super(x) {} - - operator bool() const { return bool(home()); } - bool operator!() const { return not home(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-creation.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-creation.hxx deleted file mode 100644 index 3d9205f2c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-creation.hxx +++ /dev/null @@ -1,24 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_creation : callgate -{ - friend class pqxx::connection; - friend class pqxx::pipeline; - - result_creation(reference x) : super(x) {} - - static result create( - internal::pq::PGresult *rhs, std::shared_ptr const &query, - encoding_group enc) - { - return result(rhs, query, enc); - } - - void check_status(std::string_view desc = ""sv) const - { - return home().check_status(desc); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-pipeline.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-pipeline.hxx deleted file mode 100644 index 3ebe436d2..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-pipeline.hxx +++ /dev/null @@ -1,16 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_pipeline : callgate -{ - friend class pqxx::pipeline; - - result_pipeline(reference x) : super(x) {} - - std::shared_ptr query_ptr() const - { - return home().query_ptr(); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-sql_cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-sql_cursor.hxx deleted file mode 100644 index 78b450739..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/result-sql_cursor.hxx +++ /dev/null @@ -1,13 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - - result_sql_cursor(reference x) : super(x) {} - - char const *cmd_status() const noexcept { return home().cmd_status(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/transaction-sql_cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/transaction-sql_cursor.hxx deleted file mode 100644 index 4ed78dc93..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/transaction-sql_cursor.hxx +++ /dev/null @@ -1,10 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE transaction_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - transaction_sql_cursor(reference x) : super(x) {} -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/transaction-transaction_focus.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/transaction-transaction_focus.hxx deleted file mode 100644 index ca7939a99..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/gates/transaction-transaction_focus.hxx +++ /dev/null @@ -1,30 +0,0 @@ -#include - -#include "pqxx/transaction_base.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE transaction_transaction_focus : callgate -{ - friend class pqxx::transaction_focus; - - transaction_transaction_focus(reference x) : super(x) {} - - void register_focus(transaction_focus *focus) - { - home().register_focus(focus); - } - void unregister_focus(transaction_focus *focus) noexcept - { - home().unregister_focus(focus); - } - void register_pending_error(zview error) - { - home().register_pending_error(error); - } - void register_pending_error(std::string &&error) - { - home().register_pending_error(std::move(error)); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/header-post.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/header-post.hxx deleted file mode 100644 index ff6bf8986..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/header-post.hxx +++ /dev/null @@ -1,22 +0,0 @@ -/* Compiler deficiency workarounds for compiling libpqxx headers. - * - * To be included at the end of each libpqxx header, in order to restore the - * client program's settings. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -// NO GUARDS HERE! This code should be executed every time! - -#if defined(_MSC_VER) -# pragma warning(pop) // Restore compiler's warning state -#endif - -#if !defined(PQXX_HEADER_PRE) -# error "Include pqxx/internal/header-post.hxx AFTER its 'pre' counterpart." -#endif - -#undef PQXX_HEADER_PRE diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/header-pre.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/header-pre.hxx deleted file mode 100644 index abc1a398d..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/header-pre.hxx +++ /dev/null @@ -1,169 +0,0 @@ -/* Compiler settings for compiling libpqxx headers, and workarounds for all. - * - * Include this before including any other libpqxx headers from within libpqxx. - * And to balance it out, also include header-post.hxx at the end of the batch - * of headers. - * - * The public libpqxx headers (e.g. ``) include this already; - * there's no need to do this from within an application. - * - * Include this file at the highest aggregation level possible to avoid nesting - * and to keep things simple. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ - -// NO GUARD HERE! This part should be included every time this file is. -#if defined(_MSC_VER) - -// Save compiler's warning state, and set warning level 4 for maximum -// sensitivity to warnings. -# pragma warning(push, 4) - -// Visual C++ generates some entirely unreasonable warnings. Disable them. -// Copy constructor could not be generated. -# pragma warning(disable : 4511) -// Assignment operator could not be generated. -# pragma warning(disable : 4512) -// Can't expose outside classes without exporting them. Except the MSVC docs -// say please ignore the warning if it's a standard library class. -# pragma warning(disable : 4251) -// Can't derive library classes from outside classes without exporting them. -// Except the MSVC docs say please ignore the warning if the parent class is -// in the standard library. -# pragma warning(disable : 4275) -// Can't inherit from non-exported class. -# pragma warning(disable : 4275) - -#endif // _MSC_VER - - -#if defined(PQXX_HEADER_PRE) -# error "Avoid nesting #include of pqxx/internal/header-pre.hxx." -#endif - -#define PQXX_HEADER_PRE - - -// Workarounds & definitions that need to be included even in library's headers -#include "pqxx/config-public-compiler.h" - -// Enable ISO-646 alternative operaotr representations: "and" instead of "&&" -// etc. on older compilers. C++20 removes this header. -#if __has_include() -# include -#endif - - -#if defined(PQXX_HAVE_GCC_PURE) -/// Declare function "pure": no side effects, only reads globals and its args. -# define PQXX_PURE __attribute__((pure)) -#else -# define PQXX_PURE /* pure */ -#endif - - -#if defined(__GNUC__) -/// Tell the compiler to optimise a function for size, not speed. -# define PQXX_COLD __attribute__((cold)) -#else -# define PQXX_COLD /* cold */ -#endif - - -// Workarounds for Windows -#ifdef _WIN32 - -/* For now, export DLL symbols if _DLL is defined. This is done automatically - * by the compiler when linking to the dynamic version of the runtime library, - * according to "gzh" - */ -# if defined(PQXX_SHARED) && !defined(PQXX_LIBEXPORT) -# define PQXX_LIBEXPORT __declspec(dllimport) -# endif // PQXX_SHARED && !PQXX_LIBEXPORT - - -// Workarounds for Microsoft Visual C++ -# ifdef _MSC_VER - -// Suppress vtables on abstract classes. -# define PQXX_NOVTABLE __declspec(novtable) - -// Automatically link with the appropriate libpq (static or dynamic, debug or -// release). The default is to use the release DLL. Define PQXX_PQ_STATIC to -// link to a static version of libpq, and _DEBUG to link to a debug version. -// The two may be combined. -# if defined(PQXX_AUTOLINK) -# if defined(PQXX_PQ_STATIC) -# ifdef _DEBUG -# pragma comment(lib, "libpqd") -# else -# pragma comment(lib, "libpq") -# endif -# else -# ifdef _DEBUG -# pragma comment(lib, "libpqddll") -# else -# pragma comment(lib, "libpqdll") -# endif -# endif -# endif - -// If we're not compiling libpqxx itself, automatically link with the -// appropriate libpqxx library. To link with the libpqxx DLL, define -// PQXX_SHARED; the default is to link with the static library. A static link -// is the recommended practice. -// -// The preprocessor macro PQXX_INTERNAL is used to detect whether we -// are compiling the libpqxx library itself. When you compile the library -// yourself using your own project file, make sure to include this macro. -# if defined(PQXX_AUTOLINK) && !defined(PQXX_INTERNAL) -# ifdef PQXX_SHARED -# ifdef _DEBUG -# pragma comment(lib, "libpqxxD") -# else -# pragma comment(lib, "libpqxx") -# endif -# else // !PQXX_SHARED -# ifdef _DEBUG -# pragma comment(lib, "libpqxx_staticD") -# else -# pragma comment(lib, "libpqxx_static") -# endif -# endif -# endif - -# endif // _MSC_VER - -#elif defined(PQXX_HAVE_GCC_VISIBILITY) // !_WIN32 - -# define PQXX_LIBEXPORT __attribute__((visibility("default"))) -# define PQXX_PRIVATE __attribute__((visibility("hidden"))) - -#endif // PQXX_HAVE_GCC_VISIBILITY - - -#ifndef PQXX_LIBEXPORT -# define PQXX_LIBEXPORT /* libexport */ -#endif - -#ifndef PQXX_PRIVATE -# define PQXX_PRIVATE /* private */ -#endif - -#ifndef PQXX_NOVTABLE -# define PQXX_NOVTABLE /* novtable */ -#endif - -// C++20: Assume support. -#if defined(PQXX_HAVE_LIKELY) -# define PQXX_LIKELY [[likely]] -# define PQXX_UNLIKELY [[unlikely]] -#else -# define PQXX_LIKELY /* [[likely]] */ -# define PQXX_UNLIKELY /* [[unlikely]] */ -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/ignore-deprecated-post.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/ignore-deprecated-post.hxx deleted file mode 100644 index cebcf0594..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/ignore-deprecated-post.hxx +++ /dev/null @@ -1,15 +0,0 @@ -/// End a code block started by "ignore-deprecated-pre.hxx". - -#if !defined(PQXX_IGNORING_DEPRECATED) -# error "Ended an 'ignore-deprecated' block while none was active." -#endif - -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#endif // __GNUC__ - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -#undef PQXX_IGNORING_DEPRECATED diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/ignore-deprecated-pre.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/ignore-deprecated-pre.hxx deleted file mode 100644 index 8ac57afaa..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/ignore-deprecated-pre.hxx +++ /dev/null @@ -1,28 +0,0 @@ -/** Start a block of deprecated code which may call other deprecated code. - * - * Most compilers will emit warnings when deprecated code is invoked from - * non-deprecated code. But some compilers (notably gcc) will always emit the - * warning even when the calling code is also deprecated. - * - * This header starts a block where those warnings are suppressed. It can be - * included inside a code block. - * - * Always match the #include with a closing #include of - * "ignore-deprecated-post.hxx". To avoid mistakes, keep the enclosed area as - * small as possible. - */ -#if defined(PQXX_IGNORING_DEPRECATED) -# error "Started an 'ignore-deprecated' block inside another." -#endif - -#define PQXX_IGNORING_DEPRECATED - -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif // __GNUC__ - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4996) -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/libpq-forward.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/libpq-forward.hxx deleted file mode 100644 index 9e74f79ec..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/libpq-forward.hxx +++ /dev/null @@ -1,31 +0,0 @@ -/** Minimal forward declarations of libpq types needed in libpqxx headers. - * - * DO NOT INCLUDE THIS FILE when building client programs. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -extern "C" -{ - struct pg_conn; - struct pg_result; - struct pgNotify; -} - -/// Forward declarations of libpq types as needed in libpqxx headers. -namespace pqxx::internal::pq -{ -using PGconn = pg_conn; -using PGresult = pg_result; -using PGnotify = pgNotify; -using PQnoticeProcessor = void (*)(void *, char const *); -} // namespace pqxx::internal::pq - -namespace pqxx -{ -/// PostgreSQL database row identifier. -using oid = unsigned int; -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/result_iter.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/result_iter.hxx deleted file mode 100644 index 1fa1f7d8a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/result_iter.hxx +++ /dev/null @@ -1,124 +0,0 @@ -/** Result loops. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT_ITER -#define PQXX_H_RESULT_ITER - -#include - -#include "pqxx/strconv.hxx" - -namespace pqxx -{ -class result; -} // namespace pqxx - - -namespace pqxx::internal -{ -// C++20: Replace with generator? -/// Iterator for looped unpacking of a result. -template class result_iter -{ -public: - using value_type = std::tuple; - - /// Construct an "end" iterator. - result_iter() = default; - - explicit result_iter(result const &home) : - m_home{&home}, m_size{std::size(home)} - { - if (not std::empty(home)) - read(); - } - result_iter(result_iter const &) = default; - - result_iter &operator++() - { - m_index++; - if (m_index >= m_size) - m_home = nullptr; - else - read(); - return *this; - } - - /// Comparison only works for comparing to end(). - bool operator==(result_iter const &rhs) const - { - return m_home == rhs.m_home; - } - bool operator!=(result_iter const &rhs) const { return not(*this == rhs); } - - value_type const &operator*() const { return m_value; } - -private: - void read() { (*m_home)[m_index].convert(m_value); } - - result const *m_home{nullptr}; - result::size_type m_index{0}; - result::size_type m_size; - value_type m_value; -}; - - -template class result_iteration -{ -public: - using iterator = result_iter; - explicit result_iteration(result const &home) : m_home{home} - { - constexpr auto tup_size{sizeof...(TYPE)}; - if (home.columns() != tup_size) - throw usage_error{internal::concat( - "Tried to extract ", to_string(tup_size), - " field(s) from a result with ", to_string(home.columns()), - " column(s).")}; - } - iterator begin() const - { - if (std::size(m_home) == 0) - return end(); - else - return iterator{m_home}; - } - iterator end() const { return {}; } - -private: - pqxx::result const &m_home; -}; -} // namespace pqxx::internal - - -template inline auto pqxx::result::iter() const -{ - return pqxx::internal::result_iteration{*this}; -} - - -template -inline void pqxx::result::for_each(CALLABLE &&func) const -{ - using args_tuple = internal::args_t; - constexpr auto sz{std::tuple_size_v}; - static_assert( - sz > 0, - "Callback for for_each must take parameters, one for each column in the " - "result."); - - auto const cols{this->columns()}; - if (sz != cols) - throw usage_error{internal::concat( - "Callback to for_each takes ", sz, "parameter", (sz == 1) ? "" : "s", - ", but result set has ", cols, "field", (cols == 1) ? "" : "s", ".")}; - - using pass_tuple = pqxx::internal::strip_types_t; - for (auto const r : *this) std::apply(func, r.as_tuple()); -} -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/result_iterator.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/result_iterator.hxx deleted file mode 100644 index 3f27a1d3f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/result_iterator.hxx +++ /dev/null @@ -1,389 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT_ITERATOR -#define PQXX_H_RESULT_ITERATOR - -#include "pqxx/row.hxx" - - -/* Result iterator. - * - * Don't include this header from your own application; it is included for you - * by other libpqxx headers. - */ - -namespace pqxx -{ -/// Iterator for rows in a result. Use as result::const_iterator. -/** A result, once obtained, cannot be modified. Therefore there is no - * plain iterator type for result. However its const_iterator type can be - * used to inspect its rows without changing them. - */ -class PQXX_LIBEXPORT const_result_iterator : public row -{ -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = row const; - using pointer = row const *; - using reference = row; - using size_type = result_size_type; - using difference_type = result_difference_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create an iterator, but in an unusable state. - const_result_iterator() noexcept = default; - /// Copy an iterator. - const_result_iterator(const_result_iterator const &) noexcept = default; - /// Move an iterator. - const_result_iterator(const_result_iterator &&) noexcept = default; - - /// Begin iterating a @ref row. - const_result_iterator(row const &t) noexcept : row{t} {} -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /** - * @name Dereferencing operators - * - * An iterator "points to" its own row, which is also itself. This makes it - * easy to address a @ref result as a two-dimensional container, without - * going through the intermediate step of dereferencing the iterator. It - * makes the interface similar to C pointer/array semantics. - * - * IIRC Alex Stepanov, the inventor of the STL, once remarked that having - * this as standard behaviour for pointers would be useful in some - * algorithms. So even if this makes me look foolish, I would seem to be in - * distinguished company. - */ - //@{ - /// Dereference the iterator. - [[nodiscard]] pointer operator->() const { return this; } - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Dereference the iterator. - [[nodiscard]] reference operator*() const { return *this; } -#include "pqxx/internal/ignore-deprecated-post.hxx" - //@} - - /** - * @name Field access - */ - //@{ - using row::back; - using row::front; - using row::operator[]; - using row::at; - using row::rownumber; - //@} - - /** - * @name Manipulations - */ - //@{ - const_result_iterator &operator=(const_result_iterator const &rhs) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::operator=(rhs); -#include "pqxx/internal/ignore-deprecated-post.hxx" - return *this; - } - - const_result_iterator &operator=(const_result_iterator &&rhs) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::operator=(std::move(rhs)); -#include "pqxx/internal/ignore-deprecated-post.hxx" - return *this; - } - - const_result_iterator operator++(int); - const_result_iterator &operator++() - { - ++m_index; - return *this; - } - const_result_iterator operator--(int); - const_result_iterator &operator--() - { - --m_index; - return *this; - } - - const_result_iterator &operator+=(difference_type i) - { - m_index += i; - return *this; - } - const_result_iterator &operator-=(difference_type i) - { - m_index -= i; - return *this; - } - - /// Interchange two iterators in an exception-safe manner. - void swap(const_result_iterator &other) noexcept - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::swap(other); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool operator==(const_result_iterator const &i) const - { - return m_index == i.m_index; - } - [[nodiscard]] bool operator!=(const_result_iterator const &i) const - { - return m_index != i.m_index; - } - [[nodiscard]] bool operator<(const_result_iterator const &i) const - { - return m_index < i.m_index; - } - [[nodiscard]] bool operator<=(const_result_iterator const &i) const - { - return m_index <= i.m_index; - } - [[nodiscard]] bool operator>(const_result_iterator const &i) const - { - return m_index > i.m_index; - } - [[nodiscard]] bool operator>=(const_result_iterator const &i) const - { - return m_index >= i.m_index; - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] inline const_result_iterator operator+(difference_type) const; - friend const_result_iterator - operator+(difference_type, const_result_iterator const &); - [[nodiscard]] inline const_result_iterator operator-(difference_type) const; - [[nodiscard]] inline difference_type - operator-(const_result_iterator const &) const; - //@} - -private: - friend class pqxx::result; - const_result_iterator(pqxx::result const *r, result_size_type i) noexcept : - row{*r, i, r->columns()} - {} -}; - - -/// Reverse iterator for result. Use as result::const_reverse_iterator. -class PQXX_LIBEXPORT const_reverse_result_iterator - : private const_result_iterator -{ -public: - using super = const_result_iterator; - using iterator_type = const_result_iterator; - using iterator_type::difference_type; - using iterator_type::iterator_category; - using iterator_type::pointer; - using value_type = iterator_type::value_type; - using reference = iterator_type::reference; - - /// Create an iterator, but in an unusable state. - const_reverse_result_iterator() = default; - /// Copy an iterator. - const_reverse_result_iterator(const_reverse_result_iterator const &rhs) = - default; - /// Copy a reverse iterator from a regular iterator. - explicit const_reverse_result_iterator(const_result_iterator const &rhs) : - const_result_iterator{rhs} - { - super::operator--(); - } - - /// Move a regular iterator into a reverse iterator. - explicit const_reverse_result_iterator(const_result_iterator const &&rhs) : - const_result_iterator{std::move(rhs)} - { - super::operator--(); - } - - /// Return the underlying "regular" iterator (as per standard library). - [[nodiscard]] PQXX_PURE const_result_iterator base() const noexcept; - - /** - * @name Dereferencing operators - */ - //@{ - /// Dereference iterator. - using const_result_iterator::operator->; - /// Dereference iterator. - using const_result_iterator::operator*; - //@} - - /** - * @name Field access - */ - //@{ - using const_result_iterator::back; - using const_result_iterator::front; - using const_result_iterator::operator[]; - using const_result_iterator::at; - using const_result_iterator::rownumber; - //@} - - /** - * @name Manipulations - */ - //@{ - const_reverse_result_iterator & - operator=(const_reverse_result_iterator const &r) - { - iterator_type::operator=(r); - return *this; - } - const_reverse_result_iterator &operator=(const_reverse_result_iterator &&r) - { - iterator_type::operator=(std::move(r)); - return *this; - } - const_reverse_result_iterator &operator++() - { - iterator_type::operator--(); - return *this; - } - const_reverse_result_iterator operator++(int); - const_reverse_result_iterator &operator--() - { - iterator_type::operator++(); - return *this; - } - const_reverse_result_iterator operator--(int); - const_reverse_result_iterator &operator+=(difference_type i) - { - iterator_type::operator-=(i); - return *this; - } - const_reverse_result_iterator &operator-=(difference_type i) - { - iterator_type::operator+=(i); - return *this; - } - - void swap(const_reverse_result_iterator &other) noexcept - { - const_result_iterator::swap(other); - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] const_reverse_result_iterator - operator+(difference_type i) const - { - return const_reverse_result_iterator(base() - i); - } - [[nodiscard]] const_reverse_result_iterator operator-(difference_type i) - { - return const_reverse_result_iterator(base() + i); - } - [[nodiscard]] difference_type - operator-(const_reverse_result_iterator const &rhs) const - { - return rhs.const_result_iterator::operator-(*this); - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool - operator==(const_reverse_result_iterator const &rhs) const noexcept - { - return iterator_type::operator==(rhs); - } - [[nodiscard]] bool - operator!=(const_reverse_result_iterator const &rhs) const noexcept - { - return not operator==(rhs); - } - - [[nodiscard]] bool operator<(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator>(rhs); - } - [[nodiscard]] bool operator<=(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator>=(rhs); - } - [[nodiscard]] bool operator>(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator<(rhs); - } - [[nodiscard]] bool operator>=(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator<=(rhs); - } - //@} -}; - - -inline const_result_iterator -const_result_iterator::operator+(result::difference_type o) const -{ - return {&m_result, size_type(result::difference_type(m_index) + o)}; -} - -inline const_result_iterator -operator+(result::difference_type o, const_result_iterator const &i) -{ - return i + o; -} - -inline const_result_iterator -const_result_iterator::operator-(result::difference_type o) const -{ - return {&m_result, result_size_type(result::difference_type(m_index) - o)}; -} - -inline result::difference_type -const_result_iterator::operator-(const const_result_iterator &i) const -{ - return result::difference_type(num() - i.num()); -} - -inline const_result_iterator result::end() const noexcept -{ - return {this, size()}; -} - - -inline const_result_iterator result::cend() const noexcept -{ - return end(); -} - - -inline const_reverse_result_iterator -operator+(result::difference_type n, const_reverse_result_iterator const &i) -{ - return const_reverse_result_iterator{i.base() - n}; -} - -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/sql_cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/sql_cursor.hxx deleted file mode 100644 index a26d06306..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/sql_cursor.hxx +++ /dev/null @@ -1,118 +0,0 @@ -/** Internal wrapper for SQL cursors. Supports higher-level cursor classes. - * - * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SQL_CURSOR -#define PQXX_H_SQL_CURSOR - -namespace pqxx::internal -{ -/// Cursor with SQL positioning semantics. -/** Thin wrapper around an SQL cursor, with SQL's ideas of positioning. - * - * SQL cursors have pre-increment/pre-decrement semantics, with on either end - * of the result set a special position that does not repesent a row. This - * class models SQL cursors for the purpose of implementing more C++-like - * semantics on top. - * - * Positions of actual rows are numbered starting at 1. Position 0 exists but - * does not refer to a row. There is a similar non-row position at the end of - * the result set. - * - * Don't use this at home. You deserve better. Use the stateles_cursor - * instead. - */ -class PQXX_LIBEXPORT sql_cursor : public cursor_base -{ -public: - sql_cursor( - transaction_base &t, std::string_view query, std::string_view cname, - cursor_base::access_policy ap, cursor_base::update_policy up, - cursor_base::ownership_policy op, bool hold); - - sql_cursor( - transaction_base &t, std::string_view cname, - cursor_base::ownership_policy op); - - ~sql_cursor() noexcept { close(); } - - result fetch(difference_type rows, difference_type &displacement); - result fetch(difference_type rows) - { - difference_type d = 0; - return fetch(rows, d); - } - difference_type move(difference_type rows, difference_type &displacement); - difference_type move(difference_type rows) - { - difference_type d = 0; - return move(rows, d); - } - - /// Current position, or -1 for unknown - /** - * The starting position, just before the first row, counts as position zero. - * - * Position may be unknown if (and only if) this cursor was adopted, and has - * never hit its starting position (position zero). - */ - difference_type pos() const noexcept { return m_pos; } - - /// End position, or -1 for unknown - /** - * Returns the final position, just after the last row in the result set. The - * starting position, just before the first row, counts as position zero. - * - * End position is unknown until it is encountered during use. - */ - difference_type endpos() const noexcept { return m_endpos; } - - /// Return zero-row result for this cursor. - result const &empty_result() const noexcept { return m_empty_result; } - - void close() noexcept; - -private: - difference_type adjust(difference_type hoped, difference_type actual); - static std::string stridestring(difference_type); - /// Initialize cached empty result. Call only at beginning or end! - void init_empty_result(transaction_base &); - - /// Connection in which this cursor lives. - connection &m_home; - - /// Zero-row result from this cursor (or plain empty one if cursor is - /// adopted) - result m_empty_result; - - result m_cached_current_row; - - /// Is this cursor adopted (as opposed to created by this cursor object)? - bool m_adopted; - - /// Will this cursor object destroy its SQL cursor when it dies? - cursor_base::ownership_policy m_ownership; - - /// At starting position (-1), somewhere in the middle (0), or past end (1) - int m_at_end; - - /// Position, or -1 for unknown - difference_type m_pos; - - /// End position, or -1 for unknown - difference_type m_endpos = -1; -}; - - -PQXX_LIBEXPORT result_size_type obtain_stateless_cursor_size(sql_cursor &); -PQXX_LIBEXPORT result stateless_cursor_retrieve( - sql_cursor &, result::difference_type size, - result::difference_type begin_pos, result::difference_type end_pos); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/statement_parameters.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/statement_parameters.hxx deleted file mode 100644 index b078bf6e0..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/statement_parameters.hxx +++ /dev/null @@ -1,131 +0,0 @@ -/** Common implementation for statement parameter lists. - * - * These are used for both prepared statements and parameterized statements. - * - * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STATEMENT_PARAMETER -#define PQXX_H_STATEMENT_PARAMETER - -#include -#include -#include -#include -#include - -#include "pqxx/binarystring.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/util.hxx" - - -namespace pqxx::internal -{ -template -constexpr inline auto const iterator_identity{ - [](decltype(*std::declval()) x) { return x; }}; - - -/// Marker type: pass a dynamically-determined number of statement parameters. -/** @deprecated Use @ref params instead. - * - * Normally when invoking a prepared or parameterised statement, the number - * of parameters is known at compile time. For instance, - * `t.exec_prepared("foo", 1, "x");` executes statement `foo` with two - * parameters, an `int` and a C string. - * - * But sometimes you may want to pass a number of parameters known only at run - * time. In those cases, a @ref dynamic_params encodes a dynamically - * determined number of parameters. You can mix these with regular, static - * parameter lists, and you can re-use them for multiple statement invocations. - * - * A dynamic_params object does not store copies of its parameters, so make - * sure they remain accessible until you've executed the statement. - * - * The ACCESSOR is an optional callable (such as a lambda). If you pass an - * accessor `a`, then each parameter `p` goes into your statement as `a(p)`. - */ -template)> -class dynamic_params -{ -public: - /// Wrap a sequence of pointers or iterators. - constexpr dynamic_params(IT begin, IT end) : - m_begin(begin), m_end(end), m_accessor(iterator_identity) - {} - - /// Wrap a sequence of pointers or iterators. - /** This version takes an accessor callable. If you pass an accessor `acc`, - * then any parameter `p` will go into the statement's parameter list as - * `acc(p)`. - */ - constexpr dynamic_params(IT begin, IT end, ACCESSOR &acc) : - m_begin(begin), m_end(end), m_accessor(acc) - {} - - /// Wrap a container. - template - explicit constexpr dynamic_params(C &container) : - dynamic_params(std::begin(container), std::end(container)) - {} - - /// Wrap a container. - /** This version takes an accessor callable. If you pass an accessor `acc`, - * then any parameter `p` will go into the statement's parameter list as - * `acc(p)`. - */ - template - explicit constexpr dynamic_params(C &container, ACCESSOR &acc) : - dynamic_params(std::begin(container), std::end(container), acc) - {} - - constexpr IT begin() const noexcept { return m_begin; } - constexpr IT end() const noexcept { return m_end; } - - constexpr auto access(decltype(*std::declval()) value) const - -> decltype(std::declval()(value)) - { - return m_accessor(value); - } - -private: - IT const m_begin, m_end; - ACCESSOR m_accessor = iterator_identity; -}; - - -/// Internal type: encode statement parameters. -/** Compiles arguments for prepared statements and parameterised queries into - * a format that can be passed into libpq. - * - * Objects of this type are meant to be short-lived: a `c_params` lives and - * dies entirely within the call to execute. So, for example, if you pass in a - * non-null pointer as a parameter, @ref params may simply use that pointer as - * a parameter value, without arranging longer-term storage for the data to - * which it points. All values referenced by parameters must remain "live" - * until the parameterised or prepared statement has been executed. - */ -struct PQXX_LIBEXPORT c_params -{ - c_params() = default; - /// Copying these objects is pointless and expensive. Don't do it. - c_params(c_params const &) = delete; - c_params(c_params &&) = default; - - /// Pre-allocate storage for `n` parameters. - void reserve(std::size_t n) &; - - /// As used by libpq: pointers to parameter values. - std::vector values; - /// As used by libpq: lengths of non-null arguments, in bytes. - std::vector lengths; - /// As used by libpq: effectively boolean "is this a binary parameter?" - std::vector formats; -}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/stream_iterator.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/stream_iterator.hxx deleted file mode 100644 index f240dcfa7..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/stream_iterator.hxx +++ /dev/null @@ -1,105 +0,0 @@ -/** Stream iterators. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_ITERATOR -#define PQXX_H_STREAM_ITERATOR - -#include - -namespace pqxx -{ -class stream_from; -} - - -namespace pqxx::internal -{ -// C++20: Replace with generator? -/// Input iterator for stream_from. -/** Just barely enough to support range-based "for" loops. Don't assume that - * any of the usual behaviour works beyond that. - */ -template class stream_input_iterator -{ -public: - using value_type = std::tuple; - - /// Construct an "end" iterator. - stream_input_iterator() = default; - - explicit stream_input_iterator(stream_from &home) : m_home(&home) - { - advance(); - } - stream_input_iterator(stream_input_iterator const &) = default; - - stream_input_iterator &operator++() - { - advance(); - return *this; - } - - value_type const &operator*() const { return m_value; } - - /// Comparison only works for comparing to end(). - bool operator==(stream_input_iterator const &rhs) const - { - return m_home == rhs.m_home; - } - /// Comparison only works for comparing to end(). - bool operator!=(stream_input_iterator const &rhs) const - { - return not(*this == rhs); - } - -private: - void advance() - { - if (m_home == nullptr) - throw usage_error{"Moving stream_from iterator beyond end()."}; - if (not((*m_home) >> m_value)) - m_home = nullptr; - } - - stream_from *m_home{nullptr}; - value_type m_value; -}; - - -// C++20: Replace with generator? -/// Iteration over a @ref stream_from. -template class stream_input_iteration -{ -public: - using iterator = stream_input_iterator; - explicit stream_input_iteration(stream_from &home) : m_home{home} {} - iterator begin() const { return iterator{m_home}; } - iterator end() const { return {}; } - -private: - stream_from &m_home; -}; - - -// C++20: Replace with generator? -/// Iteration over a @ref stream_from, deleting it once done. -template class owning_stream_input_iteration -{ -public: - using iterator = stream_input_iterator; - explicit owning_stream_input_iteration(std::unique_ptr &&home) : - m_home{std::move(home)} - {} - iterator begin() const { return iterator{*m_home.get()}; } - iterator end() const { return {}; } - -private: - std::unique_ptr m_home; -}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/wait.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/wait.hxx deleted file mode 100644 index 7a82e6553..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/internal/wait.hxx +++ /dev/null @@ -1,18 +0,0 @@ -#if !defined(PQXX_WAIT_HXX) -# define PQXX_WAIT_HXX - -namespace pqxx::internal -{ -/// Wait. -/** This is normally `std::this_thread::sleep_for()`. But MinGW's `thread` - * header doesn't work, so we must be careful about including it. - */ -void PQXX_LIBEXPORT wait_for(unsigned int microseconds); - - -/// Wait for a socket to be ready for reading/writing, or timeout. -PQXX_LIBEXPORT void wait_fd( - int fd, bool for_read, bool for_write, unsigned seconds = 1, - unsigned microseconds = 0); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/isolation b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/isolation deleted file mode 100644 index 1b801329b..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/isolation +++ /dev/null @@ -1,8 +0,0 @@ -/** Transaction isolation levels. - * - * Policies and traits describing SQL transaction isolation levels - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/isolation.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/isolation.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/isolation.hxx deleted file mode 100644 index 0698c6ab4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/isolation.hxx +++ /dev/null @@ -1,75 +0,0 @@ -/* Definitions for transaction isolation levels, and such. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ISOLATION -#define PQXX_H_ISOLATION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Should a transaction be read-only, or read-write? -/** No, this is not an isolation level. So it really doesn't belong here. - * But it's not really worth a separate header. - */ -enum class write_policy -{ - read_only, - read_write -}; - - -/// Transaction isolation levels. -/** These are as defined in the SQL standard. But there are a few notes - * specific to PostgreSQL. - * - * First, postgres does not support "read uncommitted." The lowest level you - * can get is "read committed," which is better. PostgreSQL is built on the - * MVCC paradigm, which guarantees "read committed" isolation without any - * additional performance overhead, so there was no point in providing the - * lower level. - * - * Second, "repeatable read" also makes more isolation guarantees than the - * standard requires. According to the standard, this level prevents "dirty - * reads" and "nonrepeatable reads," but not "phantom reads." In postgres, - * it actually prevents all three. - * - * Third, "serializable" is only properly supported starting at postgres 9.1. - * If you request "serializable" isolation on an older backend, you will get - * the same isolation as in "repeatable read." It's better than the - * "repeatable read" defined in the SQL standard, but not a complete - * implementation of the standard's "serializable" isolation level. - * - * In general, a lower isolation level will allow more surprising interactions - * between ongoing transactions, but improve performance. A higher level - * gives you more protection from subtle concurrency bugs, but sometimes it - * may not be possible to complete your transaction without avoiding paradoxes - * in the data. In that case a transaction may fail, and the application will - * have to re-do the whole thing based on the latest state of the database. - * (If you want to retry your code in that situation, have a look at the - * transactor framework.) - * - * Study the levels and design your application with the right level in mind. - */ -enum isolation_level -{ - // PostgreSQL only has the better isolation levels. - // read_uncommitted, - - read_committed, - repeatable_read, - serializable, -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/largeobject b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/largeobject deleted file mode 100644 index 1f2f94790..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/largeobject +++ /dev/null @@ -1,8 +0,0 @@ -/** Large Objects interface. - * - * Supports direct access to large objects, as well as through I/O streams - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/largeobject.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/largeobject.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/largeobject.hxx deleted file mode 100644 index ebafc51d8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/largeobject.hxx +++ /dev/null @@ -1,735 +0,0 @@ -/* Large Objects interface. Deprecated; use blob instead. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_LARGEOBJECT -#define PQXX_H_LARGEOBJECT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/dbtransaction.hxx" - - -namespace pqxx -{ -/// Identity of a large object. -/** @deprecated Use the @ref blob class instead. - * - * Encapsulates the identity of a large object. - * - * A largeobject must be accessed only from within a backend transaction, but - * the object's identity remains valid as long as the object exists. - */ -class PQXX_LIBEXPORT largeobject -{ -public: - using size_type = large_object_size_type; - - /// Refer to a nonexistent large object (similar to what a null pointer - /// does). - [[deprecated("Use blob instead.")]] largeobject() noexcept = default; - - /// Create new large object. - /** @param t Backend transaction in which the object is to be created. - */ - [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t); - - /// Wrap object with given oid. - /** Convert combination of a transaction and object identifier into a - * large object identity. Does not affect the database. - * @param o Object identifier for the given object. - */ - [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept : - m_id{o} - {} - - /// Import large object from a local file. - /** Creates a large object containing the data found in the given file. - * @param t Backend transaction in which the large object is to be created. - * @param file A filename on the client program's filesystem. - */ - [[deprecated("Use blob instead.")]] largeobject( - dbtransaction &t, std::string_view file); - - /// Take identity of an opened large object. - /** Copy identity of already opened large object. Note that this may be done - * as an implicit conversion. - * @param o Already opened large object to copy identity from. - */ - [[deprecated("Use blob instead.")]] largeobject( - largeobjectaccess const &o) noexcept; - - /// Object identifier. - /** The number returned by this function identifies the large object in the - * database we're connected to (or oid_none is returned if we refer to the - * null object). - */ - [[nodiscard]] oid id() const noexcept { return m_id; } - - /** - * @name Identity comparisons - * - * These operators compare the object identifiers of large objects. This has - * nothing to do with the objects' actual contents; use them only for keeping - * track of containers of references to large objects and such. - */ - //@{ - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator==(largeobject const &other) const - { - return m_id == other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator!=(largeobject const &other) const - { - return m_id != other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator<=(largeobject const &other) const - { - return m_id <= other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator>=(largeobject const &other) const - { - return m_id >= other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator<(largeobject const &other) const - { - return m_id < other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator>(largeobject const &other) const - { - return m_id > other.m_id; - } - //@} - - /// Export large object's contents to a local file - /** Writes the data stored in the large object to the given file. - * @param t Transaction in which the object is to be accessed - * @param file A filename on the client's filesystem - */ - void to_file(dbtransaction &t, std::string_view file) const; - - /// Delete large object from database - /** Unlike its low-level equivalent cunlink, this will throw an exception if - * deletion fails. - * @param t Transaction in which the object is to be deleted - */ - void remove(dbtransaction &t) const; - -protected: - PQXX_PURE static internal::pq::PGconn * - raw_connection(dbtransaction const &T); - - PQXX_PRIVATE std::string reason(connection const &, int err) const; - -private: - oid m_id = oid_none; -}; - - -/// Accessor for large object's contents. -/** @deprecated Use the `blob` class instead. - */ -class PQXX_LIBEXPORT largeobjectaccess : private largeobject -{ -public: - using largeobject::size_type; - using off_type = size_type; - using pos_type = size_type; - - /// Open mode: `in`, `out` (can be combined using "bitwise or"). - /** According to the C++ standard, these should be in `std::ios_base`. We - * take them from derived class `std::ios` instead, which is easier on the - * eyes. - * - * Historical note: taking it from std::ios was originally a workaround for a - * problem with gcc 2.95. - */ - using openmode = std::ios::openmode; - - /// Default open mode: in, out, binary. - static constexpr auto default_mode{ - std::ios::in | std::ios::out | std::ios::binary}; - - /// Seek direction: `beg`, `cur`, `end`. - using seekdir = std::ios::seekdir; - - /// Create new large object and open it. - /** - * @param t Backend transaction in which the object is to be created. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] explicit largeobjectaccess( - dbtransaction &t, openmode mode = default_mode); - - /// Open large object with given oid. - /** Convert combination of a transaction and object identifier into a - * large object identity. Does not affect the database. - * @param t Transaction in which the object is to be accessed. - * @param o Object identifier for the given object. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, oid o, openmode mode = default_mode); - - /// Open given large object. - /** Open a large object with the given identity for reading and/or writing. - * @param t Transaction in which the object is to be accessed. - * @param o Identity for the large object to be accessed. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, largeobject o, openmode mode = default_mode); - - /// Import large object from a local file and open it. - /** Creates a large object containing the data found in the given file. - * @param t Backend transaction in which the large object is to be created. - * @param file A filename on the client program's filesystem. - * @param mode Access mode, defaults to ios_base::in | ios_base::out. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, std::string_view file, openmode mode = default_mode); - - ~largeobjectaccess() noexcept { close(); } - - /// Object identifier. - /** The number returned by this function uniquely identifies the large object - * in the context of the database we're connected to. - */ - using largeobject::id; - - /// Export large object's contents to a local file. - /** Writes the data stored in the large object to the given file. - * @param file A filename on the client's filesystem. - */ - void to_file(std::string_view file) const - { - largeobject::to_file(m_trans, file); - } - - using largeobject::to_file; - - /** - * @name High-level access to object contents. - */ - //@{ - /// Write data to large object. - /** @warning The size of a write is currently limited to 2GB. - * - * @param buf Data to write. - * @param len Number of bytes from Buf to write. - */ - void write(char const buf[], std::size_t len); - - /// Write string to large object. - /** If not all bytes could be written, an exception is thrown. - * @param buf Data to write; no terminating zero is written. - */ - void write(std::string_view buf) { write(std::data(buf), std::size(buf)); } - - /// Read data from large object. - /** Throws an exception if an error occurs while reading. - * @param buf Location to store the read data in. - * @param len Number of bytes to try and read. - * @return Number of bytes read, which may be less than the number requested - * if the end of the large object is reached. - */ - size_type read(char buf[], std::size_t len); - - /// Seek in large object's data stream. - /** Throws an exception if an error occurs. - * @return The new position in the large object - */ - size_type seek(size_type dest, seekdir dir); - - /// Report current position in large object's data stream. - /** Throws an exception if an error occurs. - * @return The current position in the large object. - */ - [[nodiscard]] size_type tell() const; - //@} - - /** - * @name Low-level access to object contents. - * - * These functions provide a more "C-like" access interface, returning - * special values instead of throwing exceptions on error. These functions - * are generally best avoided in favour of the high-level access functions, - * which behave more like C++ functions should. - * - * Due to libpq's underlying API, some operations are limited to "int" - * sizes, typically 2 GB, even though a large object can grow much larger. - */ - //@{ - /// Seek in large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param dest Offset to go to. - * @param dir Origin to which dest is relative: ios_base::beg (from beginning - * of the object), ios_base::cur (from current access position), or - * ios_base;:end (from end of object). - * @return New position in large object, or -1 if an error occurred. - */ - pos_type cseek(off_type dest, seekdir dir) noexcept; - - /// Write to large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param buf Data to write. - * @param len Number of bytes to write. - * @return Number of bytes actually written, or -1 if an error occurred. - */ - off_type cwrite(char const buf[], std::size_t len) noexcept; - - /// Read from large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param buf Area where incoming bytes should be stored. - * @param len Number of bytes to read. - * @return Number of bytes actually read, or -1 if an error occurred.. - */ - off_type cread(char buf[], std::size_t len) noexcept; - - /// Report current position in large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @return Current position in large object, of -1 if an error occurred. - */ - [[nodiscard]] pos_type ctell() const noexcept; - //@} - - /** - * @name Error/warning output - */ - //@{ - /// Issue message to transaction's notice processor. - void process_notice(zview) noexcept; - //@} - - using largeobject::remove; - - using largeobject::operator==; - using largeobject::operator!=; - using largeobject::operator<; - using largeobject::operator<=; - using largeobject::operator>; - using largeobject::operator>=; - - largeobjectaccess() = delete; - largeobjectaccess(largeobjectaccess const &) = delete; - largeobjectaccess operator=(largeobjectaccess const &) = delete; - -private: - PQXX_PRIVATE std::string reason(int err) const; - internal::pq::PGconn *raw_connection() const - { - return largeobject::raw_connection(m_trans); - } - - PQXX_PRIVATE void open(openmode mode); - void close() noexcept; - - dbtransaction &m_trans; - int m_fd = -1; -}; - - -/// Streambuf to use large objects in standard I/O streams. -/** @deprecated Access large objects directly using the @ref blob class. - * - * The standard streambuf classes provide uniform access to data storage such - * as files or string buffers, so they can be accessed using standard input or - * output streams. This streambuf implementation provided similar access to - * large objects, so they could be read and written using the same stream - * classes. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class largeobject_streambuf : public std::basic_streambuf -{ - using size_type = largeobject::size_type; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - using openmode = largeobjectaccess::openmode; - using seekdir = largeobjectaccess::seekdir; - - /// Default open mode: in, out, binary. - static constexpr auto default_mode{ - std::ios::in | std::ios::out | std::ios::binary}; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - [[deprecated("Use blob instead.")]] largeobject_streambuf( - dbtransaction &t, largeobject o, openmode mode = default_mode, - size_type buf_size = 512) : - m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr} - { - initialize(mode); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - [[deprecated("Use blob instead.")]] largeobject_streambuf( - dbtransaction &t, oid o, openmode mode = default_mode, - size_type buf_size = 512) : - m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr} - { - initialize(mode); - } - - virtual ~largeobject_streambuf() noexcept - { - delete[] m_p; - delete[] m_g; - } - - /// For use by large object stream classes. - void process_notice(zview const &s) { m_obj.process_notice(s); } - -protected: - virtual int sync() override - { - // setg() sets eback, gptr, egptr. - this->setg(this->eback(), this->eback(), this->egptr()); - return overflow(eof()); - } - - virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override - { - return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir)); - } - - virtual pos_type seekpos(pos_type pos, openmode) override - { - largeobjectaccess::pos_type const newpos{ - m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)}; - return adjust_eof(newpos); - } - - virtual int_type overflow(int_type ch) override - { - auto *const pp{this->pptr()}; - if (pp == nullptr) - return eof(); - auto *const pb{this->pbase()}; - int_type res{0}; - - if (pp > pb) - { - auto const write_sz{pp - pb}; - auto const written_sz{ - m_obj.cwrite(pb, static_cast(pp - pb))}; - if (internal::cmp_less_equal(written_sz, 0)) - throw internal_error{ - "pqxx::largeobject: write failed " - "(is transaction still valid on write or flush?), " - "libpq reports error"}; - else if (write_sz != written_sz) - throw internal_error{ - "pqxx::largeobject: write failed " - "(is transaction still valid on write or flush?), " + - std::to_string(written_sz) + "/" + std::to_string(write_sz) + - " bytes written"}; - auto const out{adjust_eof(written_sz)}; - - if constexpr (std::is_arithmetic_v) - res = check_cast(out, "largeobject position"sv); - else - res = int_type(out); - } - this->setp(m_p, m_p + m_bufsize); - - // Write that one more character, if it's there. - if (ch != eof()) - { - *this->pptr() = static_cast(ch); - this->pbump(1); - } - return res; - } - - virtual int_type overflow() { return overflow(eof()); } - - virtual int_type underflow() override - { - if (this->gptr() == nullptr) - return eof(); - auto *const eb{this->eback()}; - auto const res{adjust_eof( - m_obj.cread(this->eback(), static_cast(m_bufsize)))}; - this->setg( - eb, eb, eb + (res == eof() ? 0 : static_cast(res))); - return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb); - } - -private: - /// Shortcut for traits_type::eof(). - static int_type eof() { return traits_type::eof(); } - - /// Helper: change error position of -1 to EOF (probably a no-op). - template static std::streampos adjust_eof(INTYPE pos) - { - bool const at_eof{pos == -1}; - if constexpr (std::is_arithmetic_v) - { - return check_cast( - (at_eof ? eof() : pos), "large object seek"sv); - } - else - { - return std::streampos(at_eof ? eof() : pos); - } - } - - void initialize(openmode mode) - { - if ((mode & std::ios::in) != 0) - { - m_g = new char_type[unsigned(m_bufsize)]; - this->setg(m_g, m_g, m_g); - } - if ((mode & std::ios::out) != 0) - { - m_p = new char_type[unsigned(m_bufsize)]; - this->setp(m_p, m_p + m_bufsize); - } - } - - size_type const m_bufsize; - largeobjectaccess m_obj; - - /// Get & put buffers. - char_type *m_g, *m_p; -}; - - -/// Input stream that gets its data from a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This class worked like any other istream, but to read data from a large - * object. It supported all formatting and streaming operations of - * `std::istream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_ilostream : public std::basic_istream -{ - using super = std::basic_istream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create a basic_ilostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_ilostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::in | std::ios::binary, buf_size} - { - super::init(&m_buf); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// Create a basic_ilostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Identifier of a large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_ilostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::in | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - -private: - largeobject_streambuf m_buf; -}; - -using ilostream = basic_ilostream; - - -/// Output stream that writes data back to a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This worked like any other ostream, but to write data to a large object. - * It supported all formatting and streaming operations of `std::ostream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_olostream : public std::basic_ostream -{ - using super = std::basic_ostream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create a basic_olostream. - /** - * @param t transaction in which this stream is to exist. - * @param o a large object to access. - * @param buf_size size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_olostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// Create a basic_olostream. - /** - * @param t transaction in which this stream is to exist. - * @param o a large object to access. - * @param buf_size size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_olostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - ~basic_olostream() - { - try - { - m_buf.pubsync(); - m_buf.pubsync(); - } - catch (std::exception const &e) - { - m_buf.process_notice(e.what()); - } - } - -private: - largeobject_streambuf m_buf; -}; - -using olostream = basic_olostream; - - -/// Stream that reads and writes a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This worked like a std::iostream, but to read data from, or write data to, a - * large object. It supported all formatting and streaming operations of - * `std::iostream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_lostream : public std::basic_iostream -{ - using super = std::basic_iostream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - - /// Create a basic_lostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_lostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{ - t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - /// Create a basic_lostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_lostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{ - t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - ~basic_lostream() - { - try - { - m_buf.pubsync(); - m_buf.pubsync(); - } - catch (std::exception const &e) - { - m_buf.process_notice(e.what()); - } - } - -private: - largeobject_streambuf m_buf; -}; - -using lostream = basic_lostream; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/nontransaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/nontransaction deleted file mode 100644 index bb5b79724..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/nontransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::nontransaction class. - * - * pqxx::nontransaction provides nontransactional database access. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/nontransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/nontransaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/nontransaction.hxx deleted file mode 100644 index c50715594..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/nontransaction.hxx +++ /dev/null @@ -1,76 +0,0 @@ -/* Definition of the pqxx::nontransaction class. - * - * pqxx::nontransaction provides nontransactional database access - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_NONTRANSACTION -#define PQXX_H_NONTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/connection.hxx" -#include "pqxx/result.hxx" -#include "pqxx/transaction.hxx" - -namespace pqxx -{ -using namespace std::literals; - -/// Simple "transaction" class offering no transactional integrity. -/** - * @ingroup transactions - * - * nontransaction, like transaction or any other transaction_base-derived - * class, provides access to a database through a connection. Unlike its - * siblings, however, nontransaction does not maintain any kind of - * transactional integrity. This may be useful eg. for read-only access to the - * database that does not require a consistent, atomic view on its data; or for - * operations that are not allowed within a backend transaction, such as - * creating tables. - * - * For queries that update the database, however, a real transaction is likely - * to be faster unless the transaction consists of only a single record update. - * - * Also, you can keep a nontransaction open for as long as you like. Actual - * back-end transactions are limited in lifespan, and will sometimes fail just - * because they took too long to execute or were left idle for too long. This - * will not happen with a nontransaction (although the connection may still - * time out, e.g. when the network is unavailable for a very long time). - * - * Any query executed in a nontransaction is committed immediately, and neither - * commit() nor abort() has any effect. - * - * Database features that require a backend transaction, such as cursors or - * large objects, will not work in a nontransaction. - */ -class PQXX_LIBEXPORT nontransaction final : public transaction_base -{ -public: - /// Constructor. - /** Create a "dummy" transaction. - * @param c Connection in which this "transaction" will operate. - * @param tname Optional tname for the transaction, beginning with a letter - * and containing only letters and digits. - */ - nontransaction(connection &c, std::string_view tname = ""sv) : - transaction_base{c, tname, std::shared_ptr{}} - { - register_transaction(); - } - - virtual ~nontransaction() override { close(); } - -private: - virtual void do_commit() override {} -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/notification b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/notification deleted file mode 100644 index a0bd1c73e..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/notification +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::notification_receiver functor interface. - * - * pqxx::notification_receiver handles incoming notifications. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/notification.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/notification.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/notification.hxx deleted file mode 100644 index b59b8567a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/notification.hxx +++ /dev/null @@ -1,94 +0,0 @@ -/* Definition of the pqxx::notification_receiver functor interface. - * - * pqxx::notification_receiver handles incoming notifications. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_NOTIFICATION -#define PQXX_H_NOTIFICATION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/types.hxx" - - -namespace pqxx -{ -/// "Observer" base class for notifications. -/** @addtogroup notification Notifications and Receivers - * - * To listen on a notification issued using the NOTIFY command, derive your own - * class from notification_receiver and define its function-call operator to - * perform whatever action you wish to take when the given notification - * arrives. Then create an object of that class and pass it to your connection. - * DO NOT use raw SQL to listen for notifications, or your attempts to listen - * won't be resumed when a connection fails--and you'll have no way to notice. - * - * Notifications never arrive inside a transaction, not even in a - * nontransaction. Therefore, you are free to open a transaction of your own - * inside your receiver's function invocation operator. - * - * Notifications you are listening for may arrive anywhere within libpqxx code, - * but be aware that **PostgreSQL defers notifications occurring inside - * transactions.** (This was done for excellent reasons; just think about what - * happens if the transaction where you happen to handle an incoming - * notification is later rolled back for other reasons). So if you're keeping - * a transaction open, don't expect any of your receivers on the same - * connection to be notified. - * - * (For very similar reasons, outgoing notifications are also not sent until - * the transaction that sends them commits.) - * - * Multiple receivers on the same connection may listen on a notification of - * the same name. An incoming notification is processed by invoking all - * receivers (zero or more) of the same name. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver -{ -public: - /// Register the receiver with a connection. - /** - * @param c Connnection to operate on. - * @param channel Name of the notification to listen for. - */ - notification_receiver(connection &c, std::string_view channel); - /// Register the receiver with a connection. - notification_receiver(notification_receiver const &) = delete; - /// Register the receiver with a connection. - notification_receiver &operator=(notification_receiver const &) = delete; - /// Deregister the receiver. - virtual ~notification_receiver(); - - /// The channel that this receiver listens on. - [[nodiscard]] std::string const &channel() const & { return m_channel; } - - // TODO: Change API to take payload as zview instead of string ref. - /// Overridable: action to invoke when notification arrives. - /** - * @param payload An optional string that may have been passed to the NOTIFY - * command. - * @param backend_pid Process ID of the database backend process that served - * our connection when the notification arrived. The actual process ID - * behind the connection may have changed by the time this method is called. - */ - virtual void operator()(std::string const &payload, int backend_pid) = 0; - -protected: - connection &conn() const noexcept { return m_conn; } - -private: - connection &m_conn; - std::string m_channel; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/params b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/params deleted file mode 100644 index 4098782aa..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/params +++ /dev/null @@ -1,8 +0,0 @@ -/** Helper classes for passing statement parameters. - * - * Use these for prepared statements and parameterised statements. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/params.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/params.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/params.hxx deleted file mode 100644 index 2d29cdfed..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/params.hxx +++ /dev/null @@ -1,383 +0,0 @@ -/* Helpers for prepared statements and parameterised statements. - * - * See the connection class for more about such statements. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_PARAMS -#define PQXX_H_PARAMS - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/statement_parameters.hxx" -#include "pqxx/types.hxx" - - -/// @deprecated The new @ref params class replaces all of this. -namespace pqxx::prepare -{ -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * sequence ranging from `begin` to `end` exclusively. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic sequences. - * - * @param begin A pointer or iterator for iterating parameters. - * @param end A pointer or iterator for iterating parameters. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(IT begin, IT end) -{ - return pqxx::internal::dynamic_params(begin, end); -} - - -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * container of parameter values. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic containers. - * - * @param container A container of parameter values. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(C const &container) -{ - using IT = typename C::const_iterator; -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return pqxx::internal::dynamic_params{container}; -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * container of parameter values. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic containers. - * - * @param container A container of parameter values. - * @param accessor For each parameter `p`, pass `accessor(p)`. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(C &container, ACCESSOR accessor) -{ - using IT = decltype(std::begin(container)); -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return pqxx::internal::dynamic_params{container, accessor}; -#include "pqxx/internal/ignore-deprecated-post.hxx" -} -} // namespace pqxx::prepare - - -namespace pqxx -{ -/// Generate parameter placeholders for use in an SQL statement. -/** When you want to pass parameters to a prepared statement or a parameterised - * statement, you insert placeholders into the SQL. During invocation, the - * database replaces those with the respective parameter values you passed. - * - * The placeholders look like `$1` (for the first parameter value), `$2` (for - * the second), and so on. You can just write those directly in your - * statement. But for those rare cases where it becomes difficult to track - * which number a placeholder should have, you can use a `placeholders` object - * to count and generate them in order. - */ -template class placeholders -{ -public: - /// Maximum number of parameters we support. - static inline constexpr unsigned int max_params{ - (std::numeric_limits::max)()}; - - placeholders() - { - static constexpr auto initial{"$1\0"sv}; - initial.copy(std::data(m_buf), std::size(initial)); - } - - /// Read an ephemeral version of the current placeholder text. - /** @warning Changing the current placeholder number will overwrite this. - * Use the view immediately, or lose it. - */ - constexpr zview view() const &noexcept - { - return zview{std::data(m_buf), m_len}; - } - - /// Read the current placeholder text, as a `std::string`. - /** This will be slightly slower than converting to a `zview`. With most - * C++ implementations however, until you get into ridiculous numbers of - * parameters, the string will benefit from the Short String Optimization, or - * SSO. - */ - std::string get() const { return std::string(std::data(m_buf), m_len); } - - /// Move on to the next parameter. - void next() & - { - if (m_current >= max_params) - throw range_error{pqxx::internal::concat( - "Too many parameters in one statement: limit is ", max_params, ".")}; - ++m_current; - if (m_current % 10 == 0) - { - // Carry the 1. Don't get too clever for this relatively rare - // case, just rewrite the entire number. Leave the $ in place - // though. - char *const data{std::data(m_buf)}; - char *const end{string_traits::into_buf( - data + 1, data + std::size(m_buf), m_current)}; - // (Subtract because we don't include the trailing zero.) - m_len = check_cast(end - data, "placeholders counter") - 1; - } - else - { - PQXX_LIKELY - // Shortcut for the common case: just increment that last digit. - ++m_buf[m_len - 1]; - } - } - - /// Return the current placeholder number. The initial placeholder is 1. - COUNTER count() const noexcept { return m_current; } - -private: - /// Current placeholder number. Starts at 1. - COUNTER m_current = 1; - - /// Length of the current placeholder string, not including trailing zero. - COUNTER m_len = 2; - - /// Text buffer where we render the placeholders, with a trailing zero. - /** We keep reusing this for every subsequent placeholder, just because we - * don't like string allocations. - * - * Maximum length is the maximum base-10 digits that COUNTER can fully - * represent, plus 1 more for the extra digit that it can only partially - * fill up, plus room for the dollar sign and the trailing zero. - */ - std::array::digits10 + 3> m_buf; -}; - - -/// Build a parameter list for a parameterised or prepared statement. -/** When calling a parameterised statement or a prepared statement, you can - * pass parameters into the statement directly in the invocation, as - * additional arguments to `exec_prepared` or `exec_params`. But in - * complex cases, sometimes that's just not convenient. - * - * In those situations, you can create a `params` and append your parameters - * into that, one by one. Then you pass the `params` to `exec_prepared` or - * `exec_params`. - * - * Combinations also work: if you have a `params` containing a string - * parameter, and you call `exec_params` with an `int` argument followed by - * your `params`, you'll be passing the `int` as the first parameter and - * the string as the second. You can even insert a `params` in a `params`, - * or pass two `params` objects to a statement. - */ -class PQXX_LIBEXPORT params -{ -public: - params() = default; - - /// Pre-populate a `params` with `args`. Feel free to add more later. - template constexpr params(Args &&...args) - { - reserve(sizeof...(args)); - append_pack(std::forward(args)...); - } - - /// Pre-allocate room for at least `n` parameters. - /** This is not needed, but it may improve efficiency. - * - * Reserve space if you're going to add parameters individually, and you've - * got some idea of how many there are going to be. It may save some - * memory re-allocations. - */ - void reserve(std::size_t n) &; - - // C++20: constexpr. - /// Get the number of parameters currently in this `params`. - [[nodiscard]] auto size() const noexcept { return m_params.size(); } - - // C++20: Use the vector's ssize() directly and go noexcept+constexpr. - /// Get the number of parameters (signed). - /** Unlike `size()`, this is not yet `noexcept`. That's because C++17's - * `std::vector` does not have a `ssize()` member function. These member - * functions are `noexcept`, but `std::size()` and `std::ssize()` are - * not. - */ - [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params); } - - /// Append a null value. - void append() &; - - /// Append a non-null zview parameter. - /** The underlying data must stay valid for as long as the `params` - * remains active. - */ - void append(zview) &; - - /// Append a non-null string parameter. - /** Copies the underlying data into internal storage. For best efficiency, - * use the @ref zview variant if you can, or `std::move()` - */ - void append(std::string const &) &; - - /// Append a non-null string parameter. - void append(std::string &&) &; - - /// Append a non-null binary parameter. - /** The underlying data must stay valid for as long as the `params` - * remains active. - */ - void append(std::basic_string_view) &; - - /// Append a non-null binary parameter. - /** Copies the underlying data into internal storage. For best efficiency, - * use the `std::basic_string_view` variant if you can, or - * `std::move()`. - */ - void append(std::basic_string const &) &; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Append a non-null binary parameter. - /** The `data` object must stay in place and unchanged, for as long as the - * `params` remains active. - */ - template void append(DATA const &data) & - { - append( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif // PQXX_HAVE_CONCEPTS - - /// Append a non-null binary parameter. - void append(std::basic_string &&) &; - - /// @deprecated Append binarystring parameter. - /** The binarystring must stay valid for as long as the `params` remains - * active. - */ - void append(binarystring const &value) &; - - /// Append all parameters from value. - template - void append(pqxx::internal::dynamic_params const &value) & - { - for (auto ¶m : value) append(value.access(param)); - } - - void append(params const &value) &; - - void append(params &&value) &; - - /// Append a non-null parameter, converting it to its string - /// representation. - template void append(TYPE const &value) & - { - // TODO: Pool storage for multiple string conversions in one buffer? - if constexpr (nullness>::always_null) - { - ignore_unused(value); - m_params.emplace_back(); - } - else if (is_null(value)) - { - m_params.emplace_back(); - } - else - { - m_params.emplace_back(entry{to_string(value)}); - } - } - - /// Append all elements of `range` as parameters. - template void append_multi(RANGE const &range) & - { -#if defined(PQXX_HAVE_CONCEPTS) - if constexpr (std::ranges::sized_range) - reserve(std::size(*this) + std::size(range)); -#endif - for (auto &value : range) append(value); - } - - /// For internal use: Generate a `params` object for use in calls. - /** The params object encapsulates the pointers which we will need to pass - * to libpq when calling a parameterised or prepared statement. - * - * The pointers in the params will refer to storage owned by either the - * params object, or the caller. This is not a problem because a - * `c_params` object is guaranteed to live only while the call is going on. - * As soon as we climb back out of that call tree, we're done with that - * data. - */ - pqxx::internal::c_params make_c_params() const; - -private: - /// Recursively append a pack of params. - template - void append_pack(Arg &&arg, More &&...args) - { - this->append(std::forward(arg)); - // Recurse for remaining args. - append_pack(std::forward(args)...); - } - - /// Terminating case: append an empty parameter pack. It's not hard BTW. - constexpr void append_pack() noexcept {} - - // The way we store a parameter depends on whether it's binary or text - // (most types are text), and whether we're responsible for storing the - // contents. - using entry = std::variant< - std::nullptr_t, zview, std::string, std::basic_string_view, - std::basic_string>; - std::vector m_params; - - static constexpr std::string_view s_overflow{ - "Statement parameter length overflow."sv}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pipeline b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pipeline deleted file mode 100644 index bf828843a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pipeline +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::pipeline class. - * - * Throughput-optimized query interface. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/pipeline.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pipeline.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pipeline.hxx deleted file mode 100644 index 049dcdd58..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pipeline.hxx +++ /dev/null @@ -1,237 +0,0 @@ -/* Definition of the pqxx::pipeline class. - * - * Throughput-optimized mechanism for executing queries. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_PIPELINE -#define PQXX_H_PIPELINE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -// TODO: libpq 14 introduced a similar "pipeline mode." Can we use that? - -/// Processes several queries in FIFO manner, optimized for high throughput. -/** Use a pipeline if you want to keep doing useful work while your queries are - * executing. Result retrieval is decoupled from execution request; queries - * "go in at the front" and results "come out the back." - * - * Actually, you can retrieve the results in any order if you want, but it may - * lead to surprising "time travel" effects if any of the queries fails. In - * particular, syntax errors in the queries can confuse things and show up too - * early in the stream of results. - * - * Generally, if any of the queries fails, it will throw an exception at the - * point where you request its result. But it may happen earlier, especially - * if you request results out of chronological order. - * - * @warning While a pipeline is active, you cannot execute queries, open - * streams, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT pipeline : public transaction_focus -{ -public: - /// Identifying numbers for queries. - using query_id = long; - - pipeline(pipeline const &) = delete; - pipeline &operator=(pipeline const &) = delete; - - /// Start a pipeline. - explicit pipeline(transaction_base &t) : transaction_focus{t, s_classname} - { - init(); - } - /// Start a pipeline. Assign it a name, for more helpful error messages. - pipeline(transaction_base &t, std::string_view tname) : - transaction_focus{t, s_classname, tname} - { - init(); - } - - /// Close the pipeline. - ~pipeline() noexcept; - - /// Add query to the pipeline. - /** Queries accumulate in the pipeline, which sends them to the backend in a - * batch separated by semicolons. The queries you insert must not use this - * trick themselves, or the pipeline will get hopelessly confused! - * - * @return Identifier for this query, unique only within this pipeline. - */ - query_id insert(std::string_view) &; - - /// Wait for all ongoing or pending operations to complete, and detach. - /** Detaches from the transaction when done. - * - * This does not produce the queries' results, so it may not report any - * errors which may have occurred in their execution. To be sure that your - * statements succeeded, call @ref retrieve until the pipeline is empty. - */ - void complete(); - - /// Forget all ongoing or pending operations and retrieved results. - /** Queries already sent to the backend may still be completed, depending - * on implementation and timing. - * - * Any error state (unless caused by an internal error) will also be cleared. - * This is mostly useful in a nontransaction, since a backend transaction is - * aborted automatically when an error occurs. - * - * Detaches from the transaction when done. - */ - void flush(); - - /// Cancel ongoing query, if any. - /** May cancel any or all of the queries that have been inserted at this - * point whose results have not yet been retrieved. If the pipeline lives in - * a backend transaction, that transaction may be left in a nonfunctional - * state in which it can only be aborted. - * - * Therefore, either use this function in a nontransaction, or abort the - * transaction after calling it. - */ - void cancel(); - - /// Is result for given query available? - [[nodiscard]] bool is_finished(query_id) const; - - /// Retrieve result for given query. - /** If the query failed for whatever reason, this will throw an exception. - * The function will block if the query has not finished yet. - * @warning If results are retrieved out-of-order, i.e. in a different order - * than the one in which their queries were inserted, errors may "propagate" - * to subsequent queries. - */ - result retrieve(query_id qid) - { - return retrieve(m_queries.find(qid)).second; - } - - /// Retrieve oldest unretrieved result (possibly wait for one). - /** @return The query's identifier and its result set. */ - std::pair retrieve(); - - [[nodiscard]] bool empty() const noexcept { return std::empty(m_queries); } - - /// Set maximum number of queries to retain before issuing them to the - /// backend. - /** The pipeline will perform better if multiple queries are issued at once, - * but retaining queries until the results are needed (as opposed to issuing - * them to the backend immediately) may negate any performance benefits the - * pipeline can offer. - * - * Recommended practice is to set this value no higher than the number of - * queries you intend to insert at a time. - * @param retain_max A nonnegative "retention capacity;" passing zero will - * cause queries to be issued immediately - * @return Old retention capacity - */ - int retain(int retain_max = 2) &; - - - /// Resume retained query emission. Harmless when not needed. - void resume() &; - -private: - struct PQXX_PRIVATE Query - { - explicit Query(std::string_view q) : - query{std::make_shared(q)} - {} - - std::shared_ptr query; - result res; - }; - - using QueryMap = std::map; - - void init(); - void attach(); - void detach(); - - /// Upper bound to query id's. - static constexpr query_id qid_limit() noexcept - { - // Parenthesise this to work around an eternal Visual C++ problem: - // Without the extra parentheses, unless NOMINMAX is defined, the - // preprocessor will mistake this "max" for its annoying built-in macro - // of the same name. - return (std::numeric_limits::max)(); - } - - /// Create new query_id. - PQXX_PRIVATE query_id generate_id(); - - bool have_pending() const noexcept - { - return m_issuedrange.second != m_issuedrange.first; - } - - PQXX_PRIVATE void issue(); - - /// The given query failed; never issue anything beyond that. - void set_error_at(query_id qid) noexcept - { - PQXX_UNLIKELY - if (qid < m_error) - m_error = qid; - } - - /// Throw pqxx::internal_error. - [[noreturn]] PQXX_PRIVATE void internal_error(std::string const &err); - - PQXX_PRIVATE bool obtain_result(bool expect_none = false); - - PQXX_PRIVATE void obtain_dummy(); - PQXX_PRIVATE void get_further_available_results(); - PQXX_PRIVATE void check_end_results(); - - /// Receive any results that happen to be available; it's not urgent. - PQXX_PRIVATE void receive_if_available(); - - /// Receive results, up to stop if possible. - PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop); - std::pair retrieve(pipeline::QueryMap::iterator); - - QueryMap m_queries; - std::pair m_issuedrange; - int m_retain = 0; - int m_num_waiting = 0; - query_id m_q_id = 0; - - /// Is there a "dummy query" pending? - bool m_dummy_pending = false; - - /// Point at which an error occurred; no results beyond it will be available - query_id m_error = qid_limit(); - - /// Encoding. - /** We store this in the object to avoid the risk of exceptions at awkward - * moments. - */ - internal::encoding_group m_encoding; - - static constexpr std::string_view s_classname{"pipeline"}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pqxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pqxx deleted file mode 100644 index 17a8eaa9c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/pqxx +++ /dev/null @@ -1,28 +0,0 @@ -/// Convenience header: include all libpqxx definitions. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/array.hxx" -#include "pqxx/binarystring.hxx" -#include "pqxx/blob.hxx" -#include "pqxx/connection.hxx" -#include "pqxx/cursor.hxx" -#include "pqxx/errorhandler.hxx" -#include "pqxx/except.hxx" -#include "pqxx/largeobject.hxx" -#include "pqxx/nontransaction.hxx" -#include "pqxx/notification.hxx" -#include "pqxx/params.hxx" -#include "pqxx/pipeline.hxx" -#include "pqxx/prepared_statement.hxx" -#include "pqxx/result.hxx" -#include "pqxx/internal/result_iterator.hxx" -#include "pqxx/internal/result_iter.hxx" -#include "pqxx/robusttransaction.hxx" -#include "pqxx/row.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/stream_to.hxx" -#include "pqxx/subtransaction.hxx" -#include "pqxx/transaction.hxx" -#include "pqxx/transactor.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/prepared_statement b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/prepared_statement deleted file mode 100644 index 674be7090..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/prepared_statement +++ /dev/null @@ -1,3 +0,0 @@ -/// @deprecated Include @c instead. - -#include "params.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/prepared_statement.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/prepared_statement.hxx deleted file mode 100644 index 674be7090..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/prepared_statement.hxx +++ /dev/null @@ -1,3 +0,0 @@ -/// @deprecated Include @c instead. - -#include "params.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/range b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/range deleted file mode 100644 index 11985eca4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/range +++ /dev/null @@ -1,6 +0,0 @@ -/** Client-side support for SQL range types. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/range.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/range.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/range.hxx deleted file mode 100644 index dc480e4b7..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/range.hxx +++ /dev/null @@ -1,515 +0,0 @@ -#ifndef PQXX_H_RANGE -#define PQXX_H_RANGE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/internal/array-composite.hxx" -#include "pqxx/internal/concat.hxx" - -namespace pqxx -{ -/// An _unlimited_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should extend - * to infinity on that side. - * - * An unlimited boundary is always inclusive of "infinity" values, if the - * range's value type supports them. - */ -struct no_bound -{ - template constexpr bool extends_down_to(TYPE const &) const - { - return true; - } - template constexpr bool extends_up_to(TYPE const &) const - { - return true; - } -}; - - -/// An _inclusive_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should include - * the value. - */ -template class inclusive_bound -{ -public: - inclusive_bound() = delete; - explicit inclusive_bound(TYPE const &value) : m_value{value} - { - if (is_null(value)) - throw argument_error{"Got null value as an inclusive range bound."}; - } - - [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as a lower bound, include value? - [[nodiscard]] bool extends_down_to(TYPE const &value) const - { - return not(value < m_value); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as an upper bound, include value? - [[nodiscard]] bool extends_up_to(TYPE const &value) const - { - return not(m_value < value); - } - -private: - TYPE m_value; -}; - - -/// An _exclusive_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should _not_ - * include the value. - */ -template class exclusive_bound -{ -public: - exclusive_bound() = delete; - explicit exclusive_bound(TYPE const &value) : m_value{value} - { - if (is_null(value)) - throw argument_error{"Got null value as an exclusive range bound."}; - } - - [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as a lower bound, include value? - [[nodiscard]] bool extends_down_to(TYPE const &value) const - { - return m_value < value; - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as an upper bound, include value? - [[nodiscard]] bool extends_up_to(TYPE const &value) const - { - return value < m_value; - } - -private: - TYPE m_value; -}; - - -/// A range boundary value. -/** A range bound is either no bound at all; or an inclusive bound; or an - * exclusive bound. Pass one of the three to the constructor. - */ -template class range_bound -{ -public: - range_bound() = delete; - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(no_bound) : m_bound{} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(inclusive_bound const &bound) : m_bound{bound} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(exclusive_bound const &bound) : m_bound{bound} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(range_bound const &) = default; - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(range_bound &&) = default; - - // TODO: constexpr and/or noexcept if underlying operators support it. - bool operator==(range_bound const &rhs) const - { - if (this->is_limited()) - return ( - rhs.is_limited() and (this->is_inclusive() == rhs.is_inclusive()) and - (*this->value() == *rhs.value())); - else - return not rhs.is_limited(); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - bool operator!=(range_bound const &rhs) const { return not(*this == rhs); } - range_bound &operator=(range_bound const &) = default; - range_bound &operator=(range_bound &&) = default; - - /// Is this a finite bound? - constexpr bool is_limited() const noexcept - { - return not std::holds_alternative(m_bound); - } - - /// Is this boundary an inclusive one? - constexpr bool is_inclusive() const noexcept - { - return std::holds_alternative>(m_bound); - } - - /// Is this boundary an exclusive one? - constexpr bool is_exclusive() const noexcept - { - return std::holds_alternative>(m_bound); - } - - // TODO: constexpr/noexcept if underlying function supports it. - /// Would this bound, as a lower bound, include `value`? - bool extends_down_to(TYPE const &value) const - { - return std::visit( - [&value](auto const &bound) { return bound.extends_down_to(value); }, - m_bound); - } - - // TODO: constexpr/noexcept if underlying function supports it. - /// Would this bound, as an upper bound, include `value`? - bool extends_up_to(TYPE const &value) const - { - return std::visit( - [&value](auto const &bound) { return bound.extends_up_to(value); }, - m_bound); - } - - /// Return bound value, or `nullptr` if it's not limited. - [[nodiscard]] constexpr TYPE const *value() const &noexcept - { - return std::visit( - [](auto const &bound) noexcept { - using bound_t = std::decay_t; - if constexpr (std::is_same_v) - return static_cast(nullptr); - else - return &bound.get(); - }, - m_bound); - } - -private: - std::variant, exclusive_bound> m_bound; -}; - - -// C++20: Concepts for comparisons, construction, etc. -/// A C++ equivalent to PostgreSQL's range types. -/** You can use this as a client-side representation of a "range" in SQL. - * - * PostgreSQL defines several range types, differing in the data type over - * which they range. You can also define your own range types. - * - * Usually you'll want the server to deal with ranges. But on occasions where - * you need to work with them client-side, you may want to use @ref - * pqxx::range. (In cases where all you do is pass them along to the server - * though, it's not worth the complexity. In that case you might as well treat - * ranges as just strings.) - * - * For documentation on PostgreSQL's range types, see: - * https://www.postgresql.org/docs/current/rangetypes.html - * - * The value type must be copyable and default-constructible, and support the - * less-than (`<`) and equals (`==`) comparisons. Value initialisation must - * produce a consistent value. - */ -template class range -{ -public: - /// Create a range. - /** For each of the two bounds, pass a @ref no_bound, @ref inclusive_bound, - * or - * @ref exclusive_bound. - */ - range(range_bound lower, range_bound upper) : - m_lower{lower}, m_upper{upper} - { - if ( - lower.is_limited() and upper.is_limited() and - (*upper.value() < *lower.value())) - throw range_error{internal::concat( - "Range's lower bound (", *lower.value(), - ") is greater than its upper bound (", *upper.value(), ").")}; - } - - // TODO: constexpr and/or noexcept if underlying constructor supports it. - /// Create an empty range. - /** SQL has a separate literal to denote an empty range, but any range which - * encompasses no values is an empty range. - */ - range() : - m_lower{exclusive_bound{TYPE{}}}, - m_upper{exclusive_bound{TYPE{}}} - {} - - // TODO: constexpr and/or noexcept if underlying operators support it. - bool operator==(range const &rhs) const - { - return (this->lower_bound() == rhs.lower_bound() and - this->upper_bound() == rhs.upper_bound()) or - (this->empty() and rhs.empty()); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - bool operator!=(range const &rhs) const { return !(*this == rhs); } - - range(range const &) = default; - range(range &&) = default; - range &operator=(range const &) = default; - range &operator=(range &&) = default; - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Is this range clearly empty? - /** An empty range encompasses no values. - * - * It is possible to "fool" this. For example, if your range is of an - * integer type and has exclusive bounds of 0 and 1, it encompasses no values - * but its `empty()` will return false. The PostgreSQL implementation, by - * contrast, will notice that it is empty. Similar things can happen for - * floating-point types, but with more subtleties and edge cases. - */ - bool empty() const - { - return (m_lower.is_exclusive() or m_upper.is_exclusive()) and - m_lower.is_limited() and m_upper.is_limited() and - not(*m_lower.value() < *m_upper.value()); - } - - // TODO: constexpr and/or noexcept if underlying functions support it. - /// Does this range encompass `value`? - bool contains(TYPE value) const - { - return m_lower.extends_down_to(value) and m_upper.extends_up_to(value); - } - - // TODO: constexpr and/or noexcept if underlying operators support it. - /// Does this range encompass all of `other`? - /** This function is not particularly smart. It does not know, for example, - * that integer ranges `[0,9]` and `[0,10)` contain the same values. - */ - bool contains(range const &other) const - { - return (*this & other) == other; - } - - [[nodiscard]] constexpr range_bound const & - lower_bound() const &noexcept - { - return m_lower; - } - [[nodiscard]] constexpr range_bound const & - upper_bound() const &noexcept - { - return m_upper; - } - - // TODO: constexpr and/or noexcept if underlying operators support it. - /// Intersection of two ranges. - /** Returns a range describing those values which are in both ranges. - */ - range operator&(range const &other) const - { - range_bound lower{no_bound{}}; - if (not this->lower_bound().is_limited()) - lower = other.lower_bound(); - else if (not other.lower_bound().is_limited()) - lower = this->lower_bound(); - else if (*this->lower_bound().value() < *other.lower_bound().value()) - lower = other.lower_bound(); - else if (*other.lower_bound().value() < *this->lower_bound().value()) - lower = this->lower_bound(); - else if (this->lower_bound().is_exclusive()) - lower = this->lower_bound(); - else - lower = other.lower_bound(); - - range_bound upper{no_bound{}}; - if (not this->upper_bound().is_limited()) - upper = other.upper_bound(); - else if (not other.upper_bound().is_limited()) - upper = this->upper_bound(); - else if (*other.upper_bound().value() < *this->upper_bound().value()) - upper = other.upper_bound(); - else if (*this->upper_bound().value() < *other.upper_bound().value()) - upper = this->upper_bound(); - else if (this->upper_bound().is_exclusive()) - upper = this->upper_bound(); - else - upper = other.upper_bound(); - - if ( - lower.is_limited() and upper.is_limited() and - (*upper.value() < *lower.value())) - return {}; - else - return {lower, upper}; - } - - /// Convert to another base type. - template operator range() const - { - range_bound lower{no_bound{}}, upper{no_bound{}}; - if (lower_bound().is_inclusive()) - lower = inclusive_bound{*lower_bound().value()}; - else if (lower_bound().is_exclusive()) - lower = exclusive_bound{*lower_bound().value()}; - - if (upper_bound().is_inclusive()) - upper = inclusive_bound{*upper_bound().value()}; - else if (upper_bound().is_exclusive()) - upper = exclusive_bound{*upper_bound().value()}; - - return {lower, upper}; - } - -private: - range_bound m_lower, m_upper; -}; - - -/// String conversions for a @ref range type. -/** Conversion assumes that either your client encoding is UTF-8, or the values - * are pure ASCII. - */ -template struct string_traits> -{ - [[nodiscard]] static inline zview - to_buf(char *begin, char *end, range const &value) - { - return generic_to_buf(begin, end, value); - } - - static inline char * - into_buf(char *begin, char *end, range const &value) - { - if (value.empty()) - { - if ((end - begin) <= internal::ssize(s_empty)) - throw conversion_overrun{s_overrun.c_str()}; - char *here = begin + s_empty.copy(begin, std::size(s_empty)); - *here++ = '\0'; - return here; - } - else - { - if (end - begin < 4) - throw conversion_overrun{s_overrun.c_str()}; - char *here = begin; - *here++ = - (static_cast(value.lower_bound().is_inclusive() ? '[' : '(')); - TYPE const *lower{value.lower_bound().value()}; - // Convert bound (but go back to overwrite that trailing zero). - if (lower != nullptr) - here = string_traits::into_buf(here, end, *lower) - 1; - *here++ = ','; - TYPE const *upper{value.upper_bound().value()}; - // Convert bound (but go back to overwrite that trailing zero). - if (upper != nullptr) - here = string_traits::into_buf(here, end, *upper) - 1; - if ((end - here) < 2) - throw conversion_overrun{s_overrun.c_str()}; - *here++ = - static_cast(value.upper_bound().is_inclusive() ? ']' : ')'); - *here++ = '\0'; - return here; - } - } - - [[nodiscard]] static inline range from_string(std::string_view text) - { - if (std::size(text) < 3) - throw pqxx::conversion_error{err_bad_input(text)}; - bool left_inc{false}; - switch (text[0]) - { - case '[': left_inc = true; break; - - case '(': break; - - case 'e': - case 'E': - if ( - (std::size(text) != std::size(s_empty)) or - (text[1] != 'm' and text[1] != 'M') or - (text[2] != 'p' and text[2] != 'P') or - (text[3] != 't' and text[3] != 'T') or - (text[4] != 'y' and text[4] != 'Y')) - throw pqxx::conversion_error{err_bad_input(text)}; - return {}; - break; - - default: throw pqxx::conversion_error{err_bad_input(text)}; - } - - auto scan{internal::get_glyph_scanner(internal::encoding_group::UTF8)}; - // The field parser uses this to track which field it's parsing, and - // when not to expect a field separator. - std::size_t index{0}; - // The last field we expect to see. - static constexpr std::size_t last{1}; - // Current parsing position. We skip the opening parenthesis or bracket. - std::size_t pos{1}; - // The string may leave out either bound to indicate that it's unlimited. - std::optional lower, upper; - // We reuse the same field parser we use for composite values and arrays. - internal::parse_composite_field(index, text, pos, lower, scan, last); - internal::parse_composite_field(index, text, pos, upper, scan, last); - - // We need one more character: the closing parenthesis or bracket. - if (pos != std::size(text)) - throw pqxx::conversion_error{err_bad_input(text)}; - char const closing{text[pos - 1]}; - if (closing != ')' and closing != ']') - throw pqxx::conversion_error{err_bad_input(text)}; - bool const right_inc{closing == ']'}; - - range_bound lower_bound{no_bound{}}, upper_bound{no_bound{}}; - if (lower) - { - if (left_inc) - lower_bound = inclusive_bound{*lower}; - else - lower_bound = exclusive_bound{*lower}; - } - if (upper) - { - if (right_inc) - upper_bound = inclusive_bound{*upper}; - else - upper_bound = exclusive_bound{*upper}; - } - - return {lower_bound, upper_bound}; - } - - [[nodiscard]] static inline constexpr std::size_t - size_buffer(range const &value) noexcept - { - TYPE const *lower{value.lower_bound().value()}, - *upper{value.upper_bound().value()}; - std::size_t const lsz{ - lower == nullptr ? 0 : string_traits::size_buffer(*lower) - 1}, - usz{upper == nullptr ? 0 : string_traits::size_buffer(*upper) - 1}; - - if (value.empty()) - return std::size(s_empty) + 1; - else - return 1 + lsz + 1 + usz + 2; - } - -private: - static constexpr zview s_empty{"empty"_zv}; - static constexpr auto s_overrun{"Not enough space in buffer for range."_zv}; - - /// Compose error message for invalid range input. - static std::string err_bad_input(std::string_view text) - { - return internal::concat("Invalid range input: '", text, "'"); - } -}; - - -/// A range type does not have an innate null value. -template struct nullness> : no_null> -{}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/result b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/result deleted file mode 100644 index 523394b72..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/result +++ /dev/null @@ -1,16 +0,0 @@ -/** pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/result.hxx" - -// Now include some types which depend on result, but which the user will -// expect to see defined after including this header. -#include "pqxx/internal/result_iterator.hxx" -#include "pqxx/field.hxx" -#include "pqxx/internal/result_iter.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/result.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/result.hxx deleted file mode 100644 index 6c41cc096..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/result.hxx +++ /dev/null @@ -1,335 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT -#define PQXX_H_RESULT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include - -#include "pqxx/except.hxx" -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - -#include "pqxx/internal/encodings.hxx" - - -namespace pqxx::internal -{ -// TODO: Make noexcept (but breaks ABI). -PQXX_LIBEXPORT void clear_result(pq::PGresult const *); -} // namespace pqxx::internal - - -namespace pqxx::internal::gate -{ -class result_connection; -class result_creation; -class result_pipeline; -class result_row; -class result_sql_cursor; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Result set containing data returned by a query or command. -/** This behaves as a container (as defined by the C++ standard library) and - * provides random access const iterators to iterate over its rows. You can - * also access a row by indexing a `result R` by the row's zero-based - * number: - * - * - * for (result::size_type i=0; i < std::size(R); ++i) Process(R[i]); - * - * - * Result sets in libpqxx are lightweight, reference-counted wrapper objects - * which are relatively small and cheap to copy. Think of a result object as - * a "smart pointer" to an underlying result set. - * - * @warning The result set that a result object points to is not thread-safe. - * If you copy a result object, it still refers to the same underlying result - * set. So never copy, destroy, query, or otherwise access a result while - * another thread may be copying, destroying, querying, or otherwise accessing - * the same result set--even if it is doing so through a different result - * object! - */ -class PQXX_LIBEXPORT result -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - using reference = row; - using const_iterator = const_result_iterator; - using pointer = const_iterator; - using iterator = const_iterator; - using const_reverse_iterator = const_reverse_result_iterator; - using reverse_iterator = const_reverse_iterator; - - result() noexcept : - m_data{make_data_pointer()}, - m_query{}, - m_encoding{internal::encoding_group::MONOBYTE} - {} - - result(result const &rhs) noexcept = default; - result(result &&rhs) noexcept = default; - - /// Assign one result to another. - /** Copying results is cheap: it copies only smart pointers, but the actual - * data stays in the same place. - */ - result &operator=(result const &rhs) noexcept = default; - - /// Assign one result to another, invaliding the old one. - result &operator=(result &&rhs) noexcept = default; - - /** - * @name Comparisons - * - * You can compare results for equality. Beware: this is a very strict, - * dumb comparison. The smallest difference between two results (such as a - * string "Foo" versus a string "foo") will make them unequal. - */ - //@{ - /// Compare two results for equality. - [[nodiscard]] bool operator==(result const &) const noexcept; - /// Compare two results for inequality. - [[nodiscard]] bool operator!=(result const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - /// Iterate rows, reading them directly into a tuple of "TYPE...". - /** Converts the fields to values of the given respective types. - * - * Use this only with a ranged "for" loop. The iteration produces - * std::tuple which you can "unpack" to a series of `auto` - * variables. - */ - template auto iter() const; - - [[nodiscard]] const_reverse_iterator rbegin() const; - [[nodiscard]] const_reverse_iterator crbegin() const; - [[nodiscard]] const_reverse_iterator rend() const; - [[nodiscard]] const_reverse_iterator crend() const; - - [[nodiscard]] const_iterator begin() const noexcept; - [[nodiscard]] const_iterator cbegin() const noexcept; - [[nodiscard]] inline const_iterator end() const noexcept; - [[nodiscard]] inline const_iterator cend() const noexcept; - - [[nodiscard]] reference front() const noexcept; - [[nodiscard]] reference back() const noexcept; - - [[nodiscard]] PQXX_PURE size_type size() const noexcept; - [[nodiscard]] PQXX_PURE bool empty() const noexcept; - [[nodiscard]] size_type capacity() const noexcept { return size(); } - - /// Exchange two `result` values in an exception-safe manner. - /** If the swap fails, the two values will be exactly as they were before. - * - * The swap is not necessarily thread-safe. - */ - void swap(result &) noexcept; - - /// Index a row by number. - /** This returns a @ref row object. Generally you should not keep the row - * around as a variable, but if you do, make sure that your variable is a - * `row`, not a `row&`. - */ - [[nodiscard]] row operator[](size_type i) const noexcept; - -#if defined(PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT) - // TODO: If C++23 will let us, also accept string for the column. - [[nodiscard]] field - operator[](size_type row_num, row_size_type col_num) const noexcept; -#endif - - /// Index a row by number, but check that the row number is valid. - row at(size_type) const; - - /// Index a field by row number and column number. - field at(size_type, row_size_type) const; - - /// Let go of the result's data. - /** Use this if you need to deallocate the result data earlier than you can - * destroy the `result` object itself. - * - * Multiple `result` objects can refer to the same set of underlying data. - * The underlying data will be deallocated once all `result` objects that - * refer to it are cleared or destroyed. - */ - void clear() noexcept - { - m_data.reset(); - m_query = nullptr; - } - - /** - * @name Column information - */ - //@{ - /// Number of columns in result. - [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept; - - /// Number of given column (throws exception if it doesn't exist). - [[nodiscard]] row_size_type column_number(zview name) const; - - /// Name of column with this number (throws exception if it doesn't exist) - [[nodiscard]] char const *column_name(row_size_type number) const &; - - /// Return column's type, as an OID from the system catalogue. - [[nodiscard]] oid column_type(row_size_type col_num) const; - - /// Return column's type, as an OID from the system catalogue. - [[nodiscard]] oid column_type(zview col_name) const - { - return column_type(column_number(col_name)); - } - - /// What table did this column come from? - [[nodiscard]] oid column_table(row_size_type col_num) const; - - /// What table did this column come from? - [[nodiscard]] oid column_table(zview col_name) const - { - return column_table(column_number(col_name)); - } - - /// What column in its table did this column come from? - [[nodiscard]] row_size_type table_column(row_size_type col_num) const; - - /// What column in its table did this column come from? - [[nodiscard]] row_size_type table_column(zview col_name) const - { - return table_column(column_number(col_name)); - } - //@} - - /// Query that produced this result, if available (empty string otherwise) - [[nodiscard]] PQXX_PURE std::string const &query() const &noexcept; - - /// If command was an `INSERT` of 1 row, return oid of the inserted row. - /** @return Identifier of inserted row if exactly one row was inserted, or - * @ref oid_none otherwise. - */ - [[nodiscard]] PQXX_PURE oid inserted_oid() const; - - /// If command was `INSERT`, `UPDATE`, or `DELETE`: number of affected rows. - /** @return Number of affected rows if last command was `INSERT`, `UPDATE`, - * or `DELETE`; zero for all other commands. - */ - [[nodiscard]] PQXX_PURE size_type affected_rows() const; - - // C++20: Concept like std::invocable, but without specifying param types. - /// Run `func` on each row, passing the row's fields as parameters. - /** Goes through the rows from first to last. You provide a callable `func`. - * - * For each row in the `result`, `for_each` will call `func`. It converts - * the row's fields to the types of `func`'s parameters, and pass them to - * `func`. - * - * (Therefore `func` must have a _single_ signature. It can't be a generic - * lambda, or an object of a class with multiple overloaded function call - * operators. Otherwise, `for_each` will have no way to detect a parameter - * list without ambiguity.) - * - * If any of your parameter types is `std::string_view`, it refers to the - * underlying storage of this `result`. - * - * If any of your parameter types is a reference type, its argument will - * refer to a temporary value which only lives for the duration of that - * single invocation to `func`. If the reference is an lvalue reference, it - * must be `const`. - * - * For example, this queries employee names and salaries from the database - * and prints how much each would like to earn instead: - * ```cxx - * tx.exec("SELECT name, salary FROM employee").for_each( - * [](std::string_view name, float salary){ - * std::cout << name << " would like " << salary * 2 << ".\n"; - * }) - * ``` - * - * If `func` throws an exception, processing stops at that point and - * propagates the exception. - * - * @throws usage_error if `func`'s number of parameters does not match the - * number of columns in this result. - */ - template inline void for_each(CALLABLE &&func) const; - -private: - using data_pointer = std::shared_ptr; - - /// Underlying libpq result set. - data_pointer m_data; - - /// Factory for data_pointer. - static data_pointer - make_data_pointer(internal::pq::PGresult const *res = nullptr) noexcept - { - return {res, internal::clear_result}; - } - - friend class pqxx::internal::gate::result_pipeline; - PQXX_PURE std::shared_ptr query_ptr() const noexcept - { - return m_query; - } - - /// Query string. - std::shared_ptr m_query; - - internal::encoding_group m_encoding; - - static std::string const s_empty_string; - - friend class pqxx::field; - // TODO: noexcept. Breaks ABI. - PQXX_PURE char const *get_value(size_type row, row_size_type col) const; - // TODO: noexcept. Breaks ABI. - PQXX_PURE bool get_is_null(size_type row, row_size_type col) const; - PQXX_PURE - field_size_type get_length(size_type, row_size_type) const noexcept; - - friend class pqxx::internal::gate::result_creation; - result( - internal::pq::PGresult *rhs, std::shared_ptr query, - internal::encoding_group enc); - - PQXX_PRIVATE void check_status(std::string_view desc = ""sv) const; - - friend class pqxx::internal::gate::result_connection; - friend class pqxx::internal::gate::result_row; - bool operator!() const noexcept { return m_data.get() == nullptr; } - operator bool() const noexcept { return m_data.get() != nullptr; } - - [[noreturn]] PQXX_PRIVATE void - throw_sql_error(std::string const &Err, std::string const &Query) const; - PQXX_PRIVATE PQXX_PURE int errorposition() const; - PQXX_PRIVATE std::string status_error() const; - - friend class pqxx::internal::gate::result_sql_cursor; - PQXX_PURE char const *cmd_status() const noexcept; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/robusttransaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/robusttransaction deleted file mode 100644 index 04b71d7cc..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/robusttransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::robusttransaction class. - * - * pqxx::robusttransaction is a slower but safer transaction class. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/robusttransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/robusttransaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/robusttransaction.hxx deleted file mode 100644 index faf6dbf5e..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/robusttransaction.hxx +++ /dev/null @@ -1,120 +0,0 @@ -/* Definition of the pqxx::robusttransaction class. - * - * pqxx::robusttransaction is a slower but safer transaction class. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ROBUSTTRANSACTION -#define PQXX_H_ROBUSTTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx::internal -{ -/// Helper base class for the @ref robusttransaction class template. -class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction - : public dbtransaction -{ -public: - virtual ~basic_robusttransaction() override = 0; - -protected: - basic_robusttransaction( - connection &c, zview begin_command, std::string_view tname); - basic_robusttransaction(connection &c, zview begin_command); - -private: - using IDType = unsigned long; - - std::string m_conn_string; - std::string m_xid; - int m_backendpid = -1; - - void init(zview begin_command); - - // @warning This function will become `final`. - virtual void do_commit() override; -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @ingroup transactions - * - * @{ - */ - -/// Slightly slower, better-fortified version of transaction. -/** Requires PostgreSQL 10 or better. - * - * robusttransaction is similar to transaction, but spends more time and effort - * to deal with the hopefully rare case that the connection to the backend is - * lost just while it's trying to commit. In such cases, the client does not - * know whether the backend (on the other side of the broken connection) - * managed to commit the transaction. - * - * When this happens, robusttransaction tries to reconnect to the database and - * figure out what happened. - * - * This service level was made optional since you may not want to pay the - * overhead where it is not necessary. Certainly the use of this class makes - * no sense for local connections, or for transactions that read the database - * but never modify it, or for noncritical database manipulations. - * - * Besides being slower, it's also more complex. Which means that in practice - * a robusttransaction could actually fail more instead of less often than a - * normal transaction. What robusttransaction tries to achieve is to give you - * certainty, not just be more successful per se. - */ -template -class robusttransaction final : public internal::basic_robusttransaction -{ -public: - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - * @param tname optional human-readable name for this transaction. - */ - robusttransaction(connection &c, std::string_view tname) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd, - tname} - {} - - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - * @param tname optional human-readable name for this transaction. - */ - robusttransaction(connection &c, std::string &&tname) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd, - std::move(tname)} - {} - - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - */ - explicit robusttransaction(connection &c) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd} - {} - - virtual ~robusttransaction() noexcept override { close(); } -}; - -/** - * @} - */ -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/row b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/row deleted file mode 100644 index 62a950ac8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/row +++ /dev/null @@ -1,11 +0,0 @@ -/** pqxx::row class. - * - * pqxx::row refers to a row in a result. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/row.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/row.hxx deleted file mode 100644 index 5be5132e3..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/row.hxx +++ /dev/null @@ -1,561 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ROW -#define PQXX_H_ROW - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/except.hxx" -#include "pqxx/field.hxx" -#include "pqxx/result.hxx" - -#include "pqxx/internal/concat.hxx" - -namespace pqxx::internal -{ -template class result_iter; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// Reference to one row in a result. -/** A row represents one row (also called a row) in a query result set. - * It also acts as a container mapping column numbers or names to field - * values (see below): - * - * ```cxx - * cout << row["date"].c_str() << ": " << row["name"].c_str() << endl; - * ``` - * - * The row itself acts like a (non-modifyable) container, complete with its - * own const_iterator and const_reverse_iterator. - */ -class PQXX_LIBEXPORT row -{ -public: - using size_type = row_size_type; - using difference_type = row_difference_type; - using const_iterator = const_row_iterator; - using iterator = const_iterator; - using reference = field; - using pointer = const_row_iterator; - using const_reverse_iterator = const_reverse_row_iterator; - using reverse_iterator = const_reverse_iterator; - - row() noexcept = default; - row(row &&) noexcept = default; - row(row const &) noexcept = default; - row &operator=(row const &) noexcept = default; - row &operator=(row &&) noexcept = default; - - /** - * @name Comparison - */ - //@{ - [[nodiscard]] PQXX_PURE bool operator==(row const &) const noexcept; - [[nodiscard]] bool operator!=(row const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - [[nodiscard]] const_iterator begin() const noexcept; - [[nodiscard]] const_iterator cbegin() const noexcept; - [[nodiscard]] const_iterator end() const noexcept; - [[nodiscard]] const_iterator cend() const noexcept; - - /** - * @name Field access - */ - //@{ - [[nodiscard]] reference front() const noexcept; - [[nodiscard]] reference back() const noexcept; - - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator rbegin() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator crbegin() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator rend() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator crend() const; - - [[nodiscard]] reference operator[](size_type) const noexcept; - /** Address field by name. - * @warning This is much slower than indexing by number, or iterating. - */ - [[nodiscard]] reference operator[](zview col_name) const; - - reference at(size_type) const; - /** Address field by name. - * @warning This is much slower than indexing by number, or iterating. - */ - reference at(zview col_name) const; - - [[nodiscard]] constexpr size_type size() const noexcept - { - return m_end - m_begin; - } - - [[deprecated("Swap iterators, not rows.")]] void swap(row &) noexcept; - - /// Row number, assuming this is a real row and not end()/rend(). - [[nodiscard]] constexpr result::size_type rownumber() const noexcept - { - return m_index; - } - - /** - * @name Column information - */ - //@{ - /// Number of given column (throws exception if it doesn't exist). - [[nodiscard]] size_type column_number(zview col_name) const; - - /// Return a column's type. - [[nodiscard]] oid column_type(size_type) const; - - /// Return a column's type. - [[nodiscard]] oid column_type(zview col_name) const - { - return column_type(column_number(col_name)); - } - - /// What table did this column come from? - [[nodiscard]] oid column_table(size_type col_num) const; - - /// What table did this column come from? - [[nodiscard]] oid column_table(zview col_name) const - { - return column_table(column_number(col_name)); - } - - /// What column number in its table did this result column come from? - /** A meaningful answer can be given only if the column in question comes - * directly from a column in a table. If the column is computed in any - * other way, a logic_error will be thrown. - * - * @param col_num a zero-based column number in this result set - * @return a zero-based column number in originating table - */ - [[nodiscard]] size_type table_column(size_type) const; - - /// What column number in its table did this result column come from? - [[nodiscard]] size_type table_column(zview col_name) const - { - return table_column(column_number(col_name)); - } - //@} - - [[nodiscard]] constexpr result::size_type num() const noexcept - { - return rownumber(); - } - - /** Produce a slice of this row, containing the given range of columns. - * - * @deprecated I haven't heard of anyone caring about row slicing at all in - * at least the last 15 years. Yet it adds complexity, so unless anyone - * files a bug explaining why they really need this feature, I'm going to - * remove it. Even if they do, the feature may need an update. - * - * The slice runs from the range's starting column to the range's end - * column, exclusive. It looks just like a normal result row, except - * slices can be empty. - */ - [[deprecated("Row slicing is going away. File a bug if you need it.")]] row - slice(size_type sbegin, size_type send) const; - - /// Is this a row without fields? Can only happen to a slice. - [[nodiscard, deprecated("Row slicing is going away.")]] PQXX_PURE bool - empty() const noexcept; - - /// Extract entire row's values into a tuple. - /** Converts to the types of the tuple's respective fields. - */ - template void to(Tuple &t) const - { - check_size(std::tuple_size_v); - convert(t); - } - - template std::tuple as() const - { - check_size(sizeof...(TYPE)); - using seq = std::make_index_sequence; - return get_tuple>(seq{}); - } - -protected: - friend class const_row_iterator; - friend class result; - row(result const &r, result_size_type index, size_type cols) noexcept; - - /// Throw @ref usage_error if row size is not `expected`. - void check_size(size_type expected) const - { - if (size() != expected) - throw usage_error{internal::concat( - "Tried to extract ", expected, " field(s) from a row of ", size(), - ".")}; - } - - /// Convert to a given tuple of values, don't check sizes. - /** We need this for cases where we have a full tuple of field types, but - * not a parameter pack. - */ - template TUPLE as_tuple() const - { - using seq = std::make_index_sequence>; - return get_tuple(seq{}); - } - - template friend class pqxx::internal::result_iter; - /// Convert entire row to tuple fields, without checking row size. - template void convert(Tuple &t) const - { - extract_fields(t, std::make_index_sequence>{}); - } - - friend class field; - - /// Result set of which this is one row. - result m_result; - - /// Row number. - /** - * You'd expect this to be unsigned, but due to the way reverse iterators - * are related to regular iterators, it must be allowed to underflow to -1. - */ - result::size_type m_index = 0; - - // TODO: Remove m_begin and (if possible) m_end when we remove slice(). - /// First column in slice. This row ignores lower-numbered columns. - size_type m_begin = 0; - /// End column in slice. This row only sees lower-numbered columns. - size_type m_end = 0; - -private: - template - void extract_fields(Tuple &t, std::index_sequence) const - { - (extract_value(t), ...); - } - - template - void extract_value(Tuple &t) const; - - /// Convert row's values as a new tuple. - template - auto get_tuple(std::index_sequence) const - { - return std::make_tuple(get_field()...); - } - - /// Extract and convert a field. - template auto get_field() const - { - return (*this)[index].as>(); - } -}; - - -/// Iterator for fields in a row. Use as row::const_iterator. -class PQXX_LIBEXPORT const_row_iterator : public field -{ -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = field const; - using pointer = field const *; - using size_type = row_size_type; - using difference_type = row_difference_type; - using reference = field; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - const_row_iterator() = default; -#include "pqxx/internal/ignore-deprecated-post.hxx" - const_row_iterator(row const &t, row_size_type c) noexcept : - field{t.m_result, t.m_index, c} - {} - const_row_iterator(field const &F) noexcept : field{F} {} - const_row_iterator(const_row_iterator const &) noexcept = default; - const_row_iterator(const_row_iterator &&) noexcept = default; - - /** - * @name Dereferencing operators - */ - //@{ - [[nodiscard]] constexpr pointer operator->() const noexcept { return this; } - [[nodiscard]] reference operator*() const noexcept { return {*this}; } - //@} - - /** - * @name Manipulations - */ - //@{ - const_row_iterator &operator=(const_row_iterator const &) noexcept = default; - const_row_iterator &operator=(const_row_iterator &&) noexcept = default; - - // TODO: noexcept. Breaks ABI. - const_row_iterator operator++(int); - const_row_iterator &operator++() noexcept - { - ++m_col; - return *this; - } - // TODO: noexcept. Breaks ABI. - const_row_iterator operator--(int); - const_row_iterator &operator--() noexcept - { - --m_col; - return *this; - } - - const_row_iterator &operator+=(difference_type i) noexcept - { - m_col = size_type(difference_type(m_col) + i); - return *this; - } - const_row_iterator &operator-=(difference_type i) noexcept - { - m_col = size_type(difference_type(m_col) - i); - return *this; - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] constexpr bool - operator==(const_row_iterator const &i) const noexcept - { - return col() == i.col(); - } - [[nodiscard]] constexpr bool - operator!=(const_row_iterator const &i) const noexcept - { - return col() != i.col(); - } - [[nodiscard]] constexpr bool - operator<(const_row_iterator const &i) const noexcept - { - return col() < i.col(); - } - [[nodiscard]] constexpr bool - operator<=(const_row_iterator const &i) const noexcept - { - return col() <= i.col(); - } - [[nodiscard]] constexpr bool - operator>(const_row_iterator const &i) const noexcept - { - return col() > i.col(); - } - [[nodiscard]] constexpr bool - operator>=(const_row_iterator const &i) const noexcept - { - return col() >= i.col(); - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] inline const_row_iterator - operator+(difference_type) const noexcept; - - friend const_row_iterator - operator+(difference_type, const_row_iterator const &) noexcept; - - [[nodiscard]] inline const_row_iterator - operator-(difference_type) const noexcept; - [[nodiscard]] inline difference_type - operator-(const_row_iterator const &) const noexcept; - //@} -}; - - -/// Reverse iterator for a row. Use as row::const_reverse_iterator. -class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator -{ -public: - using super = const_row_iterator; - using iterator_type = const_row_iterator; - using iterator_type::difference_type; - using iterator_type::iterator_category; - using iterator_type::pointer; - using value_type = iterator_type::value_type; - using reference = iterator_type::reference; - - const_reverse_row_iterator() noexcept = default; - const_reverse_row_iterator(const_reverse_row_iterator const &) noexcept = - default; - const_reverse_row_iterator(const_reverse_row_iterator &&) noexcept = default; - - explicit const_reverse_row_iterator(super const &rhs) noexcept : - const_row_iterator{rhs} - { - super::operator--(); - } - - [[nodiscard]] PQXX_PURE iterator_type base() const noexcept; - - /** - * @name Dereferencing operators - */ - //@{ - using iterator_type::operator->; - using iterator_type::operator*; - //@} - - /** - * @name Manipulations - */ - //@{ - const_reverse_row_iterator & - operator=(const_reverse_row_iterator const &r) noexcept - { - iterator_type::operator=(r); - return *this; - } - const_reverse_row_iterator operator++() noexcept - { - iterator_type::operator--(); - return *this; - } - // TODO: noexcept. Breaks ABI. - const_reverse_row_iterator operator++(int); - const_reverse_row_iterator &operator--() noexcept - { - iterator_type::operator++(); - return *this; - } - const_reverse_row_iterator operator--(int); - // TODO: noexcept. Breaks ABI. - const_reverse_row_iterator &operator+=(difference_type i) noexcept - { - iterator_type::operator-=(i); - return *this; - } - const_reverse_row_iterator &operator-=(difference_type i) noexcept - { - iterator_type::operator+=(i); - return *this; - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] const_reverse_row_iterator - operator+(difference_type i) const noexcept - { - return const_reverse_row_iterator{base() - i}; - } - [[nodiscard]] const_reverse_row_iterator - operator-(difference_type i) noexcept - { - return const_reverse_row_iterator{base() + i}; - } - [[nodiscard]] difference_type - operator-(const_reverse_row_iterator const &rhs) const noexcept - { - return rhs.const_row_iterator::operator-(*this); - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool - operator==(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator==(rhs); - } - [[nodiscard]] bool - operator!=(const_reverse_row_iterator const &rhs) const noexcept - { - return !operator==(rhs); - } - - [[nodiscard]] constexpr bool - operator<(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator>(rhs); - } - [[nodiscard]] constexpr bool - operator<=(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator>=(rhs); - } - [[nodiscard]] constexpr bool - operator>(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator<(rhs); - } - [[nodiscard]] constexpr bool - operator>=(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator<=(rhs); - } - //@} -}; - - -const_row_iterator -const_row_iterator::operator+(difference_type o) const noexcept -{ - // TODO:: More direct route to home().columns()? - return { - row{home(), idx(), home().columns()}, - size_type(difference_type(col()) + o)}; -} - -inline const_row_iterator operator+( - const_row_iterator::difference_type o, const_row_iterator const &i) noexcept -{ - return i + o; -} - -inline const_row_iterator -const_row_iterator::operator-(difference_type o) const noexcept -{ - // TODO:: More direct route to home().columns()? - return { - row{home(), idx(), home().columns()}, - size_type(difference_type(col()) - o)}; -} - -inline const_row_iterator::difference_type -const_row_iterator::operator-(const_row_iterator const &i) const noexcept -{ - return difference_type(num() - i.num()); -} - - -template -inline void row::extract_value(Tuple &t) const -{ - using field_type = strip_t(t))>; - field const f{m_result, m_index, index}; - std::get(t) = from_string(f); -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/separated_list b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/separated_list deleted file mode 100644 index 1bdf51c6a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/separated_list +++ /dev/null @@ -1,6 +0,0 @@ -/** Helper similar to Python's @c str.join(). - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/separated_list.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/separated_list.hxx deleted file mode 100644 index d4230ea08..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/separated_list.hxx +++ /dev/null @@ -1,142 +0,0 @@ -/* Helper similar to Python's `str.join()`. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SEPARATED_LIST -#define PQXX_H_SEPARATED_LIST - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/strconv.hxx" - -// C++20: Simplify using std::ranges::range. -// C++20: Optimise buffer allocation using random_access_range/iterator. -namespace pqxx -{ -/** - * @defgroup utility Utility functions - */ -//@{ - -/// Represent sequence of values as a string, joined by a given separator. -/** - * Use this to turn e.g. the numbers 1, 2, and 3 into a string "1, 2, 3". - * - * @param sep separator string (to be placed between items) - * @param begin beginning of items sequence - * @param end end of items sequence - * @param access functor defining how to dereference sequence elements - */ -template -[[nodiscard]] inline std::string -separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access) -{ - if (end == begin) - return {}; - auto next{begin}; - ++next; - if (next == end) - return to_string(access(begin)); - - // From here on, we've got at least 2 elements -- meaning that we need sep. - using elt_type = strip_t; - using traits = string_traits; - - std::size_t budget{0}; - for (ITER cnt{begin}; cnt != end; ++cnt) - budget += traits::size_buffer(access(cnt)); - budget += - static_cast(std::distance(begin, end)) * std::size(sep); - - std::string result; - result.resize(budget); - - char *const data{result.data()}; - char *here{data}; - char *stop{data + budget}; - here = traits::into_buf(here, stop, access(begin)) - 1; - for (++begin; begin != end; ++begin) - { - here += sep.copy(here, std::size(sep)); - here = traits::into_buf(here, stop, access(begin)) - 1; - } - result.resize(static_cast(here - data)); - return result; -} - - -/// Render sequence as a string, using given separator between items. -template -[[nodiscard]] inline std::string -separated_list(std::string_view sep, ITER begin, ITER end) -{ - return separated_list(sep, begin, end, [](ITER i) { return *i; }); -} - - -/// Render items in a container as a string, using given separator. -template -[[nodiscard]] inline auto -separated_list(std::string_view sep, CONTAINER const &c) - /* - Always std::string; necessary because SFINAE doesn't work with the - contents of function bodies, so the check for iterability has to be in - the signature. - */ - -> typename std::enable_if< - (not std::is_void::value and - not std::is_void::value), - std::string>::type -{ - return separated_list(sep, std::begin(c), std::end(c)); -} - - -/// Render items in a tuple as a string, using given separator. -template< - typename TUPLE, std::size_t INDEX = 0, typename ACCESS, - typename std::enable_if< - (INDEX == std::tuple_size::value - 1), int>::type = 0> -[[nodiscard]] inline std::string separated_list( - std::string_view /* sep */, TUPLE const &t, ACCESS const &access) -{ - return to_string(access(&std::get(t))); -} - -template< - typename TUPLE, std::size_t INDEX = 0, typename ACCESS, - typename std::enable_if< - (INDEX < std::tuple_size::value - 1), int>::type = 0> -[[nodiscard]] inline std::string -separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access) -{ - std::string out{to_string(access(&std::get(t)))}; - out.append(sep); - out.append(separated_list(sep, t, access)); - return out; -} - -template< - typename TUPLE, std::size_t INDEX = 0, - typename std::enable_if< - (INDEX <= std::tuple_size::value), int>::type = 0> -[[nodiscard]] inline std::string -separated_list(std::string_view sep, TUPLE const &t) -{ - // TODO: Optimise allocation. - return separated_list(sep, t, [](TUPLE const &tup) { return *tup; }); -} -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/strconv b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/strconv deleted file mode 100644 index aa2c40ed5..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/strconv +++ /dev/null @@ -1,6 +0,0 @@ -/** String conversion definitions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/strconv.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/strconv.hxx deleted file mode 100644 index 863711228..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/strconv.hxx +++ /dev/null @@ -1,468 +0,0 @@ -/* String conversion definitions. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STRCONV -#define PQXX_H_STRCONV - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -#if defined(PQXX_HAVE_RANGES) && __has_include() -# include -#endif - -#include "pqxx/except.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - - -namespace pqxx::internal -{ -/// Attempt to demangle @c std::type_info::name() to something human-readable. -PQXX_LIBEXPORT std::string demangle_type_name(char const[]); -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @defgroup stringconversion String conversion - * - * The PostgreSQL server accepts and represents data in string form. It has - * its own formats for various data types. The string conversions define how - * various C++ types translate to and from their respective PostgreSQL text - * representations. - * - * Each conversion is defined by a specialisations of @c string_traits. It - * gets complicated if you want top performance, but until you do, all you - * really need to care about when converting values between C++ in-memory - * representations such as @c int and the postgres string representations is - * the @c pqxx::to_string and @c pqxx::from_string functions. - * - * If you need to convert a type which is not supported out of the box, you'll - * need to define your own specialisations for these templates, similar to the - * ones defined here and in `pqxx/conversions.hxx`. Any conversion code which - * "sees" your specialisation will now support your conversion. In particular, - * you'll be able to read result fields into a variable of the new type. - * - * There is a macro to help you define conversions for individual enumeration - * types. The conversion will represent enumeration values as numeric strings. - */ -//@{ - -/// A human-readable name for a type, used in error messages and such. -/** Actually this may not always be very user-friendly. It uses - * @c std::type_info::name(). On gcc-like compilers we try to demangle its - * output. Visual Studio produces human-friendly names out of the box. - * - * This variable is not inline. Inlining it gives rise to "memory leak" - * warnings from asan, the address sanitizer, possibly from use of - * @c std::type_info::name. - */ -template -std::string const type_name{internal::demangle_type_name(typeid(TYPE).name())}; - - -/// Traits describing a type's "null value," if any. -/** Some C++ types have a special value or state which correspond directly to - * SQL's NULL. - * - * The @c nullness traits describe whether it exists, and whether a particular - * value is null. - */ -template struct nullness -{ - /// Does this type have a null value? - static bool has_null; - - /// Is this type always null? - static bool always_null; - - /// Is @c value a null? - static bool is_null(TYPE const &value); - - /// Return a null value. - /** Don't use this in generic code to compare a value and see whether it is - * null. Some types may have multiple null values which do not compare as - * equal, or may define a null value which is not equal to anything including - * itself, like in SQL. - */ - [[nodiscard]] static TYPE null(); -}; - - -/// Nullness traits describing a type which does not have a null value. -template struct no_null -{ - /// Does @c TYPE have a "built-in null value"? - /** For example, a pointer can equal @c nullptr, which makes a very natural - * representation of an SQL null value. For such types, the code sometimes - * needs to make special allowances. - * - * for most types, such as @c int or @c std::string, there is no built-in - * null. If you want to represent an SQL null value for such a type, you - * would have to wrap it in something that does have a null value. For - * example, you could use @c std::optional for "either an @c int or a - * null value." - */ - static constexpr bool has_null = false; - - /// Are all values of this type null? - /** There are a few special C++ types which are always null - mainly - * @c std::nullptr_t. - */ - static constexpr bool always_null = false; - - /// Does a given value correspond to an SQL null value? - /** Most C++ types, such as @c int or @c std::string, have no inherent null - * value. But some types such as C-style string pointers do have a natural - * equivalent to an SQL null. - */ - [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept - { - return false; - } -}; - - -/// Traits class for use in string conversions. -/** Specialize this template for a type for which you wish to add to_string - * and from_string support. - * - * String conversions are not meant to work for nulls. Check for null before - * converting a value of @c TYPE to a string, or vice versa. - */ -template struct string_traits -{ - /// Return a @c string_view representing value, plus terminating zero. - /** Produces a @c string_view containing the PostgreSQL string representation - * for @c value. - * - * Uses the space from @c begin to @c end as a buffer, if needed. The - * returned string may lie somewhere in that buffer, or it may be a - * compile-time constant, or it may be null if value was a null value. Even - * if the string is stored in the buffer, its @c begin() may or may not be - * the same as @c begin. - * - * The @c string_view is guaranteed to be valid as long as the buffer from - * @c begin to @c end remains accessible and unmodified. - * - * @throws pqxx::conversion_overrun if the provided buffer space may not be - * enough. For maximum performance, this is a conservative estimate. It may - * complain about a buffer which is actually large enough for your value, if - * an exact check gets too expensive. - */ - [[nodiscard]] static inline zview - to_buf(char *begin, char *end, TYPE const &value); - - /// Write value's string representation into buffer at @c begin. - /** Assumes that value is non-null. - * - * Writes value's string representation into the buffer, starting exactly at - * @c begin, and ensuring a trailing zero. Returns the address just beyond - * the trailing zero, so the caller could use it as the @c begin for another - * call to @c into_buf writing a next value. - */ - static inline char *into_buf(char *begin, char *end, TYPE const &value); - - /// Parse a string representation of a @c TYPE value. - /** Throws @c conversion_error if @c value does not meet the expected format - * for a value of this type. - */ - [[nodiscard]] static inline TYPE from_string(std::string_view text); - - // C++20: Can we make these all constexpr? - /// Estimate how much buffer space is needed to represent value. - /** The estimate may be a little pessimistic, if it saves time. - * - * The estimate includes the terminating zero. - */ - [[nodiscard]] static inline std::size_t - size_buffer(TYPE const &value) noexcept; -}; - - -/// Nullness: Enums do not have an inherent null value. -template -struct nullness>> : no_null -{}; -} // namespace pqxx - - -namespace pqxx::internal -{ -/// Helper class for defining enum conversions. -/** The conversion will convert enum values to numeric strings, and vice versa. - * - * To define a string conversion for an enum type, derive a @c string_traits - * specialisation for the enum from this struct. - * - * There's usually an easier way though: the @c PQXX_DECLARE_ENUM_CONVERSION - * macro. Use @c enum_traits manually only if you need to customise your - * traits type in more detail. - */ -template struct enum_traits -{ - using impl_type = std::underlying_type_t; - using impl_traits = string_traits; - - [[nodiscard]] static constexpr zview - to_buf(char *begin, char *end, ENUM const &value) - { - return impl_traits::to_buf(begin, end, to_underlying(value)); - } - - static constexpr char *into_buf(char *begin, char *end, ENUM const &value) - { - return impl_traits::into_buf(begin, end, to_underlying(value)); - } - - [[nodiscard]] static ENUM from_string(std::string_view text) - { - return static_cast(impl_traits::from_string(text)); - } - - [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept - { - return impl_traits::size_buffer(to_underlying(value)); - } - -private: - // C++23: Replace with std::to_underlying. - static constexpr impl_type to_underlying(ENUM const &value) noexcept - { - return static_cast(value); - } -}; -} // namespace pqxx::internal - - -/// Macro: Define a string conversion for an enum type. -/** This specialises the @c pqxx::string_traits template, so use it in the - * @c ::pqxx namespace. - * - * For example: - * - * #include - * #include - * enum X { xa, xb }; - * namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(x); } - * int main() { std::cout << pqxx::to_string(xa) << std::endl; } - */ -#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \ - template<> struct string_traits : pqxx::internal::enum_traits \ - {}; \ - template<> inline std::string const type_name { #ENUM } - - -namespace pqxx -{ -/// Parse a value in postgres' text format as a TYPE. -/** If the form of the value found in the string does not match the expected - * type, e.g. if a decimal point is found when converting to an integer type, - * the conversion fails. Overflows (e.g. converting "9999999999" to a 16-bit - * C++ type) are also treated as errors. If in some cases this behaviour - * should be inappropriate, convert to something bigger such as @c long @c int - * first and then truncate the resulting value. - * - * Only the simplest possible conversions are supported. Fancy features like - * hexadecimal or octal, spurious signs, or exponent notation won't work. - * Whitespace is not stripped away. Only the kinds of strings that come out of - * PostgreSQL and out of to_string() can be converted. - */ -template -[[nodiscard]] inline TYPE from_string(std::string_view text) -{ - return string_traits::from_string(text); -} - - -/// "Convert" a std::string_view to a std::string_view. -/** Just returns its input. - * - * @warning Of course the result is only valid for as long as the original - * string remains valid! Never access the string referenced by the return - * value after the original has been destroyed. - */ -template<> -[[nodiscard]] inline std::string_view from_string(std::string_view text) -{ - return text; -} - - -/// Attempt to convert postgres-generated string to given built-in object. -/** This is like the single-argument form of the function, except instead of - * returning the value, it sets @c value. - * - * You may find this more convenient in that it infers the type you want from - * the argument you pass. But there are disadvantages: it requires an - * assignment operator, and it may be less efficient. - */ -template inline void from_string(std::string_view text, T &value) -{ - value = from_string(text); -} - - -/// Convert a value to a readable string that PostgreSQL will understand. -/** The conversion does no special formatting, and ignores any locale settings. - * The resulting string will be human-readable and in a format suitable for use - * in SQL queries. It won't have niceties such as "thousands separators" - * though. - */ -template inline std::string to_string(TYPE const &value); - - -/// Convert multiple values to strings inside a single buffer. -/** There must be enough room for all values, or this will throw - * @c conversion_overrun. You can obtain a conservative estimate of the buffer - * space required by calling @c size_buffer() on the values. - * - * The @c std::string_view results may point into the buffer, so don't assume - * that they will remain valid after you destruct or move the buffer. - */ -template -[[nodiscard]] inline std::vector -to_buf(char *here, char const *end, TYPE... value) -{ - return {[&here, end](auto v) { - auto begin = here; - here = string_traits::into_buf(begin, end, v); - // Exclude the trailing zero out of the string_view. - auto len{static_cast(here - begin) - 1}; - return std::string_view{begin, len}; - }(value)...}; -} - -/// Convert a value to a readable string that PostgreSQL will understand. -/** This variant of to_string can sometimes save a bit of time in loops, by - * re-using a std::string for multiple conversions. - */ -template -inline void into_string(TYPE const &value, std::string &out); - - -/// Is @c value null? -template -[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept -{ - return nullness>::is_null(value); -} - - -/// Estimate how much buffer space is needed to represent values as a string. -/** The estimate may be a little pessimistic, if it saves time. It also - * includes room for a terminating zero after each value. - */ -template -[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept -{ - return (string_traits>::size_buffer(value) + ...); -} - - -/// Does this type translate to an SQL array? -/** Specialisations may override this to be true for container types. - * - * This may not always be a black-and-white choice. For instance, a - * @c std::string is a container, but normally it translates to an SQL string, - * not an SQL array. - */ -template inline constexpr bool is_sql_array{false}; - - -/// Can we use this type in arrays and composite types without quoting them? -/** Define this as @c true only if values of @c TYPE can never contain any - * special characters that might need escaping or confuse the parsing of array - * or composite * types, such as commas, quotes, parentheses, braces, newlines, - * and so on. - * - * When converting a value of such a type to a string in an array or a field in - * a composite type, we do not need to add quotes, nor escape any special - * characters. - * - * This is just an optimisation, so it defaults to @c false to err on the side - * of slow correctness. - */ -template inline constexpr bool is_unquoted_safe{false}; - - -/// Element separator between SQL array elements of this type. -template inline constexpr char array_separator{','}; - - -/// What's the preferred format for passing non-null parameters of this type? -/** This affects how we pass parameters of @c TYPE when calling parameterised - * statements or prepared statements. - * - * Generally we pass parameters in text format, but binary strings are the - * exception. We also pass nulls in binary format, so this function need not - * handle null values. - */ -template inline constexpr format param_format(TYPE const &) -{ - return format::text; -} - - -/// Implement @c string_traits::to_buf by calling @c into_buf. -/** When you specialise @c string_traits for a new type, most of the time its - * @c to_buf implementation has no special optimisation tricks and just writes - * its text into the buffer it receives from the caller, starting at the - * beginning. - * - * In that common situation, you can implement @c to_buf as just a call to - * @c generic_to_buf. It will call @c into_buf and return the right result for - * @c to_buf. - */ -template -inline zview generic_to_buf(char *begin, char *end, TYPE const &value) -{ - using traits = string_traits; - // The trailing zero does not count towards the zview's size, so subtract 1 - // from the result we get from into_buf(). - if (is_null(value)) - return {}; - else - return {begin, traits::into_buf(begin, end, value) - begin - 1}; -} - - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: Binary string, akin to @c std::string for binary data. -/** Any type that satisfies this concept can represent an SQL BYTEA value. - * - * A @c binary has a @c begin(), @c end(), @c size(), and @data(). Each byte - * is a @c std::byte, and they must all be laid out contiguously in memory so - * we can reference them by a pointer. - */ -template -concept binary = std::ranges::contiguous_range and - std::is_same_v>, std::byte>; -#endif -//@} -} // namespace pqxx - - -#include "pqxx/internal/conversions.hxx" -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_from b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_from deleted file mode 100644 index 972762443..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_from +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::stream_from class. - * - * pqxx::stream_from enables optimized batch reads from a database table. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_from.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_from.hxx deleted file mode 100644 index ff4a93d2e..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_from.hxx +++ /dev/null @@ -1,361 +0,0 @@ -/* Definition of the pqxx::stream_from class. - * - * pqxx::stream_from enables optimized batch reads from a database table. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_FROM -#define PQXX_H_STREAM_FROM - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/connection.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/internal/stream_iterator.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/transaction_focus.hxx" - - -namespace pqxx -{ -class transaction_base; - - -/// Pass this to a `stream_from` constructor to stream table contents. -/** @deprecated Use @ref stream_from::table() instead. - */ -constexpr from_table_t from_table; -/// Pass this to a `stream_from` constructor to stream query results. -/** @deprecated Use stream_from::query() instead. - */ -constexpr from_query_t from_query; - - -/// Stream data from the database. -/** For larger data sets, retrieving data this way is likely to be faster than - * executing a query and then iterating and converting the rows fields. You - * will also be able to start processing before all of the data has come in. - * - * There are also downsides. Not all kinds of query will work in a stream. - * But straightforward `SELECT` and `UPDATE ... RETURNING` queries should work. - * This function makes use of @ref pqxx::stream_from, which in turn uses - * PostgreSQL's `COPY` command, so see the documentation for those to get the - * full details. - * - * There are other downsides. If there stream encounters an error, it may - * leave the entire connection in an unusable state, so you'll have to give the - * whole thing up. Finally, opening a stream puts the connection in a special - * state, so you won't be able to do many other things with the connection or - * the transaction while the stream is open. - * - * There are two ways of starting a stream: you stream either all rows in a - * table (using one of the factories, `table()` or `raw_table()`), or the - * results of a query (using the `query()` factory). - * - * Usually you'll want the `stream` convenience wrapper in - * @ref transaction_base, * so you don't need to deal with this class directly. - * - * @warning While a stream is active, you cannot execute queries, open a - * pipeline, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT stream_from : transaction_focus -{ -public: - using raw_line = - std::pair>, std::size_t>; - - /// Factory: Execute query, and stream the results. - /** The query can be a SELECT query or a VALUES query; or it can be an - * UPDATE, INSERT, or DELETE with a RETURNING clause. - * - * The query is executed as part of a COPY statement, so there are additional - * restrictions on what kind of query you can use here. See the PostgreSQL - * documentation for the COPY command: - * - * https://www.postgresql.org/docs/current/sql-copy.html - */ - static stream_from query(transaction_base &tx, std::string_view q) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return {tx, from_query, q}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /** - * @name Streaming data from tables - * - * You can use `stream_from` to read a table's contents. This is a quick - * and easy way to read a table, but it comes with limitations. It cannot - * stream from a view, only from a table. It does not support conditions. - * And there are no guarantees about ordering. If you need any of those - * things, consider streaming from a query instead. - */ - //@{ - - /// Factory: Stream data from a pre-quoted table and columns. - /** Use this factory if you need to create multiple streams using the same - * table path and/or columns list, and you want to save a bit of work on - * composing the internal SQL statement for starting the stream. It lets you - * compose the string representations for the table path and the columns - * list, so you can compute these once and then re-use them later. - * - * @param tx The transaction within which the stream will operate. - * @param path Name or path for the table upon which the stream will - * operate. If any part of the table path may contain special - * characters or be case-sensitive, quote the path using - * pqxx::connection::quote_table(). - * @param columns Columns which the stream will read. They should be - * comma-separated and, if needed, quoted. You can produce the string - * using pqxx::connection::quote_columns(). If you omit this argument, - * the stream will read all columns in the table, in schema order. - */ - static stream_from raw_table( - transaction_base &tx, std::string_view path, - std::string_view columns = ""sv); - - /// Factory: Stream data from a given table. - /** This is the convenient way to stream from a table. - */ - static stream_from table( - transaction_base &tx, table_path path, - std::initializer_list columns = {}); - //@} - - /// Execute query, and stream over the results. - /** @deprecated Use factory function @ref query instead. - */ - [[deprecated("Use query() factory instead.")]] stream_from( - transaction_base &, from_query_t, std::string_view query); - - /// Stream all rows in table, all columns. - /** @deprecated Use factories @ref table or @ref raw_table instead. - */ - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &, from_table_t, std::string_view table); - - /// Stream given columns from all rows in table. - /** @deprecated Use factories @ref table or @ref raw_table instead. - */ - template - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &, from_table_t, std::string_view table, - Iter columns_begin, Iter columns_end); - - /// Stream given columns from all rows in table. - /** @deprecated Use factory function @ref query instead. - */ - template - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &tx, from_table_t, std::string_view table, - Columns const &columns); - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// @deprecated Use factories @ref table or @ref raw_table instead. - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &tx, std::string_view table) : - stream_from{tx, from_table, table} - {} -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// @deprecated Use factories @ref table or @ref raw_table instead. - template - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &tx, std::string_view table, Columns const &columns) : - stream_from{tx, from_table, table, columns} - {} - - /// @deprecated Use factories @ref table or @ref raw_table instead. - template - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &, std::string_view table, Iter columns_begin, - Iter columns_end); - - ~stream_from() noexcept; - - /// May this stream still produce more data? - [[nodiscard]] constexpr operator bool() const noexcept - { - return not m_finished; - } - /// Has this stream produced all the data it is going to produce? - [[nodiscard]] constexpr bool operator!() const noexcept - { - return m_finished; - } - - /// Finish this stream. Call this before continuing to use the connection. - /** Consumes all remaining lines, and closes the stream. - * - * This may take a while if you're abandoning the stream before it's done, so - * skip it in error scenarios where you're not planning to use the connection - * again afterwards. - */ - void complete(); - - /// Read one row into a tuple. - /** Converts the row's fields into the fields making up the tuple. - * - * For a column which can contain nulls, be sure to give the corresponding - * tuple field a type which can be null. For example, to read a field as - * `int` when it may contain nulls, read it as `std::optional`. - * Using `std::shared_ptr` or `std::unique_ptr` will also work. - */ - template stream_from &operator>>(Tuple &); - - /// Doing this with a `std::variant` is going to be horrifically borked. - template - stream_from &operator>>(std::variant &) = delete; - - /// Iterate over this stream. Supports range-based "for" loops. - /** Produces an input iterator over the stream. - * - * Do not call this yourself. Use it like "for (auto data : stream.iter())". - */ - template [[nodiscard]] auto iter() & - { - return pqxx::internal::stream_input_iteration{*this}; - } - - /// Read a row. Return fields as views, valid until you read the next row. - /** Returns `nullptr` when there are no more rows to read. Do not attempt - * to read any further rows after that. - * - * Do not access the vector, or the storage referenced by the views, after - * closing or completing the stream, or after attempting to read a next row. - * - * A @ref pqxx::zview is like a `std::string_view`, but with the added - * guarantee that if its data pointer is non-null, the string is followed by - * a terminating zero (which falls just outside the view itself). - * - * If any of the views' data pointer is null, that means that the - * corresponding SQL field is null. - * - * @warning The return type may change in the future, to support C++20 - * coroutine-based usage. - */ - std::vector const *read_row() &; - - /// Read a raw line of text from the COPY command. - /** @warning Do not use this unless you really know what you're doing. */ - raw_line get_raw_line(); - -private: - // TODO: Clean up this signature once we cull the deprecated constructors. - /// @deprecated - stream_from( - transaction_base &tx, std::string_view table, std::string_view columns, - from_table_t); - - // TODO: Clean up this signature once we cull the deprecated constructors. - /// @deprecated - stream_from( - transaction_base &, std::string_view unquoted_table, - std::string_view columns, from_table_t, int); - - template - void extract_fields(Tuple &t, std::index_sequence) const - { - (extract_value(t), ...); - } - - pqxx::internal::glyph_scanner_func *m_glyph_scanner; - - /// Current row's fields' text, combined into one reusable string. - std::string m_row; - - /// The current row's fields. - std::vector m_fields; - - bool m_finished = false; - - void close(); - - template - void extract_value(Tuple &) const; - - /// Read a line of COPY data, write `m_row` and `m_fields`. - void parse_line(); -}; - - -template -inline stream_from::stream_from( - transaction_base &tx, from_table_t, std::string_view table_name, - Columns const &columns) : - stream_from{ - tx, from_table, table_name, std::begin(columns), std::end(columns)} -{} - - -template -inline stream_from::stream_from( - transaction_base &tx, from_table_t, std::string_view table, - Iter columns_begin, Iter columns_end) : - stream_from{ - tx, table, separated_list(",", columns_begin, columns_end), - from_table, 1} -{} - - -template inline stream_from &stream_from::operator>>(Tuple &t) -{ - if (m_finished) - return *this; - static constexpr auto tup_size{std::tuple_size_v}; - m_fields.reserve(tup_size); - parse_line(); - if (m_finished) - return *this; - - if (std::size(m_fields) != tup_size) - throw usage_error{internal::concat( - "Tried to extract ", tup_size, " field(s) from a stream of ", - std::size(m_fields), ".")}; - - extract_fields(t, std::make_index_sequence{}); - return *this; -} - - -template -inline void stream_from::extract_value(Tuple &t) const -{ - using field_type = strip_t(t))>; - using nullity = nullness; - assert(index < std::size(m_fields)); - if constexpr (nullity::always_null) - { - if (std::data(m_fields[index]) != nullptr) - throw conversion_error{"Streaming non-null value into null field."}; - } - else if (std::data(m_fields[index]) == nullptr) - { - if constexpr (nullity::has_null) - std::get(t) = nullity::null(); - else - internal::throw_null_conversion(type_name); - } - else - { - // Don't ever try to convert a non-null value to nullptr_t! - std::get(t) = from_string(m_fields[index]); - } -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_to b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_to deleted file mode 100644 index 8760cf1f4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_to +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::stream_to class. - * - * pqxx::stream_to enables optimized batch updates to a database table. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/stream_to.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_to.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_to.hxx deleted file mode 100644 index 2a49d8f85..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/stream_to.hxx +++ /dev/null @@ -1,455 +0,0 @@ -/* Definition of the pqxx::stream_to class. - * - * pqxx::stream_to enables optimized batch updates to a database table. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_TO -#define PQXX_H_STREAM_TO - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/separated_list.hxx" -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -/// Efficiently write data directly to a database table. -/** If you wish to insert rows of data into a table, you can compose INSERT - * statements and execute them. But it's slow and tedious, and you need to - * worry about quoting and escaping the data. - * - * If you're just inserting a single row, it probably won't matter much. You - * can use prepared or parameterised statements to take care of the escaping - * for you. But if you're inserting large numbers of rows you will want - * something better. - * - * Inserting rows one by one using INSERT statements involves a lot of - * pointless overhead, especially when you are working with a remote database - * server over the network. You may end up sending each row over the network - * as a separate query, and waiting for a reply. Do it "in bulk" using - * `stream_to`, and you may find that it goes many times faster. Sometimes - * you gain orders of magnitude in speed. - * - * Here's how it works: you create a `stream_to` stream to start writing to - * your table. You will probably want to specify the columns. Then, you - * feed your data into the stream one row at a time. And finally, you call the - * stream's @ref complete function to tell it to finalise the operation, wait - * for completion, and check for errors. - * - * (You _must_ complete the stream before committing or aborting the - * transaction. The connection is in a special state while the stream is - * active, where it can't process commands, and can't commit or abort a - * transaction.) - * - * So how do you feed a row of data into the stream? There's several ways, but - * the preferred one is to call its @ref write_values. Pass the field values - * as arguments. Doesn't matter what type they are, as long as libpqxx knows - * how to convert them to PostgreSQL's text format: `int`, `std::string` or - * `std:string_view`, `float` and `double`, `bool`... lots of basic types - * are supported. If some of the values are null, feel free to use - * `std::optional`, `std::shared_ptr`, or `std::unique_ptr`. - * - * The arguments' types don't even have to match the fields' SQL types. If you - * want to insert an `int` into a `DECIMAL` column, that's your choice -- it - * will produce a `DECIMAL` value which happens to be integral. Insert a - * `float` into a `VARCHAR` column? That's fine, you'll get a string whose - * contents happen to read like a number. And so on. You can even insert - * different types of value in the same column on different rows. If you have - * a code path where a particular field is always null, just insert `nullptr`. - * - * There is another way to insert rows: the `<<` ("shift-left") operator. - * It's not as fast and it doesn't support variable arguments: each row must be - * either a `std::tuple` or something iterable, such as a `std::vector`, or - * anything else with a `begin()` and `end()`. - * - * @warning While a stream is active, you cannot execute queries, open a - * pipeline, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT stream_to : transaction_focus -{ -public: - /// Stream data to a pre-quoted table and columns. - /** This factory can be useful when it's not convenient to provide the - * columns list in the form of a `std::initializer_list`, or when the list - * of columns is simply not known at compile time. - * - * Also use this if you need to create multiple streams using the same table - * path and/or columns list, and you want to save a bit of work on composing - * the internal SQL statement for starting the stream. It lets you compose - * the string representations for the table path and the columns list, so you - * can compute these once and then re-use them later. - * - * @param tx The transaction within which the stream will operate. - * @param path Name or path for the table upon which the stream will - * operate. If any part of the table path may contain special - * characters or be case-sensitive, quote the path using - * pqxx::connection::quote_table(). - * @param columns Columns to which the stream will write. They should be - * comma-separated and, if needed, quoted. You can produce the string - * using pqxx::connection::quote_columns(). If you omit this argument, - * the stream will write all columns in the table, in schema order. - */ - static stream_to raw_table( - transaction_base &tx, std::string_view path, std::string_view columns = "") - { - return {tx, path, columns}; - } - - /// Create a `stream_to` writing to a named table and columns. - /** Use this to stream data to a table, where the list of columns is known at - * compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns Optionally, the columns to which the stream should write. - * If you do not pass this, the stream will write to all columns in the - * table, in schema order. - */ - static stream_to table( - transaction_base &tx, table_path path, - std::initializer_list columns = {}) - { - auto const &conn{tx.conn()}; - return raw_table(tx, conn.quote_table(path), conn.quote_columns(columns)); - } - -#if defined(PQXX_HAVE_CONCEPTS) - /// Create a `stream_to` writing to a named table and columns. - /** Use this version to stream data to a table, when the list of columns is - * not known at compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns The columns to which the stream should write. - */ - template - static stream_to - table(transaction_base &tx, table_path path, COLUMNS const &columns) - { - auto const &conn{tx.conn()}; - return stream_to::raw_table( - tx, conn.quote_table(path), tx.conn().quote_columns(columns)); - } - - /// Create a `stream_to` writing to a named table and columns. - /** Use this version to stream data to a table, when the list of columns is - * not known at compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns The columns to which the stream should write. - */ - template - static stream_to - table(transaction_base &tx, std::string_view path, COLUMNS const &columns) - { - return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns)); - } -#endif // PQXX_HAVE_CONCEPTS - - /// Create a stream, without specifying columns. - /** @deprecated Use @ref table or @ref raw_table as a factory. - * - * Fields will be inserted in whatever order the columns have in the - * database. - * - * You'll probably want to specify the columns, so that the mapping between - * your data fields and the table is explicit in your code, and not hidden - * in an "implicit contract" between your code and your schema. - */ - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &tx, std::string_view table_name) : - stream_to{tx, table_name, ""sv} - {} - - /// Create a stream, specifying column names as a container of strings. - /** @deprecated Use @ref table or @ref raw_table as a factory. - */ - template - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &, std::string_view table_name, Columns const &columns); - - /// Create a stream, specifying column names as a sequence of strings. - /** @deprecated Use @ref table or @ref raw_table as a factory. - */ - template - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &, std::string_view table_name, Iter columns_begin, - Iter columns_end); - - ~stream_to() noexcept; - - /// Does this stream still need to @ref complete()? - [[nodiscard]] constexpr operator bool() const noexcept - { - return not m_finished; - } - /// Has this stream been through its concluding @c complete()? - [[nodiscard]] constexpr bool operator!() const noexcept - { - return m_finished; - } - - /// Complete the operation, and check for errors. - /** Always call this to close the stream in an orderly fashion, even after - * an error. (In the case of an error, abort the transaction afterwards.) - * - * The only circumstance where it's safe to skip this is after an error, if - * you're discarding the entire connection. - */ - void complete(); - - /// Insert a row of data. - /** Returns a reference to the stream, so you can chain the calls. - * - * The @c row can be a tuple, or any type that can be iterated. Each - * item becomes a field in the row, in the same order as the columns you - * specified when creating the stream. - * - * If you don't already happen to have your fields in the form of a tuple or - * container, prefer @c write_values. It's faster and more convenient. - */ - template stream_to &operator<<(Row const &row) - { - write_row(row); - return *this; - } - - /// Stream a `stream_from` straight into a `stream_to`. - /** This can be useful when copying between different databases. If the - * source and the destination are on the same database, you'll get better - * performance doing it all in a regular query. - */ - stream_to &operator<<(stream_from &); - - /// Insert a row of data, given in the form of a @c std::tuple or container. - /** The @c row can be a tuple, or any type that can be iterated. Each - * item becomes a field in the row, in the same order as the columns you - * specified when creating the stream. - * - * The preferred way to insert a row is @c write_values. - */ - template void write_row(Row const &row) - { - fill_buffer(row); - write_buffer(); - } - - /// Insert values as a row. - /** This is the recommended way of inserting data. Pass your field values, - * of any convertible type. - */ - template void write_values(Ts const &...fields) - { - fill_buffer(fields...); - write_buffer(); - } - -private: - /// Stream a pre-quoted table name and columns list. - stream_to( - transaction_base &tx, std::string_view path, std::string_view columns); - - bool m_finished = false; - - /// Reusable buffer for a row. Saves doing an allocation for each row. - std::string m_buffer; - - /// Reusable buffer for converting/escaping a field. - std::string m_field_buf; - - /// Glyph scanner, for parsing the client encoding. - internal::glyph_scanner_func *m_scanner; - - /// Write a row of raw text-format data into the destination table. - void write_raw_line(std::string_view); - - /// Write a row of data from @c m_buffer into the destination table. - /** Resets the buffer for the next row. - */ - void write_buffer(); - - /// COPY encoding for a null field, plus subsequent separator. - static constexpr std::string_view null_field{"\\N\t"}; - - /// Estimate buffer space needed for a field which is always null. - template - static std::enable_if_t::always_null, std::size_t> - estimate_buffer(T const &) - { - return std::size(null_field); - } - - /// Estimate buffer space needed for field f. - /** The estimate is not very precise. We don't actually know how much space - * we'll need once the escaping comes in. - */ - template - static std::enable_if_t::always_null, std::size_t> - estimate_buffer(T const &field) - { - return is_null(field) ? std::size(null_field) : size_buffer(field); - } - - /// Append escaped version of @c data to @c m_buffer, plus a tab. - void escape_field_to_buffer(std::string_view data); - - /// Append string representation for @c f to @c m_buffer. - /** This is for the general case, where the field may contain a value. - * - * Also appends a tab. The tab is meant to be a separator, not a terminator, - * so if you write any fields at all, you'll end up with one tab too many - * at the end of the buffer. - */ - template - std::enable_if_t::always_null> - append_to_buffer(Field const &f) - { - // We append each field, terminated by a tab. That will leave us with - // one tab too many, assuming we write any fields at all; we remove that - // at the end. - if (is_null(f)) - { - // Easy. Append null and tab in one go. - m_buffer.append(null_field); - } - else - { - // Convert f into m_buffer. - - using traits = string_traits; - auto const budget{estimate_buffer(f)}; - auto const offset{std::size(m_buffer)}; - - if constexpr (std::is_arithmetic_v) - { - // Specially optimised for "safe" types, which never need any - // escaping. Convert straight into m_buffer. - - // The budget we get from size_buffer() includes room for the trailing - // zero, which we must remove. But we're also inserting tabs between - // fields, so we re-purpose the extra byte for that. - auto const total{offset + budget}; - m_buffer.resize(total); - auto const data{m_buffer.data()}; - char *const end{traits::into_buf(data + offset, data + total, f)}; - *(end - 1) = '\t'; - // Shrink to fit. Keep the tab though. - m_buffer.resize(static_cast(end - data)); - } - else if constexpr ( - std::is_same_v or - std::is_same_v or - std::is_same_v) - { - // This string may need escaping. - m_field_buf.resize(budget); - escape_field_to_buffer(f); - } - else - { - // This field needs to be converted to a string, and after that, - // escaped as well. - m_field_buf.resize(budget); - auto const data{m_field_buf.data()}; - escape_field_to_buffer( - traits::to_buf(data, data + std::size(m_field_buf), f)); - } - } - } - - /// Append string representation for a null field to @c m_buffer. - /** This special case is for types which are always null. - * - * Also appends a tab. The tab is meant to be a separator, not a terminator, - * so if you write any fields at all, you'll end up with one tab too many - * at the end of the buffer. - */ - template - std::enable_if_t::always_null> - append_to_buffer(Field const &) - { - m_buffer.append(null_field); - } - - /// Write raw COPY line into @c m_buffer, based on a container of fields. - template - std::enable_if_t> - fill_buffer(Container const &c) - { - // To avoid unnecessary allocations and deallocations, we run through c - // twice: once to determine how much buffer space we may need, and once to - // actually write it into the buffer. - std::size_t budget{0}; - for (auto const &f : c) budget += estimate_buffer(f); - m_buffer.reserve(budget); - for (auto const &f : c) append_to_buffer(f); - } - - /// Estimate how many buffer bytes we need to write tuple. - template - static std::size_t - budget_tuple(Tuple const &t, std::index_sequence) - { - return (estimate_buffer(std::get(t)) + ...); - } - - /// Write tuple of fields to @c m_buffer. - template - void append_tuple(Tuple const &t, std::index_sequence) - { - (append_to_buffer(std::get(t)), ...); - } - - /// Write raw COPY line into @c m_buffer, based on a tuple of fields. - template void fill_buffer(std::tuple const &t) - { - using indexes = std::make_index_sequence; - - m_buffer.reserve(budget_tuple(t, indexes{})); - append_tuple(t, indexes{}); - } - - /// Write raw COPY line into @c m_buffer, based on varargs fields. - template void fill_buffer(const Ts &...fields) - { - (..., append_to_buffer(fields)); - } - - constexpr static std::string_view s_classname{"stream_to"}; -}; - - -template -inline stream_to::stream_to( - transaction_base &tx, std::string_view table_name, Columns const &columns) : - stream_to{tx, table_name, std::begin(columns), std::end(columns)} -{} - - -template -inline stream_to::stream_to( - transaction_base &tx, std::string_view table_name, Iter columns_begin, - Iter columns_end) : - stream_to{ - tx, - tx.quote_name( - table_name, - separated_list(",", columns_begin, columns_end, [&tx](auto col) { - return tx.quote_name(*col); - }))} -{} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/subtransaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/subtransaction deleted file mode 100644 index e0d154903..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/subtransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::subtransaction class. - * - * pqxx::subtransaction is a nested transaction, i.e. one inside a transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/subtransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/subtransaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/subtransaction.hxx deleted file mode 100644 index e66b7a7a8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/subtransaction.hxx +++ /dev/null @@ -1,96 +0,0 @@ -/* Definition of the pqxx::subtransaction class. - * - * pqxx::subtransaction is a nested transaction, i.e. one within a transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SUBTRANSACTION -#define PQXX_H_SUBTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx -{ -/** - * @ingroup transactions - */ -/// "Transaction" nested within another transaction -/** A subtransaction can be executed inside a backend transaction, or inside - * another subtransaction. This can be useful when, for example, statements in - * a transaction may harmlessly fail and you don't want them to abort the - * entire transaction. Here's an example of how a temporary table may be - * dropped before re-creating it, without failing if the table did not exist: - * - * ```cxx - * void do_job(connection &C) - * { - * string const temptable = "fleetingtable"; - * - * work W(C, "do_job"); - * do_firstpart(W); - * - * // Attempt to delete our temporary table if it already existed. - * try - * { - * subtransaction S(W, "droptemp"); - * S.exec0("DROP TABLE " + temptable); - * S.commit(); - * } - * catch (undefined_table const &) - * { - * // Table did not exist. Which is what we were hoping to achieve anyway. - * // Carry on without regrets. - * } - * - * // S may have gone into a failed state and been destroyed, but the - * // upper-level transaction W is still fine. We can continue to use it. - * W.exec0("CREATE TEMP TABLE " + temptable + "(bar integer, splat - * varchar)"); - * - * do_lastpart(W); - * } - * ``` - * - * (This is just an example. If you really wanted to do drop a table without - * an error if it doesn't exist, you'd use DROP TABLE IF EXISTS.) - * - * There are no isolation levels inside a transaction. They are not needed - * because all actions within the same backend transaction are always performed - * sequentially anyway. - * - * @warning While the subtransaction is "live," you cannot execute queries or - * open streams etc. on its parent transaction. A transaction can have at most - * one object of a type derived from @ref pqxx::transaction_focus active on it - * at a time. - */ -class PQXX_LIBEXPORT subtransaction : public transaction_focus, - public dbtransaction -{ -public: - /// Nest a subtransaction nested in another transaction. - explicit subtransaction(dbtransaction &t, std::string_view tname = ""sv); - - /// Nest a subtransaction in another subtransaction. - explicit subtransaction(subtransaction &t, std::string_view name = ""sv); - - virtual ~subtransaction() noexcept override; - -private: - std::string quoted_name() const - { - return quote_name(transaction_focus::name()); - } - virtual void do_commit() override; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/time b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/time deleted file mode 100644 index 85df05744..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/time +++ /dev/null @@ -1,6 +0,0 @@ -/** Date/time string conversions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/time.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/time.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/time.hxx deleted file mode 100644 index effed05e0..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/time.hxx +++ /dev/null @@ -1,88 +0,0 @@ -/** Support for date/time values. - * - * At the moment this supports dates, but not times. - */ -#ifndef PQXX_H_TIME -#define PQXX_H_TIME - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/internal/concat.hxx" -#include "pqxx/strconv.hxx" - - -#if defined(PQXX_HAVE_YEAR_MONTH_DAY) - -namespace pqxx -{ -using namespace std::literals; - -template<> -struct nullness - : no_null -{}; - - -/// String representation for a Gregorian date in ISO-8601 format. -/** @warning Experimental. There may still be design problems, particularly - * when it comes to BC years. - * - * PostgreSQL supports a choice of date formats, but libpqxx does not. The - * other formats in turn support a choice of "month before day" versus "day - * before month," meaning that it's not necessarily known which format a given - * date is supposed to be. So I repeat: ISO-8601-style format only! - * - * Invalid dates will not convert. This includes February 29 on non-leap - * years, which is why it matters that `year_month_day` represents a - * _Gregorian_ date. - * - * The range of years is limited. At the time of writing, PostgreSQL 14 - * supports years from 4713 BC to 294276 AD inclusive, and C++20 supports - * a range of 32767 BC to 32767 AD inclusive. So in practice, years must fall - * between 4713 BC and 32767 AD, inclusive. - * - * @warning Support for BC (or BCE) years is still experimental. I still need - * confirmation on this issue: it looks as if C++ years are astronomical years, - * which means they have a Year Zero. Regular BC/AD years do not have a year - * zero, so the year 1 AD follows directly after 1 BC. - * - * So, what to our calendars (and to PostgreSQL) is the year "0001 BC" seems to - * count as year "0" in a `std::chrono::year_month_day`. The year 0001 AD is - * still equal to 1 as you'd expect, and all AD years work normally, but all - * years before then are shifted by one. For instance, the year 543 BC would - * be -542 in C++. - */ -template<> struct PQXX_LIBEXPORT string_traits -{ - [[nodiscard]] static zview - to_buf(char *begin, char *end, std::chrono::year_month_day const &value) - { - return generic_to_buf(begin, end, value); - } - - static char * - into_buf(char *begin, char *end, std::chrono::year_month_day const &value); - - [[nodiscard]] static std::chrono::year_month_day - from_string(std::string_view text); - - [[nodiscard]] static std::size_t - size_buffer(std::chrono::year_month_day const &) noexcept - { - static_assert(int{(std::chrono::year::min)()} >= -99999); - static_assert(int{(std::chrono::year::max)()} <= 99999); - return 5 + 1 + 2 + 1 + 2 + std::size(s_bc) + 1; - } - -private: - /// The "BC" suffix for years before 1 AD. - static constexpr std::string_view s_bc{" BC"sv}; -}; -} // namespace pqxx -#endif // PQXX_HAVE_YEAR_MONTH_DAY -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction deleted file mode 100644 index a7ae39d43..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::transaction class. - * - * pqxx::transaction represents a standard database transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction.hxx deleted file mode 100644 index e90917e38..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction.hxx +++ /dev/null @@ -1,108 +0,0 @@ -/* Definition of the pqxx::transaction class. - * pqxx::transaction represents a standard database transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION -#define PQXX_H_TRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx::internal -{ -/// Helper base class for the @ref transaction class template. -class PQXX_LIBEXPORT basic_transaction : public dbtransaction -{ -protected: - basic_transaction( - connection &c, zview begin_command, std::string_view tname); - basic_transaction(connection &c, zview begin_command, std::string &&tname); - basic_transaction(connection &c, zview begin_command); - - virtual ~basic_transaction() noexcept override = 0; - -private: - virtual void do_commit() override; -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @ingroup transactions - */ -//@{ - -/// Standard back-end transaction, templatised on isolation level. -/** This is the type you'll normally want to use to represent a transaction on - * the database. - * - * Usage example: double all wages. - * - * ```cxx - * extern connection C; - * work T(C); - * try - * { - * T.exec0("UPDATE employees SET wage=wage*2"); - * T.commit(); // NOTE: do this inside try block - * } - * catch (exception const &e) - * { - * cerr << e.what() << endl; - * T.abort(); // Usually not needed; same happens when T's life ends. - * } - * ``` - */ -template< - isolation_level ISOLATION = isolation_level::read_committed, - write_policy READWRITE = write_policy::read_write> -class transaction final : public internal::basic_transaction -{ -public: - /// Begin a transaction. - /** - * @param c Connection for this transaction to operate on. - * @param tname Optional name for transaction. Must begin with a letter and - * may contain letters and digits only. - */ - transaction(connection &c, std::string_view tname) : - internal::basic_transaction{ - c, internal::begin_cmd, tname} - {} - - /// Begin a transaction. - /** - * @param c Connection for this transaction to operate on. - * may contain letters and digits only. - */ - explicit transaction(connection &c) : - internal::basic_transaction{ - c, internal::begin_cmd} - {} - - virtual ~transaction() noexcept override { close(); } -}; - - -/// The default transaction type. -using work = transaction<>; - -/// Read-only transaction. -using read_transaction = - transaction; - -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_base b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_base deleted file mode 100644 index c39219aac..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_base +++ /dev/null @@ -1,9 +0,0 @@ -/** Base for the transaction classes. - * - * pqxx::transaction_base defines the interface for any abstract class that - * represents a database transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transaction_base.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_base.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_base.hxx deleted file mode 100644 index 4363cc56a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_base.hxx +++ /dev/null @@ -1,810 +0,0 @@ -/* Common code and definitions for the transaction classes. - * - * pqxx::transaction_base defines the interface for any abstract class that - * represents a database transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION_BASE -#define PQXX_H_TRANSACTION_BASE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -/* End-user programs need not include this file, unless they define their own - * transaction classes. This is not something the typical program should want - * to do. - * - * However, reading this file is worthwhile because it defines the public - * interface for the available transaction classes such as transaction and - * nontransaction. - */ - -#include "pqxx/connection.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/isolation.hxx" -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/util.hxx" - -namespace pqxx::internal::gate -{ -class transaction_subtransaction; -class transaction_sql_cursor; -class transaction_stream_to; -class transaction_transaction_focus; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -using namespace std::literals; - - -class transaction_focus; - - -/** - * @defgroup transactions Transaction classes - * - * All database access goes through instances of these classes. - * However, not all implementations of this interface need to provide full - * transactional integrity. - * - * Several implementations of this interface are shipped with libpqxx, - * including the plain transaction class, the entirely unprotected - * nontransaction, and the more cautious robusttransaction. - */ - -/// Interface definition (and common code) for "transaction" classes. -/** - * @ingroup transactions - * - * Abstract base class for all transaction types. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base -{ -public: - transaction_base() = delete; - transaction_base(transaction_base const &) = delete; - transaction_base(transaction_base &&) = delete; - transaction_base &operator=(transaction_base const &) = delete; - transaction_base &operator=(transaction_base &&) = delete; - - virtual ~transaction_base() = 0; - - /// Commit the transaction. - /** Make the effects of this transaction definite. If you destroy a - * transaction without invoking its @ref commit() first, that will implicitly - * abort it. (For the @ref nontransaction class though, "commit" and "abort" - * really don't do anything, hence its name.) - * - * There is, however, a minute risk that you might lose your connection to - * the database at just the wrong moment here. In that case, libpqxx may be - * unable to determine whether the database was able to complete the - * transaction, or had to roll it back. In that scenario, @ref commit() will - * throw an in_doubt_error. There is a different transaction class called - * @ref robusttransaction which takes some special precautions to reduce this - * risk. - */ - void commit(); - - /// Abort the transaction. - /** No special effort is required to call this function; it will be called - * implicitly when the transaction is destructed. - */ - void abort(); - - /** - * @ingroup escaping-functions - * - * Use these when writing SQL queries that incorporate C++ values as SQL - * constants. - * - * The functions you see here are just convenience shortcuts to the same - * functions on the connection object. - */ - //@{ - /// Escape string for use as SQL string literal in this transaction. - template [[nodiscard]] auto esc(ARGS &&...args) const - { - return conn().esc(std::forward(args)...); - } - - /// Escape binary data for use as SQL string literal in this transaction. - /** Raw, binary data is treated differently from regular strings. Binary - * strings are never interpreted as text, so they may safely include byte - * values or byte sequences that don't happen to represent valid characters - * in the character encoding being used. - * - * The binary string does not stop at the first zero byte, as is the case - * with textual strings. Instead, it may contain zero bytes anywhere. If - * it happens to contain bytes that look like quote characters, or other - * things that can disrupt their use in SQL queries, they will be replaced - * with special escape sequences. - */ - template [[nodiscard]] auto esc_raw(ARGS &&...args) const - { - return conn().esc_raw(std::forward(args)...); - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(zview text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return conn().unesc_raw(text); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard]] std::basic_string unesc_bin(zview text) - { - return conn().unesc_bin(text); - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(char const *text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return conn().unesc_raw(text); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard]] std::basic_string unesc_bin(char const text[]) - { - return conn().unesc_bin(text); - } - - /// Represent object as SQL string, including quoting & escaping. - /** Nulls are recognized and represented as SQL nulls. */ - template [[nodiscard]] std::string quote(T const &t) const - { - return conn().quote(t); - } - - [[deprecated( - "Use std::basic_string instead of binarystring.")]] std::string - quote(binarystring const &t) const - { - return conn().quote(t.bytes_view()); - } - - /// Binary-escape and quote a binary string for use as an SQL constant. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(unsigned char const bin[], std::size_t len) const - { - return quote(binary_cast(bin, len)); - } - - /// Binary-escape and quote a binary string for use as an SQL constant. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(zview bin) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Binary-escape and quote a binary string for use as an SQL constant. - /** For binary data you can also just use @ref quote(data). */ - template - [[nodiscard]] std::string quote_raw(DATA const &data) const - { - return conn().quote_raw(data); - } -#endif - - /// Escape an SQL identifier for use in a query. - [[nodiscard]] std::string quote_name(std::string_view identifier) const - { - return conn().quote_name(identifier); - } - - /// Escape string for literal LIKE match. - [[nodiscard]] std::string - esc_like(std::string_view bin, char escape_char = '\\') const - { - return conn().esc_like(bin, escape_char); - } - //@} - - /** - * @name Command execution - * - * There are many functions for executing (or "performing") a command (or - * "query"). This is the most fundamental thing you can do with the library, - * and you always do it from a transaction class. - * - * Command execution can throw many types of exception, including sql_error, - * broken_connection, and many sql_error subtypes such as - * feature_not_supported or insufficient_privilege. But any exception thrown - * by the C++ standard library may also occur here. All exceptions you will - * see libpqxx throw are derived from std::exception. - * - * One unusual feature in libpqxx is that you can give your query a name or - * description. This does not mean anything to the database, but sometimes - * it can help libpqxx produce more helpful error messages, making problems - * in your code easier to debug. - * - * Many of the execution functions used to accept a `desc` argument, a - * human-readable description of the statement for use in error messages. - * This could make failures easier to debug. Future versions will use - * C++20's `std::source_location` to identify the failing statement. - */ - //@{ - - /// Execute a command. - /** - * @param query Query or command to execute. - * @param desc Optional identifier for query, to help pinpoint SQL errors. - * @return A result set describing the query's or command's result. - */ - [[deprecated("The desc parameter is going away.")]] result - exec(std::string_view query, std::string_view desc); - - /// Execute a command. - /** - * @param query Query or command to execute. - * @return A result set describing the query's or command's result. - */ - result exec(std::string_view query) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec(query, std::string_view{}); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute a command. - /** - * @param query Query or command to execute. - * @param desc Optional identifier for query, to help pinpoint SQL errors. - * @return A result set describing the query's or command's result. - */ - [[deprecated( - "Pass your query as a std::string_view, not stringstream.")]] result - exec(std::stringstream const &query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec(query.str(), desc); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command, which should return zero rows of data. - /** Works like @ref exec, but fails if the result contains data. It still - * returns a result, however, which may contain useful metadata. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] result - exec0(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(0, query, desc); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command, which should return zero rows of data. - /** Works like @ref exec, but fails if the result contains data. It still - * returns a result, however, which may contain useful metadata. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - result exec0(zview query) { return exec_n(0, query); } - - /// Execute command returning a single row of data. - /** Works like @ref exec, but requires the result to contain exactly one row. - * The row can be addressed directly, without the need to find the first row - * in a result set. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] row - exec1(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(1, query, desc).front(); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command returning a single row of data. - /** Works like @ref exec, but requires the result to contain exactly one row. - * The row can be addressed directly, without the need to find the first row - * in a result set. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - row exec1(zview query) { return exec_n(1, query).front(); } - - /// Execute command, expect given number of rows. - /** Works like @ref exec, but checks that the result has exactly the expected - * number of rows. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] result - exec_n(result::size_type rows, zview query, std::string_view desc); - - /// Execute command, expect given number of rows. - /** Works like @ref exec, but checks that the result has exactly the expected - * number of rows. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - result exec_n(result::size_type rows, zview query) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(rows, query, std::string_view{}); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Perform query, expecting exactly 1 row with 1 field, and convert it. - /** This is convenience shorthand for querying exactly one value from the - * database. It returns that value, converted to the type you specify. - */ - template - [[deprecated("The desc parameter is going away.")]] TYPE - query_value(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row const r{exec1(query, desc)}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - if (std::size(r) != 1) - throw usage_error{internal::concat( - "Queried single value from result with ", std::size(r), " columns.")}; - return r[0].as(); - } - - /// Perform query, expecting exactly 1 row with 1 field, and convert it. - /** This is convenience shorthand for querying exactly one value from the - * database. It returns that value, converted to the type you specify. - */ - template TYPE query_value(zview query) - { - row const r{exec1(query)}; - if (std::size(r) != 1) - throw usage_error{internal::concat( - "Queried single value from result with ", std::size(r), " columns.")}; - return r[0].as(); - } - - /// Execute a query, and loop over the results row by row. - /** Converts the rows to `std::tuple`, of the column types you specify. - * - * Use this with a range-based "for" loop. It executes the query, and - * directly maps the resulting rows onto a `std::tuple` of the types you - * specify. It starts before all the data from the server is in, so if your - * network connection to the server breaks while you're iterating, you'll get - * an exception partway through. - * - * The stream lives entirely within the lifetime of the transaction. Make - * sure you destroy the stream before you destroy the transaction. Either - * iterate the stream all the way to the end, or destroy first the stream - * and then the transaction without touching either in any other way. Until - * the stream has finished, the transaction is in a special state where it - * cannot execute queries. - * - * As a special case, tuple may contain `std::string_view` fields, but the - * strings to which they point will only remain valid until you extract the - * next row. After that, the memory holding the string may be overwritten or - * deallocated. - * - * If any of the columns can be null, and the C++ type to which it translates - * does not have a null value, wrap the type in `std::optional` (or if - * you prefer, `std::shared_ptr` or `std::unique_ptr)`. These templates - * do recognise null values, and libpqxx will know how to convert to them. - * - * The connection is in a special state until the iteration finishes. So if - * it does not finish due to a `break` or a `return` or an exception, then - * the entire connection becomes effectively unusable. - * - * Querying in this way is faster than the `exec()` methods for larger - * results (but slower for small ones). You can start processing rows before - * the full result is in. Also, `stream()` scales better in terms of memory - * usage. Where @ref exec() reads the entire result into memory at once, - * `stream()` will read and process one row at at a time. - * - * Your query executes as part of a COPY command, not as a stand-alone query, - * so there are limitations to what you can do in the query. It can be - * either a SELECT or VALUES query; or an INSERT, UPDATE, or DELETE with a - * RETURNING clause. See the documentation for PostgreSQL's COPY command for - * the details: - * - * https://www.postgresql.org/docs/current/sql-copy.html - * - * Iterating in this way does require each of the field types you pass to be - * default-constructible, copy-constructible, and assignable. These - * requirements may be loosened once libpqxx moves on to C++20. - */ - template - [[nodiscard]] auto stream(std::string_view query) & - { - // Tricky: std::make_unique() supports constructors but not RVO functions. - return pqxx::internal::owning_stream_input_iteration{ - std::unique_ptr{ - new stream_from{stream_from::query(*this, query)}}}; - } - - // C++20: Concept like std::invocable, but without specifying param types. - /// Perform a streaming query, and for each result row, call `func`. - /** Here, `func` can be a function, a `std::function`, a lambda, or an - * object that supports the function call operator. Of course `func` must - * have an unambiguous signature; it can't be overloaded or generic. - * - * The `for_each` function executes `query` in a stream using - * @ref pqxx::stream_from. Every time a row of data comes in from the - * server, it converts the row's fields to the types of `func`'s respective - * parameters, and calls `func` with those values. - * - * This will not work for all queries, but straightforward `SELECT` and - * `UPDATE ... RETURNING` queries should work. Consult the documentation for - * @ref pqxx::stream_from and PostgreSQL's underlying `COPY` command for the - * full details. - * - * Streaming a query like this is likely to be slower than the @ref exec() - * functions for small result sets, but faster for large result sets. So if - * performance matters, you'll want to use `for_each` if you query large - * amounts of data, but not if you do lots of queries with small outputs. - */ - template - inline auto for_each(std::string_view query, CALLABLE &&func) - { - using param_types = - pqxx::internal::strip_types_t>; - param_types const *const sample{nullptr}; - auto data_stream{stream_like(query, sample)}; - for (auto const &fields : data_stream) std::apply(func, fields); - } - - /** - * @name Parameterized statements - * - * You'll often need parameters in the queries you execute: "select the - * car with this licence plate." If the parameter is a string, you need to - * quote it and escape any special characters inside it, or it may become a - * target for an SQL injection attack. If it's an integer (for example), - * you need to convert it to a string, but in the database's format, without - * locale-specific niceties like "," separators between the thousands. - * - * Parameterised statements are an easier and safer way to do this. They're - * like prepared statements, but for a single use. You don't need to name - * them, and you don't need to prepare them first. - * - * Your query will include placeholders like `$1` and `$2` etc. in the places - * where you want the arguments to go. Then, you pass the argument values - * and the actual query is constructed for you. - * - * Pass the exact right number of parameters, and in the right order. The - * parameters in the query don't have to be neatly ordered from `$1` to - * `$2` to `$3` - but you must pass the argument for `$1` first, the one - * for `$2` second, etc. - * - * @warning Beware of "nul" bytes. Any string you pass as a parameter will - * end at the first char with value zero. If you pass a string that contains - * a zero byte, the last byte in the value will be the one just before the - * zero. - */ - //@{ - /// Execute an SQL statement with parameters. - template result exec_params(zview query, Args &&...args) - { - params pp(args...); - return internal_exec_params(query, pp.make_c_params()); - } - - // Execute parameterised statement, expect a single-row result. - /** @throw unexpected_rows if the result does not consist of exactly one row. - */ - template row exec_params1(zview query, Args &&...args) - { - return exec_params_n(1, query, std::forward(args)...).front(); - } - - // Execute parameterised statement, expect a result with zero rows. - /** @throw unexpected_rows if the result contains rows. - */ - template result exec_params0(zview query, Args &&...args) - { - return exec_params_n(0, query, std::forward(args)...); - } - - // Execute parameterised statement, expect exactly a given number of rows. - /** @throw unexpected_rows if the result contains the wrong number of rows. - */ - template - result exec_params_n(std::size_t rows, zview query, Args &&...args) - { - auto const r{exec_params(query, std::forward(args)...)}; - check_rowcount_params(rows, std::size(r)); - return r; - } - //@} - - /** - * @name Prepared statements - * - * These are very similar to parameterised statements. The difference is - * that you prepare them in advance, giving them identifying names. You can - * then call them by these names, passing in the argument values appropriate - * for that call. - * - * You prepare a statement on the connection, using - * @ref pqxx::connection::prepare(). But you then call the statement in a - * transaction, using the functions you see here. - * - * Never try to prepare, execute, or unprepare a prepared statement manually - * using direct SQL queries when you also use the libpqxx equivalents. For - * any given statement, either prepare, manage, and execute it through the - * dedicated libpqxx functions; or do it all directly in SQL. Don't mix the - * two, or the code may get confused. - * - * See \ref prepared for a full discussion. - * - * @warning Beware of "nul" bytes. Any string you pass as a parameter will - * end at the first char with value zero. If you pass a string that contains - * a zero byte, the last byte in the value will be the one just before the - * zero. If you need a zero byte, you're dealing with binary strings, not - * regular strings. Represent binary strings on the SQL side as `BYTEA` - * (or as large objects). On the C++ side, use types like - * `std::basic_string` or `std::basic_string_view` - * or (in C++20) `std::vector`. Also, consider large objects on - * the SQL side and @ref blob on the C++ side. - */ - //@{ - - /// Execute a prepared statement, with optional arguments. - template - result exec_prepared(zview statement, Args &&...args) - { - params pp(args...); - return internal_exec_prepared(statement, pp.make_c_params()); - } - - /// Execute a prepared statement, and expect a single-row result. - /** @throw pqxx::unexpected_rows if the result was not exactly 1 row. - */ - template - row exec_prepared1(zview statement, Args &&...args) - { - return exec_prepared_n(1, statement, std::forward(args)...).front(); - } - - /// Execute a prepared statement, and expect a result with zero rows. - /** @throw pqxx::unexpected_rows if the result contained rows. - */ - template - result exec_prepared0(zview statement, Args &&...args) - { - return exec_prepared_n(0, statement, std::forward(args)...); - } - - /// Execute a prepared statement, expect a result with given number of rows. - /** @throw pqxx::unexpected_rows if the result did not contain exactly the - * given number of rows. - */ - template - result - exec_prepared_n(result::size_type rows, zview statement, Args &&...args) - { - auto const r{exec_prepared(statement, std::forward(args)...)}; - check_rowcount_prepared(statement, rows, std::size(r)); - return r; - } - - //@} - - /** - * @name Error/warning output - */ - //@{ - /// Have connection process a warning message. - void process_notice(char const msg[]) const { m_conn.process_notice(msg); } - /// Have connection process a warning message. - void process_notice(zview msg) const { m_conn.process_notice(msg); } - //@} - - /// The connection in which this transaction lives. - [[nodiscard]] constexpr connection &conn() const noexcept { return m_conn; } - - /// Set session variable using SQL "SET" command. - /** @deprecated To set a transaction-local variable, execute an SQL `SET` - * command. To set a session variable, use the connection's - * @ref set_session_var function. - * - * @warning When setting a string value, you must make sure that the string - * is "safe." If you call @ref quote() on the string, it will return a - * safely escaped and quoted version for use as an SQL literal. - * - * @warning This function executes SQL. Do not try to set or get variables - * while a pipeline or table stream is active. - * - * @param var The variable to set. - * @param value The new value to store in the variable. This can be any SQL - * expression. - */ - [[deprecated( - "Set transaction-local variables using SQL SET statements.")]] void - set_variable(std::string_view var, std::string_view value); - - /// Read session variable using SQL "SHOW" command. - /** @warning This executes SQL. Do not try to set or get variables while a - * pipeline or table stream is active. - */ - [[deprecated("Read variables using SQL SHOW statements.")]] std::string - get_variable(std::string_view); - - // C++20: constexpr. - /// Transaction name, if you passed one to the constructor; or empty string. - [[nodiscard]] std::string_view name() const &noexcept { return m_name; } - -protected: - /// Create a transaction (to be called by implementation classes only). - /** The name, if nonempty, must begin with a letter and may contain letters - * and digits only. - */ - transaction_base( - connection &c, std::string_view tname, - std::shared_ptr rollback_cmd) : - m_conn{c}, m_name{tname}, m_rollback_cmd{rollback_cmd} - {} - - /// Create a transaction (to be called by implementation classes only). - /** Its rollback command will be "ROLLBACK". - * - * The name, if nonempty, must begin with a letter and may contain letters - * and digits only. - */ - transaction_base(connection &c, std::string_view tname); - - /// Create a transaction (to be called by implementation classes only). - explicit transaction_base(connection &c); - - /// Register this transaction with the connection. - void register_transaction(); - - /// End transaction. To be called by implementing class' destructor. - void close() noexcept; - - /// To be implemented by derived implementation class: commit transaction. - virtual void do_commit() = 0; - - /// Transaction type-specific way of aborting a transaction. - /** @warning This will become "final", since this function can be called - * from the implementing class destructor. - */ - virtual void do_abort(); - - /// Set the rollback command. - void set_rollback_cmd(std::shared_ptr cmd) - { - m_rollback_cmd = cmd; - } - - /// Execute query on connection directly. - result direct_exec(std::string_view, std::string_view desc = ""sv); - result - direct_exec(std::shared_ptr, std::string_view desc = ""sv); - -private: - enum class status - { - active, - aborted, - committed, - in_doubt - }; - - PQXX_PRIVATE void check_pending_error(); - - result - internal_exec_prepared(zview statement, internal::c_params const &args); - - result internal_exec_params(zview query, internal::c_params const &args); - - /// Throw unexpected_rows if prepared statement returned wrong no. of rows. - void check_rowcount_prepared( - zview statement, result::size_type expected_rows, - result::size_type actual_rows); - - /// Throw unexpected_rows if wrong row count from parameterised statement. - void - check_rowcount_params(std::size_t expected_rows, std::size_t actual_rows); - - /// Describe this transaction to humans, e.g. "transaction 'foo'". - [[nodiscard]] std::string description() const; - - friend class pqxx::internal::gate::transaction_transaction_focus; - PQXX_PRIVATE void register_focus(transaction_focus *); - PQXX_PRIVATE void unregister_focus(transaction_focus *) noexcept; - PQXX_PRIVATE void register_pending_error(zview) noexcept; - PQXX_PRIVATE void register_pending_error(std::string &&) noexcept; - - /// Like @ref stream(), but takes a tuple rather than a parameter pack. - template - auto stream_like(std::string_view query, std::tuple const *) - { - return stream(query); - } - - connection &m_conn; - - /// Current "focus": a pipeline, a nested transaction, a stream... - /** This pointer is used for only one purpose: sanity checks against mistakes - * such as opening one while another is still active. - */ - transaction_focus const *m_focus = nullptr; - - status m_status = status::active; - bool m_registered = false; - std::string m_name; - std::string m_pending_error; - - /// SQL command for aborting this type of transaction. - std::shared_ptr m_rollback_cmd; - - static constexpr std::string_view s_type_name{"transaction"sv}; -}; - - -// C++20: Can borrowed_range help? -/// Forbidden specialisation: underlying buffer immediately goes out of scope. -template<> -std::string_view transaction_base::query_value( - zview query, std::string_view desc) = delete; -/// Forbidden specialisation: underlying buffer immediately goes out of scope. -template<> -zview transaction_base::query_value( - zview query, std::string_view desc) = delete; - -} // namespace pqxx - - -namespace pqxx::internal -{ -/// The SQL command for starting a given type of transaction. -template -extern const zview begin_cmd; - -// These are not static members, so "constexpr" does not imply "inline". -template<> -inline constexpr zview begin_cmd{ - "BEGIN"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN READ ONLY"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL REPEATABLE READ"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL SERIALIZABLE"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY"_zv}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_focus b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_focus deleted file mode 100644 index fe78a9bcc..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_focus +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Transaction focus: types which monopolise a transaction's attention. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/types.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_focus.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_focus.hxx deleted file mode 100644 index 0707e3cc4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transaction_focus.hxx +++ /dev/null @@ -1,89 +0,0 @@ -/** Transaction focus: types which monopolise a transaction's attention. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION_FOCUS -#define PQXX_H_TRANSACTION_FOCUS - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Base class for things that monopolise a transaction's attention. -/** You probably won't need to use this class. But it can be useful to _know_ - * that a given libpqxx class is derived from it. - * - * Pipelines, SQL statements, and data streams are examples of classes derived - * from `transaction_focus`. For any given transaction, only one object of - * such a class can be active at any given time. - */ -class PQXX_LIBEXPORT transaction_focus -{ -public: - transaction_focus( - transaction_base &t, std::string_view cname, std::string_view oname) : - m_trans{t}, m_classname{cname}, m_name{oname} - {} - - transaction_focus( - transaction_base &t, std::string_view cname, std::string &&oname) : - m_trans{t}, m_classname{cname}, m_name{std::move(oname)} - {} - - transaction_focus(transaction_base &t, std::string_view cname) : - m_trans{t}, m_classname{cname} - {} - - transaction_focus() = delete; - transaction_focus(transaction_focus const &) = delete; - transaction_focus &operator=(transaction_focus const &) = delete; - - /// Class name, for human consumption. - [[nodiscard]] constexpr std::string_view classname() const noexcept - { - return m_classname; - } - - /// Name for this object, if the caller passed one; empty string otherwise. - [[nodiscard]] std::string_view name() const &noexcept { return m_name; } - - [[nodiscard]] std::string description() const - { - return pqxx::internal::describe_object(m_classname, m_name); - } - - /// Can't move a transaction_focus. - /** Moving the transaction_focus would break the transaction's reference back - * to the object. - */ - transaction_focus(transaction_focus &&) = delete; - - /// Can't move a transaction_focus. - /** Moving the transaction_focus would break the transaction's reference back - * to the object. - */ - transaction_focus &operator=(transaction_focus &&) = delete; - -protected: - void register_me(); - void unregister_me() noexcept; - void reg_pending_error(std::string const &) noexcept; - bool registered() const noexcept { return m_registered; } - - transaction_base &m_trans; - -private: - bool m_registered = false; - std::string_view m_classname; - std::string m_name; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transactor b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transactor deleted file mode 100644 index 29d1b9640..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transactor +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::transactor class. - * - * pqxx::transactor is a framework-style wrapper for safe transactions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transactor.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transactor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transactor.hxx deleted file mode 100644 index eefd04ba1..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/transactor.hxx +++ /dev/null @@ -1,147 +0,0 @@ -/* Transactor framework, a wrapper for safely retryable transactions. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTOR -#define PQXX_H_TRANSACTOR - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/connection.hxx" -#include "pqxx/transaction.hxx" - -namespace pqxx -{ -/** - * @defgroup transactor Transactor framework - * - * Sometimes a transaction can fail for completely transient reasons, such as a - * conflict with another transaction in SERIALIZABLE isolation. The right way - * to handle those failures is often just to re-run the transaction from - * scratch. - * - * For example, your REST API might be handling each HTTP request in its own - * database transaction, and if this kind of transient failure happens, you - * simply want to "replay" the whole request, in a fresh transaction. - * - * You won't necessarily want to execute the exact same SQL commands with the - * exact same data. Some of your SQL statements may depend on state that can - * vary between retries. Data in the database may already have changed, for - * instance. So instead of dumbly replaying the SQL, you re-run the same - * application code that produced those SQL commands, from the start. - * - * The transactor framework makes it a little easier for you to do this safely, - * and avoid typical pitfalls. You encapsulate the work that you want to do - * into a callable that you pass to the @ref perform function. - * - * Here's how it works. You write your transaction code as a lambda or - * function, which creates its own transaction object, does its work, and - * commits at the end. You pass that callback to @ref pqxx::perform, which - * runs it for you. - * - * If there's a failure inside your callback, there will be an exception. Your - * transaction object goes out of scope and gets destroyed, so that it aborts - * implicitly. Seeing this, @ref perform tries running your callback again. It - * stops doing that when the callback succeeds, or when it has failed too many - * times, or when there's an error that leaves the database in an unknown - * state, such as a lost connection just while we're waiting for the database - * to confirm a commit. It all depends on the type of exception. - * - * The callback takes no arguments. If you're using lambdas, the easy way to - * pass arguments is for the lambda to "capture" them from your variables. Or, - * if you're using functions, you may want to use `std::bind`. - * - * Once your callback succeeds, it can return a result, and @ref perform will - * return that result back to you. - */ -//@{ - -/// Simple way to execute a transaction with automatic retry. -/** - * Executes your transaction code as a callback. Repeats it until it completes - * normally, or it throws an error other than the few libpqxx-generated - * exceptions that the framework understands, or after a given number of failed - * attempts, or if the transaction ends in an "in-doubt" state. - * - * (An in-doubt state is one where libpqxx cannot determine whether the server - * finally committed a transaction or not. This can happen if the network - * connection to the server is lost just while we're waiting for its reply to - * a "commit" statement. The server may have completed the commit, or not, but - * it can't tell you because there's no longer a connection. - * - * Using this still takes a bit of care. If your callback makes use of data - * from the database, you'll probably have to query that data within your - * callback. If the attempt to perform your callback fails, and the framework - * tries again, you'll be in a new transaction and the data in the database may - * have changed under your feet. - * - * Also be careful about changing variables or data structures from within - * your callback. The run may still fail, and perhaps get run again. The - * ideal way to do it (in most cases) is to return your result from your - * callback, and change your program's data state only after @ref perform - * completes successfully. - * - * @param callback Transaction code that can be called with no arguments. - * @param attempts Maximum number of times to attempt performing callback. - * Must be greater than zero. - * @return Whatever your callback returns. - */ -template -inline auto perform(TRANSACTION_CALLBACK &&callback, int attempts = 3) - -> std::invoke_result_t -{ - if (attempts <= 0) - throw std::invalid_argument{ - "Zero or negative number of attempts passed to pqxx::perform()."}; - - for (; attempts > 0; --attempts) - { - try - { - return std::invoke(callback); - } - catch (in_doubt_error const &) - { - // Not sure whether transaction went through or not. The last thing in - // the world that we should do now is try again! - throw; - } - catch (statement_completion_unknown const &) - { - // Not sure whether our last statement succeeded. Don't risk running it - // again. - throw; - } - catch (broken_connection const &) - { - // Connection failed. May be worth retrying, if the transactor opens its - // own connection. - if (attempts <= 1) - throw; - continue; - } - catch (transaction_rollback const &) - { - // Some error that may well be transient, such as serialization failure - // or deadlock. Worth retrying. - if (attempts <= 1) - throw; - continue; - } - } - throw pqxx::internal_error{"No outcome reached on perform()."}; -} -} // namespace pqxx -//@} -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/types b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/types deleted file mode 100644 index 23a5caae1..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/types +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Basic typedefs and forward declarations. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/types.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/types.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/types.hxx deleted file mode 100644 index f95b598f8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/types.hxx +++ /dev/null @@ -1,173 +0,0 @@ -/* Basic type aliases and forward declarations. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TYPES -#define PQXX_H_TYPES - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#if defined(PQXX_HAVE_CONCEPTS) && __has_include() -# include -#endif - - -namespace pqxx -{ -/// Number of rows in a result set. -using result_size_type = int; - -/// Difference between result sizes. -using result_difference_type = int; - -/// Number of fields in a row of database data. -using row_size_type = int; - -/// Difference between row sizes. -using row_difference_type = int; - -/// Number of bytes in a field of database data. -using field_size_type = std::size_t; - -/// Number of bytes in a large object. -using large_object_size_type = int64_t; - - -// Forward declarations, to help break compilation dependencies. -// These won't necessarily include all classes in libpqxx. -class binarystring; -class connection; -class const_result_iterator; -class const_reverse_result_iterator; -class const_reverse_row_iterator; -class const_row_iterator; -class dbtransaction; -class field; -class largeobjectaccess; -class notification_receiver; -struct range_error; -class result; -class row; -class stream_from; -class transaction_base; - -/// Marker for @ref stream_from constructors: "stream from table." -/** @deprecated Use @ref stream_from::table() instead. - */ -struct from_table_t -{}; - -/// Marker for @ref stream_from constructors: "stream from query." -/** @deprecated Use @ref stream_from::query() instead. - */ -struct from_query_t -{}; - - -/// Format code: is data text or binary? -/** Binary-compatible with libpq's format codes. - */ -enum class format : int -{ - text = 0, - binary = 1, -}; - - -/// Remove any constness, volatile, and reference-ness from a type. -/** @deprecated In C++20 we'll replace this with std::remove_cvref. - */ -template -using strip_t = std::remove_cv_t>; - - -#if defined(PQXX_HAVE_CONCEPTS) -/// The type of a container's elements. -/** At the time of writing there's a similar thing in `std::experimental`, - * which we may or may not end up using for this. - */ -template -using value_type = strip_t()))>; -#else // PQXX_HAVE_CONCEPTS -/// The type of a container's elements. -/** At the time of writing there's a similar thing in `std::experimental`, - * which we may or may not end up using for this. - */ -template -using value_type = strip_t()))>; -#endif // PQXX_HAVE_CONCEPTS - - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: Any type that we can read as a string of `char`. -template -concept char_string = std::ranges::contiguous_range and - std::same_as < strip_t>, -char > ; - -/// Concept: Anything we can iterate to get things we can read as strings. -template -concept char_strings = - std::ranges::range and char_string>>; - -/// Concept: Anything we might want to treat as binary data. -template -concept potential_binary = std::ranges::contiguous_range and - (sizeof(value_type) == 1); -#endif // PQXX_HAVE_CONCEPTS - - -// C++20: Retire these compatibility definitions. -#if defined(PQXX_HAVE_CONCEPTS) - -/// Template argument type for a range. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_RANGE_ARG std::ranges::range - -/// Template argument type for @ref char_string. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRING_ARG pqxx::char_string - -/// Template argument type for @ref char_strings -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRINGS_ARG pqxx::char_strings - -#else // PQXX_HAVE_CONCEPTS - -/// Template argument type for a range. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_RANGE_ARG typename - -/// Template argument type for @ref char_string. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRING_ARG typename - -/// Template argument type for @ref char_strings -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRINGS_ARG typename - -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/util b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/util deleted file mode 100644 index 6d85ab611..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/util +++ /dev/null @@ -1,6 +0,0 @@ -/** Various utility definitions for libpqxx. - */ -// Actual definitions in .hxx file so editors and such recognize file type -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/util.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/util.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/util.hxx deleted file mode 100644 index 4aa5ecf57..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/util.hxx +++ /dev/null @@ -1,521 +0,0 @@ -/* Various utility definitions for libpqxx. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_UTIL -#define PQXX_H_UTIL - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -#include "pqxx/except.hxx" -#include "pqxx/internal/encodings.hxx" -#include "pqxx/types.hxx" -#include "pqxx/version.hxx" - - -/// The home of all libpqxx classes, functions, templates, etc. -namespace pqxx -{} - -#include - - -/// Internal items for libpqxx' own use. Do not use these yourself. -namespace pqxx::internal -{ - -// C++20: Retire wrapper. -/// Same as `std::cmp_less`, or a workaround where that's not available. -template -inline constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_less(lhs, rhs); -#else - // We need a variable just because lgtm.com gives off a false positive - // warning when we compare the values directly. It considers that a - // "self-comparison." - constexpr bool left_signed{std::is_signed_v}; - if constexpr (left_signed == std::is_signed_v) - return lhs < rhs; - else if constexpr (std::is_signed_v) - return (lhs <= 0) ? true : (std::make_unsigned_t(lhs) < rhs); - else - return (rhs <= 0) ? false : (lhs < std::make_unsigned_t(rhs)); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_greater, or workaround if not available. -template -inline constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_greater(lhs, rhs); -#else - return cmp_less(rhs, lhs); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_less_equal, or workaround if not available. -template -inline constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_less_equal(lhs, rhs); -#else - return not cmp_less(rhs, lhs); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_greater_equal, or workaround if not available. -template -inline constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_greater_equal(lhs, rhs); -#else - return not cmp_less(lhs, rhs); -#endif -} - - -/// Efficiently concatenate two strings. -/** This is a special case of concatenate(), needed because dependency - * management does not let us use that function here. - */ -[[nodiscard]] inline std::string cat2(std::string_view x, std::string_view y) -{ - std::string buf; - auto const xs{std::size(x)}, ys{std::size(y)}; - buf.resize(xs + ys); - x.copy(std::data(buf), xs); - y.copy(std::data(buf) + xs, ys); - return buf; -} -} // namespace pqxx::internal - - -namespace pqxx -{ -using namespace std::literals; - -/// Suppress compiler warning about an unused item. -template inline constexpr void ignore_unused(T &&...) noexcept -{} - - -/// Cast a numeric value to another type, or throw if it underflows/overflows. -/** Both types must be arithmetic types, and they must either be both integral - * or both floating-point types. - */ -template -inline TO check_cast(FROM value, std::string_view description) -{ - static_assert(std::is_arithmetic_v); - static_assert(std::is_arithmetic_v); - static_assert(std::is_integral_v == std::is_integral_v); - - // The rest of this code won't quite work for bool, but bool is trivially - // convertible to other arithmetic types as far as I can see. - if constexpr (std::is_same_v) - return static_cast(value); - - // Depending on our "if constexpr" conditions, this parameter may not be - // needed. Some compilers will warn. - ignore_unused(description); - - using from_limits = std::numeric_limits; - using to_limits = std::numeric_limits; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_signed_v) - { - if (value < to_limits::lowest()) - throw range_error{internal::cat2("Cast underflow: "sv, description)}; - } - else - { - // FROM is signed, but TO is not. Treat this as a special case, because - // there may not be a good broader type in which the compiler can even - // perform our check. - if (value < 0) - throw range_error{internal::cat2( - "Casting negative value to unsigned type: "sv, description)}; - } - } - else - { - // No need to check: the value is unsigned so can't fall below the range - // of the TO type. - } - - if constexpr (std::is_integral_v) - { - using unsigned_from = std::make_unsigned_t; - using unsigned_to = std::make_unsigned_t; - constexpr auto from_max{static_cast((from_limits::max)())}; - constexpr auto to_max{static_cast((to_limits::max)())}; - if constexpr (from_max > to_max) - { - if (internal::cmp_greater(value, to_max)) - throw range_error{internal::cat2("Cast overflow: "sv, description)}; - } - } - else if constexpr ((from_limits::max)() > (to_limits::max)()) - { - if (value > (to_limits::max)()) - throw range_error{internal::cat2("Cast overflow: ", description)}; - } - - return static_cast(value); -} - - -/** Check library version at link time. - * - * Ensures a failure when linking an application against a radically - * different libpqxx version than the one against which it was compiled. - * - * Sometimes application builds fail in unclear ways because they compile - * using headers from libpqxx version X, but then link against libpqxx - * binary version Y. A typical scenario would be one where you're building - * against a libpqxx which you have built yourself, but a different version - * is installed on the system. - * - * The check_library_version template is declared for any library version, - * but only actually defined for the version of the libpqxx binary against - * which the code is linked. - * - * If the library binary is a different version than the one declared in - * these headers, then this call will fail to link: there will be no - * definition for the function with these exact template parameter values. - * There will be a definition, but the version in the parameter values will - * be different. - */ -inline PQXX_PRIVATE void check_version() noexcept -{ - // There is no particular reason to do this here in @ref connection, except - // to ensure that every meaningful libpqxx client will execute it. The call - // must be in the execution path somewhere or the compiler won't try to link - // it. We can't use it to initialise a global or class-static variable, - // because a smart compiler might resolve it at compile time. - // - // On the other hand, we don't want to make a useless function call too - // often for performance reasons. A local static variable is initialised - // only on the definition's first execution. Compilers will be well - // optimised for this behaviour, so there's a minimal one-time cost. - static auto const version_ok{internal::PQXX_VERSION_CHECK()}; - ignore_unused(version_ok); -} - - -/// Descriptor of library's thread-safety model. -/** This describes what the library knows about various risks to thread-safety. - */ -struct PQXX_LIBEXPORT thread_safety_model -{ - /// Is the underlying libpq build thread-safe? - bool safe_libpq = false; - - /// Is Kerberos thread-safe? - /** @warning Is currently always `false`. - * - * If your application uses Kerberos, all accesses to libpqxx or Kerberos - * must be serialized. Confine their use to a single thread, or protect it - * with a global lock. - */ - bool safe_kerberos = false; - - /// A human-readable description of any thread-safety issues. - std::string description; -}; - - -/// Describe thread safety available in this build. -[[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety(); - - -#if defined(PQXX_HAVE_CONCEPTS) -# define PQXX_POTENTIAL_BINARY_ARG pqxx::potential_binary -#else -# define PQXX_POTENTIAL_BINARY_ARG typename -#endif - - -/// Cast binary data to a type that libpqxx will recognise as binary. -/** There are many different formats for storing binary data in memory. You - * may have yours as a `std::string`, or a `std::vector`, or one of - * many other types. - * - * But for libpqxx to recognise your data as binary, it needs to be a - * `std::basic_string`, or a `std::basic_string_view`; - * or in C++20 or better, any contiguous block of `std::byte`. - * - * Use `binary_cast` as a convenience helper to cast your data as a - * `std::basic_string_view`. - * - * @warning There are two things you should be aware of! First, the data must - * be contiguous in memory. In C++20 the compiler will enforce this, but in - * C++17 it's your own problem. Second, you must keep the object where you - * store the actual data alive for as long as you might use this function's - * return value. - */ -template -std::basic_string_view binary_cast(TYPE const &data) -{ - static_assert(sizeof(value_type) == 1); - return { - reinterpret_cast( - const_cast const *>( - std::data(data))), - std::size(data)}; -} - - -#if defined(PQXX_HAVE_CONCEPTS) -template -concept char_sized = (sizeof(CHAR) == 1); -# define PQXX_CHAR_SIZED_ARG char_sized -#else -# define PQXX_CHAR_SIZED_ARG typename -#endif - -/// Construct a type that libpqxx will recognise as binary. -/** Takes a data pointer and a size, without being too strict about their - * types, and constructs a `std::basic_string_view` pointing to - * the same data. - * - * This makes it a little easier to turn binary data, in whatever form you - * happen to have it, into binary data as libpqxx understands it. - */ -template -std::basic_string_view binary_cast(CHAR const *data, SIZE size) -{ - static_assert(sizeof(CHAR) == 1); - return { - reinterpret_cast(data), - check_cast(size, "binary data size")}; -} - - -/// The "null" oid. -constexpr oid oid_none{0}; -} // namespace pqxx - - -/// Private namespace for libpqxx's internal use; do not access. -/** This namespace hides definitions internal to libpqxx. These are not - * supposed to be used by client programs, and they may change at any time - * without notice. - * - * Conversely, if you find something in this namespace tremendously useful, by - * all means do lodge a request for its publication. - * - * @warning Here be dragons! - */ -namespace pqxx::internal -{ -using namespace std::literals; - - -/// A safer and more generic replacement for `std::isdigit`. -/** Turns out `std::isdigit` isn't as easy to use as it sounds. It takes an - * `int`, but requires it to be nonnegative. Which means it's an outright - * liability on systems where `char` is signed. - */ -template inline constexpr bool is_digit(CHAR c) noexcept -{ - return (c >= '0') and (c <= '9'); -} - - -/// Describe an object for humans, based on class name and optional name. -/** Interprets an empty name as "no name given." - */ -[[nodiscard]] std::string -describe_object(std::string_view class_name, std::string_view name); - - -/// Check validity of registering a new "guest" in a "host." -/** The host might be e.g. a connection, and the guest a transaction. The - * host can only have one guest at a time, so it is an error to register a new - * guest while the host already has a guest. - * - * If the new registration is an error, this function throws a descriptive - * exception. - * - * Pass the old guest (if any) and the new guest (if any), for both, a type - * name (at least if the guest is not null), and optionally an object name - * (but which may be omitted if the caller did not assign one). - */ -void check_unique_register( - void const *old_guest, std::string_view old_class, std::string_view old_name, - void const *new_guest, std::string_view new_class, - std::string_view new_name); - - -/// Like @ref check_unique_register, but for un-registering a guest. -/** Pass the guest which was registered, as well as the guest which is being - * unregistered, so that the function can check that they are the same one. - */ -void check_unique_unregister( - void const *old_guest, std::string_view old_class, std::string_view old_name, - void const *new_guest, std::string_view new_class, - std::string_view new_name); - - -/// Compute buffer size needed to escape binary data for use as a BYTEA. -/** This uses the hex-escaping format. The return value includes room for the - * "\x" prefix. - */ -inline constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept -{ - return 2 + (2 * binary_bytes) + 1; -} - - -/// Compute binary size from the size of its escaped version. -/** Do not include a terminating zero in `escaped_bytes`. - */ -inline constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept -{ - return (escaped_bytes - 2) / 2; -} - - -// TODO: Use actual binary type for "data". -/// Hex-escape binary data into a buffer. -/** The buffer must be able to accommodate - * `size_esc_bin(std::size(binary_data))` bytes, and the function will write - * exactly that number of bytes into the buffer. This includes a trailing - * zero. - */ -void PQXX_LIBEXPORT -esc_bin(std::basic_string_view binary_data, char buffer[]) noexcept; - - -/// Hex-escape binary data into a std::string. -std::string PQXX_LIBEXPORT -esc_bin(std::basic_string_view binary_data); - - -/// Reconstitute binary data from its escaped version. -void PQXX_LIBEXPORT -unesc_bin(std::string_view escaped_data, std::byte buffer[]); - - -/// Reconstitute binary data from its escaped version. -std::basic_string - PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data); - - -/// Transitional: std::ssize(), or custom implementation if not available. -template auto ssize(T const &c) -{ -#if defined(__cpp_lib_ssize) && __cplusplus >= __cpp_lib_ssize - return std::ssize(c); -#else - using signed_t = std::make_signed_t; - return static_cast(std::size(c)); -#endif // __cpp_lib_ssize -} - - -/// Helper for determining a function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple args_f(RETURN (&func)(ARGS...)); - - -/// Helper for determining a `std::function`'s parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple args_f(std::function const &); - - -/// Helper for determining a member function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple member_args_f(RETURN (CLASS::*)(ARGS...)); - - -/// Helper for determining a const member function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple member_args_f(RETURN (CLASS::*)(ARGS...) const); - - -/// Helper for determining a callable type's parameter types. -/** This specialisation should work for lambdas. - * - * This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -auto args_f(CALLABLE const &f) - -> decltype(member_args_f(&CALLABLE::operator())); - - -/// A callable's parameter types, as a tuple. -template -using args_t = decltype(args_f(std::declval())); - - -/// Helper: Apply `strip_t` to each of a tuple type's component types. -/** This function has no definition. It is not meant to be called, only to be - * used to deduce the right types. - */ -template -std::tuple...> strip_types(std::tuple const &); - - -/// Take a tuple type and apply @ref strip_t to its component types. -template -using strip_types_t = decltype(strip_types(std::declval())); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/version b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/version deleted file mode 100644 index 8dd5e48d4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/version +++ /dev/null @@ -1,7 +0,0 @@ -/** libpqxx version info. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/version.hxx" -#include "pqxx/internal/header-post.hxx" - diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/version.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/version.hxx deleted file mode 100644 index a159f1bed..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/version.hxx +++ /dev/null @@ -1,55 +0,0 @@ -/* Version info for libpqxx. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_VERSION - -# if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -# endif - -/// Full libpqxx version string. -# define PQXX_VERSION "7.7.3" -/// Library ABI version. -# define PQXX_ABI "7.7" - -/// Major version number. -# define PQXX_VERSION_MAJOR 7 -/// Minor version number. -# define PQXX_VERSION_MINOR 7 - -# define PQXX_VERSION_CHECK check_pqxx_version_7_7 - -namespace pqxx::internal -{ -/// Library version check stub. -/** Helps detect version mismatches between libpqxx headers and the libpqxx - * library binary. - * - * Sometimes users run into trouble linking their code against libpqxx because - * they build their own libpqxx, but the system also has a different version - * installed. The declarations in the headers against which they compile their - * code will differ from the ones used to build the libpqxx version they're - * using, leading to confusing link errors. The solution is to generate a link - * error when the libpqxx binary is not the same version as the libpqxx headers - * used to compile the code. - * - * This function's definition is in the libpqxx binary, so it's based on the - * version as found in the binary. The headers contain a call to the function, - * whose name contains the libpqxx version as found in the headers. (The - * library build process will use its own local headers even if another version - * of the headers is installed on the system.) - * - * If the libpqxx binary was compiled for a different version than the user's - * code, linking will fail with an error: `check_pqxx_version_*_*` will not - * exist for the given version number. - */ -PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/zview b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/zview deleted file mode 100644 index 66ea2a625..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/zview +++ /dev/null @@ -1,6 +0,0 @@ -/** Zero-terminated string view class. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/zview.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/zview.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/zview.hxx deleted file mode 100644 index 36a779f51..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/include/pqxx/zview.hxx +++ /dev/null @@ -1,163 +0,0 @@ -/* Zero-terminated string view. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/zview instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ZVIEW -#define PQXX_H_ZVIEW - -#include -#include -#include - -#include "pqxx/types.hxx" - - -namespace pqxx -{ -/// Marker-type wrapper: zero-terminated `std::string_view`. -/** @warning Use this only if the underlying string is zero-terminated. - * - * When you construct a zview, you are promising that if the data pointer is - * non-null, the underlying string is zero-terminated. It otherwise behaves - * exactly like a std::string_view. - * - * The terminating zero is not "in" the string, so it does not count as part of - * the view's length. - * - * The added guarantee lets the view be used as a C-style string, which often - * matters since libpqxx builds on top of a C library. For this reason, zview - * also adds a @ref c_str method. - */ -class zview : public std::string_view -{ -public: - constexpr zview() noexcept = default; - - /// Convenience overload: construct using pointer and signed length. - constexpr zview(char const text[], std::ptrdiff_t len) : - std::string_view{text, static_cast(len)} - {} - - /// Convenience overload: construct using pointer and signed length. - constexpr zview(char text[], std::ptrdiff_t len) : - std::string_view{text, static_cast(len)} - {} - - /// Explicitly promote a `string_view` to a `zview`. - explicit constexpr zview(std::string_view other) noexcept : - std::string_view{other} - {} - - /// Construct from any initialiser you might use for `std::string_view`. - /** @warning Only do this if you are sure that the string is zero-terminated. - */ - template - explicit constexpr zview(Args &&...args) : - std::string_view(std::forward(args)...) - {} - - // C++20: constexpr. - /// @warning There's an implicit conversion from `std::string`. - zview(std::string const &str) noexcept : - std::string_view{str.c_str(), str.size()} - {} - - /// Construct a `zview` from a C-style string. - /** @warning This scans the string to discover its length. So if you need to - * do it many times, it's probably better to create the `zview` once and - * re-use it. - */ - constexpr zview(char const str[]) : std::string_view{str} {} - - /// Construct a `zview` from a string literal. - /** A C++ string literal ("foo") normally looks a lot like a pointer to - * char const, but that's not really true. It's actually an array of char, - * which _devolves_ to a pointer when you pass it. - * - * For the purpose of creating a `zview` there is one big difference: if we - * know the array's size, we don't need to scan through the string in order - * to find out its length. - */ - template - constexpr zview(char const (&literal)[size]) : zview(literal, size - 1) - {} - - /// Either a null pointer, or a zero-terminated text buffer. - [[nodiscard]] constexpr char const *c_str() const &noexcept - { - return data(); - } -}; - - -/// Support @ref zview literals. -/** You can "import" this selectively into your namespace, without pulling in - * all of the @ref pqxx namespace: - * - * ```cxx - * using pqxx::operator"" _zv; - * ``` - */ -constexpr zview operator"" _zv(char const str[], std::size_t len) noexcept -{ - return zview{str, len}; -} -} // namespace pqxx - - -#if defined(PQXX_HAVE_CONCEPTS) -/// A zview is a view. -template<> inline constexpr bool std::ranges::enable_view{true}; - - -/// A zview is a borrowed range. -template<> -inline constexpr bool std::ranges::enable_borrowed_range{true}; - -namespace pqxx::internal -{ -/// Concept: T is a known zero-terminated string type. -/** There's no unified API for these string types. It's just a check for some - * known types. Any code that makes use of the concept will still have to - * support each of these individually. - */ -template -concept ZString = std::is_convertible_v < strip_t, -char const * > or std::is_convertible_v, zview> or - std::is_convertible_v; -} // namespace pqxx::internal -#endif // PQXX_HAVE_CONCEPTS - - -namespace pqxx::internal -{ -/// Get a raw C string pointer. -inline constexpr char const *as_c_string(char const str[]) noexcept -{ - return str; -} -/// Get a raw C string pointer. -template -inline constexpr char const *as_c_string(char (&str)[N]) noexcept -{ - return str; -} -/// Get a raw C string pointer. -inline constexpr char const *as_c_string(pqxx::zview str) noexcept -{ - return str.c_str(); -} -// C++20: Make this constexpr. -/// Get a raw C string pointer. -inline char const *as_c_string(std::string const &str) noexcept -{ - return str.c_str(); -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-config-version.cmake b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-config-version.cmake deleted file mode 100644 index c47d6956d..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-config-version.cmake +++ /dev/null @@ -1,70 +0,0 @@ -# This is a basic version file for the Config-mode of find_package(). -# It is used by write_basic_package_version_file() as input file for configure_file() -# to create a version-file which can be installed along a config.cmake file. -# -# The created file sets PACKAGE_VERSION_EXACT if the current version string and -# the requested version string are exactly the same and it sets -# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, -# but only if the requested major version is the same as the current one. -# The variable CVF_VERSION must be set before calling configure_file(). - - -set(PACKAGE_VERSION "7.7.3") - -if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - - if("7.7.3" MATCHES "^([0-9]+)\\.") - set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") - if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) - string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") - endif() - else() - set(CVF_VERSION_MAJOR "7.7.3") - endif() - - if(PACKAGE_FIND_VERSION_RANGE) - # both endpoints of the range must have the expected major version - math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") - if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR - OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) - OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) - set(PACKAGE_VERSION_COMPATIBLE FALSE) - elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR - AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) - OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) - set(PACKAGE_VERSION_COMPATIBLE TRUE) - else() - set(PACKAGE_VERSION_COMPATIBLE FALSE) - endif() - else() - if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) - set(PACKAGE_VERSION_COMPATIBLE TRUE) - else() - set(PACKAGE_VERSION_COMPATIBLE FALSE) - endif() - - if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) - set(PACKAGE_VERSION_EXACT TRUE) - endif() - endif() -endif() - - -# if the installed project requested no architecture check, don't perform the check -if("FALSE") - return() -endif() - -# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: -if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") - return() -endif() - -# check that the installed version has the same 32/64bit-ness as the one which is currently searching: -if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") - math(EXPR installedBits "8 * 8") - set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") - set(PACKAGE_VERSION_UNSUITABLE TRUE) -endif() diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-config.cmake b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-config.cmake deleted file mode 100644 index cb25a05f2..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-config.cmake +++ /dev/null @@ -1,4 +0,0 @@ -include(CMakeFindDependencyMacro) -find_dependency(PostgreSQL) - -include("${CMAKE_CURRENT_LIST_DIR}/libpqxx-targets.cmake") diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-targets-noconfig.cmake b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-targets-noconfig.cmake deleted file mode 100644 index 980f46098..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-targets-noconfig.cmake +++ /dev/null @@ -1,19 +0,0 @@ -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Import target "libpqxx::pqxx" for configuration "" -set_property(TARGET libpqxx::pqxx APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) -set_target_properties(libpqxx::pqxx PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "CXX" - IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libpqxx-7.7.a" - ) - -list(APPEND _IMPORT_CHECK_TARGETS libpqxx::pqxx ) -list(APPEND _IMPORT_CHECK_FILES_FOR_libpqxx::pqxx "${_IMPORT_PREFIX}/lib/libpqxx-7.7.a" ) - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-targets.cmake b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-targets.cmake deleted file mode 100644 index 4716fb7b2..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/cmake/libpqxx/libpqxx-targets.cmake +++ /dev/null @@ -1,99 +0,0 @@ -# Generated by CMake - -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) - message(FATAL_ERROR "CMake >= 2.6.0 required") -endif() -cmake_policy(PUSH) -cmake_policy(VERSION 2.6...3.20) -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Protect against multiple inclusion, which would fail when already imported targets are added once more. -set(_targetsDefined) -set(_targetsNotDefined) -set(_expectedTargets) -foreach(_expectedTarget libpqxx::pqxx) - list(APPEND _expectedTargets ${_expectedTarget}) - if(NOT TARGET ${_expectedTarget}) - list(APPEND _targetsNotDefined ${_expectedTarget}) - endif() - if(TARGET ${_expectedTarget}) - list(APPEND _targetsDefined ${_expectedTarget}) - endif() -endforeach() -if("${_targetsDefined}" STREQUAL "${_expectedTargets}") - unset(_targetsDefined) - unset(_targetsNotDefined) - unset(_expectedTargets) - set(CMAKE_IMPORT_FILE_VERSION) - cmake_policy(POP) - return() -endif() -if(NOT "${_targetsDefined}" STREQUAL "") - message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") -endif() -unset(_targetsDefined) -unset(_targetsNotDefined) -unset(_expectedTargets) - - -# Compute the installation prefix relative to this file. -get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -if(_IMPORT_PREFIX STREQUAL "/") - set(_IMPORT_PREFIX "") -endif() - -# Create imported target libpqxx::pqxx -add_library(libpqxx::pqxx STATIC IMPORTED) - -set_target_properties(libpqxx::pqxx PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" - INTERFACE_LINK_LIBRARIES "/usr/lib/x86_64-linux-gnu/libpq.so" -) - -if(CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") -endif() - -# Load information for each installed configuration. -get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -file(GLOB CONFIG_FILES "${_DIR}/libpqxx-targets-*.cmake") -foreach(f ${CONFIG_FILES}) - include(${f}) -endforeach() - -# Cleanup temporary variables. -set(_IMPORT_PREFIX) - -# Loop over all imported files and verify that they actually exist -foreach(target ${_IMPORT_CHECK_TARGETS} ) - foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) - if(NOT EXISTS "${file}" ) - message(FATAL_ERROR "The imported target \"${target}\" references the file - \"${file}\" -but this file does not exist. Possible reasons include: -* The file was deleted, renamed, or moved to another location. -* An install or uninstall procedure did not complete successfully. -* The installation package was faulty and contained - \"${CMAKE_CURRENT_LIST_FILE}\" -but not all the files it references. -") - endif() - endforeach() - unset(_IMPORT_CHECK_FILES_FOR_${target}) -endforeach() -unset(_IMPORT_CHECK_TARGETS) - -# This file does not depend on other imported targets which have -# been exported from the same project but in a separate export set. - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) -cmake_policy(POP) diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/libpqxx-7.7.a b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/libpqxx-7.7.a deleted file mode 100644 index fb941debb..000000000 Binary files a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/libpqxx-7.7.a and /dev/null differ diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/libpqxx.a b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/libpqxx.a deleted file mode 120000 index d9fcdab85..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/lib/libpqxx.a +++ /dev/null @@ -1 +0,0 @@ -libpqxx-7.7.a \ No newline at end of file diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/accessing-results.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/accessing-results.md deleted file mode 100644 index 920fb6f3b..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/accessing-results.md +++ /dev/null @@ -1,157 +0,0 @@ -Accessing results and result rows {#accessing-results} ---------------------------------- - -When you execute a query using one of the transaction `exec` functions, you -normally get a `result` object back. A `result` is a container of `row`s. - -(There are exceptions. The `exec1` functions expect exactly one row of data, -so they return just a `row`, not a full `result`.) - -Result objects are an all-or-nothing affair. The `exec` function waits until -it's received all the result data, and then gives it to you in the form of the -`result`. _(There is a faster, easier way of executing simple queries, so see -"streaming rows" below as well.)_ - -For example, your code might do: - -```cxx - pqxx::result r = tx.exec("SELECT * FROM mytable"); -``` - -Now, how do you access the data inside `r`? - -Result sets act as standard C++ containers of rows. Rows act as standard -C++ containers of fields. So the easiest way to go through them is: - -```cxx - for (auto const &row: r) - { - for (auto const &field: row) std::cout << field.c_str() << '\t'; - std::cout << '\n'; - } -``` - -But results and rows also support other kinds of access. Array-style -indexing, for instance, such as `r[rownum]`: - -```cxx - std::size_t const num_rows = std::size(r); - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - pqxx::row const row = r[rownum]; - std::size_t const num_cols = std::size(row); - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - { - pqxx::field const field = row[colnum]; - std::cout << field.c_str() << '\t'; - } - - std::cout << '\n'; - } -``` - -Every row in the result has the same number of columns, so you don't need to -look up the number of fields again for each one: - -```cxx - std::size_t const num_rows = std::size(r); - std::size_t const num_cols = r.columns(); - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - pqxx::row const row = r[rownum]; - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - { - pqxx::field const field = row[colnum]; - std::cout << field.c_str() << '\t'; - } - - std::cout << '\n'; - } -``` - -You can even address a field by indexing the `row` using the field's _name:_ - -```cxx - std::cout << row["salary"] << '\n'; -``` - -But try not to do that if speed matters, because looking up the column by name -takes time. At least you'd want to look up the column index before your loop -and then use numerical indexes inside the loop. - -For C++23 or better, there's also a two-dimensional array access operator: - -```cxx - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - std::cout result[rownum, colnum].c_str() << '\t'; - std::cout << '\n'; - } -``` - -And of course you can use classic "begin/end" loops: - -```cxx - for (auto row = std::begin(r); row != std::end(r); row++) - { - for (auto field = std::begin(row); field != std::end(row); field++) - std::cout << field->c_str() << '\t'; - std::cout << '\n'; - } -``` - -Result sets are immutable, so all iterators on results and rows are actually -`const_iterator`s. There are also `const_reverse_iterator` types, which -iterate backwards from `rbegin()` to `rend()` exclusive. - -All these iterator types provide one extra bit of convenience that you won't -normally find in C++ iterators: referential transparency. You don't need to -dereference them to get to the row or field they refer to. That is, instead -of `row->end()` you can also choose to say `row.end()`. Similarly, you -may prefer `field.c_str()` over `field->c_str()`. - -This becomes really helpful with the array-indexing operator. With regular -C++ iterators you would need ugly expressions like `(*row)[0]` or -`row->operator[](0)`. With the iterator types defined by the result and -row classes you can simply say `row[0]`. - - -Streaming rows --------------- - -There's another way to go through the rows coming out of a query. It's -usually easier and faster, but there are drawbacks. - -**One,** you start getting rows before all the data has come in from the -database. That speeds things up, but what happens if you lose your network -connection while transferring the data? Your application may already have -processed some of the data before finding out that the rest isn't coming. If -that is a problem for your application, streaming may not be the right choice. - -**Two,** streaming only works for some types of query. The `stream()` function -wraps your query in a PostgreSQL `COPY` command, and `COPY` only supports a few -commands: `SELECT`, `VALUES`, `or an `INSERT`, `UPDATE`, or `DELETE` with a -`RETURNING` clause. See the `COPY` documentation here: -https://www.postgresql.org/docs/current/sql-copy.html - -**Three,** when you convert a field to a "view" type (such as -`std::string_view` or `std::basic_string_view`), the view points to -underlying data which only stays valid until you iterate to the next row or -exit the loop. So if you want to use that data for longer than a single -iteration of the streaming loop, you'll have to store it somewhere yourself. - -Now for the good news. Streaming does make it very easy to query data and loop -over it: - -```cxx - for (auto [id, name, x, y] : - tx.stream( - "SELECT id, name, x, y FROM point")) - process(id + 1, "point-" + name, x * 10.0, y * 10.0); -``` - -The conversion to C++ types (here `int`, `std::string_view`, and two `float`s) -is built into the function. You never even see `row` objects, `field` objects, -iterators, or conversion methods. You just put in your query and you receive -your data. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/binary-data.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/binary-data.md deleted file mode 100644 index 20da8dc0c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/binary-data.md +++ /dev/null @@ -1,56 +0,0 @@ -Binary data {#binary} -=========== - -The database has two ways of storing binary data: `BYTEA` is like a string, but -containing bytes rather than text characters. And _large objects_ are more -like a separate table containing binary objects. - -Generally you'll want to use `BYTEA` for reasonably-sized values, and large -objects for very large values. - -That's the database side. On the C++ side, in libpqxx, all binary data must be -either `std::basic_string` or `std::basic_string_view`; -or if you're building in C++20 or better, anything that's a block of -contiguous `std::byte` in memory. - -So for example, if you want to write a large object, you'd create a -`pqxx::blob` object. And you might use that to write data in the form of -`std::basic_string_view`. - -Your particular binary data may look different though. You may have it in a -`std::string`, or a `std::vector`, or a pointer to `char` -accompanied by a size (which could be signed or unsigned, and of any of a few -different widths). Sometimes that's your choice, or sometimes some other -library will dictate what form it takes. - -So long as it's _basically_ still a block of bytes though, you can use -`pqxx::binary_cast` to construct a `std::basic_string_view` from it. - -There are two forms of `binary_cast`. One takes a single argument that must -support `std::data()` and `std::size()`: - - std::string hi{"Hello binary world"}; - my_blob.write(pqxx::binary_cast(hi); - -The other takes a pointer and a size: - - char const greeting[] = "Hello binary world"; - char const *hi = greeting; - my_blob.write(pqxx::binary_cast(hi, sizeof(greeting))); - - -Caveats -------- - -There are some restrictions on `binary_cast` that you must be aware of. - -First, your data must of a type that gives us _bytes._ So: `char`, -`unsigned char`, `signed char`, `int8_t`, `uint8_t`, or of course `std::byte`. -You can't feed in a vector of `double`, or anything like that. - -Second, the data must be laid out as a contiguous block in memory. If there's -no `std::data()` implementation for your type, it's not suitable. - -Third, `binary_cast` only constructs something like a `std::string_view`. It -does not make a copy of your actual data. So, make sure that your data remains -alive and in the same place while you're using it. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/datatypes.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/datatypes.md deleted file mode 100644 index bc14c8b90..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/datatypes.md +++ /dev/null @@ -1,373 +0,0 @@ -Supporting additional data types {#datatypes} -================================ - -Communication with the database mostly happens in a text format. When you -include an integer value in a query, you use `to_string` to convert it to that -text format. When you get a query result field "as a float," it converts from -the text format to a floating-point type. These conversions are everywhere in -libpqxx. - -The conversion sydstem supports many built-in types, but it is also extensible. -You can "teach" libpqxx (in the scope of your own application) to convert -additional types of values to and from PostgreSQL's string format. - -This is massively useful, but it's not for the faint of heart. You'll need to -specialise some templates. And, **the API for doing this can change with any -major libpqxx release.** - - -Converting types ----------------- - -In your application, a conversion is driven entirely by a C++ type you specify. -The value's SQL type has nothing to do with it, nor is there anything in the -string that would identify its type. - -So, if you've SELECTed a 64-bit integer from the database, and you try to -convert it to a C++ "short," one of two things will happen: either the number -is small enough to fit in your `short` (and it just works), or else it throws a -conversion exception. - -Or, your database table might have a text column, but a given field may contain -a string that _looks_ just like a number. You can convert that value to an -integer type just fine. Or to a floating-point type. All that matters to the -conversion is the actual value, and the type. - -In some cases the templates for these conversions can tell the type from the -arguments you pass them: - - auto x = to_string(99); - -In other cases you may need to instantiate template explicitly: - - auto y = from_string("99"); - - -Supporting a new type ---------------------- - -Let's say you have some other SQL type which you want to be able to store in, -or retrieve from, the database. What would it take to support that? - -Sometimes you do not need _complete_ support. You might need a conversion _to_ -a string but not _from_ a string, for example. The conversion is defined at -compile time, so don't be too afraid to be incomplete. If you leave out one of -these steps, it's not going to crash at run time or mess up your data. The -worst that can happen is that your code won't build. - -So what do you need for a complete conversion? - -First off, of course, you need a C++ type. It may be your own, but it -doesn't have to be. It could be a type from a third-party library, or even one -from the standard library that libpqxx does not yet support. - -You also specialise the `pqxx::type_name` variable to specify the type's name. -This is important for all code which mentions your type in human-readable text, -such as error messages. - -Then, does your type have a built-in null value? You specialise the -`pqxx::nullness` template to specify the details. - -Finally, you specialise the `pqxx::string_traits` template. This is where you -define the actual conversions. - -Let's go through these steps one by one. - - -Your type ---------- - -You'll need a type for which the conversions are not yet defined, because the -C++ type is what determines the right conversion. One type, one set of -conversions. - -The type doesn't have to be one that you create. The conversion logic was -designed such that you can build it around any type. So you can just as -easily build a conversion for a type that's defined somewhere else. There's -no need to include any special methods or other members inside it. That's also -how libpqxx can support converting built-in types like `int`. - -By the way, if the type is an enum, you don't need to do any of this. Just -invoke the preprocessor macro `PQXX_DECLARE_ENUM_CONVERSION`, from the global -namespace near the top of your translation unit, and pass the type as an -argument. - -The library also provides specialisations for `std::optional`, -`std::shared_ptr`, and `std::unique_ptr`. If you have conversions for -`T`, you'll also have conversions for those. - - -Specialise `type_name` ----------------------- - -When errors happen during conversion, libpqxx will compose error messages for -the user. Sometimes these will include the name of the type that's being -converted. - -To tell libpqxx the name of each type, there's a template variable called -`pqxx::type_name`. For any given type `T`, it should have a specialisation -that provides that `T`'s human-readable name: - - namespace pqxx - { - template<> std::string const type_name{"T"}; - } - -(Yes, this means that you need to define something inside the pqxx namespace. -Future versions of libpqxx may move this into a separate namespace.) - -Define this early on in your translation unit, before any code that might cause -libpqxx to need the name. That way, the libpqxx code which needs to know the -type's name can see your definition. - - -Specialise `nullness` ---------------------- - -A struct template `pqxx::nullness` defines whether your type has a natural -"null value" built in. If so, it also provides member functions for producing -and recognising null values. - -The simplest scenario is also the most common: most types don't have a null -value built in. In that case, derive your nullness traits from -`pqxx::no_null`: - - namespace pqxx - { - template<> struct nullness : pqxx::no_null {}; - } - -(Here again you're defining this in the pqxx namespace.) - -If your type does have a natural null value, the definition gets a little more -complex: - - namespace pqxx - { - template<> struct nullness - { - static constexpr bool has_null{true}; - static constexpr bool always_null{false}; - - static bool is_null(T const &value) - { - // Return whether "value" is null. - return ...; - } - - [[nodiscard]] static T null() - { - // Return a null value. - return ...; - } - }; - } - -You may be wondering why there's a function to produce a null value, but also a -function to check whether a value is null. Why not just compare the value to -the result of `null()`? Because two null values may not be equal. `T` may -have several different null values. Or it may override the comparison -operator, similar to SQL where NULL is not equal to NULL. - -As a third case, your type may be one that _always_ represents a null value. -This is the case for `std::nullptr_t` and `std::nullopt_t`. In that case, you -set `nullness::always_null` to `true` (as well as `has_null` of course), -and you won't need to define any actual conversions. - - -Specialise `string_traits` -------------------------- - -This part is more work. (You can skip it for types that are _always_ null, -but those will be rare.) Specialise the `pqxx::string_traits` template: - - namespace pqxx - { - template<> struct string_traits - { - static T from_string(std::string_view text); - static zview to_buf(char *begin, char *end, T const &value); - static char *into_buf(char *begin, char *end, T const &value); - static std::size_t size_buffer(T const &value) noexcept; - }; - } - -You'll also need to write those member functions, or as many of them as needed -to get your code to build. - - -### `from_string` - -We start off simple: `from_string` parses a string as a value of `T`, and -returns that value. - -The string may not be zero-terminated; it's just the `string_view` from -beginning to end (exclusive). In your tests, cover cases where the string -does not end in a zero byte. - -It's perfectly possible that the string isn't actually a `T` value. Mistakes -happen. In that case, throw a `pqxx::conversion_error`. - -(Of course it's also possible that you run into some other error, so it's fine -to throw different exceptions as well. But when it's definitely "this is not -the right format for a `T`," throw `conversion_error`.) - - -### `to_buf` - -In this function, you convert a value of `T` into a string that the postgres -server will understand. - -The caller will provide you with a buffer where you can write the string, if -you need it: from `begin` to `end` exclusive. It's a half-open interval, so -don't access `*end`. - -If the buffer is insufficient for you to do the conversion, throw a -`pqxx::conversion_overrun`. It doesn't have to be exact: you can be a little -pessimistic and demand a bit more space than you need. Just be sure to throw -the exception if there's any risk of overrunning the buffer. - -You don't _have_ to use the buffer for this function though. For example, -`pqxx::string_traits::to_buf` returns a compile-time constant string and -ignores the buffer. - -Even if you do use the buffer, your string does not _have_ to start at the -beginning of the buffer. For example, the integer conversions start by writing -the _least_ significant digit to the _end_ of the buffer, and then writes the -more significant digits before it. It was just more convenient. - -Return a `pqxx::zview`. This is basically a `std::string_view`, but with one -difference: a `zview` guarantees that there will be a valid zero byte right -after the `string_view`. The zero byte is not counted as part of its size, but -it will be there. - -Expressed in code, this rule must hold: - - void invariant(zview z) - { - assert(z[std::size(z)] == 0); - } - -Make sure you write your trailing zero _before_ the `end`. If the trailing -zero doesn't fit in the buffer, then there's just not enough room to perform -the conversion. - -Beware of locales when converting. If you use standard library features like -`sprintf`, they may obey whatever locale is currently set on the system. That -means that a simple integer like 1000000 may come out as "1000000" on your -system, but as "1,000,000" on mine, or as "1.000.000" for somebody else, and on -an Indian system it may be "1,00,000". Values coming from or going to the -database should be in non-localised formats. You can use libpqxx functions for -those conversions: `pqxx::from_string`, `pqxx::to_string`, `pqxx::to_buf`. - - -### `into_buf` - -This is a stricter version of `to_buf`. All the same requirements apply, but -in addition you must write your string into the buffer provided, starting -_exactly_ at `begin`. - -That's why this function returns just a simple pointer: the address right -behind the trailing zero. If the caller wants to use the string, they can -find it at `begin`. If they want to write a different value into the rest of -the buffer, they can start at the location you returned. - - -### `size_buffer` - -Here you estimate how much buffer space you need for converting a `T` to a -string. Be precise if you can, but pessimistic if you must. It's usually -better to waste a few unnecessary bytes than to spend a lot of time computing -the exact buffer space you need. And failing the conversion because you -under-budgeted the buffer is worst of all. - -Include the trailing zero in the buffer size. If your `to_buf` takes more -space than just what's needed to store the result, include that too. - -Make `size_buffer` a `constexpr` function if you can. It can allow the caller -to allocate the buffer on the stack, with a size known at compile time. - - -Optional: Specialise `is_unquoted_safe` ---------------------------------------- - -When converting arrays or composite values to strings, libpqxx may need to -quote values and escape any special characters. This takes time. - -Some types though, such as integral or floating-point types, can never have -any special characters such as quotes, commas, or backslashes in their string -representations. In such cases, there's no need to quote or escape such values -in arrays or composite types. - -If your type is like that, you can tell libpqxx about this by defining: - - namespace pqxx - { - template<> inline constexpr bool is_unquoted_safe{true}; - } - -The code that converts this type of field to strings in an array or a composite -type can then use a simpler, more efficient variant of the code. It's always -safe to leave this out; it's _just_ an optimisation for when you're completely -sure that it's safe. - -Do not do this if a string representation of your type may contain a comma; -semicolon; parenthesis; brace; quote; backslash; newline; or any other -character that might need escaping. - - -Optional: Specialise `param_format` ------------------------------------ - -This one you don't generally need to worry about. Read on if you're writing a -type which represents raw binary data, or if you're writing a template where -_some specialisations_ may contain raw binary data. - -When you call parameterised statements, or prepared statements with parameters, -libpqxx needs to your parameters on to libpq, the underlying C-level PostgreSQL -client library. - -There are two formats for doing that: _text_ and _binary._ In the first, we -represent all values as strings, and the server then converts them into its own -internal binary representation. That's what the string conversions are all -about, and it's what we do for almost all types of parameters. - -But we do it differently when the parameter is a contiguous series of raw bytes -and the corresponding SQL type is `BYTEA`. There is a text format for those, -but we bypass it for efficiency. The server can use the binary data in the -exact same form, without any conversion or extra processing. The binary data -is also twice as compact during transport. - -(People sometimes ask why we can't just treat all types as binary. However the -general case isn't so clear-cut. The binary formats are not documented, there -are no guarantees that they will be platform-independent or that they will -remain stable, and there's no really solid way to detect when we might get the -format wrong. But also, the conversions aren't necessarily as straightforward -and efficient as they sound. So, for the general case, libpqxx sticks with the -text formats. Raw binary data alone stands out as a clear win.) - -Long story short, the machinery for passing parameters needs to know: is this -parameter a binary string, or not? In the normal case it can assume "no," and -that's what it does. The text format is always a safe choice; we just try to -use the binary format where it's faster. - -The `param_format` function template is what makes the decision. We specialise -it for types which may be binary strings, and use the default for all other -types. - -"Types which _may_ be binary"? You might think we know whether a type is a -binary type or not. But there are some complications with generic types. - -Templates like `std::shared_ptr`, `std::optional`, and so on act like -"wrappers" for another type. A `std::optional` is binary if `T` is binary. -Otherwise, it's not. If you're building support for a template of this nature, -you'll probably want to implement `param_format` for it. - -The decision to use binary format is made based on a given object, not -necessarily based on the type in general. Look at `std::variant`. If you have -a `std::variant` type which can hold an `int` or a binary string, is that a -binary parameter? We can't decide without knowing the individual object. - -Containers are another hard case. Should we pass `std::vector` in binary? -Even when `T` is a binary type, we don't currently have any way to pass an -array in binary format, so we always pass it as text. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/escaping.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/escaping.md deleted file mode 100644 index 2ad9fe3db..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/escaping.md +++ /dev/null @@ -1,74 +0,0 @@ -String escaping {#escaping} -=============== - -Writing queries as strings is easy. But sometimes you need a variable in -there: `"SELECT id FROM user WHERE name = '" + name + "'"`. - -This is dangerous. See the bug? If `name` can contain quotes, you may have -an SQL injection vulnerability there, where users can enter nasty stuff like -"`.'; DROP TABLE user`". Or if you're lucky, it's just a nasty bug that you -discover when `name` happens to be "d'Arcy". - -So, you'll need to _escape_ the `name` before you insert it. This is where -quotes and other problematic characters are marked as "this is just a character -in the string, not the end of the string." There are -[several functions](@ref escaping-functions) in libpqxx to do this for you. - - -SQL injection -------------- - -To understand what SQL injection vulnerabilities are and why they should be -prevented, imagine you use the following SQL statement somewhere in your -program: - - TX.exec( - "SELECT number,amount " - "FROM accounts " - "WHERE allowed_to_see('" + userid + "','" + password + "')"); - -This shows a logged-in user important information on all accounts he is -authorized to view. The userid and password strings are variables entered -by the user himself. - -Now, if the user is actually an attacker who knows (or can guess) the -general shape of this SQL statement, imagine he enters the following -password: - - x') OR ('x' = 'x - -Does that make sense to you? Probably not. But if this is inserted into -the SQL string by the C++ code above, the query becomes: - - SELECT number,amount - FROM accounts - WHERE allowed_to_see('user','x') OR ('x' = 'x') - -Is this what you wanted to happen? Probably not! The neat `allowed_to_see()` -clause is completely circumvented by the "`OR ('x' = 'x')`" clause, which is -always `true`. Therefore, the attacker will get to see all accounts in the -database! - - -Using the esc functions ------------------------ - -Here's how you can fix the problem in the example above: - - TX.exec( - "SELECT number,amount " - "FROM accounts " - "WHERE allowed_to_see('" + TX.esc(userid) + "', " - "'" + TX.esc(password) + "')"); - -Now, the quotes embedded in the attacker's string will be neatly escaped so -they can't "break out" of the quoted SQL string they were meant to go into: - - SELECT number,amount - FROM accounts - WHERE allowed_to_see('user', 'x'') OR (''x'' = ''x') - -If you look carefully, you'll see that thanks to the added escape characters -(a single-quote is escaped in SQL by doubling it) all we get is a very -strange-looking password string--but not a change in the SQL statement. - diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/getting-started.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/getting-started.md deleted file mode 100644 index 1b87b881f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/getting-started.md +++ /dev/null @@ -1,142 +0,0 @@ -Getting started {#getting-started} -=============== - -The most basic three types in libpqxx are the _connection_, the _transaction_, -and the _result_. - -They fit together as follows: -* You connect to the database by creating a `pqxx::connection` object (see - @ref connections). - -* You create a transaction object (see @ref transactions) operating on that - connection. You'll usually want the `pqxx::work` variety. - - Once you're done you call the transaction's `commit` function to make its - work final. If you don't call this, the work will be rolled back when the - transaction object is destroyed. - -* Until then, use the transaction's `exec`, `query_value`, and `stream` - functions (and variants) to execute SQL statements. You pass the statements - themselves in as simple strings. (See @ref streams for more about data - streaming). - -* Most of the `exec` functions return a `pqxx::result` object, which acts - as a standard container of rows: `pqxx::row`. - - Each row in a result, in turn, acts as a container of fields: `pqxx::field`. - See @ref accessing-results for more about results, rows, and fields. - -* Each field's data is stored internally as a text string, in a format defined - by PostgreSQL. You can convert field or row values using their `as()` and - `to()` member functions. - -* After you've closed the transaction, the connection is free to run a next - transaction. - -Here's a very basic example. It connects to the default database (you'll -need to have one set up), queries it for a very simple result, converts it to -an `int`, and prints it out. It also contains some basic error handling. - - #include - #include - - int main() - { - try - { - // Connect to the database. In practice we may have to pass some - // arguments to say where the database server is, and so on. - // The constructor parses options exactly like libpq's - // PQconnectdb/PQconnect, see: - // https://www.postgresql.org/docs/10/static/libpq-connect.html - pqxx::connection c; - - // Start a transaction. In libpqxx, you always work in one. - pqxx::work w(c); - - // work::exec1() executes a query returning a single row of data. - // We'll just ask the database to return the number 1 to us. - pqxx::row r = w.exec1("SELECT 1"); - - // Commit your transaction. If an exception occurred before this - // point, execution will have left the block, and the transaction will - // have been destroyed along the way. In that case, the failed - // transaction would implicitly abort instead of getting to this point. - w.commit(); - - // Look at the first and only field in the row, parse it as an integer, - // and print it. - // - // "r[0]" returns the first field, which has an "as<...>()" member - // function template to convert its contents from their string format - // to a type of your choice. - std::cout << r[0].as() << std::endl; - } - catch (std::exception const &e) - { - std::cerr << e.what() << std::endl; - return 1; - } - } - -This prints the number 1. Notice that you can keep the result object around -after you've closed the transaction or even the connection. There are -situations where you can't do it, but generally it's fine. If you're -interested: you can install your own callbacks for receiving error messages -from the database, and in that case you'll have to keep the connection object -alive. But otherwise, it's nice to be able to "fire and forget" your -connection and deal with the data. - -You can also convert an entire row to a series of C++-side types in one go, -using the @c as member function on the row: - - pqxx::connection c; - pqxx::work w(c); - pqxx::row r = w.exec1("SELECT 1, 2, 'Hello'"); - auto [one, two, hello] = r.as(); - std::cout << (one + two) << ' ' << std::strlen(hello) << std::endl; - -Here's a slightly more complicated example. It takes an argument from the -command line and retrieves a string with that value. The interesting part is -that it uses the escaping-and-quoting function `quote` to embed this -string value in SQL safely. It also reads the result field's value as a -plain C-style string using its `c_str` function. - - #include - #include - #include - - int main(int argc, char *argv[]) - { - try - { - if (!argv[1]) throw std::runtime_error("Give me a string!"); - - pqxx::connection c; - pqxx::work w(c); - - // work::exec() returns a full result set, which can consist of any - // number of rows. - pqxx::result r = w.exec("SELECT " + w.quote(argv[1])); - - // End our transaction here. We can still use the result afterwards. - w.commit(); - - // Print the first field of the first row. Read it as a C string, - // just like std::string::c_str() does. - std::cout << r[0][0].c_str() << std::endl; - } - catch (std::exception const &e) - { - std::cerr << e.what() << std::endl; - return 1; - } - } - -You can find more about converting field values to native types, or -converting values to strings for use with libpqxx, under -@ref stringconversion. More about getting to the rows and fields of a -result is under @ref accessing-results. - -If you want to handle exceptions thrown by libpqxx in more detail, for -example to print the SQL contents of a query that failed, see @ref exception. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/mainpage.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/mainpage.md deleted file mode 100644 index 5d4b8f9b2..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/mainpage.md +++ /dev/null @@ -1,28 +0,0 @@ -libpqxx {#mainpage} -======= - -@version 7.7.3 -@author Jeroen T. Vermeulen -@see http://pqxx.org -@see https://github.com/jtv/libpqxx - -Welcome to libpqxx, the C++ API to the PostgreSQL database management system. - -Compiling this package requires PostgreSQL to be installed -- including the -C headers for client development. The library builds on top of PostgreSQL's -standard C API, libpq. The libpq headers are not needed to compile client -programs, however. - -For a quick introduction to installing and using libpqxx, see the README.md -file. The latest information can be found at http://pqxx.org/ - - -Some links that should help you find your bearings: -* @ref getting-started -* @ref thread-safety -* @ref connections -* @ref transactions -* @ref escaping -* @ref performance -* @ref transactor -* @ref datatypes diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/parameters.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/parameters.md deleted file mode 100644 index 7ac792025..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/parameters.md +++ /dev/null @@ -1,90 +0,0 @@ -Statement parameters {#parameters} -==================== - -When you execute a prepared statement (see @ref prepared), or a parameterised -statement (using functions like `pqxx::connection::exec_params`), you may write -special _placeholders_ in the query text. They look like `$1`, `$2`, and so -on. - -If you execute the query and pass parameter values, the call will respectively -substitute the first where it finds `$1`, the second where it finds `$2`, et -cetera. - -Doing this saves you work. If you don't use statement parameters, you'll need -to quote and escape your values (see `connection::quote()` and friends) as you -insert them into your query as literal values. - -Or if you forget to do that, you leave yourself open to horrible -[SQL injection attacks](https://xkcd.com/327/). Trust me, I was born in a town -whose name started with an apostrophe! - -Statement parameters save you this work. With these parameters you can pass -your values as-is, and they will go across the wire to the database in a safe -format. - -In some cases it may even be faster! When a parameter represents binary data -(as in the SQL `BYTEA` type), libpqxx will send it directly as binary, which is -a bit more efficient. If you insert the binary data directly in your query -text, your CPU will have some extra work to do, converting the data into a text -format, escaping it, and adding quotes. - - -Dynamic parameter lists ------------------------ - -In rare cases you may just not know how many parameters you'll pass into your -statement when you call it. - -For these situations, have a look at `params`. It lets you compose your -parameters list on the fly, even add whole ranges of parameters at a time. - -You can pass a `params` into your statement as a normal parameter. It will -fill in all the parameter values it contains into that position of the -statement's overall parameter list. - -So if you call your statement passing a regular parameter `a`, a -`params` containing just a parameter `b`, and another regular parameter `c`, -then your call will pass parameters `a`, `b`, and `c`. Or if the params object -is empty, it will pass just `a` and `c`. If the params object contains `x` and -`y`, your call will pass `a, x, y, c`. - -You can mix static and dynamic parameters freely. Don't go overboard though: -complexity is where bugs happen! - - -Generating placeholders ------------------------ - -If your code gets particularly complex, it may sometimes happen that it becomes -hard to track which parameter value belongs with which placeholder. Did you -intend to pass this numeric value as `$7`, or as `$8`? The answer may depend -on an `if` that happened earlier in a different function. - -(Generally if things get that complex, it's a good idea to look for simpler -solutions. But especially when performance matters, sometimes you can't avoid -complexity like that.) - -There's a little helper class called `placeholders`. You can use it as a -counter which produces those placeholder strings, `$1`, `$2`, `$3`, et cetera. -When you start generating a complex statement, you can create both a `params` -and a `placeholders`: - - pqxx::params values; - pqxx::placeholders name; - -Let's say you've got some complex code to generate the conditions for an SQL -"WHERE" clause. You'll generally want to do these things close together in -your, so that you don't accidentally update one part and forget another: - - if (extra_clause) - { - // Extend the query text, using the current placeholder. - query += " AND x = " + name.get(); - // Add the parameter value. - values.append(my_x); - // Move on to the next placeholder value. - name.next(); - } - -Depending on the starting value of `name`, this might add to `query` a fragment -like "` AND x = $3`" or "` AND x = $5`". diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/performance.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/performance.md deleted file mode 100644 index 6c403684f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/performance.md +++ /dev/null @@ -1,24 +0,0 @@ -Performance features {#performance} -==================== - -If your program's database interaction is not as efficient as it needs to be, -the first place to look is usually the SQL you're executing. But libpqxx -has a few specialized features to help you squeeze more performance out -of how you issue commands and retrieve data: - -* @ref streams. Use these as a faster way to transfer data between your - code and the database. -* `std::string_view` and `pqxx::zview`. In places where traditional C++ worked - with `std::string`, see whether `std::string_view` or `pqxx::zview` will - do. Of course that means that you'll have to look at the data's lifetime - more carefully, but it'll save the computer a lot of copying. -* @ref prepared. These can be executed many times without the server - parsing and planning them anew each time. They also save you having to - escape string parameters. -* `pqxx::pipeline` lets you send queries to the database in batches, and - continue other processing while they are executing. -* `pqxx::connecting` lets you start setting up a database connection, but - without blocking the thread. - -As always of course, don't risk the quality of your code for optimizations -that you don't need! diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/prepared-statement.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/prepared-statement.md deleted file mode 100644 index 5193866a6..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/prepared-statement.md +++ /dev/null @@ -1,125 +0,0 @@ -Prepared statements {#prepared} -=================== - -Prepared statements are SQL queries that you define once and then invoke -as many times as you like, typically with varying parameters. It's basically -a function that you can define ad hoc. - -If you have an SQL statement that you're going to execute many times in -quick succession, it may be more efficient to prepare it once and reuse it. -This saves the database backend the effort of parsing complex SQL and -figuring out an efficient execution plan. Another nice side effect is that -you don't need to worry about escaping parameters. Some corporate coding -standards require all SQL parameters to be passed in this way, to reduce the -risk of programmer mistakes leaving room for SQL injections. - - -Preparing a statement ---------------------- - -You create a prepared statement by preparing it on the connection (using the -`pqxx::connection::prepare` functions), passing an identifier and its SQL text. - -The identifier is the name by which the prepared statement will be known; it -should consist of ASCII letters, digits, and underscores only, and start with -an ASCII letter. The name is case-sensitive. - -```cxx - void prepare_my_statement(pqxx::connection &c) - { - c.prepare( - "my_statement", - "SELECT * FROM Employee WHERE name = 'Xavier'"); - } -``` - -Once you've done this, you'll be able to call `my_statement` from any -transaction you execute on the same connection. For this, use the -`pqxx::transaction_base::exec_prepared` functions. - -```cxx - pqxx::result execute_my_statement(pqxx::transaction_base &t) - { - return t.exec_prepared("my_statement"); - } -``` - - -Parameters ----------- - -Did I mention that prepared statements can have parameters? The query text -can contain `$1`, `$2` etc. as placeholders for parameter values that you -will provide when you invoke the prepared satement. - -See @ref parameters for more about this. And here's a simple example of -preparing a statement and invoking it with parameters: - -```cxx - void prepare_find(pqxx::connection &c) - { - // Prepare a statement called "find" that looks for employees with a - // given name (parameter 1) whose salary exceeds a given number - // (parameter 2). - c.prepare( - "find", - "SELECT * FROM Employee WHERE name = $1 AND salary > $2"); - } -``` - -This example looks up the prepared statement "find," passes `name` and -`min_salary` as parameters, and invokes the statement with those values: - -```cxx - pqxx::result execute_find( - pqxx::transaction_base &t, std::string name, int min_salary) - { - return t.exec_prepared("find", name, min_salary); - } -``` - - -A special prepared statement ----------------------------- - -There is one special case: the _nameless_ prepared statement. You may prepare -a statement without a name, i.e. whose name is an empty string. The unnamed -statement can be redefined at any time, without un-preparing it first. - - -Performance note ----------------- - -Don't assume that using prepared statements will speed up your application. -There are cases where prepared statements are actually slower than plain SQL. - -The reason is that the backend can often produce a better execution plan when -it knows the statement's actual parameter values. - -For example, say you've got a web application and you're querying for users -with status "inactive" who have email addresses in a given domain name X. If -X is a very popular provider, the best way for the database engine to plan the -query may be to list the inactive users first and then filter for the email -addresses you're looking for. But in other cases, it may be much faster to -find matching email addresses first and then see which of their owners are -"inactive." A prepared statement must be planned to fit either case, but a -direct query will be optimised based on table statistics, partial indexes, etc. - - -Zero bytes ----------- - -@warning Beware of "nul" bytes! - -Any string you pass as a parameter will end at the _first char with value -zero._ If you pass a string that contains a zero byte, the last byte in the -value will be the one just before the zero. - -So, if you need a zero byte in a string, consider that it's really a _binary -string,_ which is not the same thing as a text string. SQL represents binary -data as the `BYTEA` type, or in binary large objects ("blobs"). - -In libpqxx, you represent binary data as a range of `std::byte`. They must be -contiguous in memory, so that libpqxx can pass pointers to the underlying C -library. So you might use `std::basic_string`, or -`std::basic_string_view`, or `std::vector`. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/streams.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/streams.md deleted file mode 100644 index 3df4d6126..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/streams.md +++ /dev/null @@ -1,107 +0,0 @@ -Streams {#streams} -======= - -Most of the time it's fine to retrieve data from the database using `SELECT` -queries, and store data using `INSERT`. But for those cases where efficiency -matters, there are two classes to help you do this better: `stream_from` and -`stream_to`. They're less flexible than SQL queries, and there's the risk of -losing your connection while you're in mid-stream, but you get some speed and -memory efficiencies in return. - -Both stream classes do data conversion for you: `stream_from` receives values -from the database in PostgreSQL's text format, and converts them to the C++ -types you specify. Likewise, `stream_to` converts C++ values you provide to -PostgreSQL's text format for transfer. (On its end, the database of course -converts values to and from their SQL types.) - - -Null values ------------ - -So how do you deal with nulls? It depends on the C++ type you're using. Some -types may have a built-in null value. For instance, if you have a -`char const *` value and you convert it to an SQL string, then converting a -`nullptr` will produce a NULL SQL value. - -But what do you do about C++ types which don't have a built-in null value, such -as `int`? The trick is to wrap it in `std::optional`. The difference between -`int` and `std::optional` is that the former always has an `int` value, -and the latter doesn't have to. - -Actually it's not just `std::optional`. You can do the same thing with -`std::unique_ptr` or `std::shared_ptr`. A smart pointer is less efficient than -`std::optional` in most situations because they allocate their value on the -heap, but sometimes that's what you want in order to save moving or copying -large values around. - -This part is not generic though. It won't work with just any smart-pointer -type, just the ones which are explicitly supported: `shared_ptr` and -`unique_ptr`. If you really need to, you can build support for additional -wrappers and smart pointers by copying the implementation patterns from the -existing smart-pointer support. - - -stream\_from ------------- - -Use `stream_from` to read data directly from the database. It's faster than -the transaction's `exec` functions if the result contains enough rows. But -also, you won't need to keep your full result set in memory. That can really -matter with larger data sets. - -And, you can start processing your data right after the first row of data comes -in from the server. With `exec()` you need to wait to receive all data, and -then you begin processing. With `stream_from` you can be processing data on -the client side while the server is still sending you the rest. - -You don't actually need to create a `stream_from` object yourself, though you -can. Two shorthand functions, @ref pqxx::transaction_base::stream -and @ref pqxx::transaction_base::for_each, can create the streams for you with -a minimum of overhead. - -Not all kinds of queries will work in a stream. Internally the streams make -use of PostgreSQL's `COPY` command, so see the PostgreSQL documentation for -`COPY` for the exact limitations. Basic `SELECT` and `UPDATE ... RETURNING` -queries should just work. - -As you read a row, the stream converts its fields to a tuple type containing -the value types you ask for: - - auto stream pqxx::stream_from::query( - tx, "SELECT name, points FROM score"); - std::tuple row; - while (stream >> row) - process(row); - stream.complete(); - -As the stream reads each row, it converts that row's data into your tuple, -goes through your loop body, and then promptly forgets that row's data. This -means you can easily process more data than will fit in memory. - - -stream\_to ----------- - -Use `stream_to` to write data directly to a database table. This saves you -having to perform an `INSERT` for every row, and so it can be significantly -faster if you want to insert more than just one or two rows at a time. - -As with `stream_from`, you can specify the table and the columns, and not much -else. You insert tuple-like objects of your choice: - - pqxx::stream_to stream{ - tx, - "score", - std::vector{"name", "points"}}; - for (auto const &entry: scores) - stream << entry; - stream.complete(); - -Each row is processed as you provide it, and not retained in memory after that. - -The call to `complete()` is more important here than it is for `stream_from`. -It's a lot like a "commit" or "abort" at the end of a transaction. If you omit -it, it will be done automatically during the stream's destructor. But since -destructors can't throw exceptions, any failures at that stage won't be visible -in your code. So, always call `complete()` on a `stream_to` to close it off -properly! diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/thread-safety.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/thread-safety.md deleted file mode 100644 index 07c7f9984..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/amd64/share/doc/libpqxx/thread-safety.md +++ /dev/null @@ -1,29 +0,0 @@ -Thread safety {#thread-safety} -============= - -This library does not contain any locking code to protect objects against -simultaneous modification in multi-threaded programs. Therefore it is up -to you, the user of the library, to ensure that your threaded client -programs perform no conflicting operations concurrently. - -Most of the time this isn't hard. Result sets are immutable, so you can -share them between threads without problem. The main rule is: - -@li Treat a connection, together with any and all objects related to it, as -a "world" of its own. You should generally make sure that the same "world" -is never accessed by another thread while you're doing anything non-const -in there. - -That means: don't issue a query on a transaction while you're also opening -a subtransaction, don't access a cursor while you may also be committing, -and so on. - -In particular, cursors are tricky. It's easy to perform a non-const -operation without noticing. So, if you're going to share cursors or -cursor-related objects between threads, lock very conservatively! - -Use `pqxx::describe_thread_safety` to find out at runtime what level of -thread safety is implemented in your build and version of libpqxx. It -returns a `pqxx::thread_safety_model` describing what you can and cannot rely -on. A command-line utility `tools/pqxxthreadsafety` prints out the same -information. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/array b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/array deleted file mode 100644 index 689f5b27b..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/array +++ /dev/null @@ -1,6 +0,0 @@ -/** Handling of SQL arrays. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/array.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/array.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/array.hxx deleted file mode 100644 index 8440a244f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/array.hxx +++ /dev/null @@ -1,103 +0,0 @@ -/* Handling of SQL arrays. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ARRAY -#define PQXX_H_ARRAY - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/internal/encodings.hxx" - - -namespace pqxx -{ -/// Low-level array parser. -/** Use this to read an array field retrieved from the database. - * - * This parser will only work reliably if your client encoding is UTF-8, ASCII, - * or a single-byte encoding which is a superset of ASCII (such as Latin-1). - * - * Also, the parser only supports array element types which use either a comma - * or a semicolon ("," or ";") as the separator between array elements. All - * built-in types use comma, except for one which uses semicolon, but some - * custom types may not work. - * - * The input is a C-style string containing the textual representation of an - * array, as returned by the database. The parser reads this representation - * on the fly. The string must remain in memory until parsing is done. - * - * Parse the array by making calls to @ref get_next until it returns a - * @ref juncture of "done". The @ref juncture tells you what the parser found - * in that step: did the array "nest" to a deeper level, or "un-nest" back up? - */ -class PQXX_LIBEXPORT array_parser -{ -public: - /// What's the latest thing found in the array? - enum class juncture - { - /// Starting a new row. - row_start, - /// Ending the current row. - row_end, - /// Found a NULL value. - null_value, - /// Found a string value. - string_value, - /// Parsing has completed. - done, - }; - - // TODO: constexpr noexcept. Breaks ABI. - /// Constructor. You don't need this; use @ref field::as_array instead. - /** The parser only remains valid while the data underlying the @ref result - * remains valid. Once all `result` objects referring to that data have been - * destroyed, the parser will no longer refer to valid memory. - */ - explicit array_parser( - std::string_view input, - internal::encoding_group = internal::encoding_group::MONOBYTE); - - /// Parse the next step in the array. - /** Returns what it found. If the juncture is @ref juncture::string_value, - * the string will contain the value. Otherwise, it will be empty. - * - * Call this until the @ref array_parser::juncture it returns is - * @ref juncture::done. - */ - std::pair get_next(); - -private: - std::string_view m_input; - internal::glyph_scanner_func *const m_scan; - - /// Current parsing position in the input. - std::string::size_type m_pos = 0u; - - std::string::size_type scan_single_quoted_string() const; - std::string parse_single_quoted_string(std::string::size_type end) const; - std::string::size_type scan_double_quoted_string() const; - std::string parse_double_quoted_string(std::string::size_type end) const; - std::string::size_type scan_unquoted_string() const; - std::string parse_unquoted_string(std::string::size_type end) const; - - std::string::size_type scan_glyph(std::string::size_type pos) const; - std::string::size_type - scan_glyph(std::string::size_type pos, std::string::size_type end) const; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/binarystring b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/binarystring deleted file mode 100644 index 77551d9f7..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/binarystring +++ /dev/null @@ -1,6 +0,0 @@ -/** BYTEA (binary string) conversions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/binarystring.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/binarystring.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/binarystring.hxx deleted file mode 100644 index 47c82a035..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/binarystring.hxx +++ /dev/null @@ -1,236 +0,0 @@ -/* Deprecated representation for raw, binary data. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_BINARYSTRING -#define PQXX_H_BINARYSTRING - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/result.hxx" -#include "pqxx/strconv.hxx" - -namespace pqxx -{ -class binarystring; -template<> struct string_traits; - - -/// Binary data corresponding to PostgreSQL's "BYTEA" binary-string type. -/** @ingroup escaping-functions - * @deprecated Use @c std::basic_string and - * @c std::basic_string_view for binary data. In C++20 or better, - * any @c contiguous_range of @c std::byte will do. - * - * This class represents a binary string as stored in a field of type @c bytea. - * - * Internally a binarystring is zero-terminated, but it may also contain null - * bytes, they're just like any other byte value. So don't assume that it's - * safe to treat the contents as a C-style string. - * - * The binarystring retains its value even if the result it was obtained from - * is destroyed, but it cannot be copied or assigned. - * - * \relatesalso transaction_base::quote_raw - * - * To include a @c binarystring value in an SQL query, escape and quote it - * using the transaction's @c quote_raw function. - * - * @warning This class is implemented as a reference-counting smart pointer. - * Copying, swapping, and destroying binarystring objects that refer to the - * same underlying data block is not thread-safe. If you wish to pass - * binarystrings around between threads, make sure that each of these - * operations is protected against concurrency with similar operations on the - * same object, or other objects pointing to the same data block. - */ -class PQXX_LIBEXPORT binarystring -{ -public: - using char_type = unsigned char; - using value_type = std::char_traits::char_type; - using size_type = std::size_t; - using difference_type = long; - using const_reference = value_type const &; - using const_pointer = value_type const *; - using const_iterator = const_pointer; - using const_reverse_iterator = std::reverse_iterator; - - [[deprecated("Use std::byte for binary data.")]] binarystring( - binarystring const &) = default; - - /// Read and unescape bytea field. - /** The field will be zero-terminated, even if the original bytea field - * isn't. - * @param F the field to read; must be a bytea field - */ - [[deprecated("Use std::byte for binary data.")]] explicit binarystring( - field const &); - - /// Copy binary data from std::string_view on binary data. - /** This is inefficient in that it copies the data to a buffer allocated on - * the heap. - */ - [[deprecated("Use std::byte for binary data.")]] explicit binarystring( - std::string_view); - - /// Copy binary data of given length straight out of memory. - [[deprecated("Use std::byte for binary data.")]] binarystring( - void const *, std::size_t); - - /// Efficiently wrap a buffer of binary data in a @c binarystring. - [[deprecated("Use std::byte for binary data.")]] binarystring( - std::shared_ptr ptr, size_type size) : - m_buf{std::move(ptr)}, m_size{size} - {} - - /// Size of converted string in bytes. - [[nodiscard]] size_type size() const noexcept { return m_size; } - /// Size of converted string in bytes. - [[nodiscard]] size_type length() const noexcept { return size(); } - [[nodiscard]] bool empty() const noexcept { return size() == 0; } - - [[nodiscard]] const_iterator begin() const noexcept { return data(); } - [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); } - [[nodiscard]] const_iterator end() const noexcept { return data() + m_size; } - [[nodiscard]] const_iterator cend() const noexcept { return end(); } - - [[nodiscard]] const_reference front() const noexcept { return *begin(); } - [[nodiscard]] const_reference back() const noexcept - { - return *(data() + m_size - 1); - } - - [[nodiscard]] const_reverse_iterator rbegin() const - { - return const_reverse_iterator{end()}; - } - [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); } - [[nodiscard]] const_reverse_iterator rend() const - { - return const_reverse_iterator{begin()}; - } - [[nodiscard]] const_reverse_iterator crend() const { return rend(); } - - /// Unescaped field contents. - [[nodiscard]] value_type const *data() const noexcept { return m_buf.get(); } - - [[nodiscard]] const_reference operator[](size_type i) const noexcept - { - return data()[i]; - } - - [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const noexcept; - [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept - { - return not operator==(rhs); - } - - binarystring &operator=(binarystring const &); - - /// Index contained string, checking for valid index. - const_reference at(size_type) const; - - /// Swap contents with other binarystring. - void swap(binarystring &); - - /// Raw character buffer (no terminating zero is added). - /** @warning No terminating zero is added! If the binary data did not end in - * a null character, you will not find one here. - */ - [[nodiscard]] char const *get() const noexcept - { - return reinterpret_cast(m_buf.get()); - } - - /// Read contents as a std::string_view. - [[nodiscard]] std::string_view view() const noexcept - { - return std::string_view(get(), size()); - } - - /// Read as regular C++ string (may include null characters). - /** This creates and returns a new string object. Don't call this - * repeatedly; retrieve your string once and keep it in a local variable. - * Also, do not expect to be able to compare the string's address to that of - * an earlier invocation. - */ - [[nodiscard]] std::string str() const; - - /// Access data as a pointer to @c std::byte. - [[nodiscard]] std::byte const *bytes() const - { - return reinterpret_cast(get()); - } - - /// Read data as a @c std::basic_string_view. - [[nodiscard]] std::basic_string_view bytes_view() const - { - return std::basic_string_view{bytes(), size()}; - } - -private: - std::shared_ptr m_buf; - size_type m_size{0}; -}; - - -template<> struct nullness : no_null -{}; - - -/// String conversion traits for @c binarystring. -/** Defines the conversions between a @c binarystring and its PostgreSQL - * textual format, for communication with the database. - * - * These conversions rely on the "hex" format which was introduced in - * PostgreSQL 9.0. Both your libpq and the server must be recent enough to - * speak this format. - */ -template<> struct string_traits -{ - static std::size_t size_buffer(binarystring const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf(char *begin, char *end, binarystring const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, binarystring const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - std::string_view text{value.view()}; - internal::esc_bin(binary_cast(text), begin); - return begin + budget; - } - - static binarystring from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::shared_ptr buf{ - new unsigned char[size], [](unsigned char const *x) { delete[] x; }}; - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.get())); -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return binarystring{std::move(buf), size}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - } -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/blob b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/blob deleted file mode 100644 index 3fd0afac9..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/blob +++ /dev/null @@ -1,6 +0,0 @@ -/** Binary Large Objects interface. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/blob.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/blob.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/blob.hxx deleted file mode 100644 index 6d77be724..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/blob.hxx +++ /dev/null @@ -1,351 +0,0 @@ -/* Binary Large Objects interface. - * - * Read or write large objects, stored in their own storage on the server. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_BLOB -#define PQXX_H_BLOB - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#if defined(PQXX_HAVE_PATH) -# include -#endif - -#if defined(PQXX_HAVE_RANGES) && __has_include() -# include -#endif - -#if defined(PQXX_HAVE_SPAN) && __has_include() -# include -#endif - -#include "pqxx/dbtransaction.hxx" - - -namespace pqxx -{ -/** Binary large object. - * - * This is how you store data that may be too large for the `BYTEA` type. - * Access operations are similar to those for a file: you can read, write, - * query or set the current reading/writing position, and so on. - * - * These large objects live in their own storage on the server, indexed by an - * integer object identifier ("oid"). - * - * Two `blob` objects may refer to the same actual large object in the - * database at the same time. Each will have its own reading/writing position, - * but writes to the one will of course affect what the other sees. - */ -class PQXX_LIBEXPORT blob -{ -public: - /// Create a new, empty large object. - /** You may optionally specify an oid for the new blob. If you do, then - * the new object will have that oid -- or creation will fail if there - * already is an object with that oid. - */ - [[nodiscard]] static oid create(dbtransaction &, oid = 0); - - /// Delete a large object, or fail if it does not exist. - static void remove(dbtransaction &, oid); - - /// Open blob for reading. Any attempt to write to it will fail. - [[nodiscard]] static blob open_r(dbtransaction &, oid); - // Open blob for writing. Any attempt to read from it will fail. - [[nodiscard]] static blob open_w(dbtransaction &, oid); - // Open blob for reading and/or writing. - [[nodiscard]] static blob open_rw(dbtransaction &, oid); - - /// You can default-construct a blob, but it won't do anything useful. - /** Most operations on a default-constructed blob will throw @ref - * usage_error. - */ - blob() = default; - - /// You can move a blob, but not copy it. The original becomes unusable. - blob(blob &&); - /// You can move a blob, but not copy it. The original becomes unusable. - blob &operator=(blob &&); - - blob(blob const &) = delete; - blob &operator=(blob const &) = delete; - ~blob(); - - /// Maximum number of bytes that can be read or written at a time. - /** The underlying protocol only supports reads and writes up to 2 GB - * exclusive. - * - * If you need to read or write more data to or from a binary large object, - * you'll have to break it up into chunks. - */ - static constexpr std::size_t chunk_limit = 0x7fffffff; - - /// Read up to `size` bytes of the object into `buf`. - /** Uses a buffer that you provide, resizing it as needed. If it suits you, - * this lets you allocate the buffer once and then re-use it multiple times. - * - * Resizes `buf` as needed. - * - * @warning The underlying protocol only supports reads up to 2GB at a time. - * If you need to read more, try making repeated calls to @ref append_to_buf. - */ - std::size_t read(std::basic_string &buf, std::size_t size); - -#if defined(PQXX_HAVE_SPAN) - /// Read up to `std::size(buf)` bytes from the object. - /** Retrieves bytes from the blob, at the current position, until `buf` is - * full or there are no more bytes to read, whichever comes first. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template - std::span read(std::span buf) - { - return buf.subspan(0, raw_read(std::data(buf), std::size(buf))); - } -#endif // PQXX_HAVE_SPAN - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Read up to `std::size(buf)` bytes from the object. - /** Retrieves bytes from the blob, at the current position, until `buf` is - * full or there are no more bytes to read, whichever comes first. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template std::span read(DATA &buf) - { - return {std::data(buf), raw_read(std::data(buf), std::size(buf))}; - } -#else // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN - /// Read up to `std::size(buf)` bytes from the object. - /** @deprecated As libpqxx moves to C++20 as its baseline language version, - * this will take and return `std::span`. - * - * Retrieves bytes from the blob, at the current position, until `buf` is - * full (i.e. its current size is reached), or there are no more bytes to - * read, whichever comes first. - * - * This function will not change either the size or the capacity of `buf`, - * only its contents. - * - * Returns the filled portion of `buf`. This may be empty. - */ - template - std::basic_string_view read(std::vector &buf) - { - return {std::data(buf), raw_read(std::data(buf), std::size(buf))}; - } -#endif // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN - -#if defined(PQXX_HAVE_CONCEPTS) - /// Write `data` to large object, at the current position. - /** If the writing position is at the end of the object, this will append - * `data` to the object's contents and move the writing position so that - * it's still at the end. - * - * If the writing position was not at the end, writing will overwrite the - * prior data, but it will not remove data that follows the part where you - * wrote your new data. - * - * @warning This is a big difference from writing to a file. You can - * overwrite some data in a large object, but this does not truncate the - * data that was already there. For example, if the object contained binary - * data "abc", and you write "12" at the starting position, the object will - * contain "12c". - * - * @warning The underlying protocol only supports writes up to 2 GB at a - * time. If you need to write more, try making repeated calls to - * @ref append_from_buf. - */ - template void write(DATA const &data) - { - raw_write(std::data(data), std::size(data)); - } -#else - /// Write `data` large object, at the current position. - /** If the writing position is at the end of the object, this will append - * `data` to the object's contents and move the writing position so that - * it's still at the end. - * - * If the writing position was not at the end, writing will overwrite the - * prior data, but it will not remove data that follows the part where you - * wrote your new data. - * - * @warning This is a big difference from writing to a file. You can - * overwrite some data in a large object, but this does not truncate the - * data that was already there. For example, if the object contained binary - * data "abc", and you write "12" at the starting position, the object will - * contain "12c". - * - * @warning The underlying protocol only supports writes up to 2 GB at a - * time. If you need to write more, try making repeated calls to - * @ref append_from_buf. - */ - template void write(DATA const &data) - { - raw_write(std::data(data), std::size(data)); - } -#endif - - /// Resize large object to `size` bytes. - /** If the blob is more than `size` bytes long, this removes the end so as - * to make the blob the desired length. - * - * If the blob is less than `size` bytes long, it adds enough zero bytes to - * make it the desired length. - */ - void resize(std::int64_t size); - - /// Return the current reading/writing position in the large object. - [[nodiscard]] std::int64_t tell() const; - - /// Set the current reading/writing position to an absolute offset. - /** Returns the new file offset. */ - std::int64_t seek_abs(std::int64_t offset = 0); - /// Move the current reading/writing position forwards by an offset. - /** To move backwards, pass a negative offset. - * - * Returns the new file offset. - */ - std::int64_t seek_rel(std::int64_t offset = 0); - /// Set the current position to an offset relative to the end of the blob. - /** You'll probably want an offset of zero or less. - * - * Returns the new file offset. - */ - std::int64_t seek_end(std::int64_t offset = 0); - - /// Create a binary large object containing given `data`. - /** You may optionally specify an oid for the new object. If you do, and an - * object with that oid already exists, creation will fail. - */ - static oid from_buf( - dbtransaction &tx, std::basic_string_view data, oid id = 0); - - /// Append `data` to binary large object. - /** The underlying protocol only supports appending blocks up to 2 GB. - */ - static void append_from_buf( - dbtransaction &tx, std::basic_string_view data, oid id); - - /// Read client-side file and store it server-side as a binary large object. - [[nodiscard]] static oid from_file(dbtransaction &, char const path[]); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Read client-side file and store it server-side as a binary large object. - /** This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - [[nodiscard]] static oid - from_file(dbtransaction &tx, std::filesystem::path const &path) - { - return from_file(tx, path.c_str()); - } -#endif - - /// Read client-side file and store it server-side as a binary large object. - /** In this version, you specify the binary large object's oid. If that oid - * is already in use, the operation will fail. - */ - static oid from_file(dbtransaction &, char const path[], oid); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Read client-side file and store it server-side as a binary large object. - /** In this version, you specify the binary large object's oid. If that oid - * is already in use, the operation will fail. - * - * This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - static oid - from_file(dbtransaction &tx, std::filesystem::path const &path, oid id) - { - return from_file(tx, path.c_str(), id); - } -#endif - - /// Convenience function: Read up to `max_size` bytes from blob with `id`. - /** You could easily do this yourself using the @ref open_r and @ref read - * functions, but it can save you a bit of code to do it this way. - */ - static void to_buf( - dbtransaction &, oid, std::basic_string &, - std::size_t max_size); - - /// Read part of the binary large object with `id`, and append it to `buf`. - /** Use this to break up a large read from one binary large object into one - * massive buffer. Just keep calling this function until it returns zero. - * - * The `offset` is how far into the large object your desired chunk is, and - * `append_max` says how much to try and read in one go. - */ - static std::size_t append_to_buf( - dbtransaction &tx, oid id, std::int64_t offset, - std::basic_string &buf, std::size_t append_max); - - /// Write a binary large object's contents to a client-side file. - static void to_file(dbtransaction &, oid, char const path[]); - -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - /// Write a binary large object's contents to a client-side file. - /** This overload is not available on Windows, where `std::filesystem::path` - * converts to a `wchar_t` string rather than a `char` string. - */ - static void - to_file(dbtransaction &tx, oid id, std::filesystem::path const &path) - { - to_file(tx, id, path.c_str()); - } -#endif - - /// Close this blob. - /** This does not delete the blob from the database; it only terminates your - * local object for accessing the blob. - * - * Resets the blob to a useless state similar to one that was - * default-constructed. - * - * The destructor will do this for you automatically. Still, there is a - * reason to `close()` objects explicitly where possible: if an error should - * occur while closing, `close()` can throw an exception. A destructor - * cannot. - */ - void close(); - -private: - PQXX_PRIVATE blob(connection &conn, int fd) noexcept : - m_conn{&conn}, m_fd{fd} - {} - static PQXX_PRIVATE blob open_internal(dbtransaction &, oid, int); - static PQXX_PRIVATE pqxx::internal::pq::PGconn * - raw_conn(pqxx::connection *) noexcept; - static PQXX_PRIVATE pqxx::internal::pq::PGconn * - raw_conn(pqxx::dbtransaction const &) noexcept; - static PQXX_PRIVATE std::string errmsg(connection const *); - static PQXX_PRIVATE std::string errmsg(dbtransaction const &tx) - { - return errmsg(&tx.conn()); - } - PQXX_PRIVATE std::string errmsg() const { return errmsg(m_conn); } - PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence); - std::size_t raw_read(std::byte buf[], std::size_t size); - void raw_write(std::byte const buf[], std::size_t size); - - connection *m_conn = nullptr; - int m_fd = -1; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/composite b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/composite deleted file mode 100644 index 2bfa7ade9..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/composite +++ /dev/null @@ -1,6 +0,0 @@ -/** Handling of SQL "composite types." - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/composite.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/composite.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/composite.hxx deleted file mode 100644 index 439b133a8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/composite.hxx +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef PQXX_H_COMPOSITE -#define PQXX_H_COMPOSITE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/internal/array-composite.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Parse a string representation of a value of a composite type. -/** @warning This code is still experimental. Use with care. - * - * You may use this as a helper while implementing your own @ref string_traits - * for a composite type. - * - * This function interprets `text` as the string representation of a value of - * some composite type, and sets each of `fields` to the respective values of - * its fields. The field types must be copy-assignable. - * - * The number of fields must match the number of fields in the composite type, - * and there must not be any other text in the input. The function is meant to - * handle any value string that the backend can produce, but not necessarily - * every valid alternative spelling. - * - * Fields in composite types can be null. When this happens, the C++ type of - * the corresponding field reference must be of a type that can handle nulls. - * If you are working with a type that does not have an inherent null value, - * such as e.g. `int`, consider using `std::optional`. - */ -template -inline void parse_composite( - pqxx::internal::encoding_group enc, std::string_view text, T &...fields) -{ - static_assert(sizeof...(fields) > 0); - - auto const scan{pqxx::internal::get_glyph_scanner(enc)}; - auto const data{std::data(text)}; - auto const size{std::size(text)}; - if (size == 0) - throw conversion_error{"Cannot parse composite value from empty string."}; - - std::size_t here{0}, next{scan(data, size, here)}; - if (next != 1 or data[here] != '(') - throw conversion_error{ - internal::concat("Invalid composite value string: ", text)}; - - here = next; - - constexpr auto num_fields{sizeof...(fields)}; - std::size_t index{0}; - (pqxx::internal::parse_composite_field( - index, text, here, fields, scan, num_fields - 1), - ...); - if (here != std::size(text)) - throw conversion_error{internal::concat( - "Composite value did not end at the closing parenthesis: '", text, - "'.")}; - if (text[here - 1] != ')') - throw conversion_error{internal::concat( - "Composive value did not end in parenthesis: '", text, "'")}; -} - - -/// Parse a string representation of a value of a composite type. -/** @warning This version only works for UTF-8 and single-byte encodings. - * - * For proper encoding support, use the composite-type support in the - * `field` class. - */ -template -inline void parse_composite(std::string_view text, T &...fields) -{ - parse_composite(pqxx::internal::encoding_group::MONOBYTE, text, fields...); -} -} // namespace pqxx - - -namespace pqxx::internal -{ -constexpr char empty_composite_str[]{"()"}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// Estimate the buffer size needed to represent a value of a composite type. -/** Returns a conservative estimate. - */ -template -[[nodiscard]] inline std::size_t -composite_size_buffer(T const &...fields) noexcept -{ - constexpr auto num{sizeof...(fields)}; - - // Size for a multi-field composite includes room for... - // + opening parenthesis - // + field budgets - // + separating comma per field - // - comma after final field - // + closing parenthesis - // + terminating zero - - if constexpr (num == 0) - return std::size(pqxx::internal::empty_composite_str); - else - return 1 + (pqxx::internal::size_composite_field_buffer(fields) + ...) + - num + 1; -} - - -/// Render a series of values as a single composite SQL value. -/** @warning This code is still experimental. Use with care. - * - * You may use this as a helper while implementing your own `string_traits` - * for a composite type. - */ -template -inline char *composite_into_buf(char *begin, char *end, T const &...fields) -{ - if (std::size_t(end - begin) < composite_size_buffer(fields...)) - throw conversion_error{ - "Buffer space may not be enough to represent composite value."}; - - constexpr auto num_fields{sizeof...(fields)}; - if constexpr (num_fields == 0) - { - constexpr char empty[]{"()"}; - std::memcpy(begin, empty, std::size(empty)); - return begin + std::size(empty); - } - - char *pos{begin}; - *pos++ = '('; - - (pqxx::internal::write_composite_field(pos, end, fields), ...); - - // If we've got multiple fields, "backspace" that last comma. - if constexpr (num_fields > 1) - --pos; - *pos++ = ')'; - *pos++ = '\0'; - return pos; -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/config-public-compiler.h b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/config-public-compiler.h deleted file mode 100644 index 3668a10f8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/config-public-compiler.h +++ /dev/null @@ -1,81 +0,0 @@ -/* include/pqxx/config.h.in. Generated from configure.ac by autoheader. */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ -/* Define to 1 if you have the `pq' library (-lpq). */ -/* #undef HAVE_LIBPQ */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MEMORY_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDINT_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDLIB_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRING_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_STAT_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TYPES_H */ -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -/* #undef LT_OBJDIR */ -/* Name of package */ -/* #undef PACKAGE */ -/* Define to the address where bug reports for this package should be sent. */ -/* #undef PACKAGE_BUGREPORT */ -/* Define to the full name of this package. */ -/* #undef PACKAGE_NAME */ -/* Define to the full name and version of this package. */ -/* #undef PACKAGE_STRING */ -/* Define to the one symbol short name of this package. */ -/* #undef PACKAGE_TARNAME */ -/* Define to the home page for this package. */ -/* #undef PACKAGE_URL */ -/* Define to the version of this package. */ -/* #undef PACKAGE_VERSION */ -/* Define if supports floating-point conversion. */ -#define PQXX_HAVE_CHARCONV_FLOAT -/* Define if supports integer conversion. */ -#define PQXX_HAVE_CHARCONV_INT -/* Define if compiler has C++20 std::cmp_greater etc. */ -/* #undef PQXX_HAVE_CMP */ -/* Define if compiler supports Concepts and header. */ -/* #undef PQXX_HAVE_CONCEPTS */ -/* Define if compiler supports __cxa_demangle */ -#define PQXX_HAVE_CXA_DEMANGLE -/* Define if g++ supports pure attribute */ -#define PQXX_HAVE_GCC_PURE -/* Define if g++ supports visibility attribute. */ -#define PQXX_HAVE_GCC_VISIBILITY -/* Define if likely & unlikely work. */ -/* #undef PQXX_HAVE_LIKELY */ -/* Define if operator[] can take multiple arguments. */ -/* #undef PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT */ -/* Define if compiler has usable std::filesystem::path. */ -#define PQXX_HAVE_PATH -/* Define if poll() is available. */ -#define PQXX_HAVE_POLL -/* Define if libpq has PQencryptPasswordConn (since pg 10). */ -#define PQXX_HAVE_PQENCRYPTPASSWORDCONN -/* Define if libpq has pipeline mode (since pg 14). */ -#define PQXX_HAVE_PQ_PIPELINE -/* Define if std::this_thread::sleep_for works. */ -#define PQXX_HAVE_SLEEP_FOR -/* Define if compiler has std::span. */ -/* #undef PQXX_HAVE_SPAN */ -/* Define if strerror_r() is available. */ -#define PQXX_HAVE_STRERROR_R -/* Define if strerror_s() is available. */ -/* #undef PQXX_HAVE_STRERROR_S */ -/* Define if thread_local is fully supported. */ -#define PQXX_HAVE_THREAD_LOCAL -/* Define if std::chrono has year_month_day etc. */ -/* #undef PQXX_HAVE_YEAR_MONTH_DAY */ -/* Define to 1 if you have the ANSI C header files. */ -/* #undef STDC_HEADERS */ -/* Version number of package */ -/* #undef VERSION */ diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/connection b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/connection deleted file mode 100644 index 82ff43aa5..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/connection +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::connection class. - * - * pqxx::connection encapsulates a connection to a database. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/connection.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/connection.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/connection.hxx deleted file mode 100644 index 92454bb47..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/connection.hxx +++ /dev/null @@ -1,1261 +0,0 @@ -/* Definition of the connection class. - * - * pqxx::connection encapsulates a connection to a database. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_CONNECTION -#define PQXX_H_CONNECTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Double-check in order to suppress an overzealous Visual C++ warning (#418). -#if defined(PQXX_HAVE_CONCEPTS) && __has_include() -# include -#endif - -#include "pqxx/errorhandler.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/params.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - - -/** - * @addtogroup connections - * - * Use of the libpqxx library starts here. - * - * Everything that can be done with a database through libpqxx must go through - * a @ref pqxx::connection object. It connects to a database when you create - * it, and it terminates that communication during destruction. - * - * Many things come together in this class. Handling of error and warning - * messages, for example, is defined by @ref pqxx::errorhandler objects in the - * context of a connection. Prepared statements are also defined here. - * - * When you connect to a database, you pass a connection string containing any - * parameters and options, such as the server address and the database name. - * - * These are identical to the ones in libpq, the C language binding upon which - * libpqxx itself is built: - * - * https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING - * - * There are also environment variables you can set to provide defaults, again - * as defined by libpq: - * - * https://www.postgresql.org/docs/current/libpq-envars.html - * - * You can also create a database connection _asynchronously_ using an - * intermediate @ref pqxx::connecting object. - */ - -namespace pqxx::internal -{ -class sql_cursor; - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: T is a range of pairs of zero-terminated strings. -template -concept ZKey_ZValues = std::ranges::input_range and requires(T t) -{ - {std::cbegin(t)}; - { - std::get<0>(*std::cbegin(t)) - } -> ZString; - { - std::get<1>(*std::cbegin(t)) - } -> ZString; -} and std::tuple_size_v::value_type> -== 2; -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx::internal - - -namespace pqxx::internal::gate -{ -class connection_dbtransaction; -class connection_errorhandler; -class connection_largeobject; -class connection_notification_receiver; -class connection_pipeline; -class connection_sql_cursor; -class connection_stream_from; -class connection_stream_to; -class connection_transaction; -class const_connection_largeobject; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Representation of a PostgreSQL table path. -/** A "table path" consists of a table name, optionally prefixed by a schema - * name, which in turn is optionally prefixed by a database name. - * - * A minimal example of a table path would be `{mytable}`. But a table path - * may also take the forms `{myschema,mytable}` or - * `{mydb,myschema,mytable}`. - */ -using table_path = std::initializer_list; - - -/// Encrypt a password. @deprecated Use connection::encrypt_password instead. -[[nodiscard, - deprecated("Use connection::encrypt_password instead.")]] std::string - PQXX_LIBEXPORT - encrypt_password(char const user[], char const password[]); - -/// Encrypt password. @deprecated Use connection::encrypt_password instead. -[[nodiscard, - deprecated("Use connection::encrypt_password instead.")]] inline std::string -encrypt_password(zview user, zview password) -{ -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return encrypt_password(user.c_str(), password.c_str()); -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -/// Error verbosity levels. -enum class error_verbosity : int -{ - // These values must match those in libpq's PGVerbosity enum. - terse = 0, - normal = 1, - verbose = 2 -}; - - -/// Connection to a database. -/** This is the first class to look at when you wish to work with a database - * through libpqxx. The connection opens during construction, and closes upon - * destruction. - * - * When creating a connection, you can pass a connection URI or a postgres - * connection string, to specify the database server's address, a login - * username, and so on. If you don't, the connection will try to obtain them - * from certain environment variables. If those are not set either, the - * default is to try and connect to the local system's port 5432. - * - * Find more about connection strings here: - * - * https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING - * - * The variables are documented here: - * - * https://www.postgresql.org/docs/current/libpq-envars.html - * - * To query or manipulate the database once connected, use one of the - * transaction classes (see pqxx/transaction_base.hxx) and perhaps also the - * transactor framework (see pqxx/transactor.hxx). - * - * When a connection breaks, you will typically get a @ref broken_connection - * exception. This can happen at almost any point. - * - * @warning On Unix-like systems, including GNU and BSD systems, your program - * may receive the SIGPIPE signal when the connection to the backend breaks. By - * default this signal will abort your program. Use "signal(SIGPIPE, SIG_IGN)" - * if you want your program to continue running after a connection fails. - */ -class PQXX_LIBEXPORT connection -{ -public: - connection() : connection{""} {} - - /// Connect to a database, using `options` string. - explicit connection(char const options[]) - { - check_version(); - init(options); - } - - /// Connect to a database, using `options` string. - explicit connection(zview options) : connection{options.c_str()} - { - // (Delegates to other constructor which calls check_version for us.) - } - - /// Move constructor. - /** Moving a connection is not allowed if it has an open transaction, or has - * error handlers or notification receivers registered on it. In those - * situations, other objects may hold references to the old object which - * would become invalid and might produce hard-to-diagnose bugs. - */ - connection(connection &&rhs); - -#if defined(PQXX_HAVE_CONCEPTS) - /// Connect to a database, passing options as a range of key/value pairs. - /** @warning Experimental. Requires C++20 "concepts" support. Define - * `PQXX_HAVE_CONCEPTS` to enable it. - * - * There's no need to escape the parameter values. - * - * See the PostgreSQL libpq documentation for the full list of possible - * options: - * - * https://postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS - * - * The options can be anything that can be iterated as a series of pairs of - * zero-terminated strings: `std::pair`, or - * `std::tuple`, or - * `std::map`, and so on. - */ - template - inline connection(MAPPING const ¶ms); -#endif // PQXX_HAVE_CONCEPTS - - ~connection() - { - try - { - close(); - } - catch (std::exception const &) - {} - } - - /// Move assignment. - /** Neither connection can have an open transaction, registered error - * handlers, or registered notification receivers. - */ - connection &operator=(connection &&rhs); - - connection(connection const &) = delete; - connection &operator=(connection const &) = delete; - - /// Is this connection open at the moment? - /** @warning This function is **not** needed in most code. Resist the - * temptation to check it after opening a connection. The `connection` - * constructor will throw a @ref broken_connection exception if can't connect - * to the database. - */ - [[nodiscard]] bool PQXX_PURE is_open() const noexcept; - - /// Invoke notice processor function. The message should end in newline. - void process_notice(char const[]) noexcept; - /// Invoke notice processor function. Newline at end is recommended. - /** The zview variant, with a message ending in newline, is the most - * efficient way to call process_notice. - */ - void process_notice(zview) noexcept; - - /// Enable tracing to a given output stream, or nullptr to disable. - void trace(std::FILE *) noexcept; - - /** - * @name Connection properties - * - * These are probably not of great interest, since most are derived from - * information supplied by the client program itself, but they are included - * for completeness. - * - * The connection needs to be currently active for these to work. - */ - //@{ - /// Name of database we're connected to, if any. - [[nodiscard]] char const *dbname() const; - - /// Database user ID we're connected under, if any. - [[nodiscard]] char const *username() const; - - /// Address of server, or nullptr if none specified (i.e. default or local) - [[nodiscard]] char const *hostname() const; - - /// Server port number we're connected to. - [[nodiscard]] char const *port() const; - - /// Process ID for backend process, or 0 if inactive. - [[nodiscard]] int PQXX_PURE backendpid() const &noexcept; - - /// Socket currently used for connection, or -1 for none. Use with care! - /** Query the current socket number. This is intended for event loops based - * on functions such as select() or poll(), where you're waiting for any of - * multiple file descriptors to become ready for communication. - * - * Please try to stay away from this function. It is really only meant for - * event loops that need to wait on more than one file descriptor. If all - * you need is to block until a notification arrives, for instance, use - * await_notification(). If you want to issue queries and retrieve results - * in nonblocking fashion, check out the pipeline class. - */ - [[nodiscard]] int PQXX_PURE sock() const &noexcept; - - /// What version of the PostgreSQL protocol is this connection using? - /** The answer can be 0 (when there is no connection); 3 for protocol 3.0; or - * possibly higher values as newer protocol versions come into use. - */ - [[nodiscard]] int PQXX_PURE protocol_version() const noexcept; - - /// What version of the PostgreSQL server are we connected to? - /** The result is a bit complicated: each of the major, medium, and minor - * release numbers is written as a two-digit decimal number, and the three - * are then concatenated. Thus server version 9.4.2 will be returned as the - * decimal number 90402. If there is no connection to the server, this - * returns zero. - * - * @warning When writing version numbers in your code, don't add zero at the - * beginning! Numbers beginning with zero are interpreted as octal (base-8) - * in C++. Thus, 070402 is not the same as 70402, and 080000 is not a number - * at all because there is no digit "8" in octal notation. Use strictly - * decimal notation when it comes to these version numbers. - */ - [[nodiscard]] int PQXX_PURE server_version() const noexcept; - //@} - - /// @name Text encoding - /** - * Each connection is governed by a "client encoding," which dictates how - * strings and other text is represented in bytes. The database server will - * send text data to you in this encoding, and you should use it for the - * queries and data which you send to the server. - * - * Search the PostgreSQL documentation for "character set encodings" to find - * out more about the available encodings, how to extend them, and how to use - * them. Not all server-side encodings are compatible with all client-side - * encodings or vice versa. - * - * Encoding names are case-insensitive, so e.g. "UTF8" is equivalent to - * "utf8". - * - * You can change the client encoding, but this may not work when the - * connection is in a special state, such as when streaming a table. It's - * not clear what happens if you change the encoding during a transaction, - * and then abort the transaction. - */ - //@{ - /// Get client-side character encoding, by name. - [[nodiscard]] std::string get_client_encoding() const; - - /// Set client-side character encoding, by name. - /** - * @param encoding Name of the character set encoding to use. - */ - void set_client_encoding(zview encoding) & - { - set_client_encoding(encoding.c_str()); - } - - /// Set client-side character encoding, by name. - /** - * @param encoding Name of the character set encoding to use. - */ - void set_client_encoding(char const encoding[]) &; - - /// Get the connection's encoding, as a PostgreSQL-defined code. - [[nodiscard]] int PQXX_PRIVATE encoding_id() const; - - //@} - - /// Set session variable, using SQL's `SET` command. - /** @deprecated To set a session variable, use @ref set_session_var. To set - * a transaction-local variable, execute an SQL `SET` command. - * - * @warning When setting a string value, you must escape and quote it first. - * Use the @ref quote() function to do that. - * - * @warning This executes an SQL query, so do not get or set variables while - * a table stream or pipeline is active on the same connection. - * - * @param var Variable to set. - * @param value New value for Var. This can be any SQL expression. If it's - * a string, be sure that it's properly escaped and quoted. - */ - [[deprecated("To set session variables, use set_session_var.")]] void - set_variable(std::string_view var, std::string_view value) &; - - /// Set one of the session variables to a new value. - /** This executes SQL, so do not do it while a pipeline or stream is active - * on the connection. - * - * The value you set here will last for the rest of the connection's - * duration, or until you set a new value. - * - * If you set the value while in a @ref dbtransaction (i.e. any transaction - * that is not a @ref nontransaction), then rolling back the transaction will - * undo the change. - * - * All applies to setting _session_ variables. You can also set the same - * variables as _local_ variables, in which case they will always revert to - * their previous value when the transaction ends (or when you overwrite them - * of course). To set a local variable, simply execute an SQL statement - * along the lines of "`SET LOCAL var = 'value'`" inside your transaction. - * - * @param var The variable to set. - * @param value The new value for the variable. - * @throw @ref variable_set_to_null if the value is null; this is not - * allowed. - */ - template - void set_session_var(std::string_view var, TYPE const &value) & - { - if constexpr (nullness::has_null) - { - if (nullness::is_null(value)) - throw variable_set_to_null{ - internal::concat("Attempted to set variable ", var, " to null.")}; - } - exec(internal::concat("SET ", quote_name(var), "=", quote(value))); - } - - /// Read session variable, using SQL's `SHOW` command. - /** @warning This executes an SQL query, so do not get or set variables while - * a table stream or pipeline is active on the same connection. - */ - [[deprecated("Use get_var instead.")]] std::string - get_variable(std::string_view); - - /// Read currently applicable value of a variable. - /** This function executes an SQL statement, so it won't work while a - * @ref pipeline or query stream is active on the connection. - * - * @return a blank `std::optional` if the variable's value is null, or its - * string value otherwise. - */ - std::string get_var(std::string_view var); - - /// Read currently applicable value of a variable. - /** This function executes an SQL statement, so it won't work while a - * @ref pipeline or query stream is active on the connection. - * - * If there is any possibility that the variable is null, ensure that `TYPE` - * can represent null values. - */ - template TYPE get_var_as(std::string_view var) - { - return from_string(get_var(var)); - } - - /** - * @name Notifications and Receivers - */ - //@{ - /// Check for pending notifications and take appropriate action. - /** This does not block. To wait for incoming notifications, either call - * await_notification() (it calls this function); or wait for incoming data - * on the connection's socket (i.e. wait to read), and then call this - * function repeatedly until it returns zero. After that, there are no more - * pending notifications so you may want to wait again. - * - * If any notifications are pending when you call this function, it - * processes them by finding any receivers that match the notification string - * and invoking those. If no receivers match, there is nothing to invoke but - * we do consider the notification processed. - * - * If any of the client-registered receivers throws an exception, the - * function will report it using the connection's errorhandlers. It does not - * re-throw the exceptions. - * - * @return Number of notifications processed. - */ - int get_notifs(); - - /// Wait for a notification to come in. - /** There are other events that will also terminate the wait, such as the - * backend failing. It will also wake up periodically. - * - * If a notification comes in, the call will process it, along with any other - * notifications that may have been pending. - * - * To wait for notifications into your own event loop instead, wait until - * there is incoming data on the connection's socket to be read, then call - * @ref get_notifs() repeatedly until it returns zero. - * - * @return Number of notifications processed. - */ - int await_notification(); - - /// Wait for a notification to come in, or for given timeout to pass. - /** There are other events that will also terminate the wait, such as the - * backend failing, or timeout expiring. - * - * If a notification comes in, the call will process it, along with any other - * notifications that may have been pending. - * - * To wait for notifications into your own event loop instead, wait until - * there is incoming data on the connection's socket to be read, then call - * @ref get_notifs repeatedly until it returns zero. - * - * @return Number of notifications processed - */ - int await_notification(std::time_t seconds, long microseconds); - //@} - - /** - * @name Password encryption - * - * Use this when setting a new password for the user if password encryption - * is enabled. Inputs are the SQL name for the user for whom you with to - * encrypt a password; the plaintext password; and the hash algorithm. - * - * The algorithm must be one of "md5", "scram-sha-256" (introduced in - * PostgreSQL 10), or `nullptr`. If the pointer is null, this will query - * the `password_encryption setting` from the server, and use the default - * algorithm as defined there. - * - * @return encrypted version of the password, suitable for encrypted - * PostgreSQL authentication. - * - * Thus you can change a user's password with: - * ```cxx - * void setpw(transaction_base &t, string const &user, string const &pw) - * { - * t.exec0("ALTER USER " + user + " " - * "PASSWORD '" + t.conn().encrypt_password(user,pw) + "'"); - * } - * ``` - * - * When building this against a libpq older than version 10, this will use - * an older function which only supports md5. In that case, requesting a - * different algorithm than md5 will result in a @ref feature_not_supported - * exception. - */ - //@{ - /// Encrypt a password for a given user. - [[nodiscard]] std::string - encrypt_password(zview user, zview password, zview algorithm) - { - return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str()); - } - /// Encrypt a password for a given user. - [[nodiscard]] std::string encrypt_password( - char const user[], char const password[], char const *algorithm = nullptr); - //@} - - /** - * @name Prepared statements - * - * PostgreSQL supports prepared SQL statements, i.e. statements that you can - * register under a name you choose, optimized once by the backend, and - * executed any number of times under the given name. - * - * Prepared statement definitions are not sensitive to transaction - * boundaries. A statement defined inside a transaction will remain defined - * outside that transaction, even if the transaction itself is subsequently - * aborted. Once a statement has been prepared, it will only go away if you - * close the connection or explicitly "unprepare" the statement. - * - * Use the `pqxx::transaction_base::exec_prepared` functions to execute a - * prepared statement. See @ref prepared for a full discussion. - * - * @warning Using prepared statements can save time, but if your statement - * takes parameters, it may also make your application significantly slower! - * The reason is that the server works out a plan for executing the query - * when you prepare it. At that time, of course it does not know the values - * for the parameters that you will pass. If you execute a query without - * preparing it, then the server works out the plan on the spot, with full - * knowledge of the parameter values. - * - * A statement's definition can refer to its parameters as `$1`, `$2`, etc. - * The first parameter you pass to the call provides a value for `$1`, and - * so on. - * - * Here's an example of how to use prepared statements. - * - * ```cxx - * using namespace pqxx; - * void foo(connection &c) - * { - * c.prepare("findtable", "select * from pg_tables where name=$1"); - * work tx{c}; - * result r = tx.exec_prepared("findtable", "mytable"); - * if (std::empty(r)) throw runtime_error{"mytable not found!"}; - * } - * ``` - */ - //@{ - - /// Define a prepared statement. - /** - * @param name unique name for the new prepared statement. - * @param definition SQL statement to prepare. - */ - void prepare(zview name, zview definition) & - { - prepare(name.c_str(), definition.c_str()); - } - - /** - * @param name unique name for the new prepared statement. - * @param definition SQL statement to prepare. - */ - void prepare(char const name[], char const definition[]) &; - - /// Define a nameless prepared statement. - /** - * This can be useful if you merely want to pass large binary parameters to a - * statement without otherwise wishing to prepare it. If you use this - * feature, always keep the definition and the use close together to avoid - * the nameless statement being redefined unexpectedly by code somewhere - * else. - */ - void prepare(char const definition[]) &; - void prepare(zview definition) & { return prepare(definition.c_str()); } - - /// Drop prepared statement. - void unprepare(std::string_view name); - - //@} - - // C++20: constexpr. Breaks ABI. - /// Suffix unique number to name to make it unique within session context. - /** Used internally to generate identifiers for SQL objects (such as cursors - * and nested transactions) based on a given human-readable base name. - */ - [[nodiscard]] std::string adorn_name(std::string_view); - - /** - * @defgroup escaping-functions String-escaping functions - */ - //@{ - - /// Escape string for use as SQL string literal on this connection. - /** @warning This accepts a length, and it does not require a terminating - * zero byte. But if there is a zero byte, escaping stops there even if - * it's not at the end of the string! - */ - [[deprecated("Use std::string_view or pqxx:zview.")]] std::string - esc(char const text[], std::size_t maxlen) const - { - return esc(std::string_view{text, maxlen}); - } - - /// Escape string for use as SQL string literal on this connection. - [[nodiscard]] std::string esc(char const text[]) const - { - return esc(std::string_view{text}); - } - -#if defined(PQXX_HAVE_SPAN) - /// Escape string for use as SQL string literal, into `buffer`. - /** Use this variant when you want to re-use the same buffer across multiple - * calls. If that's not the case, or convenience and simplicity are more - * important, use the single-argument variant. - * - * For every byte in `text`, there must be at least 2 bytes of space in - * `buffer`; plus there must be one byte of space for a trailing zero. - * Throws @ref range_error if this space is not available. - * - * Returns a reference to the escaped string, which is actually stored in - * `buffer`. - */ - [[nodiscard]] std::string_view - esc(std::string_view text, std::span buffer) - { - auto const size{std::size(text)}, space{std::size(buffer)}; - auto const needed{2 * size + 1}; - if (space < needed) - throw range_error{internal::concat( - "Not enough room to escape string of ", size, " byte(s): need ", - needed, " bytes of buffer space, but buffer size is ", space, ".")}; - auto const data{buffer.data()}; - return {data, esc_to_buf(text, data)}; - } -#endif - - /// Escape string for use as SQL string literal on this connection. - /** @warning This is meant for text strings only. It cannot contain bytes - * whose value is zero ("nul bytes"). - */ - [[nodiscard]] std::string esc(std::string_view text) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape binary string for use as SQL string literal on this connection. - /** This is identical to `esc_raw(data)`. */ - template [[nodiscard]] std::string esc(DATA const &data) const - { - return esc_raw(data); - } -#endif - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - /** Use this variant when you want to re-use the same buffer across multiple - * calls. If that's not the case, or convenience and simplicity are more - * important, use the single-argument variant. - * - * For every byte in `data`, there must be at least two bytes of space in - * `buffer`; plus there must be two bytes of space for a header and one for - * a trailing zero. Throws @ref range_error if this space is not available. - * - * Returns a reference to the escaped string, which is actually stored in - * `buffer`. - */ - template - [[nodiscard]] zview esc(DATA const &data, std::span buffer) const - { - auto const size{std::size(data)}, space{std::size(buffer)}; - auto const needed{internal::size_esc_bin(std::size(data))}; - if (space < needed) - throw range_error{internal::concat( - "Not enough room to escape binary string of ", size, " byte(s): need ", - needed, " bytes of buffer space, but buffer size is ", space, ".")}; - - std::basic_string_view view{std::data(data), std::size(data)}; - auto const out{std::data(buffer)}; - // Actually, in the modern format, we know beforehand exactly how many - // bytes we're going to fill. Just leave out the trailing zero. - internal::esc_bin(view, out); - return zview{out, needed - 1}; - } -#endif - - /// Escape binary string for use as SQL string literal on this connection. - [[deprecated("Use std::byte for binary data.")]] std::string - esc_raw(unsigned char const bin[], std::size_t len) const; - - /// Escape binary string for use as SQL string literal on this connection. - /** You can also just use @ref esc with a binary string. */ - [[nodiscard]] std::string esc_raw(std::basic_string_view) const; - -#if defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - /** You can also just use @ref esc with a binary string. */ - [[nodiscard]] std::string - esc_raw(std::basic_string_view, std::span buffer) const; -#endif - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape binary string for use as SQL string literal on this connection. - /** You can also just use @ref esc with a binary string. */ - template - [[nodiscard]] std::string esc_raw(DATA const &data) const - { - return esc_raw( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif - -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - /// Escape binary string for use as SQL string literal, into `buffer`. - template - [[nodiscard]] zview esc_raw(DATA const &data, std::span buffer) const - { - return this->esc(binary_cast(data), buffer); - } -#endif - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(zview text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return unesc_raw(text.c_str()); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(char const text[]) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - * - * (The data must be encoded in PostgreSQL's "hex" format. The legacy - * "bytea" escape format, used prior to PostgreSQL 9.0, is no longer - * supported.) - */ - [[nodiscard]] std::basic_string - unesc_bin(std::string_view text) const - { - std::basic_string buf; - buf.resize(pqxx::internal::size_unesc_bin(std::size(text))); - pqxx::internal::unesc_bin(text, buf.data()); - return buf; - } - - /// Escape and quote a string of binary data. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(unsigned char const bin[], std::size_t len) const; - - /// Escape and quote a string of binary data. - std::string quote_raw(std::basic_string_view) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Escape and quote a string of binary data. - /** You can also just use @ref quote with binary data. */ - template - [[nodiscard]] std::string quote_raw(DATA const &data) const - { - return quote_raw( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote an SQL identifier for use in a query. - [[nodiscard]] std::string quote_name(std::string_view identifier) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote a table name. - /** When passing just a table name, this is just another name for - * @ref quote_name. - */ - [[nodiscard]] std::string quote_table(std::string_view name) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote a table path. - /** A table path consists of a table name, optionally prefixed by a schema - * name; and if both are given, they are in turn optionally prefixed by a - * database name. - * - * Each portion of the path (database name, schema name, table name) will be - * quoted separately, and they will be joined together by dots. So for - * example, `myschema.mytable` will become `"myschema"."mytable"`. - */ - [[nodiscard]] std::string quote_table(table_path) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Quote and comma-separate a series of column names. - /** Use this to save a bit of work in cases where you repeatedly need to pass - * the same list of column names, e.g. with @ref stream_to and @ref - * stream_from. Some functions that need to quote the columns list - * internally, will have a "raw" alternative which let you do the quoting - * yourself. It's a bit of extra work, but it can in rare cases let you - * eliminate some duplicate work in quoting them repeatedly. - */ - template - inline std::string quote_columns(STRINGS const &columns) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Represent object as SQL string, including quoting & escaping. - /** - * Recognises nulls and represents them as SQL nulls. They get no quotes. - */ - template - [[nodiscard]] inline std::string quote(T const &t) const; - - [[deprecated("Use std::byte for binary data.")]] std::string - quote(binarystring const &) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape and quote binary data for use as a BYTEA value in SQL statement. - [[nodiscard]] std::string - quote(std::basic_string_view bytes) const; - - // TODO: Make "into buffer" variant to eliminate a string allocation. - /// Escape string for literal LIKE match. - /** Use this when part of an SQL "LIKE" pattern should match only as a - * literal string, not as a pattern, even if it contains "%" or "_" - * characters that would normally act as wildcards. - * - * The string does not get string-escaped or quoted. You do that later. - * - * For instance, let's say you have a string `name` entered by the user, - * and you're searching a `file` column for items that match `name` - * followed by a dot and three letters. Even if `name` contains wildcard - * characters "%" or "_", you only want those to match literally, so "_" - * only matches "_" and "%" only matches a single "%". - * - * You do that by "like-escaping" `name`, appending the wildcard pattern - * `".___"`, and finally, escaping and quoting the result for inclusion in - * your query: - * - * ```cxx - * tx.exec( - * "SELECT file FROM item WHERE file LIKE " + - * tx.quote(tx.esc_like(name) + ".___")); - * ``` - * - * The SQL "LIKE" operator also lets you choose your own escape character. - * This is supported, but must be a single-byte character. - */ - [[nodiscard]] std::string - esc_like(std::string_view text, char escape_char = '\\') const; - //@} - - /// Attempt to cancel the ongoing query, if any. - /** You can use this from another thread, and/or while a query is executing - * in a pipeline, but it's up to you to ensure that you're not canceling the - * wrong query. This may involve locking. - */ - void cancel_query(); - -#if defined(_WIN32) || __has_include() - /// Set socket to blocking (true) or nonblocking (false). - /** @warning Do not use this unless you _really_ know what you're doing. - * @warning This function is available on most systems, but not necessarily - * all. - */ - void set_blocking(bool block) &; -#endif // defined(_WIN32) || __has_include() - - /// Set session verbosity. - /** Set the verbosity of error messages to "terse", "normal" (the default), - * or "verbose." - * - * If "terse", returned messages include severity, primary text, and - * position only; this will normally fit on a single line. "normal" produces - * messages that include the above plus any detail, hint, or context fields - * (these might span multiple lines). "verbose" includes all available - * fields. - */ - void set_verbosity(error_verbosity verbosity) &noexcept; - - /// Return pointers to the active errorhandlers. - /** The entries are ordered from oldest to newest handler. - * - * You may use this to find errorhandlers that your application wants to - * delete when destroying the connection. Be aware, however, that libpqxx - * may also add errorhandlers of its own, and those will be included in the - * list. If this is a problem for you, derive your errorhandlers from a - * custom base class derived from pqxx::errorhandler. Then use dynamic_cast - * to find which of the error handlers are yours. - * - * The pointers point to the real errorhandlers. The container it returns - * however is a copy of the one internal to the connection, not a reference. - */ - [[nodiscard]] std::vector get_errorhandlers() const; - - /// Return a connection string encapsulating this connection's options. - /** The connection must be currently open for this to work. - * - * Returns a reconstruction of this connection's connection string. It may - * not exactly match the connection string you passed in when creating this - * connection. - */ - [[nodiscard]] std::string connection_string() const; - - /// Explicitly close the connection. - /** The destructor will do this for you automatically. Still, there is a - * reason to `close()` objects explicitly where possible: if an error should - * occur while closing, `close()` can throw an exception. A destructor - * cannot. - * - * Closing a connection is idempotent. Closing a connection that's already - * closed does nothing. - */ - void close(); - - /// Seize control of a raw libpq connection. - /** @warning Do not do this. Please. It's for very rare, very specific - * use-cases. The mechanism may change (or break) in unexpected ways in - * future versions. - * - * @param raw_conn a raw libpq `PQconn` pointer. - */ - static connection seize_raw_connection(internal::pq::PGconn *raw_conn) - { - return connection{raw_conn}; - } - - /// Release the raw connection without closing it. - /** @warning Do not do this. It's for very rare, very specific use-cases. - * The mechanism may change (or break) in unexpected ways in future versions. - * - * The `connection` object becomes unusable after this. - */ - internal::pq::PGconn *release_raw_connection() && - { - return std::exchange(m_conn, nullptr); - } - -private: - friend class connecting; - enum connect_mode - { - connect_nonblocking - }; - connection(connect_mode, zview connection_string); - - /// For use by @ref seize_raw_connection. - explicit connection(internal::pq::PGconn *raw_conn) : m_conn{raw_conn} {} - - /// Poll for ongoing connection, try to progress towards completion. - /** Returns a pair of "now please wait to read data from socket" and "now - * please wait to write data to socket." Both will be false when done. - * - * Throws an exception if polling indicates that the connection has failed. - */ - std::pair poll_connect(); - - // Initialise based on connection string. - void init(char const options[]); - // Initialise based on parameter names and values. - void init(char const *params[], char const *values[]); - void complete_init(); - - result make_result( - internal::pq::PGresult *pgr, std::shared_ptr const &query, - std::string_view desc = ""sv); - - void PQXX_PRIVATE set_up_state(); - - int PQXX_PRIVATE PQXX_PURE status() const noexcept; - - /// Escape a string, into a buffer allocated by the caller. - /** The buffer must have room for at least `2*std::size(text) + 1` bytes. - * - * Returns the number of bytes written, including the trailing zero. - */ - std::size_t esc_to_buf(std::string_view text, char *buf) const; - - friend class internal::gate::const_connection_largeobject; - char const *PQXX_PURE err_msg() const noexcept; - - void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept; - - result exec_prepared(std::string_view statement, internal::c_params const &); - - /// Throw @ref usage_error if this connection is not in a movable state. - void check_movable() const; - /// Throw @ref usage_error if not in a state where it can be move-assigned. - void check_overwritable() const; - - friend class internal::gate::connection_errorhandler; - void PQXX_PRIVATE register_errorhandler(errorhandler *); - void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept; - - friend class internal::gate::connection_transaction; - result exec(std::string_view, std::string_view = ""sv); - result - PQXX_PRIVATE exec(std::shared_ptr, std::string_view = ""sv); - void PQXX_PRIVATE register_transaction(transaction_base *); - void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept; - - friend class internal::gate::connection_stream_from; - std::pair>, std::size_t> - PQXX_PRIVATE read_copy_line(); - - friend class internal::gate::connection_stream_to; - void PQXX_PRIVATE write_copy_line(std::string_view); - void PQXX_PRIVATE end_copy_write(); - - friend class internal::gate::connection_largeobject; - internal::pq::PGconn *raw_connection() const { return m_conn; } - - friend class internal::gate::connection_notification_receiver; - void add_receiver(notification_receiver *); - void remove_receiver(notification_receiver *) noexcept; - - friend class internal::gate::connection_pipeline; - void PQXX_PRIVATE start_exec(char const query[]); - bool PQXX_PRIVATE consume_input() noexcept; - bool PQXX_PRIVATE is_busy() const noexcept; - internal::pq::PGresult *get_result(); - - friend class internal::gate::connection_dbtransaction; - friend class internal::gate::connection_sql_cursor; - - result exec_params(std::string_view query, internal::c_params const &args); - - /// Connection handle. - internal::pq::PGconn *m_conn = nullptr; - - /// Active transaction on connection, if any. - /** We don't use this for anything, except to check for open transactions - * when we close the connection or start a new transaction. - * - * We also don't allow move construction or move assignment while there's a - * transaction, since moving the connection in that case would leave one or - * more pointers back from the transaction to the connection dangling. - */ - transaction_base const *m_trans = nullptr; - - std::list m_errorhandlers; - - using receiver_list = - std::multimap; - /// Notification receivers. - receiver_list m_receivers; - - /// Unique number to use as suffix for identifiers (see adorn_name()). - int m_unique_id = 0; -}; - - -/// @deprecated Old base class for connection. They are now the same class. -using connection_base = connection; - - -/// An ongoing, non-blocking stepping stone to a connection. -/** Use this when you want to create a connection to the database, but without - * blocking your whole thread. It is only available on systems that have - * the `` header, and Windows. - * - * Connecting in this way is probably not "faster" (it's more complicated and - * has some extra overhead), but in some situations you can use it to make your - * application as a whole faster. It all depends on having other useful work - * to do in the same thread, and being able to wait on a socket. If you have - * other I/O going on at the same time, your event loop can wait for both the - * libpqxx socket and your own sockets, and wake up whenever any of them is - * ready to do work. - * - * Connecting in this way is not properly "asynchronous;" it's merely - * "nonblocking." This means it's not a super-high-performance mechanism like - * you might get with e.g. `io_uring`. In particular, if we need to look up - * the database hostname in DNS, that will happen synchronously. - * - * To use this, create the `connecting` object, passing a connection string. - * Then loop: If @ref wait_to_read returns true, wait for the socket to have - * incoming data on it. If @ref wait_to_write returns true, wait for the - * socket to be ready for writing. Then call @ref process to process any - * incoming or outgoing data. Do all of this until @ref done returns true (or - * there is an exception). Finally, call @ref produce to get the completed - * connection. - * - * For example: - * - * ```cxx - * pqxx::connecting cg{}; - * - * // Loop until we're done connecting. - * while (!cg.done()) - * { - * wait_for_fd(cg.sock(), cg.wait_to_read(), cg.wait_to_write()); - * cg.process(); - * } - * - * pqxx::connection conn = std::move(cg).produce(); - * - * // At this point, conn is a working connection. You can no longer use - * // cg at all. - * ``` - */ -class PQXX_LIBEXPORT connecting -{ -public: - /// Start connecting. - connecting(zview connection_string = ""_zv); - - connecting(connecting const &) = delete; - connecting(connecting &&) = default; - connecting &operator=(connecting const &) = delete; - connecting &operator=(connecting &&) = default; - - /// Get the socket. The socket may change during the connection process. - [[nodiscard]] int sock() const &noexcept { return m_conn.sock(); } - - /// Should we currently wait to be able to _read_ from the socket? - [[nodiscard]] constexpr bool wait_to_read() const &noexcept - { - return m_reading; - } - - /// Should we currently wait to be able to _write_ to the socket? - [[nodiscard]] constexpr bool wait_to_write() const &noexcept - { - return m_writing; - } - - /// Progress towards completion (but don't block). - void process() &; - - /// Is our connection finished? - [[nodiscard]] constexpr bool done() const &noexcept - { - return not m_reading and not m_writing; - } - - /// Produce the completed connection object. - /** Use this only once, after @ref done returned `true`. Once you have - * called this, the `connecting` instance has no more use or meaning. You - * can't call any of its member functions afterwards. - * - * This member function is rvalue-qualified, meaning that you can only call - * it on an rvalue instance of the class. If what you have is not an rvalue, - * turn it into one by wrapping it in `std::move()`. - */ - [[nodiscard]] connection produce() &&; - -private: - connection m_conn; - bool m_reading{false}; - bool m_writing{true}; -}; - - -template inline std::string connection::quote(T const &t) const -{ - if constexpr (nullness::always_null) - { - return "NULL"; - } - else - { - if (is_null(t)) - return "NULL"; - auto const text{to_string(t)}; - - // Okay, there's an easy way to do this and there's a hard way. The easy - // way was "quote, esc(to_string(t)), quote". I'm going with the hard way - // because it's going to save some string manipulation that will probably - // incur some unnecessary memory allocations and deallocations. - std::string buf{'\''}; - buf.resize(2 + 2 * std::size(text) + 1); - auto const content_bytes{esc_to_buf(text, buf.data() + 1)}; - auto const closing_quote{1 + content_bytes}; - buf[closing_quote] = '\''; - auto const end{closing_quote + 1}; - buf.resize(end); - return buf; - } -} - - -template -inline std::string connection::quote_columns(STRINGS const &columns) const -{ - return separated_list( - ","sv, std::cbegin(columns), std::cend(columns), - [this](auto col) { return this->quote_name(*col); }); -} - - -#if defined(PQXX_HAVE_CONCEPTS) -template -inline connection::connection(MAPPING const ¶ms) -{ - check_version(); - - std::vector keys, values; - if constexpr (std::ranges::sized_range) - { - auto const size{std::ranges::size(params) + 1}; - keys.reserve(size); - values.reserve(size); - } - for (auto const &[key, value] : params) - { - keys.push_back(internal::as_c_string(key)); - values.push_back(internal::as_c_string(value)); - } - keys.push_back(nullptr); - values.push_back(nullptr); - init(std::data(keys), std::data(values)); -} -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/cursor b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/cursor deleted file mode 100644 index e20b3a4fa..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/cursor +++ /dev/null @@ -1,8 +0,0 @@ -/** Definition of the iterator/container-style cursor classes. - * - * C++-style wrappers for SQL cursors - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/cursor.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/cursor.hxx deleted file mode 100644 index b392e2407..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/cursor.hxx +++ /dev/null @@ -1,483 +0,0 @@ -/* Definition of the iterator/container-style cursor classes. - * - * C++-style wrappers for SQL cursors. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_CURSOR -#define PQXX_H_CURSOR - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/result.hxx" -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -/// Common definitions for cursor types -/** In C++ terms, fetches are always done in pre-increment or pre-decrement - * fashion--i.e. the result does not include the row the cursor is on at the - * beginning of the fetch, and the cursor ends up being positioned on the last - * row in the result. - * - * There are singular positions akin to `end()` at both the beginning and the - * end of the cursor's range of movement, although these fit in so naturally - * with the semantics that one rarely notices them. The cursor begins at the - * first of these, but any fetch in the forward direction will move the cursor - * off this position and onto the first row before returning anything. - */ -class PQXX_LIBEXPORT cursor_base -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - - /// Cursor access-pattern policy - /** Allowing a cursor to move forward only can result in better performance, - * so use this access policy whenever possible. - */ - enum access_policy - { - /// Cursor can move forward only - forward_only, - /// Cursor can move back and forth - random_access - }; - - /// Cursor update policy - /** - * @warning Not all PostgreSQL versions support updatable cursors. - */ - enum update_policy - { - /// Cursor can be used to read data but not to write - read_only, - /// Cursor can be used to update data as well as read it - update - }; - - /// Cursor destruction policy - /** The normal thing to do is to make a cursor object the owner of the SQL - * cursor it represents. There may be cases, however, where a cursor needs - * to persist beyond the end of the current transaction (and thus also beyond - * the lifetime of the cursor object that created it!), where it can be - * "adopted" into a new cursor object. See the basic_cursor documentation - * for an explanation of cursor adoption. - * - * If a cursor is created with "loose" ownership policy, the object - * representing the underlying SQL cursor will not take the latter with it - * when its own lifetime ends, nor will its originating transaction. - * - * @warning Use this feature with care and moderation. Only one cursor - * object should be responsible for any one underlying SQL cursor at any - * given time. - */ - enum ownership_policy - { - /// Destroy SQL cursor when cursor object is closed at end of transaction - owned, - /// Leave SQL cursor in existence after close of object and transaction - loose - }; - - cursor_base() = delete; - cursor_base(cursor_base const &) = delete; - cursor_base &operator=(cursor_base const &) = delete; - - /** - * @name Special movement distances. - */ - //@{ - - // TODO: Make constexpr inline (but breaks ABI). - /// Special value: read until end. - /** @return Maximum value for result::difference_type, so the cursor will - * attempt to read the largest possible result set. - */ - [[nodiscard]] static difference_type all() noexcept; - - /// Special value: read one row only. - /** @return Unsurprisingly, 1. - */ - [[nodiscard]] static constexpr difference_type next() noexcept { return 1; } - - /// Special value: read backwards, one row only. - /** @return Unsurprisingly, -1. - */ - [[nodiscard]] static constexpr difference_type prior() noexcept - { - return -1; - } - - // TODO: Make constexpr inline (but breaks ABI). - /// Special value: read backwards from current position back to origin. - /** @return Minimum value for result::difference_type. - */ - [[nodiscard]] static difference_type backward_all() noexcept; - - //@} - - /// Name of underlying SQL cursor - /** - * @returns Name of SQL cursor, which may differ from original given name. - * @warning Don't use this to access the SQL cursor directly without going - * through the provided wrapper classes! - */ - [[nodiscard]] constexpr std::string const &name() const noexcept - { - return m_name; - } - -protected: - cursor_base(connection &, std::string_view Name, bool embellish_name = true); - - std::string const m_name; -}; -} // namespace pqxx - - -#include - - -namespace pqxx -{ -/// "Stateless cursor" class: easy API for retrieving parts of result sets -/** This is a front-end for SQL cursors, but with a more C++-like API. - * - * Actually, stateless_cursor feels entirely different from SQL cursors. You - * don't keep track of positions, fetches, and moves; you just say which rows - * you want. See the retrieve() member function. - */ -template -class stateless_cursor -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - - /// Create cursor. - /** - * @param tx The transaction within which you want to create the cursor. - * @param query The SQL query whose results the cursor should traverse. - * @param cname A hint for the cursor's name. The actual SQL cursor's name - * will be based on this (though not necessarily identical). - * @param hold Create a `WITH HOLD` cursor? Such cursors stay alive after - * the transaction has ended, so you can continue to use it. - */ - stateless_cursor( - transaction_base &tx, std::string_view query, std::string_view cname, - bool hold) : - m_cur{tx, query, cname, cursor_base::random_access, up, op, hold} - {} - - /// Adopt an existing scrolling SQL cursor. - /** This lets you define a cursor yourself, and then wrap it in a - * libpqxx-managed `stateless_cursor` object. - * - * @param tx The transaction within which you want to manage the cursor. - * @param adopted_cursor Your cursor's SQL name. - */ - stateless_cursor(transaction_base &tx, std::string_view adopted_cursor) : - m_cur{tx, adopted_cursor, op} - { - // Put cursor in known position - m_cur.move(cursor_base::backward_all()); - } - - /// Close this cursor. - /** The destructor will do this for you automatically. - * - * Closing a cursor is idempotent. Closing a cursor that's already closed - * does nothing. - */ - void close() noexcept { m_cur.close(); } - - /// Number of rows in cursor's result set - /** @note This function is not const; it may need to scroll to find the size - * of the result set. - */ - [[nodiscard]] size_type size() - { - return internal::obtain_stateless_cursor_size(m_cur); - } - - /// Retrieve rows from begin_pos (inclusive) to end_pos (exclusive) - /** Rows are numbered starting from 0 to size()-1. - * - * @param begin_pos First row to retrieve. May be one row beyond the end of - * the result set, to avoid errors for empty result sets. Otherwise, must be - * a valid row number in the result set. - * @param end_pos Row up to which to fetch. Rows are returned ordered from - * begin_pos to end_pos, i.e. in ascending order if begin_pos < end_pos but - * in descending order if begin_pos > end_pos. The end_pos may be - * arbitrarily inside or outside the result set; only existing rows are - * included in the result. - */ - result retrieve(difference_type begin_pos, difference_type end_pos) - { - return internal::stateless_cursor_retrieve( - m_cur, result::difference_type(size()), begin_pos, end_pos); - } - - /// Return this cursor's name. - [[nodiscard]] constexpr std::string const &name() const noexcept - { - return m_cur.name(); - } - -private: - internal::sql_cursor m_cur; -}; - - -class icursor_iterator; -} // namespace pqxx - - -namespace pqxx::internal::gate -{ -class icursor_iterator_icursorstream; -class icursorstream_icursor_iterator; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Simple read-only cursor represented as a stream of results -/** SQL cursors can be tricky, especially in C++ since the two languages seem - * to have been designed on different planets. An SQL cursor has two singular - * positions akin to `end()` on either side of the underlying result set. - * - * These cultural differences are hidden from view somewhat by libpqxx, which - * tries to make SQL cursors behave more like familiar C++ entities such as - * iterators, sequences, streams, and containers. - * - * Data is fetched from the cursor as a sequence of result objects. Each of - * these will contain the number of rows defined as the stream's stride, except - * of course the last block of data which may contain fewer rows. - * - * This class can create or adopt cursors that live outside any backend - * transaction, which your backend version may not support. - */ -class PQXX_LIBEXPORT icursorstream -{ -public: - using size_type = cursor_base::size_type; - using difference_type = cursor_base::difference_type; - - /// Set up a read-only, forward-only cursor. - /** Roughly equivalent to a C++ Standard Library istream, this cursor type - * supports only two operations: reading a block of rows while moving - * forward, and moving forward without reading any data. - * - * @param context Transaction context in which this cursor will be active. - * @param query SQL query whose results this cursor shall iterate. - * @param basename Suggested name for the SQL cursor; the library will append - * a unique code to ensure its uniqueness. - * @param sstride Number of rows to fetch per read operation; must be a - * positive number. - */ - icursorstream( - transaction_base &context, std::string_view query, - std::string_view basename, difference_type sstride = 1); - - /// Adopt existing SQL cursor. Use with care. - /** Forms a cursor stream around an existing SQL cursor, as returned by e.g. - * a server-side function. The SQL cursor will be cleaned up by the stream's - * destructor as if it had been created by the stream; cleaning it up by hand - * or adopting the same cursor twice is an error. - * - * Passing the name of the cursor as a string is not allowed, both to avoid - * confusion with the other constructor and to discourage unnecessary use of - * adopted cursors. - * - * @warning It is technically possible to adopt a "WITH HOLD" cursor, i.e. a - * cursor that stays alive outside its creating transaction. However, any - * cursor stream (including the underlying SQL cursor, naturally) must be - * destroyed before its transaction context object is destroyed. Therefore - * the only way to use SQL's WITH HOLD feature is to adopt the cursor, but - * defer doing so until after entering the transaction context that will - * eventually destroy it. - * - * @param context Transaction context in which this cursor will be active. - * @param cname Result field containing the name of the SQL cursor to adopt. - * @param sstride Number of rows to fetch per read operation; must be a - * positive number. - * @param op Ownership policy. Determines whether the cursor underlying this - * stream will be destroyed when the stream is closed. - */ - icursorstream( - transaction_base &context, field const &cname, difference_type sstride = 1, - cursor_base::ownership_policy op = cursor_base::owned); - - /// Return `true` if this stream may still return more data. - constexpr operator bool() const &noexcept { return not m_done; } - - /// Read new value into given result object; same as operator `>>`. - /** The result set may continue any number of rows from zero to the chosen - * stride, inclusive. An empty result will only be returned if there are no - * more rows to retrieve. - * - * @param res Write the retrieved data into this result object. - * @return Reference to this very stream, to facilitate "chained" invocations - * ("C.get(r1).get(r2);") - */ - icursorstream &get(result &res) - { - res = fetchblock(); - return *this; - } - /// Read new value into given result object; same as `get(result&)`. - /** The result set may continue any number of rows from zero to the chosen - * stride, inclusive. An empty result will only be returned if there are no - * more rows to retrieve. - * - * @param res Write the retrieved data into this result object. - * @return Reference to this very stream, to facilitate "chained" invocations - * ("C >> r1 >> r2;") - */ - icursorstream &operator>>(result &res) { return get(res); } - - /// Move given number of rows forward without reading data. - /** Ignores any stride that you may have set. It moves by a given number of - * rows, not a number of strides. - * - * @return Reference to this stream itself, to facilitate "chained" - * invocations. - */ - icursorstream &ignore(std::streamsize n = 1) &; - - /// Change stride, i.e. the number of rows to fetch per read operation. - /** - * @param stride Must be a positive number. - */ - void set_stride(difference_type stride) &; - [[nodiscard]] constexpr difference_type stride() const noexcept - { - return m_stride; - } - -private: - result fetchblock(); - - friend class internal::gate::icursorstream_icursor_iterator; - size_type forward(size_type n = 1); - void insert_iterator(icursor_iterator *) noexcept; - void remove_iterator(icursor_iterator *) const noexcept; - - void service_iterators(difference_type); - - internal::sql_cursor m_cur; - - difference_type m_stride; - difference_type m_realpos, m_reqpos; - - mutable icursor_iterator *m_iterators; - - bool m_done; -}; - - -/// Approximate istream_iterator for icursorstream. -/** Intended as an implementation of an input_iterator (as defined by the C++ - * Standard Library), this class supports only two basic operations: reading - * the current element, and moving forward. In addition to the minimal - * guarantees for istream_iterators, this class supports multiple successive - * reads of the same position (the current result set is cached in the - * iterator) even after copying and even after new data have been read from the - * stream. This appears to be a requirement for input_iterators. Comparisons - * are also supported in the general case. - * - * The iterator does not care about its own position, however. Moving an - * iterator forward moves the underlying stream forward and reads the data from - * the new stream position, regardless of the iterator's old position in the - * stream. - * - * The stream's stride defines the granularity for all iterator movement or - * access operations, i.e. "ici += 1" advances the stream by one stride's worth - * of rows, and "*ici++" reads one stride's worth of rows from the stream. - * - * @warning Do not read from the underlying stream or its cursor, move its read - * position, or change its stride, between the time the first icursor_iterator - * on it is created and the time its last icursor_iterator is destroyed. - * - * @warning Manipulating these iterators within the context of a single cursor - * stream is not thread-safe. Creating a new iterator, copying one, - * or destroying one affects the stream as a whole. - */ -class PQXX_LIBEXPORT icursor_iterator -{ -public: - using iterator_category = std::input_iterator_tag; - using value_type = result; - using pointer = result const *; - using reference = result const &; - using istream_type = icursorstream; - using size_type = istream_type::size_type; - using difference_type = istream_type::difference_type; - - icursor_iterator() noexcept; - explicit icursor_iterator(istream_type &) noexcept; - icursor_iterator(icursor_iterator const &) noexcept; - ~icursor_iterator() noexcept; - - result const &operator*() const - { - refresh(); - return m_here; - } - result const *operator->() const - { - refresh(); - return &m_here; - } - icursor_iterator &operator++(); - icursor_iterator operator++(int); - icursor_iterator &operator+=(difference_type); - icursor_iterator &operator=(icursor_iterator const &) noexcept; - - [[nodiscard]] bool operator==(icursor_iterator const &rhs) const; - [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept - { - return not operator==(rhs); - } - [[nodiscard]] bool operator<(icursor_iterator const &rhs) const; - [[nodiscard]] bool operator>(icursor_iterator const &rhs) const - { - return rhs < *this; - } - [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const - { - return not(*this > rhs); - } - [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const - { - return not(*this < rhs); - } - -private: - void refresh() const; - - friend class internal::gate::icursor_iterator_icursorstream; - difference_type pos() const noexcept { return m_pos; } - void fill(result const &); - - icursorstream *m_stream{nullptr}; - result m_here; - difference_type m_pos; - icursor_iterator *m_prev{nullptr}, *m_next{nullptr}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/dbtransaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/dbtransaction deleted file mode 100644 index fa8d26476..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/dbtransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::dbtransaction abstract base class. - * - * pqxx::dbransaction defines a real transaction on the database. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/dbtransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/dbtransaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/dbtransaction.hxx deleted file mode 100644 index d85cb170f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/dbtransaction.hxx +++ /dev/null @@ -1,70 +0,0 @@ -/* Definition of the pqxx::dbtransaction abstract base class. - * - * pqxx::dbransaction defines a real transaction on the database. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_DBTRANSACTION -#define PQXX_H_DBTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/transaction_base.hxx" - -namespace pqxx -{ -/// Abstract transaction base class: bracket transactions on the database. -/** - * @ingroup transactions - * - * Use a dbtransaction-derived object such as "work" (transaction<>) to enclose - * operations on a database in a single "unit of work." This ensures that the - * whole series of operations either succeeds as a whole or fails completely. - * In no case will it leave half-finished work behind in the database. - * - * Once processing on a transaction has succeeded and any changes should be - * allowed to become permanent in the database, call commit(). If something - * has gone wrong and the changes should be forgotten, call abort() instead. - * If you do neither, an implicit abort() is executed at destruction time. - * - * It is an error to abort a transaction that has already been committed, or to - * commit a transaction that has already been aborted. Aborting an already - * aborted transaction or committing an already committed one is allowed, to - * make error handling easier. Repeated aborts or commits have no effect after - * the first one. - * - * Database transactions are not suitable for guarding long-running processes. - * If your transaction code becomes too long or too complex, consider ways to - * break it up into smaller ones. Unfortunately there is no universal recipe - * for this. - * - * The actual operations for committing/aborting the backend transaction are - * implemented by a derived class. The implementing concrete class must also - * call @ref close from its destructor. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base -{ -protected: - /// Begin transaction. - explicit dbtransaction(connection &c) : transaction_base{c} {} - /// Begin transaction. - dbtransaction(connection &c, std::string_view tname) : - transaction_base{c, tname} - {} - /// Begin transaction. - dbtransaction( - connection &c, std::string_view tname, - std::shared_ptr rollback_cmd) : - transaction_base{c, tname, rollback_cmd} - {} -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/errorhandler b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/errorhandler deleted file mode 100644 index ea572ee79..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/errorhandler +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::errorhandler class. - * - * Callbacks for handling errors and warnings. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/errorhandler.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/errorhandler.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/errorhandler.hxx deleted file mode 100644 index 2ffb5703c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/errorhandler.hxx +++ /dev/null @@ -1,92 +0,0 @@ -/* Definition of the pqxx::errorhandler class. - * - * pqxx::errorhandler handlers errors and warnings in a database session. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/errorhandler instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ERRORHANDLER -#define PQXX_H_ERRORHANDLER - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/types.hxx" - - -namespace pqxx::internal::gate -{ -class errorhandler_connection; -} - - -namespace pqxx -{ -/** - * @addtogroup errorhandler - */ -//@{ - -/// Base class for error-handler callbacks. -/** To receive errors and warnings from a connection, subclass this with your - * own error-handler functor, and instantiate it for the connection. Destroying - * the handler un-registers it. - * - * A connection can have multiple error handlers at the same time. When the - * database connection emits an error or warning message, it passes the message - * to each error handler, starting with the most recently registered one and - * progressing towards the oldest one. However an error handler may also - * instruct the connection not to pass the message to further handlers by - * returning "false." - * - * @warning Strange things happen when a result object outlives its parent - * connection. If you register an error handler on a connection, then you must - * not access the result after destroying the connection. This applies even if - * you destroy the error handler first! - */ -class PQXX_LIBEXPORT errorhandler -{ -public: - explicit errorhandler(connection &); - virtual ~errorhandler(); - - /// Define in subclass: receive an error or warning message from the - /// database. - /** - * @return Whether the same error message should also be passed to the - * remaining, older errorhandlers. - */ - virtual bool operator()(char const msg[]) noexcept = 0; - - errorhandler() = delete; - errorhandler(errorhandler const &) = delete; - errorhandler &operator=(errorhandler const &) = delete; - -private: - connection *m_home; - - friend class internal::gate::errorhandler_connection; - void unregister() noexcept; -}; - - -/// An error handler that suppresses any previously registered error handlers. -class quiet_errorhandler : public errorhandler -{ -public: - /// Suppress error notices. - quiet_errorhandler(connection &conn) : errorhandler{conn} {} - - /// Revert to previous handling of error notices. - virtual bool operator()(char const[]) noexcept override { return false; } -}; - -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/except b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/except deleted file mode 100644 index e5dd508bf..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/except +++ /dev/null @@ -1,8 +0,0 @@ -/** libpqxx exception classes. - * - * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/except.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/except.hxx deleted file mode 100644 index 24f959437..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/except.hxx +++ /dev/null @@ -1,447 +0,0 @@ -/* Definition of libpqxx exception classes. - * - * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_EXCEPT -#define PQXX_H_EXCEPT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - - -namespace pqxx -{ -/** - * @addtogroup exception Exception classes - * - * These exception classes follow, roughly, the two-level hierarchy defined by - * the PostgreSQL SQLSTATE error codes (see Appendix A of the PostgreSQL - * documentation corresponding to your server version). This is not a complete - * mapping though. There are other differences as well, e.g. the error code - * for `statement_completion_unknown` has a separate status in libpqxx as - * @ref in_doubt_error, and `too_many_connections` is classified as a - * `broken_connection` rather than a subtype of `insufficient_resources`. - * - * @see http://www.postgresql.org/docs/9.4/interactive/errcodes-appendix.html - * - * @{ - */ - -/// Run-time failure encountered by libpqxx, similar to std::runtime_error. -struct PQXX_LIBEXPORT failure : std::runtime_error -{ - explicit failure(std::string const &); -}; - - -/// Exception class for lost or failed backend connection. -/** - * @warning When this happens on Unix-like systems, you may also get a SIGPIPE - * signal. That signal aborts the program by default, so if you wish to be - * able to continue after a connection breaks, be sure to disarm this signal. - * - * If you're working on a Unix-like system, see the manual page for - * `signal` (2) on how to deal with SIGPIPE. The easiest way to make this - * signal harmless is to make your program ignore it: - * - * ```cxx - * #include - * - * int main() - * { - * signal(SIGPIPE, SIG_IGN); - * // ... - * ``` - */ -struct PQXX_LIBEXPORT broken_connection : failure -{ - broken_connection(); - explicit broken_connection(std::string const &); -}; - - -/// The caller attempted to set a variable to null, which is not allowed. -struct PQXX_LIBEXPORT variable_set_to_null : failure -{ - variable_set_to_null(); - explicit variable_set_to_null(std::string const &); -}; - - -/// Exception class for failed queries. -/** Carries, in addition to a regular error message, a copy of the failed query - * and (if available) the SQLSTATE value accompanying the error. - */ -class PQXX_LIBEXPORT sql_error : public failure -{ - /// Query string. Empty if unknown. - std::string const m_query; - /// SQLSTATE string describing the error type, if known; or empty string. - std::string const m_sqlstate; - -public: - explicit sql_error( - std::string const &whatarg = "", std::string const &Q = "", - char const sqlstate[] = nullptr); - virtual ~sql_error() noexcept override; - - /// The query whose execution triggered the exception - [[nodiscard]] PQXX_PURE std::string const &query() const noexcept; - - /// SQLSTATE error code if known, or empty string otherwise. - [[nodiscard]] PQXX_PURE std::string const &sqlstate() const noexcept; -}; - - -/// "Help, I don't know whether transaction was committed successfully!" -/** Exception that might be thrown in rare cases where the connection to the - * database is lost while finishing a database transaction, and there's no way - * of telling whether it was actually executed by the backend. In this case - * the database is left in an indeterminate (but consistent) state, and only - * manual inspection will tell which is the case. - */ -struct PQXX_LIBEXPORT in_doubt_error : failure -{ - explicit in_doubt_error(std::string const &); -}; - - -/// The backend saw itself forced to roll back the ongoing transaction. -struct PQXX_LIBEXPORT transaction_rollback : sql_error -{ - explicit transaction_rollback( - std::string const &whatarg, std::string const &q = "", - char const sqlstate[] = nullptr); -}; - - -/// Transaction failed to serialize. Please retry it. -/** Can only happen at transaction isolation levels REPEATABLE READ and - * SERIALIZABLE. - * - * The current transaction cannot be committed without violating the guarantees - * made by its isolation level. This is the effect of a conflict with another - * ongoing transaction. The transaction may still succeed if you try to - * perform it again. - */ -struct PQXX_LIBEXPORT serialization_failure : transaction_rollback -{ - explicit serialization_failure( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// We can't tell whether our last statement succeeded. -struct PQXX_LIBEXPORT statement_completion_unknown : transaction_rollback -{ - explicit statement_completion_unknown( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// The ongoing transaction has deadlocked. Retrying it may help. -struct PQXX_LIBEXPORT deadlock_detected : transaction_rollback -{ - explicit deadlock_detected( - std::string const &whatarg, std::string const &q, - char const sqlstate[] = nullptr); -}; - - -/// Internal error in libpqxx library -struct PQXX_LIBEXPORT internal_error : std::logic_error -{ - explicit internal_error(std::string const &); -}; - - -/// Error in usage of libpqxx library, similar to std::logic_error -struct PQXX_LIBEXPORT usage_error : std::logic_error -{ - explicit usage_error(std::string const &); -}; - - -/// Invalid argument passed to libpqxx, similar to std::invalid_argument -struct PQXX_LIBEXPORT argument_error : std::invalid_argument -{ - explicit argument_error(std::string const &); -}; - - -/// Value conversion failed, e.g. when converting "Hello" to int. -struct PQXX_LIBEXPORT conversion_error : std::domain_error -{ - explicit conversion_error(std::string const &); -}; - - -/// Could not convert value to string: not enough buffer space. -struct PQXX_LIBEXPORT conversion_overrun : conversion_error -{ - explicit conversion_overrun(std::string const &); -}; - - -/// Something is out of range, similar to std::out_of_range -struct PQXX_LIBEXPORT range_error : std::out_of_range -{ - explicit range_error(std::string const &); -}; - - -/// Query returned an unexpected number of rows. -struct PQXX_LIBEXPORT unexpected_rows : public range_error -{ - explicit unexpected_rows(std::string const &msg) : range_error{msg} {} -}; - - -/// Database feature not supported in current setup. -struct PQXX_LIBEXPORT feature_not_supported : sql_error -{ - explicit feature_not_supported( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Error in data provided to SQL statement. -struct PQXX_LIBEXPORT data_exception : sql_error -{ - explicit data_exception( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT integrity_constraint_violation : sql_error -{ - explicit integrity_constraint_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT restrict_violation : integrity_constraint_violation -{ - explicit restrict_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT not_null_violation : integrity_constraint_violation -{ - explicit not_null_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT foreign_key_violation : integrity_constraint_violation -{ - explicit foreign_key_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT unique_violation : integrity_constraint_violation -{ - explicit unique_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT check_violation : integrity_constraint_violation -{ - explicit check_violation( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - integrity_constraint_violation{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_cursor_state : sql_error -{ - explicit invalid_cursor_state( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_sql_statement_name : sql_error -{ - explicit invalid_sql_statement_name( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT invalid_cursor_name : sql_error -{ - explicit invalid_cursor_name( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT syntax_error : sql_error -{ - /// Approximate position in string where error occurred, or -1 if unknown. - int const error_position; - - explicit syntax_error( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr, int pos = -1) : - sql_error{err, Q, sqlstate}, error_position{pos} - {} -}; - -struct PQXX_LIBEXPORT undefined_column : syntax_error -{ - explicit undefined_column( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT undefined_function : syntax_error -{ - explicit undefined_function( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT undefined_table : syntax_error -{ - explicit undefined_table( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - syntax_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT insufficient_privilege : sql_error -{ - explicit insufficient_privilege( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Resource shortage on the server -struct PQXX_LIBEXPORT insufficient_resources : sql_error -{ - explicit insufficient_resources( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT disk_full : insufficient_resources -{ - explicit disk_full( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - insufficient_resources{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT out_of_memory : insufficient_resources -{ - explicit out_of_memory( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - insufficient_resources{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT too_many_connections : broken_connection -{ - explicit too_many_connections(std::string const &err) : - broken_connection{err} - {} -}; - -/// PL/pgSQL error -/** Exceptions derived from this class are errors from PL/pgSQL procedures. - */ -struct PQXX_LIBEXPORT plpgsql_error : sql_error -{ - explicit plpgsql_error( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - sql_error{err, Q, sqlstate} - {} -}; - -/// Exception raised in PL/pgSQL procedure -struct PQXX_LIBEXPORT plpgsql_raise : plpgsql_error -{ - explicit plpgsql_raise( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT plpgsql_no_data_found : plpgsql_error -{ - explicit plpgsql_no_data_found( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT plpgsql_too_many_rows : plpgsql_error -{ - explicit plpgsql_too_many_rows( - std::string const &err, std::string const &Q = "", - char const sqlstate[] = nullptr) : - plpgsql_error{err, Q, sqlstate} - {} -}; - -struct PQXX_LIBEXPORT blob_already_exists : failure -{ - explicit blob_already_exists(std::string const &); -}; - -/** - * @} - */ -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/field b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/field deleted file mode 100644 index 37cb69e84..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/field +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::field class. - * - * pqxx::field refers to a field in a query result. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/field.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/field.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/field.hxx deleted file mode 100644 index b8b869fe4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/field.hxx +++ /dev/null @@ -1,542 +0,0 @@ -/* Definitions for the pqxx::field class. - * - * pqxx::field refers to a field in a query result. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_FIELD -#define PQXX_H_FIELD - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/array.hxx" -#include "pqxx/composite.hxx" -#include "pqxx/result.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/types.hxx" - -namespace pqxx -{ -/// Reference to a field in a result set. -/** A field represents one entry in a row. It represents an actual value - * in the result set, and can be converted to various types. - */ -class PQXX_LIBEXPORT field -{ -public: - using size_type = field_size_type; - - /// Constructor. Do not call this yourself; libpqxx will do it for you. - /** Create field as reference to a field in a result set. - * @param r Row that this field is part of. - * @param c Column number of this field. - */ - [[deprecated( - "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept; - - /// Constructor. Do not call this yourself; libpqxx will do it for you. - [[deprecated( - "Do not construct fields yourself. Get them from the " - "row.")]] field() noexcept = default; - - /** - * @name Comparison - */ - //@{ - // TODO: noexcept. Breaks ABI. - /// Byte-by-byte comparison of two fields (all nulls are considered equal) - /** @warning null handling is still open to discussion and change! - * - * Handling of null values differs from that in SQL where a comparison - * involving a null value yields null, so nulls are never considered equal - * to one another or even to themselves. - * - * Null handling also probably differs from the closest equivalent in C++, - * which is the NaN (Not-a-Number) value, a singularity comparable to - * SQL's null. This is because the builtin == operator demands that a == a. - * - * The usefulness of this operator is questionable. No interpretation - * whatsoever is imposed on the data; 0 and 0.0 are considered different, - * as are null vs. the empty string, or even different (but possibly - * equivalent and equally valid) encodings of the same Unicode character - * etc. - */ - [[nodiscard]] PQXX_PURE bool operator==(field const &) const; - - /// Byte-by-byte comparison (all nulls are considered equal) - /** @warning See operator==() for important information about this operator - */ - [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - /** - * @name Column information - */ - //@{ - /// Column name. - [[nodiscard]] PQXX_PURE char const *name() const &; - - /// Column type. - [[nodiscard]] oid PQXX_PURE type() const; - - /// What table did this column come from? - [[nodiscard]] PQXX_PURE oid table() const; - - /// Return row number. The first row is row 0, the second is row 1, etc. - PQXX_PURE constexpr row_size_type num() const noexcept { return col(); } - - /// What column number in its originating table did this column come from? - [[nodiscard]] PQXX_PURE row_size_type table_column() const; - //@} - - /** - * @name Content access - */ - //@{ - /// Read as `string_view`, or an empty one if null. - /** The result only remains usable while the data for the underlying - * @ref result exists. Once all `result` objects referring to that data have - * been destroyed, the `string_view` will no longer point to valid memory. - */ - [[nodiscard]] PQXX_PURE std::string_view view() const & - { - return std::string_view(c_str(), size()); - } - - /// Read as plain C string. - /** Since the field's data is stored internally in the form of a - * zero-terminated C string, this is the fastest way to read it. Use the - * to() or as() functions to convert the string to other types such as - * `int`, or to C++ strings. - * - * Do not use this for BYTEA values, or other binary values. To read those, - * convert the value to your desired type using `to()` or `as()`. For - * example: `f.as>()`. - */ - [[nodiscard]] PQXX_PURE char const *c_str() const &; - - /// Is this field's value null? - [[nodiscard]] PQXX_PURE bool is_null() const noexcept; - - /// Return number of bytes taken up by the field's value. - [[nodiscard]] PQXX_PURE size_type size() const noexcept; - - /// Read value into obj; or if null, leave obj untouched and return `false`. - /** This can be used with optional types (except pointers other than C-style - * strings). - */ - template - auto to(T &obj) const -> typename std::enable_if_t< - (not std::is_pointer::value or std::is_same::value), - bool> - { - if (is_null()) - { - return false; - } - else - { - auto const bytes{c_str()}; - from_string(bytes, obj); - return true; - } - } - - /// Read field as a composite value, write its components into `fields`. - /** @warning This is still experimental. It may change or be replaced. - * - * Returns whether the field was null. If it was, it will not touch the - * values in `fields`. - */ - template bool composite_to(T &...fields) const - { - if (is_null()) - { - return false; - } - else - { - parse_composite(m_home.m_encoding, view(), fields...); - return true; - } - } - - /// Read value into obj; or leave obj untouched and return `false` if null. - template bool operator>>(T &obj) const { return to(obj); } - - /// Read value into obj; or if null, use default value and return `false`. - /** This can be used with `std::optional`, as well as with standard smart - * pointer types, but not with raw pointers. If the conversion from a - * PostgreSQL string representation allocates a pointer (e.g. using `new`), - * then the object's later deallocation should be baked in as well, right - * from the point where the object is created. So if you want a pointer, use - * a smart pointer, not a raw pointer. - * - * There is one exception, of course: C-style strings. Those are just - * pointers to the field's internal text data. - */ - template - auto to(T &obj, T const &default_value) const -> typename std::enable_if_t< - (not std::is_pointer::value or std::is_same::value), - bool> - { - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = from_string(this->view()); - return not null; - } - - /// Return value as object of given type, or default value if null. - /** Note that unless the function is instantiated with an explicit template - * argument, the Default value's type also determines the result type. - */ - template T as(T const &default_value) const - { - if (is_null()) - return default_value; - else - return from_string(this->view()); - } - - /// Return value as object of given type, or throw exception if null. - /** Use as `as>()` or `as()` as - * an alternative to `get()`; this is disabled for use with raw pointers - * (other than C-strings) because storage for the value can't safely be - * allocated here - */ - template T as() const - { - if (is_null()) - { - if constexpr (not nullness::has_null) - internal::throw_null_conversion(type_name); - else - return nullness::null(); - } - else - { - return from_string(this->view()); - } - } - - /// Return value wrapped in some optional type (empty for nulls). - /** Use as `get()` as before to obtain previous behavior, or specify - * container type with `get()` - */ - template class O = std::optional> - constexpr O get() const - { - return as>(); - } - - // TODO: constexpr noexcept, once array_parser constructor gets those. - /// Parse the field as an SQL array. - /** Call the parser to retrieve values (and structure) from the array. - * - * Make sure the @ref result object stays alive until parsing is finished. If - * you keep the @ref row of `field` object alive, it will keep the @ref - * result object alive as well. - */ - array_parser as_array() const & - { - return array_parser{c_str(), m_home.m_encoding}; - } - //@} - - -protected: - constexpr result const &home() const noexcept { return m_home; } - constexpr result::size_type idx() const noexcept { return m_row; } - constexpr row_size_type col() const noexcept { return m_col; } - - // TODO: Create gates. - friend class pqxx::result; - friend class pqxx::row; - field( - result const &r, result_size_type row_num, row_size_type col_num) noexcept - : - m_col{col_num}, m_home{r}, m_row{row_num} - {} - - /** - * You'd expect this to be unsigned, but due to the way reverse iterators - * are related to regular iterators, it must be allowed to underflow to -1. - */ - row_size_type m_col; - -private: - result m_home; - result::size_type m_row; -}; - - -template<> inline bool field::to(std::string &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = std::string{view()}; - return not null; -} - - -template<> -inline bool field::to( - std::string &obj, std::string const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = std::string{view()}; - return not null; -} - - -/// Specialization: `to(char const *&)`. -/** The buffer has the same lifetime as the data in this result (i.e. of this - * result object, or the last remaining one copied from it etc.), so take care - * not to use it after the last result object referring to this query result is - * destroyed. - */ -template<> inline bool field::to(char const *&obj) const -{ - bool const null{is_null()}; - if (not null) - obj = c_str(); - return not null; -} - - -template<> inline bool field::to(std::string_view &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = view(); - return not null; -} - - -template<> -inline bool field::to( - std::string_view &obj, std::string_view const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = view(); - return not null; -} - - -template<> inline std::string_view field::as() const -{ - if (is_null()) - PQXX_UNLIKELY - internal::throw_null_conversion(type_name); - return view(); -} - - -template<> -inline std::string_view -field::as(std::string_view const &default_value) const -{ - return is_null() ? default_value : view(); -} - - -template<> inline bool field::to(zview &obj) const -{ - bool const null{is_null()}; - if (not null) - obj = zview{c_str(), size()}; - return not null; -} - - -template<> -inline bool field::to(zview &obj, zview const &default_value) const -{ - bool const null{is_null()}; - if (null) - obj = default_value; - else - obj = zview{c_str(), size()}; - return not null; -} - - -template<> inline zview field::as() const -{ - if (is_null()) - PQXX_UNLIKELY - internal::throw_null_conversion(type_name); - return zview{c_str(), size()}; -} - - -template<> inline zview field::as(zview const &default_value) const -{ - return is_null() ? default_value : zview{c_str(), size()}; -} - - -template> -class field_streambuf : public std::basic_streambuf -{ -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - using openmode = std::ios::openmode; - using seekdir = std::ios::seekdir; - - explicit field_streambuf(field const &f) : m_field{f} { initialize(); } - -protected: - virtual int sync() override { return traits_type::eof(); } - - virtual pos_type seekoff(off_type, seekdir, openmode) override - { - return traits_type::eof(); - } - virtual pos_type seekpos(pos_type, openmode) override - { - return traits_type::eof(); - } - virtual int_type overflow(int_type) override { return traits_type::eof(); } - virtual int_type underflow() override { return traits_type::eof(); } - -private: - field const &m_field; - - int_type initialize() - { - auto g{static_cast(const_cast(m_field.c_str()))}; - this->setg(g, g, g + std::size(m_field)); - return int_type(std::size(m_field)); - } -}; - - -/// Input stream that gets its data from a result field -/** Use this class exactly as you would any other istream to read data from a - * field. All formatting and streaming operations of `std::istream` are - * supported. What you'll typically want to use, however, is the fieldstream - * alias (which defines a @ref basic_fieldstream for `char`). This is similar - * to how e.g. `std::ifstream` relates to `std::basic_ifstream`. - * - * This class has only been tested for the char type (and its default traits). - */ -template> -class basic_fieldstream : public std::basic_istream -{ - using super = std::basic_istream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - - basic_fieldstream(field const &f) : super{nullptr}, m_buf{f} - { - super::init(&m_buf); - } - -private: - field_streambuf m_buf; -}; - -using fieldstream = basic_fieldstream; - -/// Write a result field to any type of stream -/** This can be convenient when writing a field to an output stream. More - * importantly, it lets you write a field to e.g. a `stringstream` which you - * can then use to read, format and convert the field in ways that to() does - * not support. - * - * Example: parse a field into a variable of the nonstandard - * "long long" type. - * - * ```cxx - * extern result R; - * long long L; - * stringstream S; - * - * // Write field's string into S - * S << R[0][0]; - * - * // Parse contents of S into L - * S >> L; - * ``` - */ -template -inline std::basic_ostream & -operator<<(std::basic_ostream &s, field const &value) -{ - s.write(value.c_str(), std::streamsize(std::size(value))); - return s; -} - - -/// Convert a field's value to type `T`. -/** Unlike the "regular" `from_string`, this knows how to deal with null - * values. - */ -template inline T from_string(field const &value) -{ - if (value.is_null()) - { - if constexpr (nullness::has_null) - return nullness::null(); - else - internal::throw_null_conversion(type_name); - } - else - { - return from_string(value.view()); - } -} - - -/// Convert a field's value to `nullptr_t`. -/** Yes, you read that right. This conversion does nothing useful. It always - * returns `nullptr`. - * - * Except... what if the field is not null? In that case, this throws - * @ref conversion_error. - */ -template<> -inline std::nullptr_t from_string(field const &value) -{ - if (not value.is_null()) - throw conversion_error{ - "Extracting non-null field into nullptr_t variable."}; - return nullptr; -} - - -/// Convert a field to a string. -template<> PQXX_LIBEXPORT std::string to_string(field const &value); -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/array-composite.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/array-composite.hxx deleted file mode 100644 index d2b6603e5..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/array-composite.hxx +++ /dev/null @@ -1,305 +0,0 @@ -#if !defined(PQXX_ARRAY_COMPOSITE_HXX) -# define PQXX_ARRAY_COMPOSITE_HXX - -# include - -# include "pqxx/strconv.hxx" - -namespace pqxx::internal -{ -// Find the end of a double-quoted string. -/** `input[pos]` must be the opening double quote. - * - * Returns the offset of the first position after the closing quote. - */ -inline std::size_t scan_double_quoted_string( - char const input[], std::size_t size, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - // XXX: find_char<'"', '\\'>(). - auto next{scan(input, size, pos)}; - bool at_quote{false}; - for (pos = next, next = scan(input, size, pos); pos < size; - pos = next, next = scan(input, size, pos)) - { - if (at_quote) - { - if (next - pos == 1 and input[pos] == '"') - { - // We just read a pair of double quotes. Carry on. - at_quote = false; - } - else - { - // We just read one double quote, and now we're at a character that's - // not a second double quote. Ergo, that last character was the - // closing double quote and this is the position right after it. - return pos; - } - } - else if (next - pos == 1) - { - switch (input[pos]) - { - case '\\': - // Backslash escape. Skip ahead by one more character. - pos = next; - next = scan(input, size, pos); - break; - - case '"': - // This is either the closing double quote, or the first of a pair of - // double quotes. - at_quote = true; - break; - } - } - else - { - // Multibyte character. Carry on. - } - } - if (not at_quote) - throw argument_error{ - "Missing closing double-quote: " + std::string{input}}; - return pos; -} - - -/// Un-quote and un-escape a double-quoted SQL string. -inline std::string parse_double_quoted_string( - char const input[], std::size_t end, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - std::string output; - // Maximum output size is same as the input size, minus the opening and - // closing quotes. Or in the extreme opposite case, the real number could be - // half that. Usually it'll be a pretty close estimate. - output.reserve(std::size_t(end - pos - 2)); - - for (auto here{scan(input, end, pos)}, next{scan(input, end, here)}; - here < end - 1; here = next, next = scan(input, end, here)) - { - // A backslash here is always an escape. So is a double-quote, since we're - // inside the double-quoted string. In either case, we can just ignore the - // escape character and use the next character. This is the one redeeming - // feature of SQL's escaping system. - if ((next - here == 1) and (input[here] == '\\' or input[here] == '"')) - { - // Skip escape. - here = next; - next = scan(input, end, here); - } - output.append(input + here, input + next); - } - return output; -} - - -/// Find the end of an unquoted string in an array or composite-type value. -/** Stops when it gets to the end of the input; or when it sees any of the - * characters in STOP which has not been escaped. - * - * For array values, STOP is a comma, a semicolon, or a closing brace. For - * a value of a composite type, STOP is a comma or a closing parenthesis. - */ -template -inline std::size_t scan_unquoted_string( - char const input[], std::size_t size, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - bool at_backslash{false}; - auto next{scan(input, size, pos)}; - while ((pos < size) and - ((next - pos) > 1 or at_backslash or ((input[pos] != STOP) and ...))) - { - pos = next; - next = scan(input, size, pos); - at_backslash = - ((not at_backslash) and ((next - pos) == 1) and (input[pos] == '\\')); - } - return pos; -} - - -/// Parse an unquoted array entry or cfield of a composite-type field. -inline std::string parse_unquoted_string( - char const input[], std::size_t end, std::size_t pos, - pqxx::internal::glyph_scanner_func *scan) -{ - std::string output; - bool at_backslash{false}; - output.reserve(end - pos); - for (auto next{scan(input, end, pos)}; pos < end; - pos = next, next = scan(input, end, pos)) - { - at_backslash = - ((not at_backslash) and ((next - pos) == 1) and (input[pos] == '\\')); - if (not at_backslash) - output.append(input + pos, next - pos); - } - return output; -} - - -/// Parse a field of a composite-type value. -/** `T` is the C++ type of the field we're parsing, and `index` is its - * zero-based number. - * - * Strip off the leading parenthesis or bracket yourself before parsing. - * However, this function will parse the lcosing parenthesis or bracket. - * - * After a successful parse, `pos` will point at `std::end(text)`. - * - * For the purposes of parsing, ranges and arrays count as compositve values, - * so this function supports parsing those. If you specifically need a closing - * parenthesis, check afterwards that `text` did not end in a bracket instead. - * - * @param index Index of the current field, zero-based. It will increment for - * the next field. - * @param input Full input text for the entire composite-type value. - * @param pos Starting position (in `input`) of the field that we're parsing. - * After parsing, this will point at the beginning of the next field if - * there is one, or one position past the last character otherwise. - * @param field Destination for the parsed value. - * @param scan Glyph scanning function for the relevant encoding type. - * @param last_field Number of the last field in the value (zero-based). When - * parsing the last field, this will equal `index`. - */ -template -inline void parse_composite_field( - std::size_t &index, std::string_view input, std::size_t &pos, T &field, - glyph_scanner_func *scan, std::size_t last_field) -{ - assert(index <= last_field); - auto next{scan(std::data(input), std::size(input), pos)}; - if ((next - pos) != 1) - throw conversion_error{"Non-ASCII character in composite-type syntax."}; - - // Expect a field. - switch (input[pos]) - { - case ',': - case ')': - case ']': - // The field is empty, i.e, null. - if constexpr (nullness::has_null) - field = nullness::null(); - else - throw conversion_error{ - "Can't read composite field " + to_string(index) + ": C++ type " + - type_name + " does not support nulls."}; - break; - - case '"': { - auto const stop{scan_double_quoted_string( - std::data(input), std::size(input), pos, scan)}; - auto const text{ - parse_double_quoted_string(std::data(input), stop, pos, scan)}; - field = from_string(text); - pos = stop; - } - break; - - default: { - auto const stop{scan_unquoted_string<',', ')', ']'>( - std::data(input), std::size(input), pos, scan)}; - auto const text{parse_unquoted_string(std::data(input), stop, pos, scan)}; - field = from_string(text); - pos = stop; - } - break; - } - - // Expect a comma or a closing parenthesis. - next = scan(std::data(input), std::size(input), pos); - - if ((next - pos) != 1) - throw conversion_error{ - "Unexpected non-ASCII character after composite field: " + - std::string{input}}; - - if (index < last_field) - { - if (input[pos] != ',') - throw conversion_error{ - "Found '" + std::string{input[pos]} + - "' in composite value where comma was expected: " + std::data(input)}; - } - else - { - if (input[pos] == ',') - throw conversion_error{ - "Composite value contained more fields than the expected " + - to_string(last_field) + ": " + std::data(input)}; - if (input[pos] != ')' and input[pos] != ']') - throw conversion_error{ - "Composite value has unexpected characters where closing parenthesis " - "was expected: " + - std::string{input}}; - if (next != std::size(input)) - throw conversion_error{ - "Composite value has unexpected text after closing parenthesis: " + - std::string{input}}; - } - - pos = next; - ++index; -} - - -/// Conservatively estimate buffer size needed for a composite field. -template -inline std::size_t size_composite_field_buffer(T const &field) -{ - if constexpr (is_unquoted_safe) - { - // Safe to copy, without quotes or escaping. Drop the terminating zero. - return size_buffer(field) - 1; - } - else - { - // + Opening quote. - // + Field budget. - // - Terminating zero. - // + Escaping for each byte in the field's string representation. - // - Escaping for terminating zero. - // + Closing quote. - return 1 + 2 * (size_buffer(field) - 1) + 1; - } -} - - -template -inline void write_composite_field(char *&pos, char *end, T const &field) -{ - if constexpr (is_unquoted_safe) - { - // No need for quoting or escaping. Convert it straight into its final - // place in the buffer, and "backspace" the trailing zero. - pos = string_traits::into_buf(pos, end, field) - 1; - } - else - { - // The field may need escaping, which means we need an intermediate buffer. - // To avoid allocating that at run time, we use the end of the buffer that - // we have. - auto const budget{size_buffer(field)}; - *pos++ = '"'; - - // Now escape buf into its final position. - for (char const c : string_traits::to_buf(end - budget, end, field)) - { - if ((c == '"') or (c == '\\')) - *pos++ = '\\'; - - *pos++ = c; - } - - *pos++ = '"'; - } - - *pos++ = ','; -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/callgate.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/callgate.hxx deleted file mode 100644 index 42f7703e3..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/callgate.hxx +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef PQXX_H_CALLGATE -#define PQXX_H_CALLGATE - -/* -Here's what a typical gate class definition looks like: - -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE @gateclass@ : callgate<@host@> -{ - friend class @client@; - - @gateclass@(reference x) : super(x) {} - - // Methods here. Use home() to access the host-class object. -}; -} // namespace pqxx::internal::gate -*/ - -namespace pqxx::internal -{ -/// Base class for call gates. -/** - * A call gate defines a limited, private interface on the host class that - * specified client classes can access. - * - * The metaphor works as follows: the gate stands in front of a "home," which - * is really a class, and only lets specific friends in. - * - * To implement a call gate that gives client C access to host H, - * * derive a gate class from callgate; - * * make the gate class a friend of H; - * * make C a friend of the gate class; and - * * implement "stuff C can do with H" as private members in the gate class. - * - * This special kind of "gated" friendship gives C private access to H, but - * only through an expressly limited interface. The gate class can access its - * host object as home(). - * - * Keep gate classes entirely stateless. They should be ultra-lightweight - * wrappers for their host classes, and be optimized away as much as possible - * by the compiler. Once you start adding state, you're on a slippery slope - * away from the pure, clean, limited interface pattern that gate classes are - * meant to implement. - * - * Ideally, all member functions of the gate class should be one-liners passing - * calls straight on to the host class. It can be useful however to break this - * rule temporarily during inter-class refactoring. - */ -template class PQXX_PRIVATE callgate -{ -protected: - /// This class, to keep constructors easy. - using super = callgate; - /// A reference to the host class. Helps keep constructors easy. - using reference = HOME &; - - callgate(reference x) : m_home(x) {} - - /// The home object. The gate class has full "private" access. - reference home() const noexcept { return m_home; } - -private: - reference m_home; -}; -} // namespace pqxx::internal - -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/concat.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/concat.hxx deleted file mode 100644 index cd28bde7c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/concat.hxx +++ /dev/null @@ -1,45 +0,0 @@ -#if !defined(PQXX_CONCAT_HXX) -# define PQXX_CONCAT_HXX - -# include -# include - -# include "pqxx/strconv.hxx" - -namespace pqxx::internal -{ -/// Convert item to a string, write it into [here, end). -template -void render_item(TYPE const &item, char *&here, char *end) -{ - here = string_traits::into_buf(here, end, item) - 1; -} - - -// C++20: Support non-random_access_range ranges. -/// Efficiently combine a bunch of items into one big string. -/** Use this as an optimised version of string concatentation. It takes just - * about any type; it will represent each item as a string according to its - * @ref string_traits. - * - * This is a simpler, more specialised version of @ref separated_list for a - * statically known series of items, possibly of different types. - */ -template -[[nodiscard]] inline std::string concat(TYPE... item) -{ - std::string buf; - // Size to accommodate string representations of all inputs, minus their - // terminating zero bytes. - buf.resize(size_buffer(item...)); - - char *const data{buf.data()}; - char *here = data; - char *end = data + std::size(buf); - (render_item(item, here, end), ...); - - buf.resize(static_cast(here - data)); - return buf; -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/conversions.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/conversions.hxx deleted file mode 100644 index 1df4fdead..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/conversions.hxx +++ /dev/null @@ -1,1188 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#if defined(PQXX_HAVE_SPAN) && __has_include() -# include -#endif - -#include -#include -#include - -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" - - -/* Internal helpers for string conversion, and conversion implementations. - * - * Do not include this header directly. The libpqxx headers do it for you. - */ -namespace pqxx::internal -{ -/// Convert a number in [0, 9] to its ASCII digit. -inline constexpr char number_to_digit(int i) noexcept -{ - return static_cast(i + '0'); -} - - -/// Compute numeric value of given textual digit (assuming that it is a digit). -constexpr int digit_to_number(char c) noexcept -{ - return c - '0'; -} - - -/// Summarize buffer overrun. -/** Don't worry about the exact parameter types: the sizes will be reasonably - * small, and nonnegative. - */ -std::string PQXX_LIBEXPORT -state_buffer_overrun(int have_bytes, int need_bytes); - - -template -inline std::string state_buffer_overrun(HAVE have_bytes, NEED need_bytes) -{ - return state_buffer_overrun( - static_cast(have_bytes), static_cast(need_bytes)); -} - - -/// Throw exception for attempt to convert null to given type. -[[noreturn]] PQXX_LIBEXPORT void -throw_null_conversion(std::string const &type); - - -/// Deliberately nonfunctional conversion traits for `char` types. -/** There are no string conversions for `char` and its signed and unsigned - * variants. Such a conversion would be dangerously ambiguous: should we treat - * it as text, or as a small integer? It'd be an open invitation for bugs. - * - * But the error message when you get this wrong is very cryptic. So, we - * derive dummy @ref string_traits implementations from this dummy type, and - * ensure that the compiler disallows their use. The compiler error message - * will at least contain a hint of the root of the problem. - */ -template struct disallowed_ambiguous_char_conversion -{ - static char *into_buf(char *, char *, CHAR_TYPE) = delete; - static constexpr zview - to_buf(char *, char *, CHAR_TYPE const &) noexcept = delete; - - static constexpr std::size_t - size_buffer(CHAR_TYPE const &) noexcept = delete; - static CHAR_TYPE from_string(std::string_view) = delete; -}; - - -template PQXX_LIBEXPORT extern std::string to_string_float(T); - - -/// Generic implementation for into_buf, on top of to_buf. -template -inline char *generic_into_buf(char *begin, char *end, T const &value) -{ - zview const text{string_traits::to_buf(begin, end, value)}; - auto const space{end - begin}; - // Include the trailing zero. - auto const len = std::size(text) + 1; - if (internal::cmp_greater(len, space)) - throw conversion_overrun{ - "Not enough buffer space to insert " + type_name + ". " + - state_buffer_overrun(space, len)}; - std::memmove(begin, text.data(), len); - return begin + len; -} - - -/// String traits for builtin integral types (though not bool). -template struct integral_traits -{ - static PQXX_LIBEXPORT T from_string(std::string_view text); - static PQXX_LIBEXPORT zview to_buf(char *begin, char *end, T const &value); - static PQXX_LIBEXPORT char *into_buf(char *begin, char *end, T const &value); - - static constexpr std::size_t size_buffer(T const &) noexcept - { - /** Includes a sign if needed; the number of base-10 digits which the type - * can reliably represent; the one extra base-10 digit which the type can - * only partially represent; and the terminating zero. - */ - return std::is_signed_v + std::numeric_limits::digits10 + 1 + 1; - } -}; - - -/// String traits for builtin floating-point types. -template struct float_traits -{ - static PQXX_LIBEXPORT T from_string(std::string_view text); - static PQXX_LIBEXPORT zview to_buf(char *begin, char *end, T const &value); - static PQXX_LIBEXPORT char *into_buf(char *begin, char *end, T const &value); - - // Return a nonnegative integral value's number of decimal digits. - static constexpr std::size_t digits10(std::size_t value) noexcept - { - if (value < 10) - return 1; - else - return 1 + digits10(value / 10); - } - - static constexpr std::size_t size_buffer(T const &) noexcept - { - using lims = std::numeric_limits; - // See #328 for a detailed discussion on the maximum number of digits. - // - // In a nutshell: for the big cases, the scientific notation is always - // the shortest one, and therefore the one that to_chars will pick. - // - // So... How long can the scientific notation get? 1 (for sign) + 1 (for - // decimal point) + 1 (for 'e') + 1 (for exponent sign) + max_digits10 + - // max number of digits in the exponent + 1 (terminating zero). - // - // What's the max number of digits in the exponent? It's the max number of - // digits out of the most negative exponent and the most positive one. - // - // The longest positive exponent is easy: 1 + ceil(log10(max_exponent10)). - // (The extra 1 is because 10^n takes up 1 + n digits, not n.) - // - // The longest negative exponent is a bit harder: min_exponent10 gives us - // the smallest power of 10 which a normalised version of T can represent. - // But the smallest denormalised power of 10 that T can represent is - // another max_digits10 powers of 10 below that. - // needs a minus sign. - // - // All this stuff messes with my head a bit because it's on the order of - // log10(log10(n)). It's easy to get the number of logs wrong. - auto const max_pos_exp{digits10(lims::max_exponent10)}; - // Really want std::abs(lims::min_exponent10), but MSVC 2017 apparently has - // problems with std::abs. So we use -lims::min_exponent10 instead. - auto const max_neg_exp{ - digits10(lims::max_digits10 - lims::min_exponent10)}; - return 1 + // Sign. - 1 + // Decimal point. - std::numeric_limits::max_digits10 + // Mantissa digits. - 1 + // Exponent "e". - 1 + // Exponent sign. - // Spell this weirdly to stop Windows compilers from reading this as - // a call to their "max" macro when NOMINMAX is not defined. - (std::max)(max_pos_exp, max_neg_exp) + // Exponent digits. - 1; // Terminating zero. - } -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// The built-in arithmetic types do not have inherent null values. -template -struct nullness>> : no_null -{}; - - -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits - : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits - : internal::integral_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; -template<> -struct string_traits : internal::float_traits -{}; -template<> inline constexpr bool is_unquoted_safe{true}; - - -template<> struct string_traits -{ - static PQXX_LIBEXPORT bool from_string(std::string_view text); - - static constexpr zview to_buf(char *, char *, bool const &value) noexcept - { - return value ? "true"_zv : "false"_zv; - } - - static char *into_buf(char *begin, char *end, bool const &value) - { - return pqxx::internal::generic_into_buf(begin, end, value); - } - - static constexpr std::size_t size_buffer(bool const &) noexcept { return 6; } -}; - - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - -/// We don't support conversion to/from `char` types. -/** Why are these disallowed? Because they are ambiguous. It's not inherently - * clear whether we should treat values of these types as text or as small - * integers. Either choice would lead to bugs. - */ -template<> -struct string_traits - : internal::disallowed_ambiguous_char_conversion -{}; - - -template<> inline constexpr bool is_unquoted_safe{true}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - /// Technically, you could have an optional of an always-null type. - static constexpr bool always_null = nullness::always_null; - static constexpr bool is_null(std::optional const &v) noexcept - { - return ((not v.has_value()) or pqxx::is_null(*v)); - } - static constexpr std::optional null() { return {}; } -}; - - -template -inline constexpr format param_format(std::optional const &value) -{ - return param_format(*value); -} - - -template struct string_traits> -{ - static char *into_buf(char *begin, char *end, std::optional const &value) - { - return string_traits::into_buf(begin, end, *value); - } - - static zview to_buf(char *begin, char *end, std::optional const &value) - { - if (value.has_value()) - return string_traits::to_buf(begin, end, *value); - else - return {}; - } - - static std::optional from_string(std::string_view text) - { - return std::optional{ - std::in_place, string_traits::from_string(text)}; - } - - static std::size_t size_buffer(std::optional const &value) noexcept - { - return pqxx::size_buffer(value.value()); - } -}; - - -template -inline constexpr bool is_unquoted_safe>{is_unquoted_safe}; - - -template struct nullness> -{ - static constexpr bool has_null = (nullness::has_null or ...); - static constexpr bool always_null = (nullness::always_null and ...); - static constexpr bool is_null(std::variant const &value) noexcept - { - return std::visit( - [](auto const &i) noexcept { - return nullness>::is_null(i); - }, - value); - } - - // We don't support `null()` for `std::variant`. - /** It would be technically possible to have a `null` in the case where just - * one of the types has a null, but it gets complicated and arbitrary. - */ - static constexpr std::variant null() = delete; -}; - - -template struct string_traits> -{ - static char * - into_buf(char *begin, char *end, std::variant const &value) - { - return std::visit( - [begin, end](auto const &i) { - return string_traits>::into_buf(begin, end, i); - }, - value); - } - static zview to_buf(char *begin, char *end, std::variant const &value) - { - return std::visit( - [begin, end](auto const &i) { - return string_traits>::to_buf(begin, end, i); - }, - value); - } - static std::size_t size_buffer(std::variant const &value) noexcept - { - return std::visit( - [](auto const &i) noexcept { return pqxx::size_buffer(i); }, value); - } - - /** There's no from_string for std::variant. We could have one with a rule - * like "pick the first type which fits the value," but we'd have to look - * into how natural that API feels to users. - */ - static std::variant from_string(std::string_view) = delete; -}; - - -template -inline constexpr format param_format(std::variant const &value) -{ - return std::visit([](auto &v) { return param_format(v); }, value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - (is_unquoted_safe and ...)}; - - -template inline T from_string(std::stringstream const &text) -{ - return from_string(text.str()); -} - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::nullptr_t) = delete; - - static constexpr zview - to_buf(char *, char *, std::nullptr_t const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::nullptr_t = nullptr) noexcept - { - return 0; - } - static std::nullptr_t from_string(std::string_view) = delete; -}; - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::nullopt_t) = delete; - - static constexpr zview - to_buf(char *, char *, std::nullopt_t const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::nullopt_t) noexcept - { - return 0; - } - static std::nullopt_t from_string(std::string_view) = delete; -}; - - -template<> struct string_traits -{ - static char *into_buf(char *, char *, std::monostate) = delete; - - static constexpr zview - to_buf(char *, char *, std::monostate const &) noexcept - { - return {}; - } - - static constexpr std::size_t size_buffer(std::monostate) noexcept - { - return 0; - } - static std::monostate from_string(std::string_view) = delete; -}; - - -template<> inline constexpr bool is_unquoted_safe{true}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(char const *t) noexcept - { - return t == nullptr; - } - static constexpr char const *null() noexcept { return nullptr; } -}; - - -/// String traits for C-style string ("pointer to char const"). -template<> struct string_traits -{ - static char const *from_string(std::string_view text) { return text.data(); } - - static zview to_buf(char *begin, char *end, char const *const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, char const *const &value) - { - auto const space{end - begin}; - // Count the trailing zero, even though std::strlen() and friends don't. - auto const len{std::strlen(value) + 1}; - if (space < ptrdiff_t(len)) - throw conversion_overrun{ - "Could not copy string: buffer too small. " + - pqxx::internal::state_buffer_overrun(space, len)}; - std::memmove(begin, value, len); - return begin + len; - } - - static std::size_t size_buffer(char const *const &value) noexcept - { - return std::strlen(value) + 1; - } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(char const *t) noexcept - { - return t == nullptr; - } - static constexpr char const *null() { return nullptr; } -}; - - -/// String traits for non-const C-style string ("pointer to char"). -template<> struct string_traits -{ - static char *into_buf(char *begin, char *end, char *const &value) - { - return string_traits::into_buf(begin, end, value); - } - static zview to_buf(char *begin, char *end, char *const &value) - { - return string_traits::to_buf(begin, end, value); - } - static std::size_t size_buffer(char *const &value) noexcept - { - return string_traits::size_buffer(value); - } - - /// Don't allow conversion to this type since it breaks const-safety. - static char *from_string(std::string_view) = delete; -}; - - -template struct nullness : no_null -{}; - - -/// String traits for C-style string constant ("array of char"). -/** @warning This assumes that every array-of-char is a C-style string literal. - * So, it must include a trailing zero. and it must have static duration. - */ -template struct string_traits -{ - static constexpr zview - to_buf(char *, char *, char const (&value)[N]) noexcept - { - return zview{value, N - 1}; - } - - static char *into_buf(char *begin, char *end, char const (&value)[N]) - { - if (internal::cmp_less(end - begin, size_buffer(value))) - throw conversion_overrun{ - "Could not convert char[] to string: too long for buffer."}; - std::memcpy(begin, value, N); - return begin + N; - } - static constexpr std::size_t size_buffer(char const (&)[N]) noexcept - { - return N; - } - - /// Don't allow conversion to this type. - static void from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -template<> struct string_traits -{ - static std::string from_string(std::string_view text) - { - return std::string{text}; - } - - static char *into_buf(char *begin, char *end, std::string const &value) - { - if (internal::cmp_greater_equal(std::size(value), end - begin)) - throw conversion_overrun{ - "Could not convert string to string: too long for buffer."}; - // Include the trailing zero. - value.copy(begin, std::size(value)); - begin[std::size(value)] = '\0'; - return begin + std::size(value) + 1; - } - - static zview to_buf(char *begin, char *end, std::string const &value) - { - return generic_to_buf(begin, end, value); - } - - static std::size_t size_buffer(std::string const &value) noexcept - { - return std::size(value) + 1; - } -}; - - -/// There's no real null for `std::string_view`. -/** I'm not sure how clear-cut this is: a `string_view` may have a null - * data pointer, which is analogous to a null `char` pointer. - */ -template<> struct nullness : no_null -{}; - - -/// String traits for `string_view`. -template<> struct string_traits -{ - static constexpr std::size_t - size_buffer(std::string_view const &value) noexcept - { - return std::size(value) + 1; - } - - static char *into_buf(char *begin, char *end, std::string_view const &value) - { - if (internal::cmp_greater_equal(std::size(value), end - begin)) - throw conversion_overrun{ - "Could not store string_view: too long for buffer."}; - value.copy(begin, std::size(value)); - begin[std::size(value)] = '\0'; - return begin + std::size(value) + 1; - } - - /// Don't convert to this type; it has nowhere to store its contents. - static std::string_view from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -/// String traits for `zview`. -template<> struct string_traits -{ - static constexpr std::size_t - size_buffer(std::string_view const &value) noexcept - { - return std::size(value) + 1; - } - - static char *into_buf(char *begin, char *end, zview const &value) - { - auto const size{std::size(value)}; - if (internal::cmp_less_equal(end - begin, std::size(value))) - throw conversion_overrun{"Not enough buffer space to store this zview."}; - value.copy(begin, size); - begin[size] = '\0'; - return begin + size + 1; - } - - static std::string_view to_buf(char *begin, char *end, zview const &value) - { - return {into_buf(begin, end, value), std::size(value)}; - } - - /// Don't convert to this type; it has nowhere to store its contents. - static zview from_string(std::string_view) = delete; -}; - - -template<> struct nullness : no_null -{}; - - -template<> struct string_traits -{ - static std::size_t size_buffer(std::stringstream const &) = delete; - - static std::stringstream from_string(std::string_view text) - { - std::stringstream stream; - stream.write(text.data(), std::streamsize(std::size(text))); - return stream; - } - - static char *into_buf(char *, char *, std::stringstream const &) = delete; - static std::string_view - to_buf(char *, char *, std::stringstream const &) = delete; -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::nullptr_t const &) noexcept - { - return true; - } - static constexpr std::nullptr_t null() noexcept { return nullptr; } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::nullopt_t const &) noexcept - { - return true; - } - static constexpr std::nullopt_t null() noexcept { return std::nullopt; } -}; - - -template<> struct nullness -{ - static constexpr bool has_null = true; - static constexpr bool always_null = true; - static constexpr bool is_null(std::monostate const &) noexcept - { - return true; - } - static constexpr std::monostate null() noexcept { return {}; } -}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(std::unique_ptr const &t) noexcept - { - return not t or pqxx::is_null(*t); - } - static constexpr std::unique_ptr null() { return {}; } -}; - - -template -struct string_traits> -{ - static std::unique_ptr from_string(std::string_view text) - { - return std::make_unique(string_traits::from_string(text)); - } - - static char * - into_buf(char *begin, char *end, std::unique_ptr const &value) - { - return string_traits::into_buf(begin, end, *value); - } - - static zview - to_buf(char *begin, char *end, std::unique_ptr const &value) - { - if (value) - return string_traits::to_buf(begin, end, *value); - else - return {}; - } - - static std::size_t - size_buffer(std::unique_ptr const &value) noexcept - { - return pqxx::size_buffer(*value.get()); - } -}; - - -template -inline format param_format(std::unique_ptr const &value) -{ - return param_format(*value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - is_unquoted_safe}; - - -template struct nullness> -{ - static constexpr bool has_null = true; - static constexpr bool always_null = false; - static constexpr bool is_null(std::shared_ptr const &t) noexcept - { - return not t or pqxx::is_null(*t); - } - static constexpr std::shared_ptr null() { return {}; } -}; - - -template struct string_traits> -{ - static std::shared_ptr from_string(std::string_view text) - { - return std::make_shared(string_traits::from_string(text)); - } - - static zview to_buf(char *begin, char *end, std::shared_ptr const &value) - { - return string_traits::to_buf(begin, end, *value); - } - static char * - into_buf(char *begin, char *end, std::shared_ptr const &value) - { - return string_traits::into_buf(begin, end, *value); - } - static std::size_t size_buffer(std::shared_ptr const &value) noexcept - { - return pqxx::size_buffer(*value); - } -}; - - -template format param_format(std::shared_ptr const &value) -{ - return param_format(*value); -} - - -template -inline constexpr bool is_unquoted_safe>{ - is_unquoted_safe}; - - -template<> -struct nullness> - : no_null> -{}; - - -#if defined(PQXX_HAVE_CONCEPTS) -template struct nullness : no_null -{}; - - -template inline constexpr format param_format(DATA const &) -{ - return format::binary; -} - - -template struct string_traits -{ - static std::size_t size_buffer(DATA const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf(char *begin, char *end, DATA const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, DATA const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - static DATA from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::basic_string buf; - buf.resize(size); - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.data())); - return buf; - } -}; -#endif // PQXX_HAVE_CONCEPTS - - -template<> struct string_traits> -{ - static std::size_t - size_buffer(std::basic_string const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview - to_buf(char *begin, char *end, std::basic_string const &value) - { - return generic_to_buf(begin, end, value); - } - - static char * - into_buf(char *begin, char *end, std::basic_string const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - static std::basic_string from_string(std::string_view text) - { - auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; - std::basic_string buf; - buf.resize(size); - pqxx::internal::unesc_bin(text, reinterpret_cast(buf.data())); - return buf; - } -}; - - -template<> -inline constexpr format param_format(std::basic_string const &) -{ - return format::binary; -} - - -template<> -struct nullness> - : no_null> -{}; - - -template<> struct string_traits> -{ - static std::size_t - size_buffer(std::basic_string_view const &value) noexcept - { - return internal::size_esc_bin(std::size(value)); - } - - static zview to_buf( - char *begin, char *end, std::basic_string_view const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf( - char *begin, char *end, std::basic_string_view const &value) - { - auto const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to escape binary data."}; - internal::esc_bin(value, begin); - return begin + budget; - } - - // There's no from_string, because there's nobody to hold the data. -}; - -template<> -inline constexpr format param_format(std::basic_string_view const &) -{ - return format::binary; -} -} // namespace pqxx - - -namespace pqxx::internal -{ -/// String traits for SQL arrays. -template struct array_string_traits -{ -private: - using elt_type = strip_t>; - using elt_traits = string_traits; - static constexpr zview s_null{"NULL"}; - -public: - static zview to_buf(char *begin, char *end, Container const &value) - { - return generic_to_buf(begin, end, value); - } - - static char *into_buf(char *begin, char *end, Container const &value) - { - std::size_t const budget{size_buffer(value)}; - if (internal::cmp_less(end - begin, budget)) - throw conversion_overrun{ - "Not enough buffer space to convert array to string."}; - - char *here = begin; - *here++ = '{'; - - bool nonempty{false}; - for (auto const &elt : value) - { - if (is_null(elt)) - { - s_null.copy(here, std::size(s_null)); - here += std::size(s_null); - } - else if constexpr (is_sql_array) - { - // Render nested array in-place. Then erase the trailing zero. - here = elt_traits::into_buf(here, end, elt) - 1; - } - else if constexpr (is_unquoted_safe) - { - // No need to quote or escape. Just convert the value straight into - // its place in the array, and "backspace" the trailing zero. - here = elt_traits::into_buf(here, end, elt) - 1; - } - else - { - *here++ = '"'; - - // Use the tail end of the destination buffer as an intermediate - // buffer. - auto const elt_budget{pqxx::size_buffer(elt)}; - for (char const c : elt_traits::to_buf(end - elt_budget, end, elt)) - { - if (c == '\\' or c == '"') - *here++ = '\\'; - *here++ = c; - } - *here++ = '"'; - } - *here++ = array_separator; - nonempty = true; - } - - // Erase that last comma, if present. - if (nonempty) - here--; - - *here++ = '}'; - *here++ = '\0'; - - return here; - } - - static std::size_t size_buffer(Container const &value) noexcept - { - if constexpr (is_unquoted_safe) - return 3 + std::accumulate( - std::begin(value), std::end(value), std::size_t{}, - [](std::size_t acc, elt_type const &elt) { - return acc + - (pqxx::is_null(elt) ? - std::size(s_null) : - elt_traits::size_buffer(elt)) - - 1; - }); - else - return 3 + std::accumulate( - std::begin(value), std::end(value), std::size_t{}, - [](std::size_t acc, elt_type const &elt) { - // Opening and closing quotes, plus worst-case escaping, - // but don't count the trailing zeroes. - std::size_t const elt_size{ - pqxx::is_null(elt) ? std::size(s_null) : - elt_traits::size_buffer(elt) - 1}; - return acc + 2 * elt_size + 2; - }); - } - - // We don't yet support parsing of array types using from_string. Doing so - // would require a reference to the connection. -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -template -struct nullness> : no_null> -{}; - - -template -struct string_traits> - : internal::array_string_traits> -{}; - - -/// We don't know how to pass array params in binary format, so pass as text. -template -inline constexpr format param_format(std::vector const &) -{ - return format::text; -} - - -/// A `std::vector` is a binary string. Other vectors are not. -template -inline constexpr format param_format(std::vector const &) -{ - return format::binary; -} - - -template inline constexpr bool is_sql_array>{true}; - - -template -struct nullness> : no_null> -{}; - - -template -struct string_traits> - : internal::array_string_traits> -{}; - - -/// We don't know how to pass array params in binary format, so pass as text. -template -inline constexpr format param_format(std::array const &) -{ - return format::text; -} - - -/// An array of `std::byte` is a binary string. -template -inline constexpr format param_format(std::array const &) -{ - return format::binary; -} - - -template -inline constexpr bool is_sql_array>{true}; -} // namespace pqxx - - -namespace pqxx -{ -template inline std::string to_string(T const &value) -{ - if (is_null(value)) - throw conversion_error{ - "Attempt to convert null " + type_name + " to a string."}; - - std::string buf; - // We can't just reserve() space; modifying the terminating zero leads to - // undefined behaviour. - buf.resize(size_buffer(value)); - auto const data{buf.data()}; - auto const end{ - string_traits::into_buf(data, data + std::size(buf), value)}; - buf.resize(static_cast(end - data - 1)); - return buf; -} - - -template<> inline std::string to_string(float const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(double const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(long double const &value) -{ - return internal::to_string_float(value); -} -template<> inline std::string to_string(std::stringstream const &value) -{ - return value.str(); -} - - -template inline void into_string(T const &value, std::string &out) -{ - if (is_null(value)) - throw conversion_error{ - "Attempt to convert null " + type_name + " to a string."}; - - // We can't just reserve() data; modifying the terminating zero leads to - // undefined behaviour. - out.resize(size_buffer(value) + 1); - auto const data{out.data()}; - auto const end{ - string_traits::into_buf(data, data + std::size(out), value)}; - out.resize(static_cast(end - data - 1)); -} -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/encoding_group.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/encoding_group.hxx deleted file mode 100644 index e17736e5b..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/encoding_group.hxx +++ /dev/null @@ -1,60 +0,0 @@ -/** Enum type for supporting encodings in libpqxx - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ENCODING_GROUP -#define PQXX_H_ENCODING_GROUP - -#include - -namespace pqxx::internal -{ -// Types of encodings supported by PostgreSQL, see -// https://www.postgresql.org/docs/current/static/multibyte.html#CHARSET-TABLE -enum class encoding_group -{ - // Handles all single-byte fixed-width encodings - MONOBYTE, - - // Multibyte encodings. - // Many of these can embed ASCII-like bytes inside multibyte characters, - // notably Big5, SJIS, SHIFT_JIS_2004, GP18030, GBK, JOHAB, UHC. - BIG5, - EUC_CN, - // TODO: Merge EUC_JP and EUC_JIS_2004? - EUC_JP, - EUC_JIS_2004, - EUC_KR, - EUC_TW, - GB18030, - GBK, - JOHAB, - MULE_INTERNAL, - // TODO: Merge SJIS and SHIFT_JIS_2004? - SJIS, - SHIFT_JIS_2004, - UHC, - UTF8, -}; - - -// TODO:: Can we just use string_view now? -/// Function type: "find the end of the current glyph." -/** This type of function takes a text buffer, and a location in that buffer, - * and returns the location one byte past the end of the current glyph. - * - * The start offset marks the beginning of the current glyph. It must fall - * within the buffer. - * - * There are multiple different glyph scanner implementations, for different - * kinds of encodings. - */ -using glyph_scanner_func = - std::size_t(char const buffer[], std::size_t buffer_len, std::size_t start); -} // namespace pqxx::internal - -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/encodings.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/encodings.hxx deleted file mode 100644 index ba7fecc70..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/encodings.hxx +++ /dev/null @@ -1,90 +0,0 @@ -/** Internal string encodings support for libpqxx - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ENCODINGS -#define PQXX_H_ENCODINGS - -#include "pqxx/internal/encoding_group.hxx" - -#include -#include - - -namespace pqxx::internal -{ -char const *name_encoding(int encoding_id); - -/// Convert libpq encoding enum or encoding name to its libpqxx group. -encoding_group enc_group(int /* libpq encoding ID */); -encoding_group enc_group(std::string_view); - - -/// Look up the glyph scanner function for a given encoding group. -/** To identify the glyph boundaries in a buffer, call this to obtain the - * scanner function appropriate for the buffer's encoding. Then, repeatedly - * call the scanner function to find the glyphs. - */ -PQXX_LIBEXPORT glyph_scanner_func *get_glyph_scanner(encoding_group); - - -// TODO: For ASCII search, treat UTF8/EUC_*/MULE_INTERNAL as MONOBYTE. - -/// Find any of the ASCII characters `NEEDLE` in `haystack`. -/** Scans through `haystack` until it finds a single-byte character that - * matches any value in `NEEDLE`. - * - * If it finds one, returns its offset. If not, returns the end of the - * haystack. - */ -template -inline std::size_t find_char( - glyph_scanner_func *scanner, std::string_view haystack, - std::size_t here = 0u) -{ - auto const sz{std::size(haystack)}; - auto const data{std::data(haystack)}; - while (here < sz) - { - auto next{scanner(data, sz, here)}; - // (For some reason gcc had a problem with a right-fold here. But clang - // was fine.) - if ((... or (data[here] == NEEDLE))) - { - // Also check against a multibyte character starting with a bytes which - // just happens to match one of the ASCII bytes we're looking for. It'd - // be cleaner to check that first, but either works. So, let's apply the - // most selective filter first and skip this check in almost all cases. - if (next == here + 1) - return here; - } - - // Nope, no hit. Move on. - here = next; - } - return sz; -} - - -/// Iterate over the glyphs in a buffer. -/** Scans the glyphs in the buffer, and for each, passes its begin and its - * one-past-end pointers to `callback`. - */ -template -inline void for_glyphs( - encoding_group enc, CALLABLE callback, char const buffer[], - std::size_t buffer_len, std::size_t start = 0) -{ - auto const scan{get_glyph_scanner(enc)}; - for (std::size_t here = start, next; here < buffer_len; here = next) - { - next = scan(buffer, buffer_len, here); - callback(buffer + here, buffer + next); - } -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-errorhandler.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-errorhandler.hxx deleted file mode 100644 index ffc12a6cf..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-errorhandler.hxx +++ /dev/null @@ -1,26 +0,0 @@ -#include - -namespace pqxx -{ -class connection; -class errorhandler; -} // namespace pqxx - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_errorhandler : callgate -{ - friend class pqxx::errorhandler; - - connection_errorhandler(reference x) : super(x) {} - - void register_errorhandler(errorhandler *h) - { - home().register_errorhandler(h); - } - void unregister_errorhandler(errorhandler *h) - { - home().unregister_errorhandler(h); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-largeobject.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-largeobject.hxx deleted file mode 100644 index 49feaf9e6..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-largeobject.hxx +++ /dev/null @@ -1,35 +0,0 @@ -#include - -#include -#include - -namespace pqxx -{ -class blob; -class largeobject; -} // namespace pqxx - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_largeobject : callgate -{ - friend class pqxx::blob; - friend class pqxx::largeobject; - - connection_largeobject(reference x) : super(x) {} - - pq::PGconn *raw_connection() const { return home().raw_connection(); } -}; - - -class PQXX_PRIVATE const_connection_largeobject : callgate -{ - friend class pqxx::blob; - friend class pqxx::largeobject; - - const_connection_largeobject(reference x) : super(x) {} - - std::string error_message() const { return home().err_msg(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-notification_receiver.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-notification_receiver.hxx deleted file mode 100644 index 0bcb2db17..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-notification_receiver.hxx +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#include "pqxx/connection.hxx" - - -namespace pqxx -{ -class notification_receiver; -} - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_notification_receiver : callgate -{ - friend class pqxx::notification_receiver; - - connection_notification_receiver(reference x) : super(x) {} - - void add_receiver(notification_receiver *receiver) - { - home().add_receiver(receiver); - } - void remove_receiver(notification_receiver *receiver) noexcept - { - home().remove_receiver(receiver); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-pipeline.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-pipeline.hxx deleted file mode 100644 index c6ae6e17a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-pipeline.hxx +++ /dev/null @@ -1,23 +0,0 @@ -#include "pqxx/internal/libpq-forward.hxx" -#include - -#include "pqxx/pipeline.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_pipeline : callgate -{ - friend class pqxx::pipeline; - - connection_pipeline(reference x) : super(x) {} - - void start_exec(char const query[]) { home().start_exec(query); } - pqxx::internal::pq::PGresult *get_result() { return home().get_result(); } - void cancel_query() { home().cancel_query(); } - - bool consume_input() noexcept { return home().consume_input(); } - bool is_busy() const noexcept { return home().is_busy(); } - - int encoding_id() { return home().encoding_id(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-sql_cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-sql_cursor.hxx deleted file mode 100644 index 51a889844..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-sql_cursor.hxx +++ /dev/null @@ -1,19 +0,0 @@ -#include - -namespace pqxx::internal -{ -class sql_cursor; -} - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - - connection_sql_cursor(reference x) : super(x) {} - - result exec(char const query[]) { return home().exec(query); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-stream_from.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-stream_from.hxx deleted file mode 100644 index 8961e7146..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-stream_from.hxx +++ /dev/null @@ -1,15 +0,0 @@ -#include - -#include "pqxx/connection.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_stream_from : callgate -{ - friend class pqxx::stream_from; - - connection_stream_from(reference x) : super{x} {} - - auto read_copy_line() { return home().read_copy_line(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-stream_to.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-stream_to.hxx deleted file mode 100644 index a6974fb21..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-stream_to.hxx +++ /dev/null @@ -1,17 +0,0 @@ -#include - -#include "pqxx/stream_to.hxx" - - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_stream_to : callgate -{ - friend class pqxx::stream_to; - - connection_stream_to(reference x) : super(x) {} - - void write_copy_line(std::string_view line) { home().write_copy_line(line); } - void end_copy_write() { home().end_copy_write(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-transaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-transaction.hxx deleted file mode 100644 index 74d659253..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/connection-transaction.hxx +++ /dev/null @@ -1,44 +0,0 @@ -#include - -namespace pqxx -{ -class connection; -} - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE connection_transaction : callgate -{ - friend class pqxx::transaction_base; - - connection_transaction(reference x) : super(x) {} - - template result exec(STRING query, std::string_view desc) - { - return home().exec(query, desc); - } - - void register_transaction(transaction_base *t) - { - home().register_transaction(t); - } - void unregister_transaction(transaction_base *t) noexcept - { - home().unregister_transaction(t); - } - - auto read_copy_line() { return home().read_copy_line(); } - void write_copy_line(std::string_view line) { home().write_copy_line(line); } - void end_copy_write() { home().end_copy_write(); } - - result exec_prepared(zview statement, internal::c_params const &args) - { - return home().exec_prepared(statement, args); - } - - result exec_params(zview query, internal::c_params const &args) - { - return home().exec_params(query, args); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/errorhandler-connection.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/errorhandler-connection.hxx deleted file mode 100644 index 5560cedec..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/errorhandler-connection.hxx +++ /dev/null @@ -1,13 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE errorhandler_connection : callgate -{ - friend class pqxx::connection; - - errorhandler_connection(reference x) : super(x) {} - - void unregister() noexcept { home().unregister(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx deleted file mode 100644 index 296d22145..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx +++ /dev/null @@ -1,24 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE icursor_iterator_icursorstream : callgate -{ - friend class pqxx::icursorstream; - - icursor_iterator_icursorstream(reference x) : super(x) {} - - icursor_iterator::difference_type pos() const noexcept - { - return home().pos(); - } - - icursor_iterator *get_prev() { return home().m_prev; } - void set_prev(icursor_iterator *i) { home().m_prev = i; } - - icursor_iterator *get_next() { return home().m_next; } - void set_next(icursor_iterator *i) { home().m_next = i; } - - void fill(result const &r) { home().fill(r); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx deleted file mode 100644 index 56056d5ef..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx +++ /dev/null @@ -1,32 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE icursorstream_icursor_iterator : callgate -{ - friend class pqxx::icursor_iterator; - - icursorstream_icursor_iterator(reference x) : super(x) {} - - void insert_iterator(icursor_iterator *i) noexcept - { - home().insert_iterator(i); - } - - void remove_iterator(icursor_iterator *i) const noexcept - { - home().remove_iterator(i); - } - - icursorstream::size_type forward() { return home().forward(); } - icursorstream::size_type forward(icursorstream::size_type n) - { - return home().forward(n); - } - - void service_iterators(icursorstream::difference_type p) - { - home().service_iterators(p); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-connection.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-connection.hxx deleted file mode 100644 index daa0808c0..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-connection.hxx +++ /dev/null @@ -1,14 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_connection : callgate -{ - friend class pqxx::connection; - - result_connection(reference x) : super(x) {} - - operator bool() const { return bool(home()); } - bool operator!() const { return not home(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-creation.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-creation.hxx deleted file mode 100644 index 3d9205f2c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-creation.hxx +++ /dev/null @@ -1,24 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_creation : callgate -{ - friend class pqxx::connection; - friend class pqxx::pipeline; - - result_creation(reference x) : super(x) {} - - static result create( - internal::pq::PGresult *rhs, std::shared_ptr const &query, - encoding_group enc) - { - return result(rhs, query, enc); - } - - void check_status(std::string_view desc = ""sv) const - { - return home().check_status(desc); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-pipeline.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-pipeline.hxx deleted file mode 100644 index 3ebe436d2..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-pipeline.hxx +++ /dev/null @@ -1,16 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_pipeline : callgate -{ - friend class pqxx::pipeline; - - result_pipeline(reference x) : super(x) {} - - std::shared_ptr query_ptr() const - { - return home().query_ptr(); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-sql_cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-sql_cursor.hxx deleted file mode 100644 index 78b450739..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/result-sql_cursor.hxx +++ /dev/null @@ -1,13 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE result_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - - result_sql_cursor(reference x) : super(x) {} - - char const *cmd_status() const noexcept { return home().cmd_status(); } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/transaction-sql_cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/transaction-sql_cursor.hxx deleted file mode 100644 index 4ed78dc93..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/transaction-sql_cursor.hxx +++ /dev/null @@ -1,10 +0,0 @@ -#include - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE transaction_sql_cursor : callgate -{ - friend class pqxx::internal::sql_cursor; - transaction_sql_cursor(reference x) : super(x) {} -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/transaction-transaction_focus.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/transaction-transaction_focus.hxx deleted file mode 100644 index ca7939a99..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/gates/transaction-transaction_focus.hxx +++ /dev/null @@ -1,30 +0,0 @@ -#include - -#include "pqxx/transaction_base.hxx" - -namespace pqxx::internal::gate -{ -class PQXX_PRIVATE transaction_transaction_focus : callgate -{ - friend class pqxx::transaction_focus; - - transaction_transaction_focus(reference x) : super(x) {} - - void register_focus(transaction_focus *focus) - { - home().register_focus(focus); - } - void unregister_focus(transaction_focus *focus) noexcept - { - home().unregister_focus(focus); - } - void register_pending_error(zview error) - { - home().register_pending_error(error); - } - void register_pending_error(std::string &&error) - { - home().register_pending_error(std::move(error)); - } -}; -} // namespace pqxx::internal::gate diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/header-post.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/header-post.hxx deleted file mode 100644 index ff6bf8986..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/header-post.hxx +++ /dev/null @@ -1,22 +0,0 @@ -/* Compiler deficiency workarounds for compiling libpqxx headers. - * - * To be included at the end of each libpqxx header, in order to restore the - * client program's settings. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -// NO GUARDS HERE! This code should be executed every time! - -#if defined(_MSC_VER) -# pragma warning(pop) // Restore compiler's warning state -#endif - -#if !defined(PQXX_HEADER_PRE) -# error "Include pqxx/internal/header-post.hxx AFTER its 'pre' counterpart." -#endif - -#undef PQXX_HEADER_PRE diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/header-pre.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/header-pre.hxx deleted file mode 100644 index abc1a398d..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/header-pre.hxx +++ /dev/null @@ -1,169 +0,0 @@ -/* Compiler settings for compiling libpqxx headers, and workarounds for all. - * - * Include this before including any other libpqxx headers from within libpqxx. - * And to balance it out, also include header-post.hxx at the end of the batch - * of headers. - * - * The public libpqxx headers (e.g. ``) include this already; - * there's no need to do this from within an application. - * - * Include this file at the highest aggregation level possible to avoid nesting - * and to keep things simple. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ - -// NO GUARD HERE! This part should be included every time this file is. -#if defined(_MSC_VER) - -// Save compiler's warning state, and set warning level 4 for maximum -// sensitivity to warnings. -# pragma warning(push, 4) - -// Visual C++ generates some entirely unreasonable warnings. Disable them. -// Copy constructor could not be generated. -# pragma warning(disable : 4511) -// Assignment operator could not be generated. -# pragma warning(disable : 4512) -// Can't expose outside classes without exporting them. Except the MSVC docs -// say please ignore the warning if it's a standard library class. -# pragma warning(disable : 4251) -// Can't derive library classes from outside classes without exporting them. -// Except the MSVC docs say please ignore the warning if the parent class is -// in the standard library. -# pragma warning(disable : 4275) -// Can't inherit from non-exported class. -# pragma warning(disable : 4275) - -#endif // _MSC_VER - - -#if defined(PQXX_HEADER_PRE) -# error "Avoid nesting #include of pqxx/internal/header-pre.hxx." -#endif - -#define PQXX_HEADER_PRE - - -// Workarounds & definitions that need to be included even in library's headers -#include "pqxx/config-public-compiler.h" - -// Enable ISO-646 alternative operaotr representations: "and" instead of "&&" -// etc. on older compilers. C++20 removes this header. -#if __has_include() -# include -#endif - - -#if defined(PQXX_HAVE_GCC_PURE) -/// Declare function "pure": no side effects, only reads globals and its args. -# define PQXX_PURE __attribute__((pure)) -#else -# define PQXX_PURE /* pure */ -#endif - - -#if defined(__GNUC__) -/// Tell the compiler to optimise a function for size, not speed. -# define PQXX_COLD __attribute__((cold)) -#else -# define PQXX_COLD /* cold */ -#endif - - -// Workarounds for Windows -#ifdef _WIN32 - -/* For now, export DLL symbols if _DLL is defined. This is done automatically - * by the compiler when linking to the dynamic version of the runtime library, - * according to "gzh" - */ -# if defined(PQXX_SHARED) && !defined(PQXX_LIBEXPORT) -# define PQXX_LIBEXPORT __declspec(dllimport) -# endif // PQXX_SHARED && !PQXX_LIBEXPORT - - -// Workarounds for Microsoft Visual C++ -# ifdef _MSC_VER - -// Suppress vtables on abstract classes. -# define PQXX_NOVTABLE __declspec(novtable) - -// Automatically link with the appropriate libpq (static or dynamic, debug or -// release). The default is to use the release DLL. Define PQXX_PQ_STATIC to -// link to a static version of libpq, and _DEBUG to link to a debug version. -// The two may be combined. -# if defined(PQXX_AUTOLINK) -# if defined(PQXX_PQ_STATIC) -# ifdef _DEBUG -# pragma comment(lib, "libpqd") -# else -# pragma comment(lib, "libpq") -# endif -# else -# ifdef _DEBUG -# pragma comment(lib, "libpqddll") -# else -# pragma comment(lib, "libpqdll") -# endif -# endif -# endif - -// If we're not compiling libpqxx itself, automatically link with the -// appropriate libpqxx library. To link with the libpqxx DLL, define -// PQXX_SHARED; the default is to link with the static library. A static link -// is the recommended practice. -// -// The preprocessor macro PQXX_INTERNAL is used to detect whether we -// are compiling the libpqxx library itself. When you compile the library -// yourself using your own project file, make sure to include this macro. -# if defined(PQXX_AUTOLINK) && !defined(PQXX_INTERNAL) -# ifdef PQXX_SHARED -# ifdef _DEBUG -# pragma comment(lib, "libpqxxD") -# else -# pragma comment(lib, "libpqxx") -# endif -# else // !PQXX_SHARED -# ifdef _DEBUG -# pragma comment(lib, "libpqxx_staticD") -# else -# pragma comment(lib, "libpqxx_static") -# endif -# endif -# endif - -# endif // _MSC_VER - -#elif defined(PQXX_HAVE_GCC_VISIBILITY) // !_WIN32 - -# define PQXX_LIBEXPORT __attribute__((visibility("default"))) -# define PQXX_PRIVATE __attribute__((visibility("hidden"))) - -#endif // PQXX_HAVE_GCC_VISIBILITY - - -#ifndef PQXX_LIBEXPORT -# define PQXX_LIBEXPORT /* libexport */ -#endif - -#ifndef PQXX_PRIVATE -# define PQXX_PRIVATE /* private */ -#endif - -#ifndef PQXX_NOVTABLE -# define PQXX_NOVTABLE /* novtable */ -#endif - -// C++20: Assume support. -#if defined(PQXX_HAVE_LIKELY) -# define PQXX_LIKELY [[likely]] -# define PQXX_UNLIKELY [[unlikely]] -#else -# define PQXX_LIKELY /* [[likely]] */ -# define PQXX_UNLIKELY /* [[unlikely]] */ -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/ignore-deprecated-post.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/ignore-deprecated-post.hxx deleted file mode 100644 index cebcf0594..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/ignore-deprecated-post.hxx +++ /dev/null @@ -1,15 +0,0 @@ -/// End a code block started by "ignore-deprecated-pre.hxx". - -#if !defined(PQXX_IGNORING_DEPRECATED) -# error "Ended an 'ignore-deprecated' block while none was active." -#endif - -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#endif // __GNUC__ - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -#undef PQXX_IGNORING_DEPRECATED diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/ignore-deprecated-pre.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/ignore-deprecated-pre.hxx deleted file mode 100644 index 8ac57afaa..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/ignore-deprecated-pre.hxx +++ /dev/null @@ -1,28 +0,0 @@ -/** Start a block of deprecated code which may call other deprecated code. - * - * Most compilers will emit warnings when deprecated code is invoked from - * non-deprecated code. But some compilers (notably gcc) will always emit the - * warning even when the calling code is also deprecated. - * - * This header starts a block where those warnings are suppressed. It can be - * included inside a code block. - * - * Always match the #include with a closing #include of - * "ignore-deprecated-post.hxx". To avoid mistakes, keep the enclosed area as - * small as possible. - */ -#if defined(PQXX_IGNORING_DEPRECATED) -# error "Started an 'ignore-deprecated' block inside another." -#endif - -#define PQXX_IGNORING_DEPRECATED - -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif // __GNUC__ - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4996) -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/libpq-forward.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/libpq-forward.hxx deleted file mode 100644 index 9e74f79ec..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/libpq-forward.hxx +++ /dev/null @@ -1,31 +0,0 @@ -/** Minimal forward declarations of libpq types needed in libpqxx headers. - * - * DO NOT INCLUDE THIS FILE when building client programs. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -extern "C" -{ - struct pg_conn; - struct pg_result; - struct pgNotify; -} - -/// Forward declarations of libpq types as needed in libpqxx headers. -namespace pqxx::internal::pq -{ -using PGconn = pg_conn; -using PGresult = pg_result; -using PGnotify = pgNotify; -using PQnoticeProcessor = void (*)(void *, char const *); -} // namespace pqxx::internal::pq - -namespace pqxx -{ -/// PostgreSQL database row identifier. -using oid = unsigned int; -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/result_iter.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/result_iter.hxx deleted file mode 100644 index 1fa1f7d8a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/result_iter.hxx +++ /dev/null @@ -1,124 +0,0 @@ -/** Result loops. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT_ITER -#define PQXX_H_RESULT_ITER - -#include - -#include "pqxx/strconv.hxx" - -namespace pqxx -{ -class result; -} // namespace pqxx - - -namespace pqxx::internal -{ -// C++20: Replace with generator? -/// Iterator for looped unpacking of a result. -template class result_iter -{ -public: - using value_type = std::tuple; - - /// Construct an "end" iterator. - result_iter() = default; - - explicit result_iter(result const &home) : - m_home{&home}, m_size{std::size(home)} - { - if (not std::empty(home)) - read(); - } - result_iter(result_iter const &) = default; - - result_iter &operator++() - { - m_index++; - if (m_index >= m_size) - m_home = nullptr; - else - read(); - return *this; - } - - /// Comparison only works for comparing to end(). - bool operator==(result_iter const &rhs) const - { - return m_home == rhs.m_home; - } - bool operator!=(result_iter const &rhs) const { return not(*this == rhs); } - - value_type const &operator*() const { return m_value; } - -private: - void read() { (*m_home)[m_index].convert(m_value); } - - result const *m_home{nullptr}; - result::size_type m_index{0}; - result::size_type m_size; - value_type m_value; -}; - - -template class result_iteration -{ -public: - using iterator = result_iter; - explicit result_iteration(result const &home) : m_home{home} - { - constexpr auto tup_size{sizeof...(TYPE)}; - if (home.columns() != tup_size) - throw usage_error{internal::concat( - "Tried to extract ", to_string(tup_size), - " field(s) from a result with ", to_string(home.columns()), - " column(s).")}; - } - iterator begin() const - { - if (std::size(m_home) == 0) - return end(); - else - return iterator{m_home}; - } - iterator end() const { return {}; } - -private: - pqxx::result const &m_home; -}; -} // namespace pqxx::internal - - -template inline auto pqxx::result::iter() const -{ - return pqxx::internal::result_iteration{*this}; -} - - -template -inline void pqxx::result::for_each(CALLABLE &&func) const -{ - using args_tuple = internal::args_t; - constexpr auto sz{std::tuple_size_v}; - static_assert( - sz > 0, - "Callback for for_each must take parameters, one for each column in the " - "result."); - - auto const cols{this->columns()}; - if (sz != cols) - throw usage_error{internal::concat( - "Callback to for_each takes ", sz, "parameter", (sz == 1) ? "" : "s", - ", but result set has ", cols, "field", (cols == 1) ? "" : "s", ".")}; - - using pass_tuple = pqxx::internal::strip_types_t; - for (auto const r : *this) std::apply(func, r.as_tuple()); -} -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/result_iterator.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/result_iterator.hxx deleted file mode 100644 index 3f27a1d3f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/result_iterator.hxx +++ /dev/null @@ -1,389 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT_ITERATOR -#define PQXX_H_RESULT_ITERATOR - -#include "pqxx/row.hxx" - - -/* Result iterator. - * - * Don't include this header from your own application; it is included for you - * by other libpqxx headers. - */ - -namespace pqxx -{ -/// Iterator for rows in a result. Use as result::const_iterator. -/** A result, once obtained, cannot be modified. Therefore there is no - * plain iterator type for result. However its const_iterator type can be - * used to inspect its rows without changing them. - */ -class PQXX_LIBEXPORT const_result_iterator : public row -{ -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = row const; - using pointer = row const *; - using reference = row; - using size_type = result_size_type; - using difference_type = result_difference_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create an iterator, but in an unusable state. - const_result_iterator() noexcept = default; - /// Copy an iterator. - const_result_iterator(const_result_iterator const &) noexcept = default; - /// Move an iterator. - const_result_iterator(const_result_iterator &&) noexcept = default; - - /// Begin iterating a @ref row. - const_result_iterator(row const &t) noexcept : row{t} {} -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /** - * @name Dereferencing operators - * - * An iterator "points to" its own row, which is also itself. This makes it - * easy to address a @ref result as a two-dimensional container, without - * going through the intermediate step of dereferencing the iterator. It - * makes the interface similar to C pointer/array semantics. - * - * IIRC Alex Stepanov, the inventor of the STL, once remarked that having - * this as standard behaviour for pointers would be useful in some - * algorithms. So even if this makes me look foolish, I would seem to be in - * distinguished company. - */ - //@{ - /// Dereference the iterator. - [[nodiscard]] pointer operator->() const { return this; } - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Dereference the iterator. - [[nodiscard]] reference operator*() const { return *this; } -#include "pqxx/internal/ignore-deprecated-post.hxx" - //@} - - /** - * @name Field access - */ - //@{ - using row::back; - using row::front; - using row::operator[]; - using row::at; - using row::rownumber; - //@} - - /** - * @name Manipulations - */ - //@{ - const_result_iterator &operator=(const_result_iterator const &rhs) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::operator=(rhs); -#include "pqxx/internal/ignore-deprecated-post.hxx" - return *this; - } - - const_result_iterator &operator=(const_result_iterator &&rhs) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::operator=(std::move(rhs)); -#include "pqxx/internal/ignore-deprecated-post.hxx" - return *this; - } - - const_result_iterator operator++(int); - const_result_iterator &operator++() - { - ++m_index; - return *this; - } - const_result_iterator operator--(int); - const_result_iterator &operator--() - { - --m_index; - return *this; - } - - const_result_iterator &operator+=(difference_type i) - { - m_index += i; - return *this; - } - const_result_iterator &operator-=(difference_type i) - { - m_index -= i; - return *this; - } - - /// Interchange two iterators in an exception-safe manner. - void swap(const_result_iterator &other) noexcept - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row::swap(other); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool operator==(const_result_iterator const &i) const - { - return m_index == i.m_index; - } - [[nodiscard]] bool operator!=(const_result_iterator const &i) const - { - return m_index != i.m_index; - } - [[nodiscard]] bool operator<(const_result_iterator const &i) const - { - return m_index < i.m_index; - } - [[nodiscard]] bool operator<=(const_result_iterator const &i) const - { - return m_index <= i.m_index; - } - [[nodiscard]] bool operator>(const_result_iterator const &i) const - { - return m_index > i.m_index; - } - [[nodiscard]] bool operator>=(const_result_iterator const &i) const - { - return m_index >= i.m_index; - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] inline const_result_iterator operator+(difference_type) const; - friend const_result_iterator - operator+(difference_type, const_result_iterator const &); - [[nodiscard]] inline const_result_iterator operator-(difference_type) const; - [[nodiscard]] inline difference_type - operator-(const_result_iterator const &) const; - //@} - -private: - friend class pqxx::result; - const_result_iterator(pqxx::result const *r, result_size_type i) noexcept : - row{*r, i, r->columns()} - {} -}; - - -/// Reverse iterator for result. Use as result::const_reverse_iterator. -class PQXX_LIBEXPORT const_reverse_result_iterator - : private const_result_iterator -{ -public: - using super = const_result_iterator; - using iterator_type = const_result_iterator; - using iterator_type::difference_type; - using iterator_type::iterator_category; - using iterator_type::pointer; - using value_type = iterator_type::value_type; - using reference = iterator_type::reference; - - /// Create an iterator, but in an unusable state. - const_reverse_result_iterator() = default; - /// Copy an iterator. - const_reverse_result_iterator(const_reverse_result_iterator const &rhs) = - default; - /// Copy a reverse iterator from a regular iterator. - explicit const_reverse_result_iterator(const_result_iterator const &rhs) : - const_result_iterator{rhs} - { - super::operator--(); - } - - /// Move a regular iterator into a reverse iterator. - explicit const_reverse_result_iterator(const_result_iterator const &&rhs) : - const_result_iterator{std::move(rhs)} - { - super::operator--(); - } - - /// Return the underlying "regular" iterator (as per standard library). - [[nodiscard]] PQXX_PURE const_result_iterator base() const noexcept; - - /** - * @name Dereferencing operators - */ - //@{ - /// Dereference iterator. - using const_result_iterator::operator->; - /// Dereference iterator. - using const_result_iterator::operator*; - //@} - - /** - * @name Field access - */ - //@{ - using const_result_iterator::back; - using const_result_iterator::front; - using const_result_iterator::operator[]; - using const_result_iterator::at; - using const_result_iterator::rownumber; - //@} - - /** - * @name Manipulations - */ - //@{ - const_reverse_result_iterator & - operator=(const_reverse_result_iterator const &r) - { - iterator_type::operator=(r); - return *this; - } - const_reverse_result_iterator &operator=(const_reverse_result_iterator &&r) - { - iterator_type::operator=(std::move(r)); - return *this; - } - const_reverse_result_iterator &operator++() - { - iterator_type::operator--(); - return *this; - } - const_reverse_result_iterator operator++(int); - const_reverse_result_iterator &operator--() - { - iterator_type::operator++(); - return *this; - } - const_reverse_result_iterator operator--(int); - const_reverse_result_iterator &operator+=(difference_type i) - { - iterator_type::operator-=(i); - return *this; - } - const_reverse_result_iterator &operator-=(difference_type i) - { - iterator_type::operator+=(i); - return *this; - } - - void swap(const_reverse_result_iterator &other) noexcept - { - const_result_iterator::swap(other); - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] const_reverse_result_iterator - operator+(difference_type i) const - { - return const_reverse_result_iterator(base() - i); - } - [[nodiscard]] const_reverse_result_iterator operator-(difference_type i) - { - return const_reverse_result_iterator(base() + i); - } - [[nodiscard]] difference_type - operator-(const_reverse_result_iterator const &rhs) const - { - return rhs.const_result_iterator::operator-(*this); - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool - operator==(const_reverse_result_iterator const &rhs) const noexcept - { - return iterator_type::operator==(rhs); - } - [[nodiscard]] bool - operator!=(const_reverse_result_iterator const &rhs) const noexcept - { - return not operator==(rhs); - } - - [[nodiscard]] bool operator<(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator>(rhs); - } - [[nodiscard]] bool operator<=(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator>=(rhs); - } - [[nodiscard]] bool operator>(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator<(rhs); - } - [[nodiscard]] bool operator>=(const_reverse_result_iterator const &rhs) const - { - return iterator_type::operator<=(rhs); - } - //@} -}; - - -inline const_result_iterator -const_result_iterator::operator+(result::difference_type o) const -{ - return {&m_result, size_type(result::difference_type(m_index) + o)}; -} - -inline const_result_iterator -operator+(result::difference_type o, const_result_iterator const &i) -{ - return i + o; -} - -inline const_result_iterator -const_result_iterator::operator-(result::difference_type o) const -{ - return {&m_result, result_size_type(result::difference_type(m_index) - o)}; -} - -inline result::difference_type -const_result_iterator::operator-(const const_result_iterator &i) const -{ - return result::difference_type(num() - i.num()); -} - -inline const_result_iterator result::end() const noexcept -{ - return {this, size()}; -} - - -inline const_result_iterator result::cend() const noexcept -{ - return end(); -} - - -inline const_reverse_result_iterator -operator+(result::difference_type n, const_reverse_result_iterator const &i) -{ - return const_reverse_result_iterator{i.base() - n}; -} - -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/sql_cursor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/sql_cursor.hxx deleted file mode 100644 index a26d06306..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/sql_cursor.hxx +++ /dev/null @@ -1,118 +0,0 @@ -/** Internal wrapper for SQL cursors. Supports higher-level cursor classes. - * - * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SQL_CURSOR -#define PQXX_H_SQL_CURSOR - -namespace pqxx::internal -{ -/// Cursor with SQL positioning semantics. -/** Thin wrapper around an SQL cursor, with SQL's ideas of positioning. - * - * SQL cursors have pre-increment/pre-decrement semantics, with on either end - * of the result set a special position that does not repesent a row. This - * class models SQL cursors for the purpose of implementing more C++-like - * semantics on top. - * - * Positions of actual rows are numbered starting at 1. Position 0 exists but - * does not refer to a row. There is a similar non-row position at the end of - * the result set. - * - * Don't use this at home. You deserve better. Use the stateles_cursor - * instead. - */ -class PQXX_LIBEXPORT sql_cursor : public cursor_base -{ -public: - sql_cursor( - transaction_base &t, std::string_view query, std::string_view cname, - cursor_base::access_policy ap, cursor_base::update_policy up, - cursor_base::ownership_policy op, bool hold); - - sql_cursor( - transaction_base &t, std::string_view cname, - cursor_base::ownership_policy op); - - ~sql_cursor() noexcept { close(); } - - result fetch(difference_type rows, difference_type &displacement); - result fetch(difference_type rows) - { - difference_type d = 0; - return fetch(rows, d); - } - difference_type move(difference_type rows, difference_type &displacement); - difference_type move(difference_type rows) - { - difference_type d = 0; - return move(rows, d); - } - - /// Current position, or -1 for unknown - /** - * The starting position, just before the first row, counts as position zero. - * - * Position may be unknown if (and only if) this cursor was adopted, and has - * never hit its starting position (position zero). - */ - difference_type pos() const noexcept { return m_pos; } - - /// End position, or -1 for unknown - /** - * Returns the final position, just after the last row in the result set. The - * starting position, just before the first row, counts as position zero. - * - * End position is unknown until it is encountered during use. - */ - difference_type endpos() const noexcept { return m_endpos; } - - /// Return zero-row result for this cursor. - result const &empty_result() const noexcept { return m_empty_result; } - - void close() noexcept; - -private: - difference_type adjust(difference_type hoped, difference_type actual); - static std::string stridestring(difference_type); - /// Initialize cached empty result. Call only at beginning or end! - void init_empty_result(transaction_base &); - - /// Connection in which this cursor lives. - connection &m_home; - - /// Zero-row result from this cursor (or plain empty one if cursor is - /// adopted) - result m_empty_result; - - result m_cached_current_row; - - /// Is this cursor adopted (as opposed to created by this cursor object)? - bool m_adopted; - - /// Will this cursor object destroy its SQL cursor when it dies? - cursor_base::ownership_policy m_ownership; - - /// At starting position (-1), somewhere in the middle (0), or past end (1) - int m_at_end; - - /// Position, or -1 for unknown - difference_type m_pos; - - /// End position, or -1 for unknown - difference_type m_endpos = -1; -}; - - -PQXX_LIBEXPORT result_size_type obtain_stateless_cursor_size(sql_cursor &); -PQXX_LIBEXPORT result stateless_cursor_retrieve( - sql_cursor &, result::difference_type size, - result::difference_type begin_pos, result::difference_type end_pos); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/statement_parameters.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/statement_parameters.hxx deleted file mode 100644 index b078bf6e0..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/statement_parameters.hxx +++ /dev/null @@ -1,131 +0,0 @@ -/** Common implementation for statement parameter lists. - * - * These are used for both prepared statements and parameterized statements. - * - * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STATEMENT_PARAMETER -#define PQXX_H_STATEMENT_PARAMETER - -#include -#include -#include -#include -#include - -#include "pqxx/binarystring.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/util.hxx" - - -namespace pqxx::internal -{ -template -constexpr inline auto const iterator_identity{ - [](decltype(*std::declval()) x) { return x; }}; - - -/// Marker type: pass a dynamically-determined number of statement parameters. -/** @deprecated Use @ref params instead. - * - * Normally when invoking a prepared or parameterised statement, the number - * of parameters is known at compile time. For instance, - * `t.exec_prepared("foo", 1, "x");` executes statement `foo` with two - * parameters, an `int` and a C string. - * - * But sometimes you may want to pass a number of parameters known only at run - * time. In those cases, a @ref dynamic_params encodes a dynamically - * determined number of parameters. You can mix these with regular, static - * parameter lists, and you can re-use them for multiple statement invocations. - * - * A dynamic_params object does not store copies of its parameters, so make - * sure they remain accessible until you've executed the statement. - * - * The ACCESSOR is an optional callable (such as a lambda). If you pass an - * accessor `a`, then each parameter `p` goes into your statement as `a(p)`. - */ -template)> -class dynamic_params -{ -public: - /// Wrap a sequence of pointers or iterators. - constexpr dynamic_params(IT begin, IT end) : - m_begin(begin), m_end(end), m_accessor(iterator_identity) - {} - - /// Wrap a sequence of pointers or iterators. - /** This version takes an accessor callable. If you pass an accessor `acc`, - * then any parameter `p` will go into the statement's parameter list as - * `acc(p)`. - */ - constexpr dynamic_params(IT begin, IT end, ACCESSOR &acc) : - m_begin(begin), m_end(end), m_accessor(acc) - {} - - /// Wrap a container. - template - explicit constexpr dynamic_params(C &container) : - dynamic_params(std::begin(container), std::end(container)) - {} - - /// Wrap a container. - /** This version takes an accessor callable. If you pass an accessor `acc`, - * then any parameter `p` will go into the statement's parameter list as - * `acc(p)`. - */ - template - explicit constexpr dynamic_params(C &container, ACCESSOR &acc) : - dynamic_params(std::begin(container), std::end(container), acc) - {} - - constexpr IT begin() const noexcept { return m_begin; } - constexpr IT end() const noexcept { return m_end; } - - constexpr auto access(decltype(*std::declval()) value) const - -> decltype(std::declval()(value)) - { - return m_accessor(value); - } - -private: - IT const m_begin, m_end; - ACCESSOR m_accessor = iterator_identity; -}; - - -/// Internal type: encode statement parameters. -/** Compiles arguments for prepared statements and parameterised queries into - * a format that can be passed into libpq. - * - * Objects of this type are meant to be short-lived: a `c_params` lives and - * dies entirely within the call to execute. So, for example, if you pass in a - * non-null pointer as a parameter, @ref params may simply use that pointer as - * a parameter value, without arranging longer-term storage for the data to - * which it points. All values referenced by parameters must remain "live" - * until the parameterised or prepared statement has been executed. - */ -struct PQXX_LIBEXPORT c_params -{ - c_params() = default; - /// Copying these objects is pointless and expensive. Don't do it. - c_params(c_params const &) = delete; - c_params(c_params &&) = default; - - /// Pre-allocate storage for `n` parameters. - void reserve(std::size_t n) &; - - /// As used by libpq: pointers to parameter values. - std::vector values; - /// As used by libpq: lengths of non-null arguments, in bytes. - std::vector lengths; - /// As used by libpq: effectively boolean "is this a binary parameter?" - std::vector formats; -}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/stream_iterator.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/stream_iterator.hxx deleted file mode 100644 index f240dcfa7..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/stream_iterator.hxx +++ /dev/null @@ -1,105 +0,0 @@ -/** Stream iterators. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_ITERATOR -#define PQXX_H_STREAM_ITERATOR - -#include - -namespace pqxx -{ -class stream_from; -} - - -namespace pqxx::internal -{ -// C++20: Replace with generator? -/// Input iterator for stream_from. -/** Just barely enough to support range-based "for" loops. Don't assume that - * any of the usual behaviour works beyond that. - */ -template class stream_input_iterator -{ -public: - using value_type = std::tuple; - - /// Construct an "end" iterator. - stream_input_iterator() = default; - - explicit stream_input_iterator(stream_from &home) : m_home(&home) - { - advance(); - } - stream_input_iterator(stream_input_iterator const &) = default; - - stream_input_iterator &operator++() - { - advance(); - return *this; - } - - value_type const &operator*() const { return m_value; } - - /// Comparison only works for comparing to end(). - bool operator==(stream_input_iterator const &rhs) const - { - return m_home == rhs.m_home; - } - /// Comparison only works for comparing to end(). - bool operator!=(stream_input_iterator const &rhs) const - { - return not(*this == rhs); - } - -private: - void advance() - { - if (m_home == nullptr) - throw usage_error{"Moving stream_from iterator beyond end()."}; - if (not((*m_home) >> m_value)) - m_home = nullptr; - } - - stream_from *m_home{nullptr}; - value_type m_value; -}; - - -// C++20: Replace with generator? -/// Iteration over a @ref stream_from. -template class stream_input_iteration -{ -public: - using iterator = stream_input_iterator; - explicit stream_input_iteration(stream_from &home) : m_home{home} {} - iterator begin() const { return iterator{m_home}; } - iterator end() const { return {}; } - -private: - stream_from &m_home; -}; - - -// C++20: Replace with generator? -/// Iteration over a @ref stream_from, deleting it once done. -template class owning_stream_input_iteration -{ -public: - using iterator = stream_input_iterator; - explicit owning_stream_input_iteration(std::unique_ptr &&home) : - m_home{std::move(home)} - {} - iterator begin() const { return iterator{*m_home.get()}; } - iterator end() const { return {}; } - -private: - std::unique_ptr m_home; -}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/wait.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/wait.hxx deleted file mode 100644 index 7a82e6553..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/internal/wait.hxx +++ /dev/null @@ -1,18 +0,0 @@ -#if !defined(PQXX_WAIT_HXX) -# define PQXX_WAIT_HXX - -namespace pqxx::internal -{ -/// Wait. -/** This is normally `std::this_thread::sleep_for()`. But MinGW's `thread` - * header doesn't work, so we must be careful about including it. - */ -void PQXX_LIBEXPORT wait_for(unsigned int microseconds); - - -/// Wait for a socket to be ready for reading/writing, or timeout. -PQXX_LIBEXPORT void wait_fd( - int fd, bool for_read, bool for_write, unsigned seconds = 1, - unsigned microseconds = 0); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/isolation b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/isolation deleted file mode 100644 index 1b801329b..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/isolation +++ /dev/null @@ -1,8 +0,0 @@ -/** Transaction isolation levels. - * - * Policies and traits describing SQL transaction isolation levels - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/isolation.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/isolation.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/isolation.hxx deleted file mode 100644 index 0698c6ab4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/isolation.hxx +++ /dev/null @@ -1,75 +0,0 @@ -/* Definitions for transaction isolation levels, and such. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ISOLATION -#define PQXX_H_ISOLATION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Should a transaction be read-only, or read-write? -/** No, this is not an isolation level. So it really doesn't belong here. - * But it's not really worth a separate header. - */ -enum class write_policy -{ - read_only, - read_write -}; - - -/// Transaction isolation levels. -/** These are as defined in the SQL standard. But there are a few notes - * specific to PostgreSQL. - * - * First, postgres does not support "read uncommitted." The lowest level you - * can get is "read committed," which is better. PostgreSQL is built on the - * MVCC paradigm, which guarantees "read committed" isolation without any - * additional performance overhead, so there was no point in providing the - * lower level. - * - * Second, "repeatable read" also makes more isolation guarantees than the - * standard requires. According to the standard, this level prevents "dirty - * reads" and "nonrepeatable reads," but not "phantom reads." In postgres, - * it actually prevents all three. - * - * Third, "serializable" is only properly supported starting at postgres 9.1. - * If you request "serializable" isolation on an older backend, you will get - * the same isolation as in "repeatable read." It's better than the - * "repeatable read" defined in the SQL standard, but not a complete - * implementation of the standard's "serializable" isolation level. - * - * In general, a lower isolation level will allow more surprising interactions - * between ongoing transactions, but improve performance. A higher level - * gives you more protection from subtle concurrency bugs, but sometimes it - * may not be possible to complete your transaction without avoiding paradoxes - * in the data. In that case a transaction may fail, and the application will - * have to re-do the whole thing based on the latest state of the database. - * (If you want to retry your code in that situation, have a look at the - * transactor framework.) - * - * Study the levels and design your application with the right level in mind. - */ -enum isolation_level -{ - // PostgreSQL only has the better isolation levels. - // read_uncommitted, - - read_committed, - repeatable_read, - serializable, -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/largeobject b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/largeobject deleted file mode 100644 index 1f2f94790..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/largeobject +++ /dev/null @@ -1,8 +0,0 @@ -/** Large Objects interface. - * - * Supports direct access to large objects, as well as through I/O streams - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/largeobject.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/largeobject.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/largeobject.hxx deleted file mode 100644 index ebafc51d8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/largeobject.hxx +++ /dev/null @@ -1,735 +0,0 @@ -/* Large Objects interface. Deprecated; use blob instead. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_LARGEOBJECT -#define PQXX_H_LARGEOBJECT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/dbtransaction.hxx" - - -namespace pqxx -{ -/// Identity of a large object. -/** @deprecated Use the @ref blob class instead. - * - * Encapsulates the identity of a large object. - * - * A largeobject must be accessed only from within a backend transaction, but - * the object's identity remains valid as long as the object exists. - */ -class PQXX_LIBEXPORT largeobject -{ -public: - using size_type = large_object_size_type; - - /// Refer to a nonexistent large object (similar to what a null pointer - /// does). - [[deprecated("Use blob instead.")]] largeobject() noexcept = default; - - /// Create new large object. - /** @param t Backend transaction in which the object is to be created. - */ - [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t); - - /// Wrap object with given oid. - /** Convert combination of a transaction and object identifier into a - * large object identity. Does not affect the database. - * @param o Object identifier for the given object. - */ - [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept : - m_id{o} - {} - - /// Import large object from a local file. - /** Creates a large object containing the data found in the given file. - * @param t Backend transaction in which the large object is to be created. - * @param file A filename on the client program's filesystem. - */ - [[deprecated("Use blob instead.")]] largeobject( - dbtransaction &t, std::string_view file); - - /// Take identity of an opened large object. - /** Copy identity of already opened large object. Note that this may be done - * as an implicit conversion. - * @param o Already opened large object to copy identity from. - */ - [[deprecated("Use blob instead.")]] largeobject( - largeobjectaccess const &o) noexcept; - - /// Object identifier. - /** The number returned by this function identifies the large object in the - * database we're connected to (or oid_none is returned if we refer to the - * null object). - */ - [[nodiscard]] oid id() const noexcept { return m_id; } - - /** - * @name Identity comparisons - * - * These operators compare the object identifiers of large objects. This has - * nothing to do with the objects' actual contents; use them only for keeping - * track of containers of references to large objects and such. - */ - //@{ - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator==(largeobject const &other) const - { - return m_id == other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator!=(largeobject const &other) const - { - return m_id != other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator<=(largeobject const &other) const - { - return m_id <= other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator>=(largeobject const &other) const - { - return m_id >= other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator<(largeobject const &other) const - { - return m_id < other.m_id; - } - /// Compare object identities - /** @warning Only valid between large objects in the same database. */ - [[nodiscard]] bool operator>(largeobject const &other) const - { - return m_id > other.m_id; - } - //@} - - /// Export large object's contents to a local file - /** Writes the data stored in the large object to the given file. - * @param t Transaction in which the object is to be accessed - * @param file A filename on the client's filesystem - */ - void to_file(dbtransaction &t, std::string_view file) const; - - /// Delete large object from database - /** Unlike its low-level equivalent cunlink, this will throw an exception if - * deletion fails. - * @param t Transaction in which the object is to be deleted - */ - void remove(dbtransaction &t) const; - -protected: - PQXX_PURE static internal::pq::PGconn * - raw_connection(dbtransaction const &T); - - PQXX_PRIVATE std::string reason(connection const &, int err) const; - -private: - oid m_id = oid_none; -}; - - -/// Accessor for large object's contents. -/** @deprecated Use the `blob` class instead. - */ -class PQXX_LIBEXPORT largeobjectaccess : private largeobject -{ -public: - using largeobject::size_type; - using off_type = size_type; - using pos_type = size_type; - - /// Open mode: `in`, `out` (can be combined using "bitwise or"). - /** According to the C++ standard, these should be in `std::ios_base`. We - * take them from derived class `std::ios` instead, which is easier on the - * eyes. - * - * Historical note: taking it from std::ios was originally a workaround for a - * problem with gcc 2.95. - */ - using openmode = std::ios::openmode; - - /// Default open mode: in, out, binary. - static constexpr auto default_mode{ - std::ios::in | std::ios::out | std::ios::binary}; - - /// Seek direction: `beg`, `cur`, `end`. - using seekdir = std::ios::seekdir; - - /// Create new large object and open it. - /** - * @param t Backend transaction in which the object is to be created. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] explicit largeobjectaccess( - dbtransaction &t, openmode mode = default_mode); - - /// Open large object with given oid. - /** Convert combination of a transaction and object identifier into a - * large object identity. Does not affect the database. - * @param t Transaction in which the object is to be accessed. - * @param o Object identifier for the given object. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, oid o, openmode mode = default_mode); - - /// Open given large object. - /** Open a large object with the given identity for reading and/or writing. - * @param t Transaction in which the object is to be accessed. - * @param o Identity for the large object to be accessed. - * @param mode Access mode, defaults to ios_base::in | ios_base::out | - * ios_base::binary. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, largeobject o, openmode mode = default_mode); - - /// Import large object from a local file and open it. - /** Creates a large object containing the data found in the given file. - * @param t Backend transaction in which the large object is to be created. - * @param file A filename on the client program's filesystem. - * @param mode Access mode, defaults to ios_base::in | ios_base::out. - */ - [[deprecated("Use blob instead.")]] largeobjectaccess( - dbtransaction &t, std::string_view file, openmode mode = default_mode); - - ~largeobjectaccess() noexcept { close(); } - - /// Object identifier. - /** The number returned by this function uniquely identifies the large object - * in the context of the database we're connected to. - */ - using largeobject::id; - - /// Export large object's contents to a local file. - /** Writes the data stored in the large object to the given file. - * @param file A filename on the client's filesystem. - */ - void to_file(std::string_view file) const - { - largeobject::to_file(m_trans, file); - } - - using largeobject::to_file; - - /** - * @name High-level access to object contents. - */ - //@{ - /// Write data to large object. - /** @warning The size of a write is currently limited to 2GB. - * - * @param buf Data to write. - * @param len Number of bytes from Buf to write. - */ - void write(char const buf[], std::size_t len); - - /// Write string to large object. - /** If not all bytes could be written, an exception is thrown. - * @param buf Data to write; no terminating zero is written. - */ - void write(std::string_view buf) { write(std::data(buf), std::size(buf)); } - - /// Read data from large object. - /** Throws an exception if an error occurs while reading. - * @param buf Location to store the read data in. - * @param len Number of bytes to try and read. - * @return Number of bytes read, which may be less than the number requested - * if the end of the large object is reached. - */ - size_type read(char buf[], std::size_t len); - - /// Seek in large object's data stream. - /** Throws an exception if an error occurs. - * @return The new position in the large object - */ - size_type seek(size_type dest, seekdir dir); - - /// Report current position in large object's data stream. - /** Throws an exception if an error occurs. - * @return The current position in the large object. - */ - [[nodiscard]] size_type tell() const; - //@} - - /** - * @name Low-level access to object contents. - * - * These functions provide a more "C-like" access interface, returning - * special values instead of throwing exceptions on error. These functions - * are generally best avoided in favour of the high-level access functions, - * which behave more like C++ functions should. - * - * Due to libpq's underlying API, some operations are limited to "int" - * sizes, typically 2 GB, even though a large object can grow much larger. - */ - //@{ - /// Seek in large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param dest Offset to go to. - * @param dir Origin to which dest is relative: ios_base::beg (from beginning - * of the object), ios_base::cur (from current access position), or - * ios_base;:end (from end of object). - * @return New position in large object, or -1 if an error occurred. - */ - pos_type cseek(off_type dest, seekdir dir) noexcept; - - /// Write to large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param buf Data to write. - * @param len Number of bytes to write. - * @return Number of bytes actually written, or -1 if an error occurred. - */ - off_type cwrite(char const buf[], std::size_t len) noexcept; - - /// Read from large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @param buf Area where incoming bytes should be stored. - * @param len Number of bytes to read. - * @return Number of bytes actually read, or -1 if an error occurred.. - */ - off_type cread(char buf[], std::size_t len) noexcept; - - /// Report current position in large object's data stream. - /** Does not throw exception in case of error; inspect return value and - * `errno` instead. - * @return Current position in large object, of -1 if an error occurred. - */ - [[nodiscard]] pos_type ctell() const noexcept; - //@} - - /** - * @name Error/warning output - */ - //@{ - /// Issue message to transaction's notice processor. - void process_notice(zview) noexcept; - //@} - - using largeobject::remove; - - using largeobject::operator==; - using largeobject::operator!=; - using largeobject::operator<; - using largeobject::operator<=; - using largeobject::operator>; - using largeobject::operator>=; - - largeobjectaccess() = delete; - largeobjectaccess(largeobjectaccess const &) = delete; - largeobjectaccess operator=(largeobjectaccess const &) = delete; - -private: - PQXX_PRIVATE std::string reason(int err) const; - internal::pq::PGconn *raw_connection() const - { - return largeobject::raw_connection(m_trans); - } - - PQXX_PRIVATE void open(openmode mode); - void close() noexcept; - - dbtransaction &m_trans; - int m_fd = -1; -}; - - -/// Streambuf to use large objects in standard I/O streams. -/** @deprecated Access large objects directly using the @ref blob class. - * - * The standard streambuf classes provide uniform access to data storage such - * as files or string buffers, so they can be accessed using standard input or - * output streams. This streambuf implementation provided similar access to - * large objects, so they could be read and written using the same stream - * classes. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class largeobject_streambuf : public std::basic_streambuf -{ - using size_type = largeobject::size_type; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - using openmode = largeobjectaccess::openmode; - using seekdir = largeobjectaccess::seekdir; - - /// Default open mode: in, out, binary. - static constexpr auto default_mode{ - std::ios::in | std::ios::out | std::ios::binary}; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - [[deprecated("Use blob instead.")]] largeobject_streambuf( - dbtransaction &t, largeobject o, openmode mode = default_mode, - size_type buf_size = 512) : - m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr} - { - initialize(mode); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - [[deprecated("Use blob instead.")]] largeobject_streambuf( - dbtransaction &t, oid o, openmode mode = default_mode, - size_type buf_size = 512) : - m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr} - { - initialize(mode); - } - - virtual ~largeobject_streambuf() noexcept - { - delete[] m_p; - delete[] m_g; - } - - /// For use by large object stream classes. - void process_notice(zview const &s) { m_obj.process_notice(s); } - -protected: - virtual int sync() override - { - // setg() sets eback, gptr, egptr. - this->setg(this->eback(), this->eback(), this->egptr()); - return overflow(eof()); - } - - virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override - { - return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir)); - } - - virtual pos_type seekpos(pos_type pos, openmode) override - { - largeobjectaccess::pos_type const newpos{ - m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)}; - return adjust_eof(newpos); - } - - virtual int_type overflow(int_type ch) override - { - auto *const pp{this->pptr()}; - if (pp == nullptr) - return eof(); - auto *const pb{this->pbase()}; - int_type res{0}; - - if (pp > pb) - { - auto const write_sz{pp - pb}; - auto const written_sz{ - m_obj.cwrite(pb, static_cast(pp - pb))}; - if (internal::cmp_less_equal(written_sz, 0)) - throw internal_error{ - "pqxx::largeobject: write failed " - "(is transaction still valid on write or flush?), " - "libpq reports error"}; - else if (write_sz != written_sz) - throw internal_error{ - "pqxx::largeobject: write failed " - "(is transaction still valid on write or flush?), " + - std::to_string(written_sz) + "/" + std::to_string(write_sz) + - " bytes written"}; - auto const out{adjust_eof(written_sz)}; - - if constexpr (std::is_arithmetic_v) - res = check_cast(out, "largeobject position"sv); - else - res = int_type(out); - } - this->setp(m_p, m_p + m_bufsize); - - // Write that one more character, if it's there. - if (ch != eof()) - { - *this->pptr() = static_cast(ch); - this->pbump(1); - } - return res; - } - - virtual int_type overflow() { return overflow(eof()); } - - virtual int_type underflow() override - { - if (this->gptr() == nullptr) - return eof(); - auto *const eb{this->eback()}; - auto const res{adjust_eof( - m_obj.cread(this->eback(), static_cast(m_bufsize)))}; - this->setg( - eb, eb, eb + (res == eof() ? 0 : static_cast(res))); - return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb); - } - -private: - /// Shortcut for traits_type::eof(). - static int_type eof() { return traits_type::eof(); } - - /// Helper: change error position of -1 to EOF (probably a no-op). - template static std::streampos adjust_eof(INTYPE pos) - { - bool const at_eof{pos == -1}; - if constexpr (std::is_arithmetic_v) - { - return check_cast( - (at_eof ? eof() : pos), "large object seek"sv); - } - else - { - return std::streampos(at_eof ? eof() : pos); - } - } - - void initialize(openmode mode) - { - if ((mode & std::ios::in) != 0) - { - m_g = new char_type[unsigned(m_bufsize)]; - this->setg(m_g, m_g, m_g); - } - if ((mode & std::ios::out) != 0) - { - m_p = new char_type[unsigned(m_bufsize)]; - this->setp(m_p, m_p + m_bufsize); - } - } - - size_type const m_bufsize; - largeobjectaccess m_obj; - - /// Get & put buffers. - char_type *m_g, *m_p; -}; - - -/// Input stream that gets its data from a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This class worked like any other istream, but to read data from a large - * object. It supported all formatting and streaming operations of - * `std::istream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_ilostream : public std::basic_istream -{ - using super = std::basic_istream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create a basic_ilostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_ilostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::in | std::ios::binary, buf_size} - { - super::init(&m_buf); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// Create a basic_ilostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Identifier of a large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_ilostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::in | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - -private: - largeobject_streambuf m_buf; -}; - -using ilostream = basic_ilostream; - - -/// Output stream that writes data back to a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This worked like any other ostream, but to write data to a large object. - * It supported all formatting and streaming operations of `std::ostream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_olostream : public std::basic_ostream -{ - using super = std::basic_ostream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// Create a basic_olostream. - /** - * @param t transaction in which this stream is to exist. - * @param o a large object to access. - * @param buf_size size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_olostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// Create a basic_olostream. - /** - * @param t transaction in which this stream is to exist. - * @param o a large object to access. - * @param buf_size size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_olostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{t, o, std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - ~basic_olostream() - { - try - { - m_buf.pubsync(); - m_buf.pubsync(); - } - catch (std::exception const &e) - { - m_buf.process_notice(e.what()); - } - } - -private: - largeobject_streambuf m_buf; -}; - -using olostream = basic_olostream; - - -/// Stream that reads and writes a large object. -/** @deprecated Access large objects directly using the @ref blob class. - * - * This worked like a std::iostream, but to read data from, or write data to, a - * large object. It supported all formatting and streaming operations of - * `std::iostream`. - * - * This functionality was considered too fragile and complex, so it has been - * replaced with a single, much simpler class. - */ -template> -class basic_lostream : public std::basic_iostream -{ - using super = std::basic_iostream; - -public: - using char_type = CHAR; - using traits_type = TRAITS; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; - - /// Create a basic_lostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_lostream( - dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{ - t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - /// Create a basic_lostream. - /** - * @param t Transaction in which this stream is to exist. - * @param o Large object to access. - * @param buf_size Size of buffer to use internally (optional). - */ - [[deprecated("Use blob instead.")]] basic_lostream( - dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : - super{nullptr}, - m_buf{ - t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size} - { - super::init(&m_buf); - } - - ~basic_lostream() - { - try - { - m_buf.pubsync(); - m_buf.pubsync(); - } - catch (std::exception const &e) - { - m_buf.process_notice(e.what()); - } - } - -private: - largeobject_streambuf m_buf; -}; - -using lostream = basic_lostream; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/nontransaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/nontransaction deleted file mode 100644 index bb5b79724..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/nontransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::nontransaction class. - * - * pqxx::nontransaction provides nontransactional database access. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/nontransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/nontransaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/nontransaction.hxx deleted file mode 100644 index c50715594..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/nontransaction.hxx +++ /dev/null @@ -1,76 +0,0 @@ -/* Definition of the pqxx::nontransaction class. - * - * pqxx::nontransaction provides nontransactional database access - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_NONTRANSACTION -#define PQXX_H_NONTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/connection.hxx" -#include "pqxx/result.hxx" -#include "pqxx/transaction.hxx" - -namespace pqxx -{ -using namespace std::literals; - -/// Simple "transaction" class offering no transactional integrity. -/** - * @ingroup transactions - * - * nontransaction, like transaction or any other transaction_base-derived - * class, provides access to a database through a connection. Unlike its - * siblings, however, nontransaction does not maintain any kind of - * transactional integrity. This may be useful eg. for read-only access to the - * database that does not require a consistent, atomic view on its data; or for - * operations that are not allowed within a backend transaction, such as - * creating tables. - * - * For queries that update the database, however, a real transaction is likely - * to be faster unless the transaction consists of only a single record update. - * - * Also, you can keep a nontransaction open for as long as you like. Actual - * back-end transactions are limited in lifespan, and will sometimes fail just - * because they took too long to execute or were left idle for too long. This - * will not happen with a nontransaction (although the connection may still - * time out, e.g. when the network is unavailable for a very long time). - * - * Any query executed in a nontransaction is committed immediately, and neither - * commit() nor abort() has any effect. - * - * Database features that require a backend transaction, such as cursors or - * large objects, will not work in a nontransaction. - */ -class PQXX_LIBEXPORT nontransaction final : public transaction_base -{ -public: - /// Constructor. - /** Create a "dummy" transaction. - * @param c Connection in which this "transaction" will operate. - * @param tname Optional tname for the transaction, beginning with a letter - * and containing only letters and digits. - */ - nontransaction(connection &c, std::string_view tname = ""sv) : - transaction_base{c, tname, std::shared_ptr{}} - { - register_transaction(); - } - - virtual ~nontransaction() override { close(); } - -private: - virtual void do_commit() override {} -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/notification b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/notification deleted file mode 100644 index a0bd1c73e..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/notification +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::notification_receiver functor interface. - * - * pqxx::notification_receiver handles incoming notifications. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/notification.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/notification.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/notification.hxx deleted file mode 100644 index b59b8567a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/notification.hxx +++ /dev/null @@ -1,94 +0,0 @@ -/* Definition of the pqxx::notification_receiver functor interface. - * - * pqxx::notification_receiver handles incoming notifications. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_NOTIFICATION -#define PQXX_H_NOTIFICATION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/types.hxx" - - -namespace pqxx -{ -/// "Observer" base class for notifications. -/** @addtogroup notification Notifications and Receivers - * - * To listen on a notification issued using the NOTIFY command, derive your own - * class from notification_receiver and define its function-call operator to - * perform whatever action you wish to take when the given notification - * arrives. Then create an object of that class and pass it to your connection. - * DO NOT use raw SQL to listen for notifications, or your attempts to listen - * won't be resumed when a connection fails--and you'll have no way to notice. - * - * Notifications never arrive inside a transaction, not even in a - * nontransaction. Therefore, you are free to open a transaction of your own - * inside your receiver's function invocation operator. - * - * Notifications you are listening for may arrive anywhere within libpqxx code, - * but be aware that **PostgreSQL defers notifications occurring inside - * transactions.** (This was done for excellent reasons; just think about what - * happens if the transaction where you happen to handle an incoming - * notification is later rolled back for other reasons). So if you're keeping - * a transaction open, don't expect any of your receivers on the same - * connection to be notified. - * - * (For very similar reasons, outgoing notifications are also not sent until - * the transaction that sends them commits.) - * - * Multiple receivers on the same connection may listen on a notification of - * the same name. An incoming notification is processed by invoking all - * receivers (zero or more) of the same name. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver -{ -public: - /// Register the receiver with a connection. - /** - * @param c Connnection to operate on. - * @param channel Name of the notification to listen for. - */ - notification_receiver(connection &c, std::string_view channel); - /// Register the receiver with a connection. - notification_receiver(notification_receiver const &) = delete; - /// Register the receiver with a connection. - notification_receiver &operator=(notification_receiver const &) = delete; - /// Deregister the receiver. - virtual ~notification_receiver(); - - /// The channel that this receiver listens on. - [[nodiscard]] std::string const &channel() const & { return m_channel; } - - // TODO: Change API to take payload as zview instead of string ref. - /// Overridable: action to invoke when notification arrives. - /** - * @param payload An optional string that may have been passed to the NOTIFY - * command. - * @param backend_pid Process ID of the database backend process that served - * our connection when the notification arrived. The actual process ID - * behind the connection may have changed by the time this method is called. - */ - virtual void operator()(std::string const &payload, int backend_pid) = 0; - -protected: - connection &conn() const noexcept { return m_conn; } - -private: - connection &m_conn; - std::string m_channel; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/params b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/params deleted file mode 100644 index 4098782aa..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/params +++ /dev/null @@ -1,8 +0,0 @@ -/** Helper classes for passing statement parameters. - * - * Use these for prepared statements and parameterised statements. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/params.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/params.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/params.hxx deleted file mode 100644 index 2d29cdfed..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/params.hxx +++ /dev/null @@ -1,383 +0,0 @@ -/* Helpers for prepared statements and parameterised statements. - * - * See the connection class for more about such statements. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_PARAMS -#define PQXX_H_PARAMS - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/statement_parameters.hxx" -#include "pqxx/types.hxx" - - -/// @deprecated The new @ref params class replaces all of this. -namespace pqxx::prepare -{ -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * sequence ranging from `begin` to `end` exclusively. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic sequences. - * - * @param begin A pointer or iterator for iterating parameters. - * @param end A pointer or iterator for iterating parameters. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(IT begin, IT end) -{ - return pqxx::internal::dynamic_params(begin, end); -} - - -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * container of parameter values. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic containers. - * - * @param container A container of parameter values. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(C const &container) -{ - using IT = typename C::const_iterator; -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return pqxx::internal::dynamic_params{container}; -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -/// Pass a number of statement parameters only known at runtime. -/** @deprecated Use @ref params instead. - * - * When you call any of the `exec_params` functions, the number of arguments - * is normally known at compile time. This helper function supports the case - * where it is not. - * - * Use this function to pass a variable number of parameters, based on a - * container of parameter values. - * - * The technique combines with the regular static parameters. You can use it - * to insert dynamic parameter lists in any place, or places, among the call's - * parameters. You can even insert multiple dynamic containers. - * - * @param container A container of parameter values. - * @param accessor For each parameter `p`, pass `accessor(p)`. - * @return An object representing the parameters. - */ -template -[[deprecated("Use the params class instead.")]] constexpr inline auto -make_dynamic_params(C &container, ACCESSOR accessor) -{ - using IT = decltype(std::begin(container)); -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return pqxx::internal::dynamic_params{container, accessor}; -#include "pqxx/internal/ignore-deprecated-post.hxx" -} -} // namespace pqxx::prepare - - -namespace pqxx -{ -/// Generate parameter placeholders for use in an SQL statement. -/** When you want to pass parameters to a prepared statement or a parameterised - * statement, you insert placeholders into the SQL. During invocation, the - * database replaces those with the respective parameter values you passed. - * - * The placeholders look like `$1` (for the first parameter value), `$2` (for - * the second), and so on. You can just write those directly in your - * statement. But for those rare cases where it becomes difficult to track - * which number a placeholder should have, you can use a `placeholders` object - * to count and generate them in order. - */ -template class placeholders -{ -public: - /// Maximum number of parameters we support. - static inline constexpr unsigned int max_params{ - (std::numeric_limits::max)()}; - - placeholders() - { - static constexpr auto initial{"$1\0"sv}; - initial.copy(std::data(m_buf), std::size(initial)); - } - - /// Read an ephemeral version of the current placeholder text. - /** @warning Changing the current placeholder number will overwrite this. - * Use the view immediately, or lose it. - */ - constexpr zview view() const &noexcept - { - return zview{std::data(m_buf), m_len}; - } - - /// Read the current placeholder text, as a `std::string`. - /** This will be slightly slower than converting to a `zview`. With most - * C++ implementations however, until you get into ridiculous numbers of - * parameters, the string will benefit from the Short String Optimization, or - * SSO. - */ - std::string get() const { return std::string(std::data(m_buf), m_len); } - - /// Move on to the next parameter. - void next() & - { - if (m_current >= max_params) - throw range_error{pqxx::internal::concat( - "Too many parameters in one statement: limit is ", max_params, ".")}; - ++m_current; - if (m_current % 10 == 0) - { - // Carry the 1. Don't get too clever for this relatively rare - // case, just rewrite the entire number. Leave the $ in place - // though. - char *const data{std::data(m_buf)}; - char *const end{string_traits::into_buf( - data + 1, data + std::size(m_buf), m_current)}; - // (Subtract because we don't include the trailing zero.) - m_len = check_cast(end - data, "placeholders counter") - 1; - } - else - { - PQXX_LIKELY - // Shortcut for the common case: just increment that last digit. - ++m_buf[m_len - 1]; - } - } - - /// Return the current placeholder number. The initial placeholder is 1. - COUNTER count() const noexcept { return m_current; } - -private: - /// Current placeholder number. Starts at 1. - COUNTER m_current = 1; - - /// Length of the current placeholder string, not including trailing zero. - COUNTER m_len = 2; - - /// Text buffer where we render the placeholders, with a trailing zero. - /** We keep reusing this for every subsequent placeholder, just because we - * don't like string allocations. - * - * Maximum length is the maximum base-10 digits that COUNTER can fully - * represent, plus 1 more for the extra digit that it can only partially - * fill up, plus room for the dollar sign and the trailing zero. - */ - std::array::digits10 + 3> m_buf; -}; - - -/// Build a parameter list for a parameterised or prepared statement. -/** When calling a parameterised statement or a prepared statement, you can - * pass parameters into the statement directly in the invocation, as - * additional arguments to `exec_prepared` or `exec_params`. But in - * complex cases, sometimes that's just not convenient. - * - * In those situations, you can create a `params` and append your parameters - * into that, one by one. Then you pass the `params` to `exec_prepared` or - * `exec_params`. - * - * Combinations also work: if you have a `params` containing a string - * parameter, and you call `exec_params` with an `int` argument followed by - * your `params`, you'll be passing the `int` as the first parameter and - * the string as the second. You can even insert a `params` in a `params`, - * or pass two `params` objects to a statement. - */ -class PQXX_LIBEXPORT params -{ -public: - params() = default; - - /// Pre-populate a `params` with `args`. Feel free to add more later. - template constexpr params(Args &&...args) - { - reserve(sizeof...(args)); - append_pack(std::forward(args)...); - } - - /// Pre-allocate room for at least `n` parameters. - /** This is not needed, but it may improve efficiency. - * - * Reserve space if you're going to add parameters individually, and you've - * got some idea of how many there are going to be. It may save some - * memory re-allocations. - */ - void reserve(std::size_t n) &; - - // C++20: constexpr. - /// Get the number of parameters currently in this `params`. - [[nodiscard]] auto size() const noexcept { return m_params.size(); } - - // C++20: Use the vector's ssize() directly and go noexcept+constexpr. - /// Get the number of parameters (signed). - /** Unlike `size()`, this is not yet `noexcept`. That's because C++17's - * `std::vector` does not have a `ssize()` member function. These member - * functions are `noexcept`, but `std::size()` and `std::ssize()` are - * not. - */ - [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params); } - - /// Append a null value. - void append() &; - - /// Append a non-null zview parameter. - /** The underlying data must stay valid for as long as the `params` - * remains active. - */ - void append(zview) &; - - /// Append a non-null string parameter. - /** Copies the underlying data into internal storage. For best efficiency, - * use the @ref zview variant if you can, or `std::move()` - */ - void append(std::string const &) &; - - /// Append a non-null string parameter. - void append(std::string &&) &; - - /// Append a non-null binary parameter. - /** The underlying data must stay valid for as long as the `params` - * remains active. - */ - void append(std::basic_string_view) &; - - /// Append a non-null binary parameter. - /** Copies the underlying data into internal storage. For best efficiency, - * use the `std::basic_string_view` variant if you can, or - * `std::move()`. - */ - void append(std::basic_string const &) &; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Append a non-null binary parameter. - /** The `data` object must stay in place and unchanged, for as long as the - * `params` remains active. - */ - template void append(DATA const &data) & - { - append( - std::basic_string_view{std::data(data), std::size(data)}); - } -#endif // PQXX_HAVE_CONCEPTS - - /// Append a non-null binary parameter. - void append(std::basic_string &&) &; - - /// @deprecated Append binarystring parameter. - /** The binarystring must stay valid for as long as the `params` remains - * active. - */ - void append(binarystring const &value) &; - - /// Append all parameters from value. - template - void append(pqxx::internal::dynamic_params const &value) & - { - for (auto ¶m : value) append(value.access(param)); - } - - void append(params const &value) &; - - void append(params &&value) &; - - /// Append a non-null parameter, converting it to its string - /// representation. - template void append(TYPE const &value) & - { - // TODO: Pool storage for multiple string conversions in one buffer? - if constexpr (nullness>::always_null) - { - ignore_unused(value); - m_params.emplace_back(); - } - else if (is_null(value)) - { - m_params.emplace_back(); - } - else - { - m_params.emplace_back(entry{to_string(value)}); - } - } - - /// Append all elements of `range` as parameters. - template void append_multi(RANGE const &range) & - { -#if defined(PQXX_HAVE_CONCEPTS) - if constexpr (std::ranges::sized_range) - reserve(std::size(*this) + std::size(range)); -#endif - for (auto &value : range) append(value); - } - - /// For internal use: Generate a `params` object for use in calls. - /** The params object encapsulates the pointers which we will need to pass - * to libpq when calling a parameterised or prepared statement. - * - * The pointers in the params will refer to storage owned by either the - * params object, or the caller. This is not a problem because a - * `c_params` object is guaranteed to live only while the call is going on. - * As soon as we climb back out of that call tree, we're done with that - * data. - */ - pqxx::internal::c_params make_c_params() const; - -private: - /// Recursively append a pack of params. - template - void append_pack(Arg &&arg, More &&...args) - { - this->append(std::forward(arg)); - // Recurse for remaining args. - append_pack(std::forward(args)...); - } - - /// Terminating case: append an empty parameter pack. It's not hard BTW. - constexpr void append_pack() noexcept {} - - // The way we store a parameter depends on whether it's binary or text - // (most types are text), and whether we're responsible for storing the - // contents. - using entry = std::variant< - std::nullptr_t, zview, std::string, std::basic_string_view, - std::basic_string>; - std::vector m_params; - - static constexpr std::string_view s_overflow{ - "Statement parameter length overflow."sv}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pipeline b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pipeline deleted file mode 100644 index bf828843a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pipeline +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::pipeline class. - * - * Throughput-optimized query interface. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/pipeline.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pipeline.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pipeline.hxx deleted file mode 100644 index 049dcdd58..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pipeline.hxx +++ /dev/null @@ -1,237 +0,0 @@ -/* Definition of the pqxx::pipeline class. - * - * Throughput-optimized mechanism for executing queries. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_PIPELINE -#define PQXX_H_PIPELINE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -// TODO: libpq 14 introduced a similar "pipeline mode." Can we use that? - -/// Processes several queries in FIFO manner, optimized for high throughput. -/** Use a pipeline if you want to keep doing useful work while your queries are - * executing. Result retrieval is decoupled from execution request; queries - * "go in at the front" and results "come out the back." - * - * Actually, you can retrieve the results in any order if you want, but it may - * lead to surprising "time travel" effects if any of the queries fails. In - * particular, syntax errors in the queries can confuse things and show up too - * early in the stream of results. - * - * Generally, if any of the queries fails, it will throw an exception at the - * point where you request its result. But it may happen earlier, especially - * if you request results out of chronological order. - * - * @warning While a pipeline is active, you cannot execute queries, open - * streams, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT pipeline : public transaction_focus -{ -public: - /// Identifying numbers for queries. - using query_id = long; - - pipeline(pipeline const &) = delete; - pipeline &operator=(pipeline const &) = delete; - - /// Start a pipeline. - explicit pipeline(transaction_base &t) : transaction_focus{t, s_classname} - { - init(); - } - /// Start a pipeline. Assign it a name, for more helpful error messages. - pipeline(transaction_base &t, std::string_view tname) : - transaction_focus{t, s_classname, tname} - { - init(); - } - - /// Close the pipeline. - ~pipeline() noexcept; - - /// Add query to the pipeline. - /** Queries accumulate in the pipeline, which sends them to the backend in a - * batch separated by semicolons. The queries you insert must not use this - * trick themselves, or the pipeline will get hopelessly confused! - * - * @return Identifier for this query, unique only within this pipeline. - */ - query_id insert(std::string_view) &; - - /// Wait for all ongoing or pending operations to complete, and detach. - /** Detaches from the transaction when done. - * - * This does not produce the queries' results, so it may not report any - * errors which may have occurred in their execution. To be sure that your - * statements succeeded, call @ref retrieve until the pipeline is empty. - */ - void complete(); - - /// Forget all ongoing or pending operations and retrieved results. - /** Queries already sent to the backend may still be completed, depending - * on implementation and timing. - * - * Any error state (unless caused by an internal error) will also be cleared. - * This is mostly useful in a nontransaction, since a backend transaction is - * aborted automatically when an error occurs. - * - * Detaches from the transaction when done. - */ - void flush(); - - /// Cancel ongoing query, if any. - /** May cancel any or all of the queries that have been inserted at this - * point whose results have not yet been retrieved. If the pipeline lives in - * a backend transaction, that transaction may be left in a nonfunctional - * state in which it can only be aborted. - * - * Therefore, either use this function in a nontransaction, or abort the - * transaction after calling it. - */ - void cancel(); - - /// Is result for given query available? - [[nodiscard]] bool is_finished(query_id) const; - - /// Retrieve result for given query. - /** If the query failed for whatever reason, this will throw an exception. - * The function will block if the query has not finished yet. - * @warning If results are retrieved out-of-order, i.e. in a different order - * than the one in which their queries were inserted, errors may "propagate" - * to subsequent queries. - */ - result retrieve(query_id qid) - { - return retrieve(m_queries.find(qid)).second; - } - - /// Retrieve oldest unretrieved result (possibly wait for one). - /** @return The query's identifier and its result set. */ - std::pair retrieve(); - - [[nodiscard]] bool empty() const noexcept { return std::empty(m_queries); } - - /// Set maximum number of queries to retain before issuing them to the - /// backend. - /** The pipeline will perform better if multiple queries are issued at once, - * but retaining queries until the results are needed (as opposed to issuing - * them to the backend immediately) may negate any performance benefits the - * pipeline can offer. - * - * Recommended practice is to set this value no higher than the number of - * queries you intend to insert at a time. - * @param retain_max A nonnegative "retention capacity;" passing zero will - * cause queries to be issued immediately - * @return Old retention capacity - */ - int retain(int retain_max = 2) &; - - - /// Resume retained query emission. Harmless when not needed. - void resume() &; - -private: - struct PQXX_PRIVATE Query - { - explicit Query(std::string_view q) : - query{std::make_shared(q)} - {} - - std::shared_ptr query; - result res; - }; - - using QueryMap = std::map; - - void init(); - void attach(); - void detach(); - - /// Upper bound to query id's. - static constexpr query_id qid_limit() noexcept - { - // Parenthesise this to work around an eternal Visual C++ problem: - // Without the extra parentheses, unless NOMINMAX is defined, the - // preprocessor will mistake this "max" for its annoying built-in macro - // of the same name. - return (std::numeric_limits::max)(); - } - - /// Create new query_id. - PQXX_PRIVATE query_id generate_id(); - - bool have_pending() const noexcept - { - return m_issuedrange.second != m_issuedrange.first; - } - - PQXX_PRIVATE void issue(); - - /// The given query failed; never issue anything beyond that. - void set_error_at(query_id qid) noexcept - { - PQXX_UNLIKELY - if (qid < m_error) - m_error = qid; - } - - /// Throw pqxx::internal_error. - [[noreturn]] PQXX_PRIVATE void internal_error(std::string const &err); - - PQXX_PRIVATE bool obtain_result(bool expect_none = false); - - PQXX_PRIVATE void obtain_dummy(); - PQXX_PRIVATE void get_further_available_results(); - PQXX_PRIVATE void check_end_results(); - - /// Receive any results that happen to be available; it's not urgent. - PQXX_PRIVATE void receive_if_available(); - - /// Receive results, up to stop if possible. - PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop); - std::pair retrieve(pipeline::QueryMap::iterator); - - QueryMap m_queries; - std::pair m_issuedrange; - int m_retain = 0; - int m_num_waiting = 0; - query_id m_q_id = 0; - - /// Is there a "dummy query" pending? - bool m_dummy_pending = false; - - /// Point at which an error occurred; no results beyond it will be available - query_id m_error = qid_limit(); - - /// Encoding. - /** We store this in the object to avoid the risk of exceptions at awkward - * moments. - */ - internal::encoding_group m_encoding; - - static constexpr std::string_view s_classname{"pipeline"}; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pqxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pqxx deleted file mode 100644 index 17a8eaa9c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/pqxx +++ /dev/null @@ -1,28 +0,0 @@ -/// Convenience header: include all libpqxx definitions. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/array.hxx" -#include "pqxx/binarystring.hxx" -#include "pqxx/blob.hxx" -#include "pqxx/connection.hxx" -#include "pqxx/cursor.hxx" -#include "pqxx/errorhandler.hxx" -#include "pqxx/except.hxx" -#include "pqxx/largeobject.hxx" -#include "pqxx/nontransaction.hxx" -#include "pqxx/notification.hxx" -#include "pqxx/params.hxx" -#include "pqxx/pipeline.hxx" -#include "pqxx/prepared_statement.hxx" -#include "pqxx/result.hxx" -#include "pqxx/internal/result_iterator.hxx" -#include "pqxx/internal/result_iter.hxx" -#include "pqxx/robusttransaction.hxx" -#include "pqxx/row.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/stream_to.hxx" -#include "pqxx/subtransaction.hxx" -#include "pqxx/transaction.hxx" -#include "pqxx/transactor.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/prepared_statement b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/prepared_statement deleted file mode 100644 index 674be7090..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/prepared_statement +++ /dev/null @@ -1,3 +0,0 @@ -/// @deprecated Include @c instead. - -#include "params.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/prepared_statement.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/prepared_statement.hxx deleted file mode 100644 index 674be7090..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/prepared_statement.hxx +++ /dev/null @@ -1,3 +0,0 @@ -/// @deprecated Include @c instead. - -#include "params.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/range b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/range deleted file mode 100644 index 11985eca4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/range +++ /dev/null @@ -1,6 +0,0 @@ -/** Client-side support for SQL range types. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/range.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/range.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/range.hxx deleted file mode 100644 index dc480e4b7..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/range.hxx +++ /dev/null @@ -1,515 +0,0 @@ -#ifndef PQXX_H_RANGE -#define PQXX_H_RANGE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include - -#include "pqxx/internal/array-composite.hxx" -#include "pqxx/internal/concat.hxx" - -namespace pqxx -{ -/// An _unlimited_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should extend - * to infinity on that side. - * - * An unlimited boundary is always inclusive of "infinity" values, if the - * range's value type supports them. - */ -struct no_bound -{ - template constexpr bool extends_down_to(TYPE const &) const - { - return true; - } - template constexpr bool extends_up_to(TYPE const &) const - { - return true; - } -}; - - -/// An _inclusive_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should include - * the value. - */ -template class inclusive_bound -{ -public: - inclusive_bound() = delete; - explicit inclusive_bound(TYPE const &value) : m_value{value} - { - if (is_null(value)) - throw argument_error{"Got null value as an inclusive range bound."}; - } - - [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as a lower bound, include value? - [[nodiscard]] bool extends_down_to(TYPE const &value) const - { - return not(value < m_value); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as an upper bound, include value? - [[nodiscard]] bool extends_up_to(TYPE const &value) const - { - return not(m_value < value); - } - -private: - TYPE m_value; -}; - - -/// An _exclusive_ boundary value to a @ref pqxx::range. -/** Use this as a lower or upper bound for a range if the range should _not_ - * include the value. - */ -template class exclusive_bound -{ -public: - exclusive_bound() = delete; - explicit exclusive_bound(TYPE const &value) : m_value{value} - { - if (is_null(value)) - throw argument_error{"Got null value as an exclusive range bound."}; - } - - [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as a lower bound, include value? - [[nodiscard]] bool extends_down_to(TYPE const &value) const - { - return m_value < value; - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Would this bound, as an upper bound, include value? - [[nodiscard]] bool extends_up_to(TYPE const &value) const - { - return value < m_value; - } - -private: - TYPE m_value; -}; - - -/// A range boundary value. -/** A range bound is either no bound at all; or an inclusive bound; or an - * exclusive bound. Pass one of the three to the constructor. - */ -template class range_bound -{ -public: - range_bound() = delete; - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(no_bound) : m_bound{} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(inclusive_bound const &bound) : m_bound{bound} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(exclusive_bound const &bound) : m_bound{bound} {} - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(range_bound const &) = default; - // TODO: constexpr and/or noexcept if underlying constructor supports it. - range_bound(range_bound &&) = default; - - // TODO: constexpr and/or noexcept if underlying operators support it. - bool operator==(range_bound const &rhs) const - { - if (this->is_limited()) - return ( - rhs.is_limited() and (this->is_inclusive() == rhs.is_inclusive()) and - (*this->value() == *rhs.value())); - else - return not rhs.is_limited(); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - bool operator!=(range_bound const &rhs) const { return not(*this == rhs); } - range_bound &operator=(range_bound const &) = default; - range_bound &operator=(range_bound &&) = default; - - /// Is this a finite bound? - constexpr bool is_limited() const noexcept - { - return not std::holds_alternative(m_bound); - } - - /// Is this boundary an inclusive one? - constexpr bool is_inclusive() const noexcept - { - return std::holds_alternative>(m_bound); - } - - /// Is this boundary an exclusive one? - constexpr bool is_exclusive() const noexcept - { - return std::holds_alternative>(m_bound); - } - - // TODO: constexpr/noexcept if underlying function supports it. - /// Would this bound, as a lower bound, include `value`? - bool extends_down_to(TYPE const &value) const - { - return std::visit( - [&value](auto const &bound) { return bound.extends_down_to(value); }, - m_bound); - } - - // TODO: constexpr/noexcept if underlying function supports it. - /// Would this bound, as an upper bound, include `value`? - bool extends_up_to(TYPE const &value) const - { - return std::visit( - [&value](auto const &bound) { return bound.extends_up_to(value); }, - m_bound); - } - - /// Return bound value, or `nullptr` if it's not limited. - [[nodiscard]] constexpr TYPE const *value() const &noexcept - { - return std::visit( - [](auto const &bound) noexcept { - using bound_t = std::decay_t; - if constexpr (std::is_same_v) - return static_cast(nullptr); - else - return &bound.get(); - }, - m_bound); - } - -private: - std::variant, exclusive_bound> m_bound; -}; - - -// C++20: Concepts for comparisons, construction, etc. -/// A C++ equivalent to PostgreSQL's range types. -/** You can use this as a client-side representation of a "range" in SQL. - * - * PostgreSQL defines several range types, differing in the data type over - * which they range. You can also define your own range types. - * - * Usually you'll want the server to deal with ranges. But on occasions where - * you need to work with them client-side, you may want to use @ref - * pqxx::range. (In cases where all you do is pass them along to the server - * though, it's not worth the complexity. In that case you might as well treat - * ranges as just strings.) - * - * For documentation on PostgreSQL's range types, see: - * https://www.postgresql.org/docs/current/rangetypes.html - * - * The value type must be copyable and default-constructible, and support the - * less-than (`<`) and equals (`==`) comparisons. Value initialisation must - * produce a consistent value. - */ -template class range -{ -public: - /// Create a range. - /** For each of the two bounds, pass a @ref no_bound, @ref inclusive_bound, - * or - * @ref exclusive_bound. - */ - range(range_bound lower, range_bound upper) : - m_lower{lower}, m_upper{upper} - { - if ( - lower.is_limited() and upper.is_limited() and - (*upper.value() < *lower.value())) - throw range_error{internal::concat( - "Range's lower bound (", *lower.value(), - ") is greater than its upper bound (", *upper.value(), ").")}; - } - - // TODO: constexpr and/or noexcept if underlying constructor supports it. - /// Create an empty range. - /** SQL has a separate literal to denote an empty range, but any range which - * encompasses no values is an empty range. - */ - range() : - m_lower{exclusive_bound{TYPE{}}}, - m_upper{exclusive_bound{TYPE{}}} - {} - - // TODO: constexpr and/or noexcept if underlying operators support it. - bool operator==(range const &rhs) const - { - return (this->lower_bound() == rhs.lower_bound() and - this->upper_bound() == rhs.upper_bound()) or - (this->empty() and rhs.empty()); - } - - // TODO: constexpr and/or noexcept if underlying operator supports it. - bool operator!=(range const &rhs) const { return !(*this == rhs); } - - range(range const &) = default; - range(range &&) = default; - range &operator=(range const &) = default; - range &operator=(range &&) = default; - - // TODO: constexpr and/or noexcept if underlying operator supports it. - /// Is this range clearly empty? - /** An empty range encompasses no values. - * - * It is possible to "fool" this. For example, if your range is of an - * integer type and has exclusive bounds of 0 and 1, it encompasses no values - * but its `empty()` will return false. The PostgreSQL implementation, by - * contrast, will notice that it is empty. Similar things can happen for - * floating-point types, but with more subtleties and edge cases. - */ - bool empty() const - { - return (m_lower.is_exclusive() or m_upper.is_exclusive()) and - m_lower.is_limited() and m_upper.is_limited() and - not(*m_lower.value() < *m_upper.value()); - } - - // TODO: constexpr and/or noexcept if underlying functions support it. - /// Does this range encompass `value`? - bool contains(TYPE value) const - { - return m_lower.extends_down_to(value) and m_upper.extends_up_to(value); - } - - // TODO: constexpr and/or noexcept if underlying operators support it. - /// Does this range encompass all of `other`? - /** This function is not particularly smart. It does not know, for example, - * that integer ranges `[0,9]` and `[0,10)` contain the same values. - */ - bool contains(range const &other) const - { - return (*this & other) == other; - } - - [[nodiscard]] constexpr range_bound const & - lower_bound() const &noexcept - { - return m_lower; - } - [[nodiscard]] constexpr range_bound const & - upper_bound() const &noexcept - { - return m_upper; - } - - // TODO: constexpr and/or noexcept if underlying operators support it. - /// Intersection of two ranges. - /** Returns a range describing those values which are in both ranges. - */ - range operator&(range const &other) const - { - range_bound lower{no_bound{}}; - if (not this->lower_bound().is_limited()) - lower = other.lower_bound(); - else if (not other.lower_bound().is_limited()) - lower = this->lower_bound(); - else if (*this->lower_bound().value() < *other.lower_bound().value()) - lower = other.lower_bound(); - else if (*other.lower_bound().value() < *this->lower_bound().value()) - lower = this->lower_bound(); - else if (this->lower_bound().is_exclusive()) - lower = this->lower_bound(); - else - lower = other.lower_bound(); - - range_bound upper{no_bound{}}; - if (not this->upper_bound().is_limited()) - upper = other.upper_bound(); - else if (not other.upper_bound().is_limited()) - upper = this->upper_bound(); - else if (*other.upper_bound().value() < *this->upper_bound().value()) - upper = other.upper_bound(); - else if (*this->upper_bound().value() < *other.upper_bound().value()) - upper = this->upper_bound(); - else if (this->upper_bound().is_exclusive()) - upper = this->upper_bound(); - else - upper = other.upper_bound(); - - if ( - lower.is_limited() and upper.is_limited() and - (*upper.value() < *lower.value())) - return {}; - else - return {lower, upper}; - } - - /// Convert to another base type. - template operator range() const - { - range_bound lower{no_bound{}}, upper{no_bound{}}; - if (lower_bound().is_inclusive()) - lower = inclusive_bound{*lower_bound().value()}; - else if (lower_bound().is_exclusive()) - lower = exclusive_bound{*lower_bound().value()}; - - if (upper_bound().is_inclusive()) - upper = inclusive_bound{*upper_bound().value()}; - else if (upper_bound().is_exclusive()) - upper = exclusive_bound{*upper_bound().value()}; - - return {lower, upper}; - } - -private: - range_bound m_lower, m_upper; -}; - - -/// String conversions for a @ref range type. -/** Conversion assumes that either your client encoding is UTF-8, or the values - * are pure ASCII. - */ -template struct string_traits> -{ - [[nodiscard]] static inline zview - to_buf(char *begin, char *end, range const &value) - { - return generic_to_buf(begin, end, value); - } - - static inline char * - into_buf(char *begin, char *end, range const &value) - { - if (value.empty()) - { - if ((end - begin) <= internal::ssize(s_empty)) - throw conversion_overrun{s_overrun.c_str()}; - char *here = begin + s_empty.copy(begin, std::size(s_empty)); - *here++ = '\0'; - return here; - } - else - { - if (end - begin < 4) - throw conversion_overrun{s_overrun.c_str()}; - char *here = begin; - *here++ = - (static_cast(value.lower_bound().is_inclusive() ? '[' : '(')); - TYPE const *lower{value.lower_bound().value()}; - // Convert bound (but go back to overwrite that trailing zero). - if (lower != nullptr) - here = string_traits::into_buf(here, end, *lower) - 1; - *here++ = ','; - TYPE const *upper{value.upper_bound().value()}; - // Convert bound (but go back to overwrite that trailing zero). - if (upper != nullptr) - here = string_traits::into_buf(here, end, *upper) - 1; - if ((end - here) < 2) - throw conversion_overrun{s_overrun.c_str()}; - *here++ = - static_cast(value.upper_bound().is_inclusive() ? ']' : ')'); - *here++ = '\0'; - return here; - } - } - - [[nodiscard]] static inline range from_string(std::string_view text) - { - if (std::size(text) < 3) - throw pqxx::conversion_error{err_bad_input(text)}; - bool left_inc{false}; - switch (text[0]) - { - case '[': left_inc = true; break; - - case '(': break; - - case 'e': - case 'E': - if ( - (std::size(text) != std::size(s_empty)) or - (text[1] != 'm' and text[1] != 'M') or - (text[2] != 'p' and text[2] != 'P') or - (text[3] != 't' and text[3] != 'T') or - (text[4] != 'y' and text[4] != 'Y')) - throw pqxx::conversion_error{err_bad_input(text)}; - return {}; - break; - - default: throw pqxx::conversion_error{err_bad_input(text)}; - } - - auto scan{internal::get_glyph_scanner(internal::encoding_group::UTF8)}; - // The field parser uses this to track which field it's parsing, and - // when not to expect a field separator. - std::size_t index{0}; - // The last field we expect to see. - static constexpr std::size_t last{1}; - // Current parsing position. We skip the opening parenthesis or bracket. - std::size_t pos{1}; - // The string may leave out either bound to indicate that it's unlimited. - std::optional lower, upper; - // We reuse the same field parser we use for composite values and arrays. - internal::parse_composite_field(index, text, pos, lower, scan, last); - internal::parse_composite_field(index, text, pos, upper, scan, last); - - // We need one more character: the closing parenthesis or bracket. - if (pos != std::size(text)) - throw pqxx::conversion_error{err_bad_input(text)}; - char const closing{text[pos - 1]}; - if (closing != ')' and closing != ']') - throw pqxx::conversion_error{err_bad_input(text)}; - bool const right_inc{closing == ']'}; - - range_bound lower_bound{no_bound{}}, upper_bound{no_bound{}}; - if (lower) - { - if (left_inc) - lower_bound = inclusive_bound{*lower}; - else - lower_bound = exclusive_bound{*lower}; - } - if (upper) - { - if (right_inc) - upper_bound = inclusive_bound{*upper}; - else - upper_bound = exclusive_bound{*upper}; - } - - return {lower_bound, upper_bound}; - } - - [[nodiscard]] static inline constexpr std::size_t - size_buffer(range const &value) noexcept - { - TYPE const *lower{value.lower_bound().value()}, - *upper{value.upper_bound().value()}; - std::size_t const lsz{ - lower == nullptr ? 0 : string_traits::size_buffer(*lower) - 1}, - usz{upper == nullptr ? 0 : string_traits::size_buffer(*upper) - 1}; - - if (value.empty()) - return std::size(s_empty) + 1; - else - return 1 + lsz + 1 + usz + 2; - } - -private: - static constexpr zview s_empty{"empty"_zv}; - static constexpr auto s_overrun{"Not enough space in buffer for range."_zv}; - - /// Compose error message for invalid range input. - static std::string err_bad_input(std::string_view text) - { - return internal::concat("Invalid range input: '", text, "'"); - } -}; - - -/// A range type does not have an innate null value. -template struct nullness> : no_null> -{}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/result b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/result deleted file mode 100644 index 523394b72..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/result +++ /dev/null @@ -1,16 +0,0 @@ -/** pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/result.hxx" - -// Now include some types which depend on result, but which the user will -// expect to see defined after including this header. -#include "pqxx/internal/result_iterator.hxx" -#include "pqxx/field.hxx" -#include "pqxx/internal/result_iter.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/result.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/result.hxx deleted file mode 100644 index 6c41cc096..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/result.hxx +++ /dev/null @@ -1,335 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_RESULT -#define PQXX_H_RESULT - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include - -#include "pqxx/except.hxx" -#include "pqxx/types.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - -#include "pqxx/internal/encodings.hxx" - - -namespace pqxx::internal -{ -// TODO: Make noexcept (but breaks ABI). -PQXX_LIBEXPORT void clear_result(pq::PGresult const *); -} // namespace pqxx::internal - - -namespace pqxx::internal::gate -{ -class result_connection; -class result_creation; -class result_pipeline; -class result_row; -class result_sql_cursor; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -/// Result set containing data returned by a query or command. -/** This behaves as a container (as defined by the C++ standard library) and - * provides random access const iterators to iterate over its rows. You can - * also access a row by indexing a `result R` by the row's zero-based - * number: - * - * - * for (result::size_type i=0; i < std::size(R); ++i) Process(R[i]); - * - * - * Result sets in libpqxx are lightweight, reference-counted wrapper objects - * which are relatively small and cheap to copy. Think of a result object as - * a "smart pointer" to an underlying result set. - * - * @warning The result set that a result object points to is not thread-safe. - * If you copy a result object, it still refers to the same underlying result - * set. So never copy, destroy, query, or otherwise access a result while - * another thread may be copying, destroying, querying, or otherwise accessing - * the same result set--even if it is doing so through a different result - * object! - */ -class PQXX_LIBEXPORT result -{ -public: - using size_type = result_size_type; - using difference_type = result_difference_type; - using reference = row; - using const_iterator = const_result_iterator; - using pointer = const_iterator; - using iterator = const_iterator; - using const_reverse_iterator = const_reverse_result_iterator; - using reverse_iterator = const_reverse_iterator; - - result() noexcept : - m_data{make_data_pointer()}, - m_query{}, - m_encoding{internal::encoding_group::MONOBYTE} - {} - - result(result const &rhs) noexcept = default; - result(result &&rhs) noexcept = default; - - /// Assign one result to another. - /** Copying results is cheap: it copies only smart pointers, but the actual - * data stays in the same place. - */ - result &operator=(result const &rhs) noexcept = default; - - /// Assign one result to another, invaliding the old one. - result &operator=(result &&rhs) noexcept = default; - - /** - * @name Comparisons - * - * You can compare results for equality. Beware: this is a very strict, - * dumb comparison. The smallest difference between two results (such as a - * string "Foo" versus a string "foo") will make them unequal. - */ - //@{ - /// Compare two results for equality. - [[nodiscard]] bool operator==(result const &) const noexcept; - /// Compare two results for inequality. - [[nodiscard]] bool operator!=(result const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - /// Iterate rows, reading them directly into a tuple of "TYPE...". - /** Converts the fields to values of the given respective types. - * - * Use this only with a ranged "for" loop. The iteration produces - * std::tuple which you can "unpack" to a series of `auto` - * variables. - */ - template auto iter() const; - - [[nodiscard]] const_reverse_iterator rbegin() const; - [[nodiscard]] const_reverse_iterator crbegin() const; - [[nodiscard]] const_reverse_iterator rend() const; - [[nodiscard]] const_reverse_iterator crend() const; - - [[nodiscard]] const_iterator begin() const noexcept; - [[nodiscard]] const_iterator cbegin() const noexcept; - [[nodiscard]] inline const_iterator end() const noexcept; - [[nodiscard]] inline const_iterator cend() const noexcept; - - [[nodiscard]] reference front() const noexcept; - [[nodiscard]] reference back() const noexcept; - - [[nodiscard]] PQXX_PURE size_type size() const noexcept; - [[nodiscard]] PQXX_PURE bool empty() const noexcept; - [[nodiscard]] size_type capacity() const noexcept { return size(); } - - /// Exchange two `result` values in an exception-safe manner. - /** If the swap fails, the two values will be exactly as they were before. - * - * The swap is not necessarily thread-safe. - */ - void swap(result &) noexcept; - - /// Index a row by number. - /** This returns a @ref row object. Generally you should not keep the row - * around as a variable, but if you do, make sure that your variable is a - * `row`, not a `row&`. - */ - [[nodiscard]] row operator[](size_type i) const noexcept; - -#if defined(PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT) - // TODO: If C++23 will let us, also accept string for the column. - [[nodiscard]] field - operator[](size_type row_num, row_size_type col_num) const noexcept; -#endif - - /// Index a row by number, but check that the row number is valid. - row at(size_type) const; - - /// Index a field by row number and column number. - field at(size_type, row_size_type) const; - - /// Let go of the result's data. - /** Use this if you need to deallocate the result data earlier than you can - * destroy the `result` object itself. - * - * Multiple `result` objects can refer to the same set of underlying data. - * The underlying data will be deallocated once all `result` objects that - * refer to it are cleared or destroyed. - */ - void clear() noexcept - { - m_data.reset(); - m_query = nullptr; - } - - /** - * @name Column information - */ - //@{ - /// Number of columns in result. - [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept; - - /// Number of given column (throws exception if it doesn't exist). - [[nodiscard]] row_size_type column_number(zview name) const; - - /// Name of column with this number (throws exception if it doesn't exist) - [[nodiscard]] char const *column_name(row_size_type number) const &; - - /// Return column's type, as an OID from the system catalogue. - [[nodiscard]] oid column_type(row_size_type col_num) const; - - /// Return column's type, as an OID from the system catalogue. - [[nodiscard]] oid column_type(zview col_name) const - { - return column_type(column_number(col_name)); - } - - /// What table did this column come from? - [[nodiscard]] oid column_table(row_size_type col_num) const; - - /// What table did this column come from? - [[nodiscard]] oid column_table(zview col_name) const - { - return column_table(column_number(col_name)); - } - - /// What column in its table did this column come from? - [[nodiscard]] row_size_type table_column(row_size_type col_num) const; - - /// What column in its table did this column come from? - [[nodiscard]] row_size_type table_column(zview col_name) const - { - return table_column(column_number(col_name)); - } - //@} - - /// Query that produced this result, if available (empty string otherwise) - [[nodiscard]] PQXX_PURE std::string const &query() const &noexcept; - - /// If command was an `INSERT` of 1 row, return oid of the inserted row. - /** @return Identifier of inserted row if exactly one row was inserted, or - * @ref oid_none otherwise. - */ - [[nodiscard]] PQXX_PURE oid inserted_oid() const; - - /// If command was `INSERT`, `UPDATE`, or `DELETE`: number of affected rows. - /** @return Number of affected rows if last command was `INSERT`, `UPDATE`, - * or `DELETE`; zero for all other commands. - */ - [[nodiscard]] PQXX_PURE size_type affected_rows() const; - - // C++20: Concept like std::invocable, but without specifying param types. - /// Run `func` on each row, passing the row's fields as parameters. - /** Goes through the rows from first to last. You provide a callable `func`. - * - * For each row in the `result`, `for_each` will call `func`. It converts - * the row's fields to the types of `func`'s parameters, and pass them to - * `func`. - * - * (Therefore `func` must have a _single_ signature. It can't be a generic - * lambda, or an object of a class with multiple overloaded function call - * operators. Otherwise, `for_each` will have no way to detect a parameter - * list without ambiguity.) - * - * If any of your parameter types is `std::string_view`, it refers to the - * underlying storage of this `result`. - * - * If any of your parameter types is a reference type, its argument will - * refer to a temporary value which only lives for the duration of that - * single invocation to `func`. If the reference is an lvalue reference, it - * must be `const`. - * - * For example, this queries employee names and salaries from the database - * and prints how much each would like to earn instead: - * ```cxx - * tx.exec("SELECT name, salary FROM employee").for_each( - * [](std::string_view name, float salary){ - * std::cout << name << " would like " << salary * 2 << ".\n"; - * }) - * ``` - * - * If `func` throws an exception, processing stops at that point and - * propagates the exception. - * - * @throws usage_error if `func`'s number of parameters does not match the - * number of columns in this result. - */ - template inline void for_each(CALLABLE &&func) const; - -private: - using data_pointer = std::shared_ptr; - - /// Underlying libpq result set. - data_pointer m_data; - - /// Factory for data_pointer. - static data_pointer - make_data_pointer(internal::pq::PGresult const *res = nullptr) noexcept - { - return {res, internal::clear_result}; - } - - friend class pqxx::internal::gate::result_pipeline; - PQXX_PURE std::shared_ptr query_ptr() const noexcept - { - return m_query; - } - - /// Query string. - std::shared_ptr m_query; - - internal::encoding_group m_encoding; - - static std::string const s_empty_string; - - friend class pqxx::field; - // TODO: noexcept. Breaks ABI. - PQXX_PURE char const *get_value(size_type row, row_size_type col) const; - // TODO: noexcept. Breaks ABI. - PQXX_PURE bool get_is_null(size_type row, row_size_type col) const; - PQXX_PURE - field_size_type get_length(size_type, row_size_type) const noexcept; - - friend class pqxx::internal::gate::result_creation; - result( - internal::pq::PGresult *rhs, std::shared_ptr query, - internal::encoding_group enc); - - PQXX_PRIVATE void check_status(std::string_view desc = ""sv) const; - - friend class pqxx::internal::gate::result_connection; - friend class pqxx::internal::gate::result_row; - bool operator!() const noexcept { return m_data.get() == nullptr; } - operator bool() const noexcept { return m_data.get() != nullptr; } - - [[noreturn]] PQXX_PRIVATE void - throw_sql_error(std::string const &Err, std::string const &Query) const; - PQXX_PRIVATE PQXX_PURE int errorposition() const; - PQXX_PRIVATE std::string status_error() const; - - friend class pqxx::internal::gate::result_sql_cursor; - PQXX_PURE char const *cmd_status() const noexcept; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/robusttransaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/robusttransaction deleted file mode 100644 index 04b71d7cc..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/robusttransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::robusttransaction class. - * - * pqxx::robusttransaction is a slower but safer transaction class. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/robusttransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/robusttransaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/robusttransaction.hxx deleted file mode 100644 index faf6dbf5e..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/robusttransaction.hxx +++ /dev/null @@ -1,120 +0,0 @@ -/* Definition of the pqxx::robusttransaction class. - * - * pqxx::robusttransaction is a slower but safer transaction class. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ROBUSTTRANSACTION -#define PQXX_H_ROBUSTTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx::internal -{ -/// Helper base class for the @ref robusttransaction class template. -class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction - : public dbtransaction -{ -public: - virtual ~basic_robusttransaction() override = 0; - -protected: - basic_robusttransaction( - connection &c, zview begin_command, std::string_view tname); - basic_robusttransaction(connection &c, zview begin_command); - -private: - using IDType = unsigned long; - - std::string m_conn_string; - std::string m_xid; - int m_backendpid = -1; - - void init(zview begin_command); - - // @warning This function will become `final`. - virtual void do_commit() override; -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @ingroup transactions - * - * @{ - */ - -/// Slightly slower, better-fortified version of transaction. -/** Requires PostgreSQL 10 or better. - * - * robusttransaction is similar to transaction, but spends more time and effort - * to deal with the hopefully rare case that the connection to the backend is - * lost just while it's trying to commit. In such cases, the client does not - * know whether the backend (on the other side of the broken connection) - * managed to commit the transaction. - * - * When this happens, robusttransaction tries to reconnect to the database and - * figure out what happened. - * - * This service level was made optional since you may not want to pay the - * overhead where it is not necessary. Certainly the use of this class makes - * no sense for local connections, or for transactions that read the database - * but never modify it, or for noncritical database manipulations. - * - * Besides being slower, it's also more complex. Which means that in practice - * a robusttransaction could actually fail more instead of less often than a - * normal transaction. What robusttransaction tries to achieve is to give you - * certainty, not just be more successful per se. - */ -template -class robusttransaction final : public internal::basic_robusttransaction -{ -public: - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - * @param tname optional human-readable name for this transaction. - */ - robusttransaction(connection &c, std::string_view tname) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd, - tname} - {} - - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - * @param tname optional human-readable name for this transaction. - */ - robusttransaction(connection &c, std::string &&tname) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd, - std::move(tname)} - {} - - /** Create robusttransaction of given name. - * @param c Connection inside which this robusttransaction should live. - */ - explicit robusttransaction(connection &c) : - internal::basic_robusttransaction{ - c, pqxx::internal::begin_cmd} - {} - - virtual ~robusttransaction() noexcept override { close(); } -}; - -/** - * @} - */ -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/row b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/row deleted file mode 100644 index 62a950ac8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/row +++ /dev/null @@ -1,11 +0,0 @@ -/** pqxx::row class. - * - * pqxx::row refers to a row in a result. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" - -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/row.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/row.hxx deleted file mode 100644 index 5be5132e3..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/row.hxx +++ /dev/null @@ -1,561 +0,0 @@ -/* Definitions for the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ROW -#define PQXX_H_ROW - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/except.hxx" -#include "pqxx/field.hxx" -#include "pqxx/result.hxx" - -#include "pqxx/internal/concat.hxx" - -namespace pqxx::internal -{ -template class result_iter; -} // namespace pqxx::internal - - -namespace pqxx -{ -/// Reference to one row in a result. -/** A row represents one row (also called a row) in a query result set. - * It also acts as a container mapping column numbers or names to field - * values (see below): - * - * ```cxx - * cout << row["date"].c_str() << ": " << row["name"].c_str() << endl; - * ``` - * - * The row itself acts like a (non-modifyable) container, complete with its - * own const_iterator and const_reverse_iterator. - */ -class PQXX_LIBEXPORT row -{ -public: - using size_type = row_size_type; - using difference_type = row_difference_type; - using const_iterator = const_row_iterator; - using iterator = const_iterator; - using reference = field; - using pointer = const_row_iterator; - using const_reverse_iterator = const_reverse_row_iterator; - using reverse_iterator = const_reverse_iterator; - - row() noexcept = default; - row(row &&) noexcept = default; - row(row const &) noexcept = default; - row &operator=(row const &) noexcept = default; - row &operator=(row &&) noexcept = default; - - /** - * @name Comparison - */ - //@{ - [[nodiscard]] PQXX_PURE bool operator==(row const &) const noexcept; - [[nodiscard]] bool operator!=(row const &rhs) const noexcept - { - return not operator==(rhs); - } - //@} - - [[nodiscard]] const_iterator begin() const noexcept; - [[nodiscard]] const_iterator cbegin() const noexcept; - [[nodiscard]] const_iterator end() const noexcept; - [[nodiscard]] const_iterator cend() const noexcept; - - /** - * @name Field access - */ - //@{ - [[nodiscard]] reference front() const noexcept; - [[nodiscard]] reference back() const noexcept; - - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator rbegin() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator crbegin() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator rend() const; - // TODO: noexcept. Breaks ABI. - [[nodiscard]] const_reverse_row_iterator crend() const; - - [[nodiscard]] reference operator[](size_type) const noexcept; - /** Address field by name. - * @warning This is much slower than indexing by number, or iterating. - */ - [[nodiscard]] reference operator[](zview col_name) const; - - reference at(size_type) const; - /** Address field by name. - * @warning This is much slower than indexing by number, or iterating. - */ - reference at(zview col_name) const; - - [[nodiscard]] constexpr size_type size() const noexcept - { - return m_end - m_begin; - } - - [[deprecated("Swap iterators, not rows.")]] void swap(row &) noexcept; - - /// Row number, assuming this is a real row and not end()/rend(). - [[nodiscard]] constexpr result::size_type rownumber() const noexcept - { - return m_index; - } - - /** - * @name Column information - */ - //@{ - /// Number of given column (throws exception if it doesn't exist). - [[nodiscard]] size_type column_number(zview col_name) const; - - /// Return a column's type. - [[nodiscard]] oid column_type(size_type) const; - - /// Return a column's type. - [[nodiscard]] oid column_type(zview col_name) const - { - return column_type(column_number(col_name)); - } - - /// What table did this column come from? - [[nodiscard]] oid column_table(size_type col_num) const; - - /// What table did this column come from? - [[nodiscard]] oid column_table(zview col_name) const - { - return column_table(column_number(col_name)); - } - - /// What column number in its table did this result column come from? - /** A meaningful answer can be given only if the column in question comes - * directly from a column in a table. If the column is computed in any - * other way, a logic_error will be thrown. - * - * @param col_num a zero-based column number in this result set - * @return a zero-based column number in originating table - */ - [[nodiscard]] size_type table_column(size_type) const; - - /// What column number in its table did this result column come from? - [[nodiscard]] size_type table_column(zview col_name) const - { - return table_column(column_number(col_name)); - } - //@} - - [[nodiscard]] constexpr result::size_type num() const noexcept - { - return rownumber(); - } - - /** Produce a slice of this row, containing the given range of columns. - * - * @deprecated I haven't heard of anyone caring about row slicing at all in - * at least the last 15 years. Yet it adds complexity, so unless anyone - * files a bug explaining why they really need this feature, I'm going to - * remove it. Even if they do, the feature may need an update. - * - * The slice runs from the range's starting column to the range's end - * column, exclusive. It looks just like a normal result row, except - * slices can be empty. - */ - [[deprecated("Row slicing is going away. File a bug if you need it.")]] row - slice(size_type sbegin, size_type send) const; - - /// Is this a row without fields? Can only happen to a slice. - [[nodiscard, deprecated("Row slicing is going away.")]] PQXX_PURE bool - empty() const noexcept; - - /// Extract entire row's values into a tuple. - /** Converts to the types of the tuple's respective fields. - */ - template void to(Tuple &t) const - { - check_size(std::tuple_size_v); - convert(t); - } - - template std::tuple as() const - { - check_size(sizeof...(TYPE)); - using seq = std::make_index_sequence; - return get_tuple>(seq{}); - } - -protected: - friend class const_row_iterator; - friend class result; - row(result const &r, result_size_type index, size_type cols) noexcept; - - /// Throw @ref usage_error if row size is not `expected`. - void check_size(size_type expected) const - { - if (size() != expected) - throw usage_error{internal::concat( - "Tried to extract ", expected, " field(s) from a row of ", size(), - ".")}; - } - - /// Convert to a given tuple of values, don't check sizes. - /** We need this for cases where we have a full tuple of field types, but - * not a parameter pack. - */ - template TUPLE as_tuple() const - { - using seq = std::make_index_sequence>; - return get_tuple(seq{}); - } - - template friend class pqxx::internal::result_iter; - /// Convert entire row to tuple fields, without checking row size. - template void convert(Tuple &t) const - { - extract_fields(t, std::make_index_sequence>{}); - } - - friend class field; - - /// Result set of which this is one row. - result m_result; - - /// Row number. - /** - * You'd expect this to be unsigned, but due to the way reverse iterators - * are related to regular iterators, it must be allowed to underflow to -1. - */ - result::size_type m_index = 0; - - // TODO: Remove m_begin and (if possible) m_end when we remove slice(). - /// First column in slice. This row ignores lower-numbered columns. - size_type m_begin = 0; - /// End column in slice. This row only sees lower-numbered columns. - size_type m_end = 0; - -private: - template - void extract_fields(Tuple &t, std::index_sequence) const - { - (extract_value(t), ...); - } - - template - void extract_value(Tuple &t) const; - - /// Convert row's values as a new tuple. - template - auto get_tuple(std::index_sequence) const - { - return std::make_tuple(get_field()...); - } - - /// Extract and convert a field. - template auto get_field() const - { - return (*this)[index].as>(); - } -}; - - -/// Iterator for fields in a row. Use as row::const_iterator. -class PQXX_LIBEXPORT const_row_iterator : public field -{ -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = field const; - using pointer = field const *; - using size_type = row_size_type; - using difference_type = row_difference_type; - using reference = field; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - const_row_iterator() = default; -#include "pqxx/internal/ignore-deprecated-post.hxx" - const_row_iterator(row const &t, row_size_type c) noexcept : - field{t.m_result, t.m_index, c} - {} - const_row_iterator(field const &F) noexcept : field{F} {} - const_row_iterator(const_row_iterator const &) noexcept = default; - const_row_iterator(const_row_iterator &&) noexcept = default; - - /** - * @name Dereferencing operators - */ - //@{ - [[nodiscard]] constexpr pointer operator->() const noexcept { return this; } - [[nodiscard]] reference operator*() const noexcept { return {*this}; } - //@} - - /** - * @name Manipulations - */ - //@{ - const_row_iterator &operator=(const_row_iterator const &) noexcept = default; - const_row_iterator &operator=(const_row_iterator &&) noexcept = default; - - // TODO: noexcept. Breaks ABI. - const_row_iterator operator++(int); - const_row_iterator &operator++() noexcept - { - ++m_col; - return *this; - } - // TODO: noexcept. Breaks ABI. - const_row_iterator operator--(int); - const_row_iterator &operator--() noexcept - { - --m_col; - return *this; - } - - const_row_iterator &operator+=(difference_type i) noexcept - { - m_col = size_type(difference_type(m_col) + i); - return *this; - } - const_row_iterator &operator-=(difference_type i) noexcept - { - m_col = size_type(difference_type(m_col) - i); - return *this; - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] constexpr bool - operator==(const_row_iterator const &i) const noexcept - { - return col() == i.col(); - } - [[nodiscard]] constexpr bool - operator!=(const_row_iterator const &i) const noexcept - { - return col() != i.col(); - } - [[nodiscard]] constexpr bool - operator<(const_row_iterator const &i) const noexcept - { - return col() < i.col(); - } - [[nodiscard]] constexpr bool - operator<=(const_row_iterator const &i) const noexcept - { - return col() <= i.col(); - } - [[nodiscard]] constexpr bool - operator>(const_row_iterator const &i) const noexcept - { - return col() > i.col(); - } - [[nodiscard]] constexpr bool - operator>=(const_row_iterator const &i) const noexcept - { - return col() >= i.col(); - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] inline const_row_iterator - operator+(difference_type) const noexcept; - - friend const_row_iterator - operator+(difference_type, const_row_iterator const &) noexcept; - - [[nodiscard]] inline const_row_iterator - operator-(difference_type) const noexcept; - [[nodiscard]] inline difference_type - operator-(const_row_iterator const &) const noexcept; - //@} -}; - - -/// Reverse iterator for a row. Use as row::const_reverse_iterator. -class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator -{ -public: - using super = const_row_iterator; - using iterator_type = const_row_iterator; - using iterator_type::difference_type; - using iterator_type::iterator_category; - using iterator_type::pointer; - using value_type = iterator_type::value_type; - using reference = iterator_type::reference; - - const_reverse_row_iterator() noexcept = default; - const_reverse_row_iterator(const_reverse_row_iterator const &) noexcept = - default; - const_reverse_row_iterator(const_reverse_row_iterator &&) noexcept = default; - - explicit const_reverse_row_iterator(super const &rhs) noexcept : - const_row_iterator{rhs} - { - super::operator--(); - } - - [[nodiscard]] PQXX_PURE iterator_type base() const noexcept; - - /** - * @name Dereferencing operators - */ - //@{ - using iterator_type::operator->; - using iterator_type::operator*; - //@} - - /** - * @name Manipulations - */ - //@{ - const_reverse_row_iterator & - operator=(const_reverse_row_iterator const &r) noexcept - { - iterator_type::operator=(r); - return *this; - } - const_reverse_row_iterator operator++() noexcept - { - iterator_type::operator--(); - return *this; - } - // TODO: noexcept. Breaks ABI. - const_reverse_row_iterator operator++(int); - const_reverse_row_iterator &operator--() noexcept - { - iterator_type::operator++(); - return *this; - } - const_reverse_row_iterator operator--(int); - // TODO: noexcept. Breaks ABI. - const_reverse_row_iterator &operator+=(difference_type i) noexcept - { - iterator_type::operator-=(i); - return *this; - } - const_reverse_row_iterator &operator-=(difference_type i) noexcept - { - iterator_type::operator+=(i); - return *this; - } - //@} - - /** - * @name Arithmetic operators - */ - //@{ - [[nodiscard]] const_reverse_row_iterator - operator+(difference_type i) const noexcept - { - return const_reverse_row_iterator{base() - i}; - } - [[nodiscard]] const_reverse_row_iterator - operator-(difference_type i) noexcept - { - return const_reverse_row_iterator{base() + i}; - } - [[nodiscard]] difference_type - operator-(const_reverse_row_iterator const &rhs) const noexcept - { - return rhs.const_row_iterator::operator-(*this); - } - //@} - - /** - * @name Comparisons - */ - //@{ - [[nodiscard]] bool - operator==(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator==(rhs); - } - [[nodiscard]] bool - operator!=(const_reverse_row_iterator const &rhs) const noexcept - { - return !operator==(rhs); - } - - [[nodiscard]] constexpr bool - operator<(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator>(rhs); - } - [[nodiscard]] constexpr bool - operator<=(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator>=(rhs); - } - [[nodiscard]] constexpr bool - operator>(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator<(rhs); - } - [[nodiscard]] constexpr bool - operator>=(const_reverse_row_iterator const &rhs) const noexcept - { - return iterator_type::operator<=(rhs); - } - //@} -}; - - -const_row_iterator -const_row_iterator::operator+(difference_type o) const noexcept -{ - // TODO:: More direct route to home().columns()? - return { - row{home(), idx(), home().columns()}, - size_type(difference_type(col()) + o)}; -} - -inline const_row_iterator operator+( - const_row_iterator::difference_type o, const_row_iterator const &i) noexcept -{ - return i + o; -} - -inline const_row_iterator -const_row_iterator::operator-(difference_type o) const noexcept -{ - // TODO:: More direct route to home().columns()? - return { - row{home(), idx(), home().columns()}, - size_type(difference_type(col()) - o)}; -} - -inline const_row_iterator::difference_type -const_row_iterator::operator-(const_row_iterator const &i) const noexcept -{ - return difference_type(num() - i.num()); -} - - -template -inline void row::extract_value(Tuple &t) const -{ - using field_type = strip_t(t))>; - field const f{m_result, m_index, index}; - std::get(t) = from_string(f); -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/separated_list b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/separated_list deleted file mode 100644 index 1bdf51c6a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/separated_list +++ /dev/null @@ -1,6 +0,0 @@ -/** Helper similar to Python's @c str.join(). - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/separated_list.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/separated_list.hxx deleted file mode 100644 index d4230ea08..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/separated_list.hxx +++ /dev/null @@ -1,142 +0,0 @@ -/* Helper similar to Python's `str.join()`. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SEPARATED_LIST -#define PQXX_H_SEPARATED_LIST - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/strconv.hxx" - -// C++20: Simplify using std::ranges::range. -// C++20: Optimise buffer allocation using random_access_range/iterator. -namespace pqxx -{ -/** - * @defgroup utility Utility functions - */ -//@{ - -/// Represent sequence of values as a string, joined by a given separator. -/** - * Use this to turn e.g. the numbers 1, 2, and 3 into a string "1, 2, 3". - * - * @param sep separator string (to be placed between items) - * @param begin beginning of items sequence - * @param end end of items sequence - * @param access functor defining how to dereference sequence elements - */ -template -[[nodiscard]] inline std::string -separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access) -{ - if (end == begin) - return {}; - auto next{begin}; - ++next; - if (next == end) - return to_string(access(begin)); - - // From here on, we've got at least 2 elements -- meaning that we need sep. - using elt_type = strip_t; - using traits = string_traits; - - std::size_t budget{0}; - for (ITER cnt{begin}; cnt != end; ++cnt) - budget += traits::size_buffer(access(cnt)); - budget += - static_cast(std::distance(begin, end)) * std::size(sep); - - std::string result; - result.resize(budget); - - char *const data{result.data()}; - char *here{data}; - char *stop{data + budget}; - here = traits::into_buf(here, stop, access(begin)) - 1; - for (++begin; begin != end; ++begin) - { - here += sep.copy(here, std::size(sep)); - here = traits::into_buf(here, stop, access(begin)) - 1; - } - result.resize(static_cast(here - data)); - return result; -} - - -/// Render sequence as a string, using given separator between items. -template -[[nodiscard]] inline std::string -separated_list(std::string_view sep, ITER begin, ITER end) -{ - return separated_list(sep, begin, end, [](ITER i) { return *i; }); -} - - -/// Render items in a container as a string, using given separator. -template -[[nodiscard]] inline auto -separated_list(std::string_view sep, CONTAINER const &c) - /* - Always std::string; necessary because SFINAE doesn't work with the - contents of function bodies, so the check for iterability has to be in - the signature. - */ - -> typename std::enable_if< - (not std::is_void::value and - not std::is_void::value), - std::string>::type -{ - return separated_list(sep, std::begin(c), std::end(c)); -} - - -/// Render items in a tuple as a string, using given separator. -template< - typename TUPLE, std::size_t INDEX = 0, typename ACCESS, - typename std::enable_if< - (INDEX == std::tuple_size::value - 1), int>::type = 0> -[[nodiscard]] inline std::string separated_list( - std::string_view /* sep */, TUPLE const &t, ACCESS const &access) -{ - return to_string(access(&std::get(t))); -} - -template< - typename TUPLE, std::size_t INDEX = 0, typename ACCESS, - typename std::enable_if< - (INDEX < std::tuple_size::value - 1), int>::type = 0> -[[nodiscard]] inline std::string -separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access) -{ - std::string out{to_string(access(&std::get(t)))}; - out.append(sep); - out.append(separated_list(sep, t, access)); - return out; -} - -template< - typename TUPLE, std::size_t INDEX = 0, - typename std::enable_if< - (INDEX <= std::tuple_size::value), int>::type = 0> -[[nodiscard]] inline std::string -separated_list(std::string_view sep, TUPLE const &t) -{ - // TODO: Optimise allocation. - return separated_list(sep, t, [](TUPLE const &tup) { return *tup; }); -} -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/strconv b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/strconv deleted file mode 100644 index aa2c40ed5..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/strconv +++ /dev/null @@ -1,6 +0,0 @@ -/** String conversion definitions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/strconv.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/strconv.hxx deleted file mode 100644 index 863711228..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/strconv.hxx +++ /dev/null @@ -1,468 +0,0 @@ -/* String conversion definitions. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STRCONV -#define PQXX_H_STRCONV - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -#if defined(PQXX_HAVE_RANGES) && __has_include() -# include -#endif - -#include "pqxx/except.hxx" -#include "pqxx/util.hxx" -#include "pqxx/zview.hxx" - - -namespace pqxx::internal -{ -/// Attempt to demangle @c std::type_info::name() to something human-readable. -PQXX_LIBEXPORT std::string demangle_type_name(char const[]); -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @defgroup stringconversion String conversion - * - * The PostgreSQL server accepts and represents data in string form. It has - * its own formats for various data types. The string conversions define how - * various C++ types translate to and from their respective PostgreSQL text - * representations. - * - * Each conversion is defined by a specialisations of @c string_traits. It - * gets complicated if you want top performance, but until you do, all you - * really need to care about when converting values between C++ in-memory - * representations such as @c int and the postgres string representations is - * the @c pqxx::to_string and @c pqxx::from_string functions. - * - * If you need to convert a type which is not supported out of the box, you'll - * need to define your own specialisations for these templates, similar to the - * ones defined here and in `pqxx/conversions.hxx`. Any conversion code which - * "sees" your specialisation will now support your conversion. In particular, - * you'll be able to read result fields into a variable of the new type. - * - * There is a macro to help you define conversions for individual enumeration - * types. The conversion will represent enumeration values as numeric strings. - */ -//@{ - -/// A human-readable name for a type, used in error messages and such. -/** Actually this may not always be very user-friendly. It uses - * @c std::type_info::name(). On gcc-like compilers we try to demangle its - * output. Visual Studio produces human-friendly names out of the box. - * - * This variable is not inline. Inlining it gives rise to "memory leak" - * warnings from asan, the address sanitizer, possibly from use of - * @c std::type_info::name. - */ -template -std::string const type_name{internal::demangle_type_name(typeid(TYPE).name())}; - - -/// Traits describing a type's "null value," if any. -/** Some C++ types have a special value or state which correspond directly to - * SQL's NULL. - * - * The @c nullness traits describe whether it exists, and whether a particular - * value is null. - */ -template struct nullness -{ - /// Does this type have a null value? - static bool has_null; - - /// Is this type always null? - static bool always_null; - - /// Is @c value a null? - static bool is_null(TYPE const &value); - - /// Return a null value. - /** Don't use this in generic code to compare a value and see whether it is - * null. Some types may have multiple null values which do not compare as - * equal, or may define a null value which is not equal to anything including - * itself, like in SQL. - */ - [[nodiscard]] static TYPE null(); -}; - - -/// Nullness traits describing a type which does not have a null value. -template struct no_null -{ - /// Does @c TYPE have a "built-in null value"? - /** For example, a pointer can equal @c nullptr, which makes a very natural - * representation of an SQL null value. For such types, the code sometimes - * needs to make special allowances. - * - * for most types, such as @c int or @c std::string, there is no built-in - * null. If you want to represent an SQL null value for such a type, you - * would have to wrap it in something that does have a null value. For - * example, you could use @c std::optional for "either an @c int or a - * null value." - */ - static constexpr bool has_null = false; - - /// Are all values of this type null? - /** There are a few special C++ types which are always null - mainly - * @c std::nullptr_t. - */ - static constexpr bool always_null = false; - - /// Does a given value correspond to an SQL null value? - /** Most C++ types, such as @c int or @c std::string, have no inherent null - * value. But some types such as C-style string pointers do have a natural - * equivalent to an SQL null. - */ - [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept - { - return false; - } -}; - - -/// Traits class for use in string conversions. -/** Specialize this template for a type for which you wish to add to_string - * and from_string support. - * - * String conversions are not meant to work for nulls. Check for null before - * converting a value of @c TYPE to a string, or vice versa. - */ -template struct string_traits -{ - /// Return a @c string_view representing value, plus terminating zero. - /** Produces a @c string_view containing the PostgreSQL string representation - * for @c value. - * - * Uses the space from @c begin to @c end as a buffer, if needed. The - * returned string may lie somewhere in that buffer, or it may be a - * compile-time constant, or it may be null if value was a null value. Even - * if the string is stored in the buffer, its @c begin() may or may not be - * the same as @c begin. - * - * The @c string_view is guaranteed to be valid as long as the buffer from - * @c begin to @c end remains accessible and unmodified. - * - * @throws pqxx::conversion_overrun if the provided buffer space may not be - * enough. For maximum performance, this is a conservative estimate. It may - * complain about a buffer which is actually large enough for your value, if - * an exact check gets too expensive. - */ - [[nodiscard]] static inline zview - to_buf(char *begin, char *end, TYPE const &value); - - /// Write value's string representation into buffer at @c begin. - /** Assumes that value is non-null. - * - * Writes value's string representation into the buffer, starting exactly at - * @c begin, and ensuring a trailing zero. Returns the address just beyond - * the trailing zero, so the caller could use it as the @c begin for another - * call to @c into_buf writing a next value. - */ - static inline char *into_buf(char *begin, char *end, TYPE const &value); - - /// Parse a string representation of a @c TYPE value. - /** Throws @c conversion_error if @c value does not meet the expected format - * for a value of this type. - */ - [[nodiscard]] static inline TYPE from_string(std::string_view text); - - // C++20: Can we make these all constexpr? - /// Estimate how much buffer space is needed to represent value. - /** The estimate may be a little pessimistic, if it saves time. - * - * The estimate includes the terminating zero. - */ - [[nodiscard]] static inline std::size_t - size_buffer(TYPE const &value) noexcept; -}; - - -/// Nullness: Enums do not have an inherent null value. -template -struct nullness>> : no_null -{}; -} // namespace pqxx - - -namespace pqxx::internal -{ -/// Helper class for defining enum conversions. -/** The conversion will convert enum values to numeric strings, and vice versa. - * - * To define a string conversion for an enum type, derive a @c string_traits - * specialisation for the enum from this struct. - * - * There's usually an easier way though: the @c PQXX_DECLARE_ENUM_CONVERSION - * macro. Use @c enum_traits manually only if you need to customise your - * traits type in more detail. - */ -template struct enum_traits -{ - using impl_type = std::underlying_type_t; - using impl_traits = string_traits; - - [[nodiscard]] static constexpr zview - to_buf(char *begin, char *end, ENUM const &value) - { - return impl_traits::to_buf(begin, end, to_underlying(value)); - } - - static constexpr char *into_buf(char *begin, char *end, ENUM const &value) - { - return impl_traits::into_buf(begin, end, to_underlying(value)); - } - - [[nodiscard]] static ENUM from_string(std::string_view text) - { - return static_cast(impl_traits::from_string(text)); - } - - [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept - { - return impl_traits::size_buffer(to_underlying(value)); - } - -private: - // C++23: Replace with std::to_underlying. - static constexpr impl_type to_underlying(ENUM const &value) noexcept - { - return static_cast(value); - } -}; -} // namespace pqxx::internal - - -/// Macro: Define a string conversion for an enum type. -/** This specialises the @c pqxx::string_traits template, so use it in the - * @c ::pqxx namespace. - * - * For example: - * - * #include - * #include - * enum X { xa, xb }; - * namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(x); } - * int main() { std::cout << pqxx::to_string(xa) << std::endl; } - */ -#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \ - template<> struct string_traits : pqxx::internal::enum_traits \ - {}; \ - template<> inline std::string const type_name { #ENUM } - - -namespace pqxx -{ -/// Parse a value in postgres' text format as a TYPE. -/** If the form of the value found in the string does not match the expected - * type, e.g. if a decimal point is found when converting to an integer type, - * the conversion fails. Overflows (e.g. converting "9999999999" to a 16-bit - * C++ type) are also treated as errors. If in some cases this behaviour - * should be inappropriate, convert to something bigger such as @c long @c int - * first and then truncate the resulting value. - * - * Only the simplest possible conversions are supported. Fancy features like - * hexadecimal or octal, spurious signs, or exponent notation won't work. - * Whitespace is not stripped away. Only the kinds of strings that come out of - * PostgreSQL and out of to_string() can be converted. - */ -template -[[nodiscard]] inline TYPE from_string(std::string_view text) -{ - return string_traits::from_string(text); -} - - -/// "Convert" a std::string_view to a std::string_view. -/** Just returns its input. - * - * @warning Of course the result is only valid for as long as the original - * string remains valid! Never access the string referenced by the return - * value after the original has been destroyed. - */ -template<> -[[nodiscard]] inline std::string_view from_string(std::string_view text) -{ - return text; -} - - -/// Attempt to convert postgres-generated string to given built-in object. -/** This is like the single-argument form of the function, except instead of - * returning the value, it sets @c value. - * - * You may find this more convenient in that it infers the type you want from - * the argument you pass. But there are disadvantages: it requires an - * assignment operator, and it may be less efficient. - */ -template inline void from_string(std::string_view text, T &value) -{ - value = from_string(text); -} - - -/// Convert a value to a readable string that PostgreSQL will understand. -/** The conversion does no special formatting, and ignores any locale settings. - * The resulting string will be human-readable and in a format suitable for use - * in SQL queries. It won't have niceties such as "thousands separators" - * though. - */ -template inline std::string to_string(TYPE const &value); - - -/// Convert multiple values to strings inside a single buffer. -/** There must be enough room for all values, or this will throw - * @c conversion_overrun. You can obtain a conservative estimate of the buffer - * space required by calling @c size_buffer() on the values. - * - * The @c std::string_view results may point into the buffer, so don't assume - * that they will remain valid after you destruct or move the buffer. - */ -template -[[nodiscard]] inline std::vector -to_buf(char *here, char const *end, TYPE... value) -{ - return {[&here, end](auto v) { - auto begin = here; - here = string_traits::into_buf(begin, end, v); - // Exclude the trailing zero out of the string_view. - auto len{static_cast(here - begin) - 1}; - return std::string_view{begin, len}; - }(value)...}; -} - -/// Convert a value to a readable string that PostgreSQL will understand. -/** This variant of to_string can sometimes save a bit of time in loops, by - * re-using a std::string for multiple conversions. - */ -template -inline void into_string(TYPE const &value, std::string &out); - - -/// Is @c value null? -template -[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept -{ - return nullness>::is_null(value); -} - - -/// Estimate how much buffer space is needed to represent values as a string. -/** The estimate may be a little pessimistic, if it saves time. It also - * includes room for a terminating zero after each value. - */ -template -[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept -{ - return (string_traits>::size_buffer(value) + ...); -} - - -/// Does this type translate to an SQL array? -/** Specialisations may override this to be true for container types. - * - * This may not always be a black-and-white choice. For instance, a - * @c std::string is a container, but normally it translates to an SQL string, - * not an SQL array. - */ -template inline constexpr bool is_sql_array{false}; - - -/// Can we use this type in arrays and composite types without quoting them? -/** Define this as @c true only if values of @c TYPE can never contain any - * special characters that might need escaping or confuse the parsing of array - * or composite * types, such as commas, quotes, parentheses, braces, newlines, - * and so on. - * - * When converting a value of such a type to a string in an array or a field in - * a composite type, we do not need to add quotes, nor escape any special - * characters. - * - * This is just an optimisation, so it defaults to @c false to err on the side - * of slow correctness. - */ -template inline constexpr bool is_unquoted_safe{false}; - - -/// Element separator between SQL array elements of this type. -template inline constexpr char array_separator{','}; - - -/// What's the preferred format for passing non-null parameters of this type? -/** This affects how we pass parameters of @c TYPE when calling parameterised - * statements or prepared statements. - * - * Generally we pass parameters in text format, but binary strings are the - * exception. We also pass nulls in binary format, so this function need not - * handle null values. - */ -template inline constexpr format param_format(TYPE const &) -{ - return format::text; -} - - -/// Implement @c string_traits::to_buf by calling @c into_buf. -/** When you specialise @c string_traits for a new type, most of the time its - * @c to_buf implementation has no special optimisation tricks and just writes - * its text into the buffer it receives from the caller, starting at the - * beginning. - * - * In that common situation, you can implement @c to_buf as just a call to - * @c generic_to_buf. It will call @c into_buf and return the right result for - * @c to_buf. - */ -template -inline zview generic_to_buf(char *begin, char *end, TYPE const &value) -{ - using traits = string_traits; - // The trailing zero does not count towards the zview's size, so subtract 1 - // from the result we get from into_buf(). - if (is_null(value)) - return {}; - else - return {begin, traits::into_buf(begin, end, value) - begin - 1}; -} - - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: Binary string, akin to @c std::string for binary data. -/** Any type that satisfies this concept can represent an SQL BYTEA value. - * - * A @c binary has a @c begin(), @c end(), @c size(), and @data(). Each byte - * is a @c std::byte, and they must all be laid out contiguously in memory so - * we can reference them by a pointer. - */ -template -concept binary = std::ranges::contiguous_range and - std::is_same_v>, std::byte>; -#endif -//@} -} // namespace pqxx - - -#include "pqxx/internal/conversions.hxx" -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_from b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_from deleted file mode 100644 index 972762443..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_from +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::stream_from class. - * - * pqxx::stream_from enables optimized batch reads from a database table. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_from.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_from.hxx deleted file mode 100644 index ff4a93d2e..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_from.hxx +++ /dev/null @@ -1,361 +0,0 @@ -/* Definition of the pqxx::stream_from class. - * - * pqxx::stream_from enables optimized batch reads from a database table. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_FROM -#define PQXX_H_STREAM_FROM - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#include "pqxx/connection.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/internal/stream_iterator.hxx" -#include "pqxx/separated_list.hxx" -#include "pqxx/transaction_focus.hxx" - - -namespace pqxx -{ -class transaction_base; - - -/// Pass this to a `stream_from` constructor to stream table contents. -/** @deprecated Use @ref stream_from::table() instead. - */ -constexpr from_table_t from_table; -/// Pass this to a `stream_from` constructor to stream query results. -/** @deprecated Use stream_from::query() instead. - */ -constexpr from_query_t from_query; - - -/// Stream data from the database. -/** For larger data sets, retrieving data this way is likely to be faster than - * executing a query and then iterating and converting the rows fields. You - * will also be able to start processing before all of the data has come in. - * - * There are also downsides. Not all kinds of query will work in a stream. - * But straightforward `SELECT` and `UPDATE ... RETURNING` queries should work. - * This function makes use of @ref pqxx::stream_from, which in turn uses - * PostgreSQL's `COPY` command, so see the documentation for those to get the - * full details. - * - * There are other downsides. If there stream encounters an error, it may - * leave the entire connection in an unusable state, so you'll have to give the - * whole thing up. Finally, opening a stream puts the connection in a special - * state, so you won't be able to do many other things with the connection or - * the transaction while the stream is open. - * - * There are two ways of starting a stream: you stream either all rows in a - * table (using one of the factories, `table()` or `raw_table()`), or the - * results of a query (using the `query()` factory). - * - * Usually you'll want the `stream` convenience wrapper in - * @ref transaction_base, * so you don't need to deal with this class directly. - * - * @warning While a stream is active, you cannot execute queries, open a - * pipeline, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT stream_from : transaction_focus -{ -public: - using raw_line = - std::pair>, std::size_t>; - - /// Factory: Execute query, and stream the results. - /** The query can be a SELECT query or a VALUES query; or it can be an - * UPDATE, INSERT, or DELETE with a RETURNING clause. - * - * The query is executed as part of a COPY statement, so there are additional - * restrictions on what kind of query you can use here. See the PostgreSQL - * documentation for the COPY command: - * - * https://www.postgresql.org/docs/current/sql-copy.html - */ - static stream_from query(transaction_base &tx, std::string_view q) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return {tx, from_query, q}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /** - * @name Streaming data from tables - * - * You can use `stream_from` to read a table's contents. This is a quick - * and easy way to read a table, but it comes with limitations. It cannot - * stream from a view, only from a table. It does not support conditions. - * And there are no guarantees about ordering. If you need any of those - * things, consider streaming from a query instead. - */ - //@{ - - /// Factory: Stream data from a pre-quoted table and columns. - /** Use this factory if you need to create multiple streams using the same - * table path and/or columns list, and you want to save a bit of work on - * composing the internal SQL statement for starting the stream. It lets you - * compose the string representations for the table path and the columns - * list, so you can compute these once and then re-use them later. - * - * @param tx The transaction within which the stream will operate. - * @param path Name or path for the table upon which the stream will - * operate. If any part of the table path may contain special - * characters or be case-sensitive, quote the path using - * pqxx::connection::quote_table(). - * @param columns Columns which the stream will read. They should be - * comma-separated and, if needed, quoted. You can produce the string - * using pqxx::connection::quote_columns(). If you omit this argument, - * the stream will read all columns in the table, in schema order. - */ - static stream_from raw_table( - transaction_base &tx, std::string_view path, - std::string_view columns = ""sv); - - /// Factory: Stream data from a given table. - /** This is the convenient way to stream from a table. - */ - static stream_from table( - transaction_base &tx, table_path path, - std::initializer_list columns = {}); - //@} - - /// Execute query, and stream over the results. - /** @deprecated Use factory function @ref query instead. - */ - [[deprecated("Use query() factory instead.")]] stream_from( - transaction_base &, from_query_t, std::string_view query); - - /// Stream all rows in table, all columns. - /** @deprecated Use factories @ref table or @ref raw_table instead. - */ - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &, from_table_t, std::string_view table); - - /// Stream given columns from all rows in table. - /** @deprecated Use factories @ref table or @ref raw_table instead. - */ - template - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &, from_table_t, std::string_view table, - Iter columns_begin, Iter columns_end); - - /// Stream given columns from all rows in table. - /** @deprecated Use factory function @ref query instead. - */ - template - [[deprecated("Use table() or raw_table() factory instead.")]] stream_from( - transaction_base &tx, from_table_t, std::string_view table, - Columns const &columns); - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - /// @deprecated Use factories @ref table or @ref raw_table instead. - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &tx, std::string_view table) : - stream_from{tx, from_table, table} - {} -#include "pqxx/internal/ignore-deprecated-post.hxx" - - /// @deprecated Use factories @ref table or @ref raw_table instead. - template - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &tx, std::string_view table, Columns const &columns) : - stream_from{tx, from_table, table, columns} - {} - - /// @deprecated Use factories @ref table or @ref raw_table instead. - template - [[deprecated("Use the from_table_t overload instead.")]] stream_from( - transaction_base &, std::string_view table, Iter columns_begin, - Iter columns_end); - - ~stream_from() noexcept; - - /// May this stream still produce more data? - [[nodiscard]] constexpr operator bool() const noexcept - { - return not m_finished; - } - /// Has this stream produced all the data it is going to produce? - [[nodiscard]] constexpr bool operator!() const noexcept - { - return m_finished; - } - - /// Finish this stream. Call this before continuing to use the connection. - /** Consumes all remaining lines, and closes the stream. - * - * This may take a while if you're abandoning the stream before it's done, so - * skip it in error scenarios where you're not planning to use the connection - * again afterwards. - */ - void complete(); - - /// Read one row into a tuple. - /** Converts the row's fields into the fields making up the tuple. - * - * For a column which can contain nulls, be sure to give the corresponding - * tuple field a type which can be null. For example, to read a field as - * `int` when it may contain nulls, read it as `std::optional`. - * Using `std::shared_ptr` or `std::unique_ptr` will also work. - */ - template stream_from &operator>>(Tuple &); - - /// Doing this with a `std::variant` is going to be horrifically borked. - template - stream_from &operator>>(std::variant &) = delete; - - /// Iterate over this stream. Supports range-based "for" loops. - /** Produces an input iterator over the stream. - * - * Do not call this yourself. Use it like "for (auto data : stream.iter())". - */ - template [[nodiscard]] auto iter() & - { - return pqxx::internal::stream_input_iteration{*this}; - } - - /// Read a row. Return fields as views, valid until you read the next row. - /** Returns `nullptr` when there are no more rows to read. Do not attempt - * to read any further rows after that. - * - * Do not access the vector, or the storage referenced by the views, after - * closing or completing the stream, or after attempting to read a next row. - * - * A @ref pqxx::zview is like a `std::string_view`, but with the added - * guarantee that if its data pointer is non-null, the string is followed by - * a terminating zero (which falls just outside the view itself). - * - * If any of the views' data pointer is null, that means that the - * corresponding SQL field is null. - * - * @warning The return type may change in the future, to support C++20 - * coroutine-based usage. - */ - std::vector const *read_row() &; - - /// Read a raw line of text from the COPY command. - /** @warning Do not use this unless you really know what you're doing. */ - raw_line get_raw_line(); - -private: - // TODO: Clean up this signature once we cull the deprecated constructors. - /// @deprecated - stream_from( - transaction_base &tx, std::string_view table, std::string_view columns, - from_table_t); - - // TODO: Clean up this signature once we cull the deprecated constructors. - /// @deprecated - stream_from( - transaction_base &, std::string_view unquoted_table, - std::string_view columns, from_table_t, int); - - template - void extract_fields(Tuple &t, std::index_sequence) const - { - (extract_value(t), ...); - } - - pqxx::internal::glyph_scanner_func *m_glyph_scanner; - - /// Current row's fields' text, combined into one reusable string. - std::string m_row; - - /// The current row's fields. - std::vector m_fields; - - bool m_finished = false; - - void close(); - - template - void extract_value(Tuple &) const; - - /// Read a line of COPY data, write `m_row` and `m_fields`. - void parse_line(); -}; - - -template -inline stream_from::stream_from( - transaction_base &tx, from_table_t, std::string_view table_name, - Columns const &columns) : - stream_from{ - tx, from_table, table_name, std::begin(columns), std::end(columns)} -{} - - -template -inline stream_from::stream_from( - transaction_base &tx, from_table_t, std::string_view table, - Iter columns_begin, Iter columns_end) : - stream_from{ - tx, table, separated_list(",", columns_begin, columns_end), - from_table, 1} -{} - - -template inline stream_from &stream_from::operator>>(Tuple &t) -{ - if (m_finished) - return *this; - static constexpr auto tup_size{std::tuple_size_v}; - m_fields.reserve(tup_size); - parse_line(); - if (m_finished) - return *this; - - if (std::size(m_fields) != tup_size) - throw usage_error{internal::concat( - "Tried to extract ", tup_size, " field(s) from a stream of ", - std::size(m_fields), ".")}; - - extract_fields(t, std::make_index_sequence{}); - return *this; -} - - -template -inline void stream_from::extract_value(Tuple &t) const -{ - using field_type = strip_t(t))>; - using nullity = nullness; - assert(index < std::size(m_fields)); - if constexpr (nullity::always_null) - { - if (std::data(m_fields[index]) != nullptr) - throw conversion_error{"Streaming non-null value into null field."}; - } - else if (std::data(m_fields[index]) == nullptr) - { - if constexpr (nullity::has_null) - std::get(t) = nullity::null(); - else - internal::throw_null_conversion(type_name); - } - else - { - // Don't ever try to convert a non-null value to nullptr_t! - std::get(t) = from_string(m_fields[index]); - } -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_to b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_to deleted file mode 100644 index 8760cf1f4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_to +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::stream_to class. - * - * pqxx::stream_to enables optimized batch updates to a database table. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/stream_to.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_to.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_to.hxx deleted file mode 100644 index 2a49d8f85..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/stream_to.hxx +++ /dev/null @@ -1,455 +0,0 @@ -/* Definition of the pqxx::stream_to class. - * - * pqxx::stream_to enables optimized batch updates to a database table. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_STREAM_TO -#define PQXX_H_STREAM_TO - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/separated_list.hxx" -#include "pqxx/transaction_base.hxx" - - -namespace pqxx -{ -/// Efficiently write data directly to a database table. -/** If you wish to insert rows of data into a table, you can compose INSERT - * statements and execute them. But it's slow and tedious, and you need to - * worry about quoting and escaping the data. - * - * If you're just inserting a single row, it probably won't matter much. You - * can use prepared or parameterised statements to take care of the escaping - * for you. But if you're inserting large numbers of rows you will want - * something better. - * - * Inserting rows one by one using INSERT statements involves a lot of - * pointless overhead, especially when you are working with a remote database - * server over the network. You may end up sending each row over the network - * as a separate query, and waiting for a reply. Do it "in bulk" using - * `stream_to`, and you may find that it goes many times faster. Sometimes - * you gain orders of magnitude in speed. - * - * Here's how it works: you create a `stream_to` stream to start writing to - * your table. You will probably want to specify the columns. Then, you - * feed your data into the stream one row at a time. And finally, you call the - * stream's @ref complete function to tell it to finalise the operation, wait - * for completion, and check for errors. - * - * (You _must_ complete the stream before committing or aborting the - * transaction. The connection is in a special state while the stream is - * active, where it can't process commands, and can't commit or abort a - * transaction.) - * - * So how do you feed a row of data into the stream? There's several ways, but - * the preferred one is to call its @ref write_values. Pass the field values - * as arguments. Doesn't matter what type they are, as long as libpqxx knows - * how to convert them to PostgreSQL's text format: `int`, `std::string` or - * `std:string_view`, `float` and `double`, `bool`... lots of basic types - * are supported. If some of the values are null, feel free to use - * `std::optional`, `std::shared_ptr`, or `std::unique_ptr`. - * - * The arguments' types don't even have to match the fields' SQL types. If you - * want to insert an `int` into a `DECIMAL` column, that's your choice -- it - * will produce a `DECIMAL` value which happens to be integral. Insert a - * `float` into a `VARCHAR` column? That's fine, you'll get a string whose - * contents happen to read like a number. And so on. You can even insert - * different types of value in the same column on different rows. If you have - * a code path where a particular field is always null, just insert `nullptr`. - * - * There is another way to insert rows: the `<<` ("shift-left") operator. - * It's not as fast and it doesn't support variable arguments: each row must be - * either a `std::tuple` or something iterable, such as a `std::vector`, or - * anything else with a `begin()` and `end()`. - * - * @warning While a stream is active, you cannot execute queries, open a - * pipeline, etc. on the same transaction. A transaction can have at most one - * object of a type derived from @ref pqxx::transaction_focus active on it at a - * time. - */ -class PQXX_LIBEXPORT stream_to : transaction_focus -{ -public: - /// Stream data to a pre-quoted table and columns. - /** This factory can be useful when it's not convenient to provide the - * columns list in the form of a `std::initializer_list`, or when the list - * of columns is simply not known at compile time. - * - * Also use this if you need to create multiple streams using the same table - * path and/or columns list, and you want to save a bit of work on composing - * the internal SQL statement for starting the stream. It lets you compose - * the string representations for the table path and the columns list, so you - * can compute these once and then re-use them later. - * - * @param tx The transaction within which the stream will operate. - * @param path Name or path for the table upon which the stream will - * operate. If any part of the table path may contain special - * characters or be case-sensitive, quote the path using - * pqxx::connection::quote_table(). - * @param columns Columns to which the stream will write. They should be - * comma-separated and, if needed, quoted. You can produce the string - * using pqxx::connection::quote_columns(). If you omit this argument, - * the stream will write all columns in the table, in schema order. - */ - static stream_to raw_table( - transaction_base &tx, std::string_view path, std::string_view columns = "") - { - return {tx, path, columns}; - } - - /// Create a `stream_to` writing to a named table and columns. - /** Use this to stream data to a table, where the list of columns is known at - * compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns Optionally, the columns to which the stream should write. - * If you do not pass this, the stream will write to all columns in the - * table, in schema order. - */ - static stream_to table( - transaction_base &tx, table_path path, - std::initializer_list columns = {}) - { - auto const &conn{tx.conn()}; - return raw_table(tx, conn.quote_table(path), conn.quote_columns(columns)); - } - -#if defined(PQXX_HAVE_CONCEPTS) - /// Create a `stream_to` writing to a named table and columns. - /** Use this version to stream data to a table, when the list of columns is - * not known at compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns The columns to which the stream should write. - */ - template - static stream_to - table(transaction_base &tx, table_path path, COLUMNS const &columns) - { - auto const &conn{tx.conn()}; - return stream_to::raw_table( - tx, conn.quote_table(path), tx.conn().quote_columns(columns)); - } - - /// Create a `stream_to` writing to a named table and columns. - /** Use this version to stream data to a table, when the list of columns is - * not known at compile time. - * - * @param tx The transaction within which the stream will operate. - * @param path A @ref table_path designating the target table. - * @param columns The columns to which the stream should write. - */ - template - static stream_to - table(transaction_base &tx, std::string_view path, COLUMNS const &columns) - { - return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns)); - } -#endif // PQXX_HAVE_CONCEPTS - - /// Create a stream, without specifying columns. - /** @deprecated Use @ref table or @ref raw_table as a factory. - * - * Fields will be inserted in whatever order the columns have in the - * database. - * - * You'll probably want to specify the columns, so that the mapping between - * your data fields and the table is explicit in your code, and not hidden - * in an "implicit contract" between your code and your schema. - */ - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &tx, std::string_view table_name) : - stream_to{tx, table_name, ""sv} - {} - - /// Create a stream, specifying column names as a container of strings. - /** @deprecated Use @ref table or @ref raw_table as a factory. - */ - template - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &, std::string_view table_name, Columns const &columns); - - /// Create a stream, specifying column names as a sequence of strings. - /** @deprecated Use @ref table or @ref raw_table as a factory. - */ - template - [[deprecated("Use table() or raw_table() factory.")]] stream_to( - transaction_base &, std::string_view table_name, Iter columns_begin, - Iter columns_end); - - ~stream_to() noexcept; - - /// Does this stream still need to @ref complete()? - [[nodiscard]] constexpr operator bool() const noexcept - { - return not m_finished; - } - /// Has this stream been through its concluding @c complete()? - [[nodiscard]] constexpr bool operator!() const noexcept - { - return m_finished; - } - - /// Complete the operation, and check for errors. - /** Always call this to close the stream in an orderly fashion, even after - * an error. (In the case of an error, abort the transaction afterwards.) - * - * The only circumstance where it's safe to skip this is after an error, if - * you're discarding the entire connection. - */ - void complete(); - - /// Insert a row of data. - /** Returns a reference to the stream, so you can chain the calls. - * - * The @c row can be a tuple, or any type that can be iterated. Each - * item becomes a field in the row, in the same order as the columns you - * specified when creating the stream. - * - * If you don't already happen to have your fields in the form of a tuple or - * container, prefer @c write_values. It's faster and more convenient. - */ - template stream_to &operator<<(Row const &row) - { - write_row(row); - return *this; - } - - /// Stream a `stream_from` straight into a `stream_to`. - /** This can be useful when copying between different databases. If the - * source and the destination are on the same database, you'll get better - * performance doing it all in a regular query. - */ - stream_to &operator<<(stream_from &); - - /// Insert a row of data, given in the form of a @c std::tuple or container. - /** The @c row can be a tuple, or any type that can be iterated. Each - * item becomes a field in the row, in the same order as the columns you - * specified when creating the stream. - * - * The preferred way to insert a row is @c write_values. - */ - template void write_row(Row const &row) - { - fill_buffer(row); - write_buffer(); - } - - /// Insert values as a row. - /** This is the recommended way of inserting data. Pass your field values, - * of any convertible type. - */ - template void write_values(Ts const &...fields) - { - fill_buffer(fields...); - write_buffer(); - } - -private: - /// Stream a pre-quoted table name and columns list. - stream_to( - transaction_base &tx, std::string_view path, std::string_view columns); - - bool m_finished = false; - - /// Reusable buffer for a row. Saves doing an allocation for each row. - std::string m_buffer; - - /// Reusable buffer for converting/escaping a field. - std::string m_field_buf; - - /// Glyph scanner, for parsing the client encoding. - internal::glyph_scanner_func *m_scanner; - - /// Write a row of raw text-format data into the destination table. - void write_raw_line(std::string_view); - - /// Write a row of data from @c m_buffer into the destination table. - /** Resets the buffer for the next row. - */ - void write_buffer(); - - /// COPY encoding for a null field, plus subsequent separator. - static constexpr std::string_view null_field{"\\N\t"}; - - /// Estimate buffer space needed for a field which is always null. - template - static std::enable_if_t::always_null, std::size_t> - estimate_buffer(T const &) - { - return std::size(null_field); - } - - /// Estimate buffer space needed for field f. - /** The estimate is not very precise. We don't actually know how much space - * we'll need once the escaping comes in. - */ - template - static std::enable_if_t::always_null, std::size_t> - estimate_buffer(T const &field) - { - return is_null(field) ? std::size(null_field) : size_buffer(field); - } - - /// Append escaped version of @c data to @c m_buffer, plus a tab. - void escape_field_to_buffer(std::string_view data); - - /// Append string representation for @c f to @c m_buffer. - /** This is for the general case, where the field may contain a value. - * - * Also appends a tab. The tab is meant to be a separator, not a terminator, - * so if you write any fields at all, you'll end up with one tab too many - * at the end of the buffer. - */ - template - std::enable_if_t::always_null> - append_to_buffer(Field const &f) - { - // We append each field, terminated by a tab. That will leave us with - // one tab too many, assuming we write any fields at all; we remove that - // at the end. - if (is_null(f)) - { - // Easy. Append null and tab in one go. - m_buffer.append(null_field); - } - else - { - // Convert f into m_buffer. - - using traits = string_traits; - auto const budget{estimate_buffer(f)}; - auto const offset{std::size(m_buffer)}; - - if constexpr (std::is_arithmetic_v) - { - // Specially optimised for "safe" types, which never need any - // escaping. Convert straight into m_buffer. - - // The budget we get from size_buffer() includes room for the trailing - // zero, which we must remove. But we're also inserting tabs between - // fields, so we re-purpose the extra byte for that. - auto const total{offset + budget}; - m_buffer.resize(total); - auto const data{m_buffer.data()}; - char *const end{traits::into_buf(data + offset, data + total, f)}; - *(end - 1) = '\t'; - // Shrink to fit. Keep the tab though. - m_buffer.resize(static_cast(end - data)); - } - else if constexpr ( - std::is_same_v or - std::is_same_v or - std::is_same_v) - { - // This string may need escaping. - m_field_buf.resize(budget); - escape_field_to_buffer(f); - } - else - { - // This field needs to be converted to a string, and after that, - // escaped as well. - m_field_buf.resize(budget); - auto const data{m_field_buf.data()}; - escape_field_to_buffer( - traits::to_buf(data, data + std::size(m_field_buf), f)); - } - } - } - - /// Append string representation for a null field to @c m_buffer. - /** This special case is for types which are always null. - * - * Also appends a tab. The tab is meant to be a separator, not a terminator, - * so if you write any fields at all, you'll end up with one tab too many - * at the end of the buffer. - */ - template - std::enable_if_t::always_null> - append_to_buffer(Field const &) - { - m_buffer.append(null_field); - } - - /// Write raw COPY line into @c m_buffer, based on a container of fields. - template - std::enable_if_t> - fill_buffer(Container const &c) - { - // To avoid unnecessary allocations and deallocations, we run through c - // twice: once to determine how much buffer space we may need, and once to - // actually write it into the buffer. - std::size_t budget{0}; - for (auto const &f : c) budget += estimate_buffer(f); - m_buffer.reserve(budget); - for (auto const &f : c) append_to_buffer(f); - } - - /// Estimate how many buffer bytes we need to write tuple. - template - static std::size_t - budget_tuple(Tuple const &t, std::index_sequence) - { - return (estimate_buffer(std::get(t)) + ...); - } - - /// Write tuple of fields to @c m_buffer. - template - void append_tuple(Tuple const &t, std::index_sequence) - { - (append_to_buffer(std::get(t)), ...); - } - - /// Write raw COPY line into @c m_buffer, based on a tuple of fields. - template void fill_buffer(std::tuple const &t) - { - using indexes = std::make_index_sequence; - - m_buffer.reserve(budget_tuple(t, indexes{})); - append_tuple(t, indexes{}); - } - - /// Write raw COPY line into @c m_buffer, based on varargs fields. - template void fill_buffer(const Ts &...fields) - { - (..., append_to_buffer(fields)); - } - - constexpr static std::string_view s_classname{"stream_to"}; -}; - - -template -inline stream_to::stream_to( - transaction_base &tx, std::string_view table_name, Columns const &columns) : - stream_to{tx, table_name, std::begin(columns), std::end(columns)} -{} - - -template -inline stream_to::stream_to( - transaction_base &tx, std::string_view table_name, Iter columns_begin, - Iter columns_end) : - stream_to{ - tx, - tx.quote_name( - table_name, - separated_list(",", columns_begin, columns_end, [&tx](auto col) { - return tx.quote_name(*col); - }))} -{} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/subtransaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/subtransaction deleted file mode 100644 index e0d154903..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/subtransaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::subtransaction class. - * - * pqxx::subtransaction is a nested transaction, i.e. one inside a transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/subtransaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/subtransaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/subtransaction.hxx deleted file mode 100644 index e66b7a7a8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/subtransaction.hxx +++ /dev/null @@ -1,96 +0,0 @@ -/* Definition of the pqxx::subtransaction class. - * - * pqxx::subtransaction is a nested transaction, i.e. one within a transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_SUBTRANSACTION -#define PQXX_H_SUBTRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx -{ -/** - * @ingroup transactions - */ -/// "Transaction" nested within another transaction -/** A subtransaction can be executed inside a backend transaction, or inside - * another subtransaction. This can be useful when, for example, statements in - * a transaction may harmlessly fail and you don't want them to abort the - * entire transaction. Here's an example of how a temporary table may be - * dropped before re-creating it, without failing if the table did not exist: - * - * ```cxx - * void do_job(connection &C) - * { - * string const temptable = "fleetingtable"; - * - * work W(C, "do_job"); - * do_firstpart(W); - * - * // Attempt to delete our temporary table if it already existed. - * try - * { - * subtransaction S(W, "droptemp"); - * S.exec0("DROP TABLE " + temptable); - * S.commit(); - * } - * catch (undefined_table const &) - * { - * // Table did not exist. Which is what we were hoping to achieve anyway. - * // Carry on without regrets. - * } - * - * // S may have gone into a failed state and been destroyed, but the - * // upper-level transaction W is still fine. We can continue to use it. - * W.exec0("CREATE TEMP TABLE " + temptable + "(bar integer, splat - * varchar)"); - * - * do_lastpart(W); - * } - * ``` - * - * (This is just an example. If you really wanted to do drop a table without - * an error if it doesn't exist, you'd use DROP TABLE IF EXISTS.) - * - * There are no isolation levels inside a transaction. They are not needed - * because all actions within the same backend transaction are always performed - * sequentially anyway. - * - * @warning While the subtransaction is "live," you cannot execute queries or - * open streams etc. on its parent transaction. A transaction can have at most - * one object of a type derived from @ref pqxx::transaction_focus active on it - * at a time. - */ -class PQXX_LIBEXPORT subtransaction : public transaction_focus, - public dbtransaction -{ -public: - /// Nest a subtransaction nested in another transaction. - explicit subtransaction(dbtransaction &t, std::string_view tname = ""sv); - - /// Nest a subtransaction in another subtransaction. - explicit subtransaction(subtransaction &t, std::string_view name = ""sv); - - virtual ~subtransaction() noexcept override; - -private: - std::string quoted_name() const - { - return quote_name(transaction_focus::name()); - } - virtual void do_commit() override; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/time b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/time deleted file mode 100644 index 85df05744..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/time +++ /dev/null @@ -1,6 +0,0 @@ -/** Date/time string conversions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/time.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/time.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/time.hxx deleted file mode 100644 index effed05e0..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/time.hxx +++ /dev/null @@ -1,88 +0,0 @@ -/** Support for date/time values. - * - * At the moment this supports dates, but not times. - */ -#ifndef PQXX_H_TIME -#define PQXX_H_TIME - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/internal/concat.hxx" -#include "pqxx/strconv.hxx" - - -#if defined(PQXX_HAVE_YEAR_MONTH_DAY) - -namespace pqxx -{ -using namespace std::literals; - -template<> -struct nullness - : no_null -{}; - - -/// String representation for a Gregorian date in ISO-8601 format. -/** @warning Experimental. There may still be design problems, particularly - * when it comes to BC years. - * - * PostgreSQL supports a choice of date formats, but libpqxx does not. The - * other formats in turn support a choice of "month before day" versus "day - * before month," meaning that it's not necessarily known which format a given - * date is supposed to be. So I repeat: ISO-8601-style format only! - * - * Invalid dates will not convert. This includes February 29 on non-leap - * years, which is why it matters that `year_month_day` represents a - * _Gregorian_ date. - * - * The range of years is limited. At the time of writing, PostgreSQL 14 - * supports years from 4713 BC to 294276 AD inclusive, and C++20 supports - * a range of 32767 BC to 32767 AD inclusive. So in practice, years must fall - * between 4713 BC and 32767 AD, inclusive. - * - * @warning Support for BC (or BCE) years is still experimental. I still need - * confirmation on this issue: it looks as if C++ years are astronomical years, - * which means they have a Year Zero. Regular BC/AD years do not have a year - * zero, so the year 1 AD follows directly after 1 BC. - * - * So, what to our calendars (and to PostgreSQL) is the year "0001 BC" seems to - * count as year "0" in a `std::chrono::year_month_day`. The year 0001 AD is - * still equal to 1 as you'd expect, and all AD years work normally, but all - * years before then are shifted by one. For instance, the year 543 BC would - * be -542 in C++. - */ -template<> struct PQXX_LIBEXPORT string_traits -{ - [[nodiscard]] static zview - to_buf(char *begin, char *end, std::chrono::year_month_day const &value) - { - return generic_to_buf(begin, end, value); - } - - static char * - into_buf(char *begin, char *end, std::chrono::year_month_day const &value); - - [[nodiscard]] static std::chrono::year_month_day - from_string(std::string_view text); - - [[nodiscard]] static std::size_t - size_buffer(std::chrono::year_month_day const &) noexcept - { - static_assert(int{(std::chrono::year::min)()} >= -99999); - static_assert(int{(std::chrono::year::max)()} <= 99999); - return 5 + 1 + 2 + 1 + 2 + std::size(s_bc) + 1; - } - -private: - /// The "BC" suffix for years before 1 AD. - static constexpr std::string_view s_bc{" BC"sv}; -}; -} // namespace pqxx -#endif // PQXX_HAVE_YEAR_MONTH_DAY -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction deleted file mode 100644 index a7ae39d43..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::transaction class. - * - * pqxx::transaction represents a standard database transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transaction.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction.hxx deleted file mode 100644 index e90917e38..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction.hxx +++ /dev/null @@ -1,108 +0,0 @@ -/* Definition of the pqxx::transaction class. - * pqxx::transaction represents a standard database transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION -#define PQXX_H_TRANSACTION - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/dbtransaction.hxx" - -namespace pqxx::internal -{ -/// Helper base class for the @ref transaction class template. -class PQXX_LIBEXPORT basic_transaction : public dbtransaction -{ -protected: - basic_transaction( - connection &c, zview begin_command, std::string_view tname); - basic_transaction(connection &c, zview begin_command, std::string &&tname); - basic_transaction(connection &c, zview begin_command); - - virtual ~basic_transaction() noexcept override = 0; - -private: - virtual void do_commit() override; -}; -} // namespace pqxx::internal - - -namespace pqxx -{ -/** - * @ingroup transactions - */ -//@{ - -/// Standard back-end transaction, templatised on isolation level. -/** This is the type you'll normally want to use to represent a transaction on - * the database. - * - * Usage example: double all wages. - * - * ```cxx - * extern connection C; - * work T(C); - * try - * { - * T.exec0("UPDATE employees SET wage=wage*2"); - * T.commit(); // NOTE: do this inside try block - * } - * catch (exception const &e) - * { - * cerr << e.what() << endl; - * T.abort(); // Usually not needed; same happens when T's life ends. - * } - * ``` - */ -template< - isolation_level ISOLATION = isolation_level::read_committed, - write_policy READWRITE = write_policy::read_write> -class transaction final : public internal::basic_transaction -{ -public: - /// Begin a transaction. - /** - * @param c Connection for this transaction to operate on. - * @param tname Optional name for transaction. Must begin with a letter and - * may contain letters and digits only. - */ - transaction(connection &c, std::string_view tname) : - internal::basic_transaction{ - c, internal::begin_cmd, tname} - {} - - /// Begin a transaction. - /** - * @param c Connection for this transaction to operate on. - * may contain letters and digits only. - */ - explicit transaction(connection &c) : - internal::basic_transaction{ - c, internal::begin_cmd} - {} - - virtual ~transaction() noexcept override { close(); } -}; - - -/// The default transaction type. -using work = transaction<>; - -/// Read-only transaction. -using read_transaction = - transaction; - -//@} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_base b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_base deleted file mode 100644 index c39219aac..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_base +++ /dev/null @@ -1,9 +0,0 @@ -/** Base for the transaction classes. - * - * pqxx::transaction_base defines the interface for any abstract class that - * represents a database transaction. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transaction_base.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_base.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_base.hxx deleted file mode 100644 index 4363cc56a..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_base.hxx +++ /dev/null @@ -1,810 +0,0 @@ -/* Common code and definitions for the transaction classes. - * - * pqxx::transaction_base defines the interface for any abstract class that - * represents a database transaction. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION_BASE -#define PQXX_H_TRANSACTION_BASE - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -/* End-user programs need not include this file, unless they define their own - * transaction classes. This is not something the typical program should want - * to do. - * - * However, reading this file is worthwhile because it defines the public - * interface for the available transaction classes such as transaction and - * nontransaction. - */ - -#include "pqxx/connection.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/encoding_group.hxx" -#include "pqxx/isolation.hxx" -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/util.hxx" - -namespace pqxx::internal::gate -{ -class transaction_subtransaction; -class transaction_sql_cursor; -class transaction_stream_to; -class transaction_transaction_focus; -} // namespace pqxx::internal::gate - - -namespace pqxx -{ -using namespace std::literals; - - -class transaction_focus; - - -/** - * @defgroup transactions Transaction classes - * - * All database access goes through instances of these classes. - * However, not all implementations of this interface need to provide full - * transactional integrity. - * - * Several implementations of this interface are shipped with libpqxx, - * including the plain transaction class, the entirely unprotected - * nontransaction, and the more cautious robusttransaction. - */ - -/// Interface definition (and common code) for "transaction" classes. -/** - * @ingroup transactions - * - * Abstract base class for all transaction types. - */ -class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base -{ -public: - transaction_base() = delete; - transaction_base(transaction_base const &) = delete; - transaction_base(transaction_base &&) = delete; - transaction_base &operator=(transaction_base const &) = delete; - transaction_base &operator=(transaction_base &&) = delete; - - virtual ~transaction_base() = 0; - - /// Commit the transaction. - /** Make the effects of this transaction definite. If you destroy a - * transaction without invoking its @ref commit() first, that will implicitly - * abort it. (For the @ref nontransaction class though, "commit" and "abort" - * really don't do anything, hence its name.) - * - * There is, however, a minute risk that you might lose your connection to - * the database at just the wrong moment here. In that case, libpqxx may be - * unable to determine whether the database was able to complete the - * transaction, or had to roll it back. In that scenario, @ref commit() will - * throw an in_doubt_error. There is a different transaction class called - * @ref robusttransaction which takes some special precautions to reduce this - * risk. - */ - void commit(); - - /// Abort the transaction. - /** No special effort is required to call this function; it will be called - * implicitly when the transaction is destructed. - */ - void abort(); - - /** - * @ingroup escaping-functions - * - * Use these when writing SQL queries that incorporate C++ values as SQL - * constants. - * - * The functions you see here are just convenience shortcuts to the same - * functions on the connection object. - */ - //@{ - /// Escape string for use as SQL string literal in this transaction. - template [[nodiscard]] auto esc(ARGS &&...args) const - { - return conn().esc(std::forward(args)...); - } - - /// Escape binary data for use as SQL string literal in this transaction. - /** Raw, binary data is treated differently from regular strings. Binary - * strings are never interpreted as text, so they may safely include byte - * values or byte sequences that don't happen to represent valid characters - * in the character encoding being used. - * - * The binary string does not stop at the first zero byte, as is the case - * with textual strings. Instead, it may contain zero bytes anywhere. If - * it happens to contain bytes that look like quote characters, or other - * things that can disrupt their use in SQL queries, they will be replaced - * with special escape sequences. - */ - template [[nodiscard]] auto esc_raw(ARGS &&...args) const - { - return conn().esc_raw(std::forward(args)...); - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(zview text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return conn().unesc_raw(text); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard]] std::basic_string unesc_bin(zview text) - { - return conn().unesc_bin(text); - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string - unesc_raw(char const *text) const - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return conn().unesc_raw(text); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Unescape binary data, e.g. from a table field or notification payload. - /** Takes a binary string as escaped by PostgreSQL, and returns a restored - * copy of the original binary data. - */ - [[nodiscard]] std::basic_string unesc_bin(char const text[]) - { - return conn().unesc_bin(text); - } - - /// Represent object as SQL string, including quoting & escaping. - /** Nulls are recognized and represented as SQL nulls. */ - template [[nodiscard]] std::string quote(T const &t) const - { - return conn().quote(t); - } - - [[deprecated( - "Use std::basic_string instead of binarystring.")]] std::string - quote(binarystring const &t) const - { - return conn().quote(t.bytes_view()); - } - - /// Binary-escape and quote a binary string for use as an SQL constant. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(unsigned char const bin[], std::size_t len) const - { - return quote(binary_cast(bin, len)); - } - - /// Binary-escape and quote a binary string for use as an SQL constant. - [[deprecated("Use quote(std::basic_string_view).")]] std::string - quote_raw(zview bin) const; - -#if defined(PQXX_HAVE_CONCEPTS) - /// Binary-escape and quote a binary string for use as an SQL constant. - /** For binary data you can also just use @ref quote(data). */ - template - [[nodiscard]] std::string quote_raw(DATA const &data) const - { - return conn().quote_raw(data); - } -#endif - - /// Escape an SQL identifier for use in a query. - [[nodiscard]] std::string quote_name(std::string_view identifier) const - { - return conn().quote_name(identifier); - } - - /// Escape string for literal LIKE match. - [[nodiscard]] std::string - esc_like(std::string_view bin, char escape_char = '\\') const - { - return conn().esc_like(bin, escape_char); - } - //@} - - /** - * @name Command execution - * - * There are many functions for executing (or "performing") a command (or - * "query"). This is the most fundamental thing you can do with the library, - * and you always do it from a transaction class. - * - * Command execution can throw many types of exception, including sql_error, - * broken_connection, and many sql_error subtypes such as - * feature_not_supported or insufficient_privilege. But any exception thrown - * by the C++ standard library may also occur here. All exceptions you will - * see libpqxx throw are derived from std::exception. - * - * One unusual feature in libpqxx is that you can give your query a name or - * description. This does not mean anything to the database, but sometimes - * it can help libpqxx produce more helpful error messages, making problems - * in your code easier to debug. - * - * Many of the execution functions used to accept a `desc` argument, a - * human-readable description of the statement for use in error messages. - * This could make failures easier to debug. Future versions will use - * C++20's `std::source_location` to identify the failing statement. - */ - //@{ - - /// Execute a command. - /** - * @param query Query or command to execute. - * @param desc Optional identifier for query, to help pinpoint SQL errors. - * @return A result set describing the query's or command's result. - */ - [[deprecated("The desc parameter is going away.")]] result - exec(std::string_view query, std::string_view desc); - - /// Execute a command. - /** - * @param query Query or command to execute. - * @return A result set describing the query's or command's result. - */ - result exec(std::string_view query) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec(query, std::string_view{}); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute a command. - /** - * @param query Query or command to execute. - * @param desc Optional identifier for query, to help pinpoint SQL errors. - * @return A result set describing the query's or command's result. - */ - [[deprecated( - "Pass your query as a std::string_view, not stringstream.")]] result - exec(std::stringstream const &query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec(query.str(), desc); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command, which should return zero rows of data. - /** Works like @ref exec, but fails if the result contains data. It still - * returns a result, however, which may contain useful metadata. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] result - exec0(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(0, query, desc); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command, which should return zero rows of data. - /** Works like @ref exec, but fails if the result contains data. It still - * returns a result, however, which may contain useful metadata. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - result exec0(zview query) { return exec_n(0, query); } - - /// Execute command returning a single row of data. - /** Works like @ref exec, but requires the result to contain exactly one row. - * The row can be addressed directly, without the need to find the first row - * in a result set. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] row - exec1(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(1, query, desc).front(); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Execute command returning a single row of data. - /** Works like @ref exec, but requires the result to contain exactly one row. - * The row can be addressed directly, without the need to find the first row - * in a result set. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - row exec1(zview query) { return exec_n(1, query).front(); } - - /// Execute command, expect given number of rows. - /** Works like @ref exec, but checks that the result has exactly the expected - * number of rows. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - [[deprecated("The desc parameter is going away.")]] result - exec_n(result::size_type rows, zview query, std::string_view desc); - - /// Execute command, expect given number of rows. - /** Works like @ref exec, but checks that the result has exactly the expected - * number of rows. - * - * @throw unexpected_rows If the query returned the wrong number of rows. - */ - result exec_n(result::size_type rows, zview query) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return exec_n(rows, query, std::string_view{}); -#include "pqxx/internal/ignore-deprecated-post.hxx" - } - - /// Perform query, expecting exactly 1 row with 1 field, and convert it. - /** This is convenience shorthand for querying exactly one value from the - * database. It returns that value, converted to the type you specify. - */ - template - [[deprecated("The desc parameter is going away.")]] TYPE - query_value(zview query, std::string_view desc) - { -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row const r{exec1(query, desc)}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - if (std::size(r) != 1) - throw usage_error{internal::concat( - "Queried single value from result with ", std::size(r), " columns.")}; - return r[0].as(); - } - - /// Perform query, expecting exactly 1 row with 1 field, and convert it. - /** This is convenience shorthand for querying exactly one value from the - * database. It returns that value, converted to the type you specify. - */ - template TYPE query_value(zview query) - { - row const r{exec1(query)}; - if (std::size(r) != 1) - throw usage_error{internal::concat( - "Queried single value from result with ", std::size(r), " columns.")}; - return r[0].as(); - } - - /// Execute a query, and loop over the results row by row. - /** Converts the rows to `std::tuple`, of the column types you specify. - * - * Use this with a range-based "for" loop. It executes the query, and - * directly maps the resulting rows onto a `std::tuple` of the types you - * specify. It starts before all the data from the server is in, so if your - * network connection to the server breaks while you're iterating, you'll get - * an exception partway through. - * - * The stream lives entirely within the lifetime of the transaction. Make - * sure you destroy the stream before you destroy the transaction. Either - * iterate the stream all the way to the end, or destroy first the stream - * and then the transaction without touching either in any other way. Until - * the stream has finished, the transaction is in a special state where it - * cannot execute queries. - * - * As a special case, tuple may contain `std::string_view` fields, but the - * strings to which they point will only remain valid until you extract the - * next row. After that, the memory holding the string may be overwritten or - * deallocated. - * - * If any of the columns can be null, and the C++ type to which it translates - * does not have a null value, wrap the type in `std::optional` (or if - * you prefer, `std::shared_ptr` or `std::unique_ptr)`. These templates - * do recognise null values, and libpqxx will know how to convert to them. - * - * The connection is in a special state until the iteration finishes. So if - * it does not finish due to a `break` or a `return` or an exception, then - * the entire connection becomes effectively unusable. - * - * Querying in this way is faster than the `exec()` methods for larger - * results (but slower for small ones). You can start processing rows before - * the full result is in. Also, `stream()` scales better in terms of memory - * usage. Where @ref exec() reads the entire result into memory at once, - * `stream()` will read and process one row at at a time. - * - * Your query executes as part of a COPY command, not as a stand-alone query, - * so there are limitations to what you can do in the query. It can be - * either a SELECT or VALUES query; or an INSERT, UPDATE, or DELETE with a - * RETURNING clause. See the documentation for PostgreSQL's COPY command for - * the details: - * - * https://www.postgresql.org/docs/current/sql-copy.html - * - * Iterating in this way does require each of the field types you pass to be - * default-constructible, copy-constructible, and assignable. These - * requirements may be loosened once libpqxx moves on to C++20. - */ - template - [[nodiscard]] auto stream(std::string_view query) & - { - // Tricky: std::make_unique() supports constructors but not RVO functions. - return pqxx::internal::owning_stream_input_iteration{ - std::unique_ptr{ - new stream_from{stream_from::query(*this, query)}}}; - } - - // C++20: Concept like std::invocable, but without specifying param types. - /// Perform a streaming query, and for each result row, call `func`. - /** Here, `func` can be a function, a `std::function`, a lambda, or an - * object that supports the function call operator. Of course `func` must - * have an unambiguous signature; it can't be overloaded or generic. - * - * The `for_each` function executes `query` in a stream using - * @ref pqxx::stream_from. Every time a row of data comes in from the - * server, it converts the row's fields to the types of `func`'s respective - * parameters, and calls `func` with those values. - * - * This will not work for all queries, but straightforward `SELECT` and - * `UPDATE ... RETURNING` queries should work. Consult the documentation for - * @ref pqxx::stream_from and PostgreSQL's underlying `COPY` command for the - * full details. - * - * Streaming a query like this is likely to be slower than the @ref exec() - * functions for small result sets, but faster for large result sets. So if - * performance matters, you'll want to use `for_each` if you query large - * amounts of data, but not if you do lots of queries with small outputs. - */ - template - inline auto for_each(std::string_view query, CALLABLE &&func) - { - using param_types = - pqxx::internal::strip_types_t>; - param_types const *const sample{nullptr}; - auto data_stream{stream_like(query, sample)}; - for (auto const &fields : data_stream) std::apply(func, fields); - } - - /** - * @name Parameterized statements - * - * You'll often need parameters in the queries you execute: "select the - * car with this licence plate." If the parameter is a string, you need to - * quote it and escape any special characters inside it, or it may become a - * target for an SQL injection attack. If it's an integer (for example), - * you need to convert it to a string, but in the database's format, without - * locale-specific niceties like "," separators between the thousands. - * - * Parameterised statements are an easier and safer way to do this. They're - * like prepared statements, but for a single use. You don't need to name - * them, and you don't need to prepare them first. - * - * Your query will include placeholders like `$1` and `$2` etc. in the places - * where you want the arguments to go. Then, you pass the argument values - * and the actual query is constructed for you. - * - * Pass the exact right number of parameters, and in the right order. The - * parameters in the query don't have to be neatly ordered from `$1` to - * `$2` to `$3` - but you must pass the argument for `$1` first, the one - * for `$2` second, etc. - * - * @warning Beware of "nul" bytes. Any string you pass as a parameter will - * end at the first char with value zero. If you pass a string that contains - * a zero byte, the last byte in the value will be the one just before the - * zero. - */ - //@{ - /// Execute an SQL statement with parameters. - template result exec_params(zview query, Args &&...args) - { - params pp(args...); - return internal_exec_params(query, pp.make_c_params()); - } - - // Execute parameterised statement, expect a single-row result. - /** @throw unexpected_rows if the result does not consist of exactly one row. - */ - template row exec_params1(zview query, Args &&...args) - { - return exec_params_n(1, query, std::forward(args)...).front(); - } - - // Execute parameterised statement, expect a result with zero rows. - /** @throw unexpected_rows if the result contains rows. - */ - template result exec_params0(zview query, Args &&...args) - { - return exec_params_n(0, query, std::forward(args)...); - } - - // Execute parameterised statement, expect exactly a given number of rows. - /** @throw unexpected_rows if the result contains the wrong number of rows. - */ - template - result exec_params_n(std::size_t rows, zview query, Args &&...args) - { - auto const r{exec_params(query, std::forward(args)...)}; - check_rowcount_params(rows, std::size(r)); - return r; - } - //@} - - /** - * @name Prepared statements - * - * These are very similar to parameterised statements. The difference is - * that you prepare them in advance, giving them identifying names. You can - * then call them by these names, passing in the argument values appropriate - * for that call. - * - * You prepare a statement on the connection, using - * @ref pqxx::connection::prepare(). But you then call the statement in a - * transaction, using the functions you see here. - * - * Never try to prepare, execute, or unprepare a prepared statement manually - * using direct SQL queries when you also use the libpqxx equivalents. For - * any given statement, either prepare, manage, and execute it through the - * dedicated libpqxx functions; or do it all directly in SQL. Don't mix the - * two, or the code may get confused. - * - * See \ref prepared for a full discussion. - * - * @warning Beware of "nul" bytes. Any string you pass as a parameter will - * end at the first char with value zero. If you pass a string that contains - * a zero byte, the last byte in the value will be the one just before the - * zero. If you need a zero byte, you're dealing with binary strings, not - * regular strings. Represent binary strings on the SQL side as `BYTEA` - * (or as large objects). On the C++ side, use types like - * `std::basic_string` or `std::basic_string_view` - * or (in C++20) `std::vector`. Also, consider large objects on - * the SQL side and @ref blob on the C++ side. - */ - //@{ - - /// Execute a prepared statement, with optional arguments. - template - result exec_prepared(zview statement, Args &&...args) - { - params pp(args...); - return internal_exec_prepared(statement, pp.make_c_params()); - } - - /// Execute a prepared statement, and expect a single-row result. - /** @throw pqxx::unexpected_rows if the result was not exactly 1 row. - */ - template - row exec_prepared1(zview statement, Args &&...args) - { - return exec_prepared_n(1, statement, std::forward(args)...).front(); - } - - /// Execute a prepared statement, and expect a result with zero rows. - /** @throw pqxx::unexpected_rows if the result contained rows. - */ - template - result exec_prepared0(zview statement, Args &&...args) - { - return exec_prepared_n(0, statement, std::forward(args)...); - } - - /// Execute a prepared statement, expect a result with given number of rows. - /** @throw pqxx::unexpected_rows if the result did not contain exactly the - * given number of rows. - */ - template - result - exec_prepared_n(result::size_type rows, zview statement, Args &&...args) - { - auto const r{exec_prepared(statement, std::forward(args)...)}; - check_rowcount_prepared(statement, rows, std::size(r)); - return r; - } - - //@} - - /** - * @name Error/warning output - */ - //@{ - /// Have connection process a warning message. - void process_notice(char const msg[]) const { m_conn.process_notice(msg); } - /// Have connection process a warning message. - void process_notice(zview msg) const { m_conn.process_notice(msg); } - //@} - - /// The connection in which this transaction lives. - [[nodiscard]] constexpr connection &conn() const noexcept { return m_conn; } - - /// Set session variable using SQL "SET" command. - /** @deprecated To set a transaction-local variable, execute an SQL `SET` - * command. To set a session variable, use the connection's - * @ref set_session_var function. - * - * @warning When setting a string value, you must make sure that the string - * is "safe." If you call @ref quote() on the string, it will return a - * safely escaped and quoted version for use as an SQL literal. - * - * @warning This function executes SQL. Do not try to set or get variables - * while a pipeline or table stream is active. - * - * @param var The variable to set. - * @param value The new value to store in the variable. This can be any SQL - * expression. - */ - [[deprecated( - "Set transaction-local variables using SQL SET statements.")]] void - set_variable(std::string_view var, std::string_view value); - - /// Read session variable using SQL "SHOW" command. - /** @warning This executes SQL. Do not try to set or get variables while a - * pipeline or table stream is active. - */ - [[deprecated("Read variables using SQL SHOW statements.")]] std::string - get_variable(std::string_view); - - // C++20: constexpr. - /// Transaction name, if you passed one to the constructor; or empty string. - [[nodiscard]] std::string_view name() const &noexcept { return m_name; } - -protected: - /// Create a transaction (to be called by implementation classes only). - /** The name, if nonempty, must begin with a letter and may contain letters - * and digits only. - */ - transaction_base( - connection &c, std::string_view tname, - std::shared_ptr rollback_cmd) : - m_conn{c}, m_name{tname}, m_rollback_cmd{rollback_cmd} - {} - - /// Create a transaction (to be called by implementation classes only). - /** Its rollback command will be "ROLLBACK". - * - * The name, if nonempty, must begin with a letter and may contain letters - * and digits only. - */ - transaction_base(connection &c, std::string_view tname); - - /// Create a transaction (to be called by implementation classes only). - explicit transaction_base(connection &c); - - /// Register this transaction with the connection. - void register_transaction(); - - /// End transaction. To be called by implementing class' destructor. - void close() noexcept; - - /// To be implemented by derived implementation class: commit transaction. - virtual void do_commit() = 0; - - /// Transaction type-specific way of aborting a transaction. - /** @warning This will become "final", since this function can be called - * from the implementing class destructor. - */ - virtual void do_abort(); - - /// Set the rollback command. - void set_rollback_cmd(std::shared_ptr cmd) - { - m_rollback_cmd = cmd; - } - - /// Execute query on connection directly. - result direct_exec(std::string_view, std::string_view desc = ""sv); - result - direct_exec(std::shared_ptr, std::string_view desc = ""sv); - -private: - enum class status - { - active, - aborted, - committed, - in_doubt - }; - - PQXX_PRIVATE void check_pending_error(); - - result - internal_exec_prepared(zview statement, internal::c_params const &args); - - result internal_exec_params(zview query, internal::c_params const &args); - - /// Throw unexpected_rows if prepared statement returned wrong no. of rows. - void check_rowcount_prepared( - zview statement, result::size_type expected_rows, - result::size_type actual_rows); - - /// Throw unexpected_rows if wrong row count from parameterised statement. - void - check_rowcount_params(std::size_t expected_rows, std::size_t actual_rows); - - /// Describe this transaction to humans, e.g. "transaction 'foo'". - [[nodiscard]] std::string description() const; - - friend class pqxx::internal::gate::transaction_transaction_focus; - PQXX_PRIVATE void register_focus(transaction_focus *); - PQXX_PRIVATE void unregister_focus(transaction_focus *) noexcept; - PQXX_PRIVATE void register_pending_error(zview) noexcept; - PQXX_PRIVATE void register_pending_error(std::string &&) noexcept; - - /// Like @ref stream(), but takes a tuple rather than a parameter pack. - template - auto stream_like(std::string_view query, std::tuple const *) - { - return stream(query); - } - - connection &m_conn; - - /// Current "focus": a pipeline, a nested transaction, a stream... - /** This pointer is used for only one purpose: sanity checks against mistakes - * such as opening one while another is still active. - */ - transaction_focus const *m_focus = nullptr; - - status m_status = status::active; - bool m_registered = false; - std::string m_name; - std::string m_pending_error; - - /// SQL command for aborting this type of transaction. - std::shared_ptr m_rollback_cmd; - - static constexpr std::string_view s_type_name{"transaction"sv}; -}; - - -// C++20: Can borrowed_range help? -/// Forbidden specialisation: underlying buffer immediately goes out of scope. -template<> -std::string_view transaction_base::query_value( - zview query, std::string_view desc) = delete; -/// Forbidden specialisation: underlying buffer immediately goes out of scope. -template<> -zview transaction_base::query_value( - zview query, std::string_view desc) = delete; - -} // namespace pqxx - - -namespace pqxx::internal -{ -/// The SQL command for starting a given type of transaction. -template -extern const zview begin_cmd; - -// These are not static members, so "constexpr" does not imply "inline". -template<> -inline constexpr zview begin_cmd{ - "BEGIN"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN READ ONLY"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL REPEATABLE READ"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL SERIALIZABLE"_zv}; -template<> -inline constexpr zview begin_cmd{ - "BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY"_zv}; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_focus b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_focus deleted file mode 100644 index fe78a9bcc..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_focus +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Transaction focus: types which monopolise a transaction's attention. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/types.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_focus.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_focus.hxx deleted file mode 100644 index 0707e3cc4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transaction_focus.hxx +++ /dev/null @@ -1,89 +0,0 @@ -/** Transaction focus: types which monopolise a transaction's attention. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTION_FOCUS -#define PQXX_H_TRANSACTION_FOCUS - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include "pqxx/util.hxx" - -namespace pqxx -{ -/// Base class for things that monopolise a transaction's attention. -/** You probably won't need to use this class. But it can be useful to _know_ - * that a given libpqxx class is derived from it. - * - * Pipelines, SQL statements, and data streams are examples of classes derived - * from `transaction_focus`. For any given transaction, only one object of - * such a class can be active at any given time. - */ -class PQXX_LIBEXPORT transaction_focus -{ -public: - transaction_focus( - transaction_base &t, std::string_view cname, std::string_view oname) : - m_trans{t}, m_classname{cname}, m_name{oname} - {} - - transaction_focus( - transaction_base &t, std::string_view cname, std::string &&oname) : - m_trans{t}, m_classname{cname}, m_name{std::move(oname)} - {} - - transaction_focus(transaction_base &t, std::string_view cname) : - m_trans{t}, m_classname{cname} - {} - - transaction_focus() = delete; - transaction_focus(transaction_focus const &) = delete; - transaction_focus &operator=(transaction_focus const &) = delete; - - /// Class name, for human consumption. - [[nodiscard]] constexpr std::string_view classname() const noexcept - { - return m_classname; - } - - /// Name for this object, if the caller passed one; empty string otherwise. - [[nodiscard]] std::string_view name() const &noexcept { return m_name; } - - [[nodiscard]] std::string description() const - { - return pqxx::internal::describe_object(m_classname, m_name); - } - - /// Can't move a transaction_focus. - /** Moving the transaction_focus would break the transaction's reference back - * to the object. - */ - transaction_focus(transaction_focus &&) = delete; - - /// Can't move a transaction_focus. - /** Moving the transaction_focus would break the transaction's reference back - * to the object. - */ - transaction_focus &operator=(transaction_focus &&) = delete; - -protected: - void register_me(); - void unregister_me() noexcept; - void reg_pending_error(std::string const &) noexcept; - bool registered() const noexcept { return m_registered; } - - transaction_base &m_trans; - -private: - bool m_registered = false; - std::string_view m_classname; - std::string m_name; -}; -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transactor b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transactor deleted file mode 100644 index 29d1b9640..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transactor +++ /dev/null @@ -1,8 +0,0 @@ -/** pqxx::transactor class. - * - * pqxx::transactor is a framework-style wrapper for safe transactions. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/transactor.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transactor.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transactor.hxx deleted file mode 100644 index eefd04ba1..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/transactor.hxx +++ /dev/null @@ -1,147 +0,0 @@ -/* Transactor framework, a wrapper for safely retryable transactions. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TRANSACTOR -#define PQXX_H_TRANSACTOR - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include - -#include "pqxx/connection.hxx" -#include "pqxx/transaction.hxx" - -namespace pqxx -{ -/** - * @defgroup transactor Transactor framework - * - * Sometimes a transaction can fail for completely transient reasons, such as a - * conflict with another transaction in SERIALIZABLE isolation. The right way - * to handle those failures is often just to re-run the transaction from - * scratch. - * - * For example, your REST API might be handling each HTTP request in its own - * database transaction, and if this kind of transient failure happens, you - * simply want to "replay" the whole request, in a fresh transaction. - * - * You won't necessarily want to execute the exact same SQL commands with the - * exact same data. Some of your SQL statements may depend on state that can - * vary between retries. Data in the database may already have changed, for - * instance. So instead of dumbly replaying the SQL, you re-run the same - * application code that produced those SQL commands, from the start. - * - * The transactor framework makes it a little easier for you to do this safely, - * and avoid typical pitfalls. You encapsulate the work that you want to do - * into a callable that you pass to the @ref perform function. - * - * Here's how it works. You write your transaction code as a lambda or - * function, which creates its own transaction object, does its work, and - * commits at the end. You pass that callback to @ref pqxx::perform, which - * runs it for you. - * - * If there's a failure inside your callback, there will be an exception. Your - * transaction object goes out of scope and gets destroyed, so that it aborts - * implicitly. Seeing this, @ref perform tries running your callback again. It - * stops doing that when the callback succeeds, or when it has failed too many - * times, or when there's an error that leaves the database in an unknown - * state, such as a lost connection just while we're waiting for the database - * to confirm a commit. It all depends on the type of exception. - * - * The callback takes no arguments. If you're using lambdas, the easy way to - * pass arguments is for the lambda to "capture" them from your variables. Or, - * if you're using functions, you may want to use `std::bind`. - * - * Once your callback succeeds, it can return a result, and @ref perform will - * return that result back to you. - */ -//@{ - -/// Simple way to execute a transaction with automatic retry. -/** - * Executes your transaction code as a callback. Repeats it until it completes - * normally, or it throws an error other than the few libpqxx-generated - * exceptions that the framework understands, or after a given number of failed - * attempts, or if the transaction ends in an "in-doubt" state. - * - * (An in-doubt state is one where libpqxx cannot determine whether the server - * finally committed a transaction or not. This can happen if the network - * connection to the server is lost just while we're waiting for its reply to - * a "commit" statement. The server may have completed the commit, or not, but - * it can't tell you because there's no longer a connection. - * - * Using this still takes a bit of care. If your callback makes use of data - * from the database, you'll probably have to query that data within your - * callback. If the attempt to perform your callback fails, and the framework - * tries again, you'll be in a new transaction and the data in the database may - * have changed under your feet. - * - * Also be careful about changing variables or data structures from within - * your callback. The run may still fail, and perhaps get run again. The - * ideal way to do it (in most cases) is to return your result from your - * callback, and change your program's data state only after @ref perform - * completes successfully. - * - * @param callback Transaction code that can be called with no arguments. - * @param attempts Maximum number of times to attempt performing callback. - * Must be greater than zero. - * @return Whatever your callback returns. - */ -template -inline auto perform(TRANSACTION_CALLBACK &&callback, int attempts = 3) - -> std::invoke_result_t -{ - if (attempts <= 0) - throw std::invalid_argument{ - "Zero or negative number of attempts passed to pqxx::perform()."}; - - for (; attempts > 0; --attempts) - { - try - { - return std::invoke(callback); - } - catch (in_doubt_error const &) - { - // Not sure whether transaction went through or not. The last thing in - // the world that we should do now is try again! - throw; - } - catch (statement_completion_unknown const &) - { - // Not sure whether our last statement succeeded. Don't risk running it - // again. - throw; - } - catch (broken_connection const &) - { - // Connection failed. May be worth retrying, if the transactor opens its - // own connection. - if (attempts <= 1) - throw; - continue; - } - catch (transaction_rollback const &) - { - // Some error that may well be transient, such as serialization failure - // or deadlock. Worth retrying. - if (attempts <= 1) - throw; - continue; - } - } - throw pqxx::internal_error{"No outcome reached on perform()."}; -} -} // namespace pqxx -//@} -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/types b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/types deleted file mode 100644 index 23a5caae1..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/types +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Basic typedefs and forward declarations. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/types.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/types.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/types.hxx deleted file mode 100644 index f95b598f8..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/types.hxx +++ /dev/null @@ -1,173 +0,0 @@ -/* Basic type aliases and forward declarations. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_TYPES -#define PQXX_H_TYPES - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include - -#if defined(PQXX_HAVE_CONCEPTS) && __has_include() -# include -#endif - - -namespace pqxx -{ -/// Number of rows in a result set. -using result_size_type = int; - -/// Difference between result sizes. -using result_difference_type = int; - -/// Number of fields in a row of database data. -using row_size_type = int; - -/// Difference between row sizes. -using row_difference_type = int; - -/// Number of bytes in a field of database data. -using field_size_type = std::size_t; - -/// Number of bytes in a large object. -using large_object_size_type = int64_t; - - -// Forward declarations, to help break compilation dependencies. -// These won't necessarily include all classes in libpqxx. -class binarystring; -class connection; -class const_result_iterator; -class const_reverse_result_iterator; -class const_reverse_row_iterator; -class const_row_iterator; -class dbtransaction; -class field; -class largeobjectaccess; -class notification_receiver; -struct range_error; -class result; -class row; -class stream_from; -class transaction_base; - -/// Marker for @ref stream_from constructors: "stream from table." -/** @deprecated Use @ref stream_from::table() instead. - */ -struct from_table_t -{}; - -/// Marker for @ref stream_from constructors: "stream from query." -/** @deprecated Use @ref stream_from::query() instead. - */ -struct from_query_t -{}; - - -/// Format code: is data text or binary? -/** Binary-compatible with libpq's format codes. - */ -enum class format : int -{ - text = 0, - binary = 1, -}; - - -/// Remove any constness, volatile, and reference-ness from a type. -/** @deprecated In C++20 we'll replace this with std::remove_cvref. - */ -template -using strip_t = std::remove_cv_t>; - - -#if defined(PQXX_HAVE_CONCEPTS) -/// The type of a container's elements. -/** At the time of writing there's a similar thing in `std::experimental`, - * which we may or may not end up using for this. - */ -template -using value_type = strip_t()))>; -#else // PQXX_HAVE_CONCEPTS -/// The type of a container's elements. -/** At the time of writing there's a similar thing in `std::experimental`, - * which we may or may not end up using for this. - */ -template -using value_type = strip_t()))>; -#endif // PQXX_HAVE_CONCEPTS - - -#if defined(PQXX_HAVE_CONCEPTS) -/// Concept: Any type that we can read as a string of `char`. -template -concept char_string = std::ranges::contiguous_range and - std::same_as < strip_t>, -char > ; - -/// Concept: Anything we can iterate to get things we can read as strings. -template -concept char_strings = - std::ranges::range and char_string>>; - -/// Concept: Anything we might want to treat as binary data. -template -concept potential_binary = std::ranges::contiguous_range and - (sizeof(value_type) == 1); -#endif // PQXX_HAVE_CONCEPTS - - -// C++20: Retire these compatibility definitions. -#if defined(PQXX_HAVE_CONCEPTS) - -/// Template argument type for a range. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_RANGE_ARG std::ranges::range - -/// Template argument type for @ref char_string. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRING_ARG pqxx::char_string - -/// Template argument type for @ref char_strings -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRINGS_ARG pqxx::char_strings - -#else // PQXX_HAVE_CONCEPTS - -/// Template argument type for a range. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_RANGE_ARG typename - -/// Template argument type for @ref char_string. -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRING_ARG typename - -/// Template argument type for @ref char_strings -/** This is a concept, so only available in C++20 or better. In pre-C++20 - * environments it's just an alias for @ref typename. - */ -# define PQXX_CHAR_STRINGS_ARG typename - -#endif // PQXX_HAVE_CONCEPTS -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/util b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/util deleted file mode 100644 index 6d85ab611..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/util +++ /dev/null @@ -1,6 +0,0 @@ -/** Various utility definitions for libpqxx. - */ -// Actual definitions in .hxx file so editors and such recognize file type -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/util.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/util.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/util.hxx deleted file mode 100644 index 4aa5ecf57..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/util.hxx +++ /dev/null @@ -1,521 +0,0 @@ -/* Various utility definitions for libpqxx. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_UTIL -#define PQXX_H_UTIL - -#if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -#include "pqxx/except.hxx" -#include "pqxx/internal/encodings.hxx" -#include "pqxx/types.hxx" -#include "pqxx/version.hxx" - - -/// The home of all libpqxx classes, functions, templates, etc. -namespace pqxx -{} - -#include - - -/// Internal items for libpqxx' own use. Do not use these yourself. -namespace pqxx::internal -{ - -// C++20: Retire wrapper. -/// Same as `std::cmp_less`, or a workaround where that's not available. -template -inline constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_less(lhs, rhs); -#else - // We need a variable just because lgtm.com gives off a false positive - // warning when we compare the values directly. It considers that a - // "self-comparison." - constexpr bool left_signed{std::is_signed_v}; - if constexpr (left_signed == std::is_signed_v) - return lhs < rhs; - else if constexpr (std::is_signed_v) - return (lhs <= 0) ? true : (std::make_unsigned_t(lhs) < rhs); - else - return (rhs <= 0) ? false : (lhs < std::make_unsigned_t(rhs)); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_greater, or workaround if not available. -template -inline constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_greater(lhs, rhs); -#else - return cmp_less(rhs, lhs); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_less_equal, or workaround if not available. -template -inline constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_less_equal(lhs, rhs); -#else - return not cmp_less(rhs, lhs); -#endif -} - - -// C++20: Retire wrapper. -/// C++20 std::cmp_greater_equal, or workaround if not available. -template -inline constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept -{ -#if defined(PQXX_HAVE_CMP) - return std::cmp_greater_equal(lhs, rhs); -#else - return not cmp_less(lhs, rhs); -#endif -} - - -/// Efficiently concatenate two strings. -/** This is a special case of concatenate(), needed because dependency - * management does not let us use that function here. - */ -[[nodiscard]] inline std::string cat2(std::string_view x, std::string_view y) -{ - std::string buf; - auto const xs{std::size(x)}, ys{std::size(y)}; - buf.resize(xs + ys); - x.copy(std::data(buf), xs); - y.copy(std::data(buf) + xs, ys); - return buf; -} -} // namespace pqxx::internal - - -namespace pqxx -{ -using namespace std::literals; - -/// Suppress compiler warning about an unused item. -template inline constexpr void ignore_unused(T &&...) noexcept -{} - - -/// Cast a numeric value to another type, or throw if it underflows/overflows. -/** Both types must be arithmetic types, and they must either be both integral - * or both floating-point types. - */ -template -inline TO check_cast(FROM value, std::string_view description) -{ - static_assert(std::is_arithmetic_v); - static_assert(std::is_arithmetic_v); - static_assert(std::is_integral_v == std::is_integral_v); - - // The rest of this code won't quite work for bool, but bool is trivially - // convertible to other arithmetic types as far as I can see. - if constexpr (std::is_same_v) - return static_cast(value); - - // Depending on our "if constexpr" conditions, this parameter may not be - // needed. Some compilers will warn. - ignore_unused(description); - - using from_limits = std::numeric_limits; - using to_limits = std::numeric_limits; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_signed_v) - { - if (value < to_limits::lowest()) - throw range_error{internal::cat2("Cast underflow: "sv, description)}; - } - else - { - // FROM is signed, but TO is not. Treat this as a special case, because - // there may not be a good broader type in which the compiler can even - // perform our check. - if (value < 0) - throw range_error{internal::cat2( - "Casting negative value to unsigned type: "sv, description)}; - } - } - else - { - // No need to check: the value is unsigned so can't fall below the range - // of the TO type. - } - - if constexpr (std::is_integral_v) - { - using unsigned_from = std::make_unsigned_t; - using unsigned_to = std::make_unsigned_t; - constexpr auto from_max{static_cast((from_limits::max)())}; - constexpr auto to_max{static_cast((to_limits::max)())}; - if constexpr (from_max > to_max) - { - if (internal::cmp_greater(value, to_max)) - throw range_error{internal::cat2("Cast overflow: "sv, description)}; - } - } - else if constexpr ((from_limits::max)() > (to_limits::max)()) - { - if (value > (to_limits::max)()) - throw range_error{internal::cat2("Cast overflow: ", description)}; - } - - return static_cast(value); -} - - -/** Check library version at link time. - * - * Ensures a failure when linking an application against a radically - * different libpqxx version than the one against which it was compiled. - * - * Sometimes application builds fail in unclear ways because they compile - * using headers from libpqxx version X, but then link against libpqxx - * binary version Y. A typical scenario would be one where you're building - * against a libpqxx which you have built yourself, but a different version - * is installed on the system. - * - * The check_library_version template is declared for any library version, - * but only actually defined for the version of the libpqxx binary against - * which the code is linked. - * - * If the library binary is a different version than the one declared in - * these headers, then this call will fail to link: there will be no - * definition for the function with these exact template parameter values. - * There will be a definition, but the version in the parameter values will - * be different. - */ -inline PQXX_PRIVATE void check_version() noexcept -{ - // There is no particular reason to do this here in @ref connection, except - // to ensure that every meaningful libpqxx client will execute it. The call - // must be in the execution path somewhere or the compiler won't try to link - // it. We can't use it to initialise a global or class-static variable, - // because a smart compiler might resolve it at compile time. - // - // On the other hand, we don't want to make a useless function call too - // often for performance reasons. A local static variable is initialised - // only on the definition's first execution. Compilers will be well - // optimised for this behaviour, so there's a minimal one-time cost. - static auto const version_ok{internal::PQXX_VERSION_CHECK()}; - ignore_unused(version_ok); -} - - -/// Descriptor of library's thread-safety model. -/** This describes what the library knows about various risks to thread-safety. - */ -struct PQXX_LIBEXPORT thread_safety_model -{ - /// Is the underlying libpq build thread-safe? - bool safe_libpq = false; - - /// Is Kerberos thread-safe? - /** @warning Is currently always `false`. - * - * If your application uses Kerberos, all accesses to libpqxx or Kerberos - * must be serialized. Confine their use to a single thread, or protect it - * with a global lock. - */ - bool safe_kerberos = false; - - /// A human-readable description of any thread-safety issues. - std::string description; -}; - - -/// Describe thread safety available in this build. -[[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety(); - - -#if defined(PQXX_HAVE_CONCEPTS) -# define PQXX_POTENTIAL_BINARY_ARG pqxx::potential_binary -#else -# define PQXX_POTENTIAL_BINARY_ARG typename -#endif - - -/// Cast binary data to a type that libpqxx will recognise as binary. -/** There are many different formats for storing binary data in memory. You - * may have yours as a `std::string`, or a `std::vector`, or one of - * many other types. - * - * But for libpqxx to recognise your data as binary, it needs to be a - * `std::basic_string`, or a `std::basic_string_view`; - * or in C++20 or better, any contiguous block of `std::byte`. - * - * Use `binary_cast` as a convenience helper to cast your data as a - * `std::basic_string_view`. - * - * @warning There are two things you should be aware of! First, the data must - * be contiguous in memory. In C++20 the compiler will enforce this, but in - * C++17 it's your own problem. Second, you must keep the object where you - * store the actual data alive for as long as you might use this function's - * return value. - */ -template -std::basic_string_view binary_cast(TYPE const &data) -{ - static_assert(sizeof(value_type) == 1); - return { - reinterpret_cast( - const_cast const *>( - std::data(data))), - std::size(data)}; -} - - -#if defined(PQXX_HAVE_CONCEPTS) -template -concept char_sized = (sizeof(CHAR) == 1); -# define PQXX_CHAR_SIZED_ARG char_sized -#else -# define PQXX_CHAR_SIZED_ARG typename -#endif - -/// Construct a type that libpqxx will recognise as binary. -/** Takes a data pointer and a size, without being too strict about their - * types, and constructs a `std::basic_string_view` pointing to - * the same data. - * - * This makes it a little easier to turn binary data, in whatever form you - * happen to have it, into binary data as libpqxx understands it. - */ -template -std::basic_string_view binary_cast(CHAR const *data, SIZE size) -{ - static_assert(sizeof(CHAR) == 1); - return { - reinterpret_cast(data), - check_cast(size, "binary data size")}; -} - - -/// The "null" oid. -constexpr oid oid_none{0}; -} // namespace pqxx - - -/// Private namespace for libpqxx's internal use; do not access. -/** This namespace hides definitions internal to libpqxx. These are not - * supposed to be used by client programs, and they may change at any time - * without notice. - * - * Conversely, if you find something in this namespace tremendously useful, by - * all means do lodge a request for its publication. - * - * @warning Here be dragons! - */ -namespace pqxx::internal -{ -using namespace std::literals; - - -/// A safer and more generic replacement for `std::isdigit`. -/** Turns out `std::isdigit` isn't as easy to use as it sounds. It takes an - * `int`, but requires it to be nonnegative. Which means it's an outright - * liability on systems where `char` is signed. - */ -template inline constexpr bool is_digit(CHAR c) noexcept -{ - return (c >= '0') and (c <= '9'); -} - - -/// Describe an object for humans, based on class name and optional name. -/** Interprets an empty name as "no name given." - */ -[[nodiscard]] std::string -describe_object(std::string_view class_name, std::string_view name); - - -/// Check validity of registering a new "guest" in a "host." -/** The host might be e.g. a connection, and the guest a transaction. The - * host can only have one guest at a time, so it is an error to register a new - * guest while the host already has a guest. - * - * If the new registration is an error, this function throws a descriptive - * exception. - * - * Pass the old guest (if any) and the new guest (if any), for both, a type - * name (at least if the guest is not null), and optionally an object name - * (but which may be omitted if the caller did not assign one). - */ -void check_unique_register( - void const *old_guest, std::string_view old_class, std::string_view old_name, - void const *new_guest, std::string_view new_class, - std::string_view new_name); - - -/// Like @ref check_unique_register, but for un-registering a guest. -/** Pass the guest which was registered, as well as the guest which is being - * unregistered, so that the function can check that they are the same one. - */ -void check_unique_unregister( - void const *old_guest, std::string_view old_class, std::string_view old_name, - void const *new_guest, std::string_view new_class, - std::string_view new_name); - - -/// Compute buffer size needed to escape binary data for use as a BYTEA. -/** This uses the hex-escaping format. The return value includes room for the - * "\x" prefix. - */ -inline constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept -{ - return 2 + (2 * binary_bytes) + 1; -} - - -/// Compute binary size from the size of its escaped version. -/** Do not include a terminating zero in `escaped_bytes`. - */ -inline constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept -{ - return (escaped_bytes - 2) / 2; -} - - -// TODO: Use actual binary type for "data". -/// Hex-escape binary data into a buffer. -/** The buffer must be able to accommodate - * `size_esc_bin(std::size(binary_data))` bytes, and the function will write - * exactly that number of bytes into the buffer. This includes a trailing - * zero. - */ -void PQXX_LIBEXPORT -esc_bin(std::basic_string_view binary_data, char buffer[]) noexcept; - - -/// Hex-escape binary data into a std::string. -std::string PQXX_LIBEXPORT -esc_bin(std::basic_string_view binary_data); - - -/// Reconstitute binary data from its escaped version. -void PQXX_LIBEXPORT -unesc_bin(std::string_view escaped_data, std::byte buffer[]); - - -/// Reconstitute binary data from its escaped version. -std::basic_string - PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data); - - -/// Transitional: std::ssize(), or custom implementation if not available. -template auto ssize(T const &c) -{ -#if defined(__cpp_lib_ssize) && __cplusplus >= __cpp_lib_ssize - return std::ssize(c); -#else - using signed_t = std::make_signed_t; - return static_cast(std::size(c)); -#endif // __cpp_lib_ssize -} - - -/// Helper for determining a function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple args_f(RETURN (&func)(ARGS...)); - - -/// Helper for determining a `std::function`'s parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple args_f(std::function const &); - - -/// Helper for determining a member function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple member_args_f(RETURN (CLASS::*)(ARGS...)); - - -/// Helper for determining a const member function's parameter types. -/** This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -std::tuple member_args_f(RETURN (CLASS::*)(ARGS...) const); - - -/// Helper for determining a callable type's parameter types. -/** This specialisation should work for lambdas. - * - * This function has no definition. It's not meant to be actually called. - * It's just there for pattern-matching in the compiler, so we can use its - * hypothetical return value. - */ -template -auto args_f(CALLABLE const &f) - -> decltype(member_args_f(&CALLABLE::operator())); - - -/// A callable's parameter types, as a tuple. -template -using args_t = decltype(args_f(std::declval())); - - -/// Helper: Apply `strip_t` to each of a tuple type's component types. -/** This function has no definition. It is not meant to be called, only to be - * used to deduce the right types. - */ -template -std::tuple...> strip_types(std::tuple const &); - - -/// Take a tuple type and apply @ref strip_t to its component types. -template -using strip_types_t = decltype(strip_types(std::declval())); -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/version b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/version deleted file mode 100644 index 8dd5e48d4..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/version +++ /dev/null @@ -1,7 +0,0 @@ -/** libpqxx version info. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/version.hxx" -#include "pqxx/internal/header-post.hxx" - diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/version.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/version.hxx deleted file mode 100644 index a159f1bed..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/version.hxx +++ /dev/null @@ -1,55 +0,0 @@ -/* Version info for libpqxx. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_VERSION - -# if !defined(PQXX_HEADER_PRE) -# error "Include libpqxx headers as , not ." -# endif - -/// Full libpqxx version string. -# define PQXX_VERSION "7.7.3" -/// Library ABI version. -# define PQXX_ABI "7.7" - -/// Major version number. -# define PQXX_VERSION_MAJOR 7 -/// Minor version number. -# define PQXX_VERSION_MINOR 7 - -# define PQXX_VERSION_CHECK check_pqxx_version_7_7 - -namespace pqxx::internal -{ -/// Library version check stub. -/** Helps detect version mismatches between libpqxx headers and the libpqxx - * library binary. - * - * Sometimes users run into trouble linking their code against libpqxx because - * they build their own libpqxx, but the system also has a different version - * installed. The declarations in the headers against which they compile their - * code will differ from the ones used to build the libpqxx version they're - * using, leading to confusing link errors. The solution is to generate a link - * error when the libpqxx binary is not the same version as the libpqxx headers - * used to compile the code. - * - * This function's definition is in the libpqxx binary, so it's based on the - * version as found in the binary. The headers contain a call to the function, - * whose name contains the libpqxx version as found in the headers. (The - * library build process will use its own local headers even if another version - * of the headers is installed on the system.) - * - * If the libpqxx binary was compiled for a different version than the user's - * code, linking will fail with an error: `check_pqxx_version_*_*` will not - * exist for the given version number. - */ -PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept; -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/zview b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/zview deleted file mode 100644 index 66ea2a625..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/zview +++ /dev/null @@ -1,6 +0,0 @@ -/** Zero-terminated string view class. - */ -// Actual definitions in .hxx file so editors and such recognize file type. -#include "pqxx/internal/header-pre.hxx" -#include "pqxx/zview.hxx" -#include "pqxx/internal/header-post.hxx" diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/zview.hxx b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/zview.hxx deleted file mode 100644 index 36a779f51..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/include/pqxx/zview.hxx +++ /dev/null @@ -1,163 +0,0 @@ -/* Zero-terminated string view. - * - * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/zview instead. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#ifndef PQXX_H_ZVIEW -#define PQXX_H_ZVIEW - -#include -#include -#include - -#include "pqxx/types.hxx" - - -namespace pqxx -{ -/// Marker-type wrapper: zero-terminated `std::string_view`. -/** @warning Use this only if the underlying string is zero-terminated. - * - * When you construct a zview, you are promising that if the data pointer is - * non-null, the underlying string is zero-terminated. It otherwise behaves - * exactly like a std::string_view. - * - * The terminating zero is not "in" the string, so it does not count as part of - * the view's length. - * - * The added guarantee lets the view be used as a C-style string, which often - * matters since libpqxx builds on top of a C library. For this reason, zview - * also adds a @ref c_str method. - */ -class zview : public std::string_view -{ -public: - constexpr zview() noexcept = default; - - /// Convenience overload: construct using pointer and signed length. - constexpr zview(char const text[], std::ptrdiff_t len) : - std::string_view{text, static_cast(len)} - {} - - /// Convenience overload: construct using pointer and signed length. - constexpr zview(char text[], std::ptrdiff_t len) : - std::string_view{text, static_cast(len)} - {} - - /// Explicitly promote a `string_view` to a `zview`. - explicit constexpr zview(std::string_view other) noexcept : - std::string_view{other} - {} - - /// Construct from any initialiser you might use for `std::string_view`. - /** @warning Only do this if you are sure that the string is zero-terminated. - */ - template - explicit constexpr zview(Args &&...args) : - std::string_view(std::forward(args)...) - {} - - // C++20: constexpr. - /// @warning There's an implicit conversion from `std::string`. - zview(std::string const &str) noexcept : - std::string_view{str.c_str(), str.size()} - {} - - /// Construct a `zview` from a C-style string. - /** @warning This scans the string to discover its length. So if you need to - * do it many times, it's probably better to create the `zview` once and - * re-use it. - */ - constexpr zview(char const str[]) : std::string_view{str} {} - - /// Construct a `zview` from a string literal. - /** A C++ string literal ("foo") normally looks a lot like a pointer to - * char const, but that's not really true. It's actually an array of char, - * which _devolves_ to a pointer when you pass it. - * - * For the purpose of creating a `zview` there is one big difference: if we - * know the array's size, we don't need to scan through the string in order - * to find out its length. - */ - template - constexpr zview(char const (&literal)[size]) : zview(literal, size - 1) - {} - - /// Either a null pointer, or a zero-terminated text buffer. - [[nodiscard]] constexpr char const *c_str() const &noexcept - { - return data(); - } -}; - - -/// Support @ref zview literals. -/** You can "import" this selectively into your namespace, without pulling in - * all of the @ref pqxx namespace: - * - * ```cxx - * using pqxx::operator"" _zv; - * ``` - */ -constexpr zview operator"" _zv(char const str[], std::size_t len) noexcept -{ - return zview{str, len}; -} -} // namespace pqxx - - -#if defined(PQXX_HAVE_CONCEPTS) -/// A zview is a view. -template<> inline constexpr bool std::ranges::enable_view{true}; - - -/// A zview is a borrowed range. -template<> -inline constexpr bool std::ranges::enable_borrowed_range{true}; - -namespace pqxx::internal -{ -/// Concept: T is a known zero-terminated string type. -/** There's no unified API for these string types. It's just a check for some - * known types. Any code that makes use of the concept will still have to - * support each of these individually. - */ -template -concept ZString = std::is_convertible_v < strip_t, -char const * > or std::is_convertible_v, zview> or - std::is_convertible_v; -} // namespace pqxx::internal -#endif // PQXX_HAVE_CONCEPTS - - -namespace pqxx::internal -{ -/// Get a raw C string pointer. -inline constexpr char const *as_c_string(char const str[]) noexcept -{ - return str; -} -/// Get a raw C string pointer. -template -inline constexpr char const *as_c_string(char (&str)[N]) noexcept -{ - return str; -} -/// Get a raw C string pointer. -inline constexpr char const *as_c_string(pqxx::zview str) noexcept -{ - return str.c_str(); -} -// C++20: Make this constexpr. -/// Get a raw C string pointer. -inline char const *as_c_string(std::string const &str) noexcept -{ - return str.c_str(); -} -} // namespace pqxx::internal -#endif diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-config-version.cmake b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-config-version.cmake deleted file mode 100644 index c47d6956d..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-config-version.cmake +++ /dev/null @@ -1,70 +0,0 @@ -# This is a basic version file for the Config-mode of find_package(). -# It is used by write_basic_package_version_file() as input file for configure_file() -# to create a version-file which can be installed along a config.cmake file. -# -# The created file sets PACKAGE_VERSION_EXACT if the current version string and -# the requested version string are exactly the same and it sets -# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, -# but only if the requested major version is the same as the current one. -# The variable CVF_VERSION must be set before calling configure_file(). - - -set(PACKAGE_VERSION "7.7.3") - -if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - - if("7.7.3" MATCHES "^([0-9]+)\\.") - set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") - if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) - string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") - endif() - else() - set(CVF_VERSION_MAJOR "7.7.3") - endif() - - if(PACKAGE_FIND_VERSION_RANGE) - # both endpoints of the range must have the expected major version - math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") - if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR - OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) - OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) - set(PACKAGE_VERSION_COMPATIBLE FALSE) - elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR - AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) - OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) - set(PACKAGE_VERSION_COMPATIBLE TRUE) - else() - set(PACKAGE_VERSION_COMPATIBLE FALSE) - endif() - else() - if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) - set(PACKAGE_VERSION_COMPATIBLE TRUE) - else() - set(PACKAGE_VERSION_COMPATIBLE FALSE) - endif() - - if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) - set(PACKAGE_VERSION_EXACT TRUE) - endif() - endif() -endif() - - -# if the installed project requested no architecture check, don't perform the check -if("FALSE") - return() -endif() - -# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: -if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") - return() -endif() - -# check that the installed version has the same 32/64bit-ness as the one which is currently searching: -if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") - math(EXPR installedBits "8 * 8") - set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") - set(PACKAGE_VERSION_UNSUITABLE TRUE) -endif() diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-config.cmake b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-config.cmake deleted file mode 100644 index cb25a05f2..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-config.cmake +++ /dev/null @@ -1,4 +0,0 @@ -include(CMakeFindDependencyMacro) -find_dependency(PostgreSQL) - -include("${CMAKE_CURRENT_LIST_DIR}/libpqxx-targets.cmake") diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-targets-noconfig.cmake b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-targets-noconfig.cmake deleted file mode 100644 index 980f46098..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-targets-noconfig.cmake +++ /dev/null @@ -1,19 +0,0 @@ -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Import target "libpqxx::pqxx" for configuration "" -set_property(TARGET libpqxx::pqxx APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) -set_target_properties(libpqxx::pqxx PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "CXX" - IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libpqxx-7.7.a" - ) - -list(APPEND _IMPORT_CHECK_TARGETS libpqxx::pqxx ) -list(APPEND _IMPORT_CHECK_FILES_FOR_libpqxx::pqxx "${_IMPORT_PREFIX}/lib/libpqxx-7.7.a" ) - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-targets.cmake b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-targets.cmake deleted file mode 100644 index c7b525b18..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/cmake/libpqxx/libpqxx-targets.cmake +++ /dev/null @@ -1,99 +0,0 @@ -# Generated by CMake - -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) - message(FATAL_ERROR "CMake >= 2.6.0 required") -endif() -cmake_policy(PUSH) -cmake_policy(VERSION 2.6...3.20) -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Protect against multiple inclusion, which would fail when already imported targets are added once more. -set(_targetsDefined) -set(_targetsNotDefined) -set(_expectedTargets) -foreach(_expectedTarget libpqxx::pqxx) - list(APPEND _expectedTargets ${_expectedTarget}) - if(NOT TARGET ${_expectedTarget}) - list(APPEND _targetsNotDefined ${_expectedTarget}) - endif() - if(TARGET ${_expectedTarget}) - list(APPEND _targetsDefined ${_expectedTarget}) - endif() -endforeach() -if("${_targetsDefined}" STREQUAL "${_expectedTargets}") - unset(_targetsDefined) - unset(_targetsNotDefined) - unset(_expectedTargets) - set(CMAKE_IMPORT_FILE_VERSION) - cmake_policy(POP) - return() -endif() -if(NOT "${_targetsDefined}" STREQUAL "") - message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") -endif() -unset(_targetsDefined) -unset(_targetsNotDefined) -unset(_expectedTargets) - - -# Compute the installation prefix relative to this file. -get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -if(_IMPORT_PREFIX STREQUAL "/") - set(_IMPORT_PREFIX "") -endif() - -# Create imported target libpqxx::pqxx -add_library(libpqxx::pqxx STATIC IMPORTED) - -set_target_properties(libpqxx::pqxx PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" - INTERFACE_LINK_LIBRARIES "/usr/lib/aarch64-linux-gnu/libpq.so" -) - -if(CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") -endif() - -# Load information for each installed configuration. -get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -file(GLOB CONFIG_FILES "${_DIR}/libpqxx-targets-*.cmake") -foreach(f ${CONFIG_FILES}) - include(${f}) -endforeach() - -# Cleanup temporary variables. -set(_IMPORT_PREFIX) - -# Loop over all imported files and verify that they actually exist -foreach(target ${_IMPORT_CHECK_TARGETS} ) - foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) - if(NOT EXISTS "${file}" ) - message(FATAL_ERROR "The imported target \"${target}\" references the file - \"${file}\" -but this file does not exist. Possible reasons include: -* The file was deleted, renamed, or moved to another location. -* An install or uninstall procedure did not complete successfully. -* The installation package was faulty and contained - \"${CMAKE_CURRENT_LIST_FILE}\" -but not all the files it references. -") - endif() - endforeach() - unset(_IMPORT_CHECK_FILES_FOR_${target}) -endforeach() -unset(_IMPORT_CHECK_TARGETS) - -# This file does not depend on other imported targets which have -# been exported from the same project but in a separate export set. - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) -cmake_policy(POP) diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/libpqxx-7.7.a b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/libpqxx-7.7.a deleted file mode 100644 index 2cb705a34..000000000 Binary files a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/libpqxx-7.7.a and /dev/null differ diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/libpqxx.a b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/libpqxx.a deleted file mode 120000 index d9fcdab85..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/lib/libpqxx.a +++ /dev/null @@ -1 +0,0 @@ -libpqxx-7.7.a \ No newline at end of file diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/accessing-results.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/accessing-results.md deleted file mode 100644 index 920fb6f3b..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/accessing-results.md +++ /dev/null @@ -1,157 +0,0 @@ -Accessing results and result rows {#accessing-results} ---------------------------------- - -When you execute a query using one of the transaction `exec` functions, you -normally get a `result` object back. A `result` is a container of `row`s. - -(There are exceptions. The `exec1` functions expect exactly one row of data, -so they return just a `row`, not a full `result`.) - -Result objects are an all-or-nothing affair. The `exec` function waits until -it's received all the result data, and then gives it to you in the form of the -`result`. _(There is a faster, easier way of executing simple queries, so see -"streaming rows" below as well.)_ - -For example, your code might do: - -```cxx - pqxx::result r = tx.exec("SELECT * FROM mytable"); -``` - -Now, how do you access the data inside `r`? - -Result sets act as standard C++ containers of rows. Rows act as standard -C++ containers of fields. So the easiest way to go through them is: - -```cxx - for (auto const &row: r) - { - for (auto const &field: row) std::cout << field.c_str() << '\t'; - std::cout << '\n'; - } -``` - -But results and rows also support other kinds of access. Array-style -indexing, for instance, such as `r[rownum]`: - -```cxx - std::size_t const num_rows = std::size(r); - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - pqxx::row const row = r[rownum]; - std::size_t const num_cols = std::size(row); - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - { - pqxx::field const field = row[colnum]; - std::cout << field.c_str() << '\t'; - } - - std::cout << '\n'; - } -``` - -Every row in the result has the same number of columns, so you don't need to -look up the number of fields again for each one: - -```cxx - std::size_t const num_rows = std::size(r); - std::size_t const num_cols = r.columns(); - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - pqxx::row const row = r[rownum]; - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - { - pqxx::field const field = row[colnum]; - std::cout << field.c_str() << '\t'; - } - - std::cout << '\n'; - } -``` - -You can even address a field by indexing the `row` using the field's _name:_ - -```cxx - std::cout << row["salary"] << '\n'; -``` - -But try not to do that if speed matters, because looking up the column by name -takes time. At least you'd want to look up the column index before your loop -and then use numerical indexes inside the loop. - -For C++23 or better, there's also a two-dimensional array access operator: - -```cxx - for (std::size_t rownum=0u; rownum < num_rows; ++rownum) - { - for (std::size_t colnum=0u; colnum < num_cols; ++colnum) - std::cout result[rownum, colnum].c_str() << '\t'; - std::cout << '\n'; - } -``` - -And of course you can use classic "begin/end" loops: - -```cxx - for (auto row = std::begin(r); row != std::end(r); row++) - { - for (auto field = std::begin(row); field != std::end(row); field++) - std::cout << field->c_str() << '\t'; - std::cout << '\n'; - } -``` - -Result sets are immutable, so all iterators on results and rows are actually -`const_iterator`s. There are also `const_reverse_iterator` types, which -iterate backwards from `rbegin()` to `rend()` exclusive. - -All these iterator types provide one extra bit of convenience that you won't -normally find in C++ iterators: referential transparency. You don't need to -dereference them to get to the row or field they refer to. That is, instead -of `row->end()` you can also choose to say `row.end()`. Similarly, you -may prefer `field.c_str()` over `field->c_str()`. - -This becomes really helpful with the array-indexing operator. With regular -C++ iterators you would need ugly expressions like `(*row)[0]` or -`row->operator[](0)`. With the iterator types defined by the result and -row classes you can simply say `row[0]`. - - -Streaming rows --------------- - -There's another way to go through the rows coming out of a query. It's -usually easier and faster, but there are drawbacks. - -**One,** you start getting rows before all the data has come in from the -database. That speeds things up, but what happens if you lose your network -connection while transferring the data? Your application may already have -processed some of the data before finding out that the rest isn't coming. If -that is a problem for your application, streaming may not be the right choice. - -**Two,** streaming only works for some types of query. The `stream()` function -wraps your query in a PostgreSQL `COPY` command, and `COPY` only supports a few -commands: `SELECT`, `VALUES`, `or an `INSERT`, `UPDATE`, or `DELETE` with a -`RETURNING` clause. See the `COPY` documentation here: -https://www.postgresql.org/docs/current/sql-copy.html - -**Three,** when you convert a field to a "view" type (such as -`std::string_view` or `std::basic_string_view`), the view points to -underlying data which only stays valid until you iterate to the next row or -exit the loop. So if you want to use that data for longer than a single -iteration of the streaming loop, you'll have to store it somewhere yourself. - -Now for the good news. Streaming does make it very easy to query data and loop -over it: - -```cxx - for (auto [id, name, x, y] : - tx.stream( - "SELECT id, name, x, y FROM point")) - process(id + 1, "point-" + name, x * 10.0, y * 10.0); -``` - -The conversion to C++ types (here `int`, `std::string_view`, and two `float`s) -is built into the function. You never even see `row` objects, `field` objects, -iterators, or conversion methods. You just put in your query and you receive -your data. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/binary-data.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/binary-data.md deleted file mode 100644 index 20da8dc0c..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/binary-data.md +++ /dev/null @@ -1,56 +0,0 @@ -Binary data {#binary} -=========== - -The database has two ways of storing binary data: `BYTEA` is like a string, but -containing bytes rather than text characters. And _large objects_ are more -like a separate table containing binary objects. - -Generally you'll want to use `BYTEA` for reasonably-sized values, and large -objects for very large values. - -That's the database side. On the C++ side, in libpqxx, all binary data must be -either `std::basic_string` or `std::basic_string_view`; -or if you're building in C++20 or better, anything that's a block of -contiguous `std::byte` in memory. - -So for example, if you want to write a large object, you'd create a -`pqxx::blob` object. And you might use that to write data in the form of -`std::basic_string_view`. - -Your particular binary data may look different though. You may have it in a -`std::string`, or a `std::vector`, or a pointer to `char` -accompanied by a size (which could be signed or unsigned, and of any of a few -different widths). Sometimes that's your choice, or sometimes some other -library will dictate what form it takes. - -So long as it's _basically_ still a block of bytes though, you can use -`pqxx::binary_cast` to construct a `std::basic_string_view` from it. - -There are two forms of `binary_cast`. One takes a single argument that must -support `std::data()` and `std::size()`: - - std::string hi{"Hello binary world"}; - my_blob.write(pqxx::binary_cast(hi); - -The other takes a pointer and a size: - - char const greeting[] = "Hello binary world"; - char const *hi = greeting; - my_blob.write(pqxx::binary_cast(hi, sizeof(greeting))); - - -Caveats -------- - -There are some restrictions on `binary_cast` that you must be aware of. - -First, your data must of a type that gives us _bytes._ So: `char`, -`unsigned char`, `signed char`, `int8_t`, `uint8_t`, or of course `std::byte`. -You can't feed in a vector of `double`, or anything like that. - -Second, the data must be laid out as a contiguous block in memory. If there's -no `std::data()` implementation for your type, it's not suitable. - -Third, `binary_cast` only constructs something like a `std::string_view`. It -does not make a copy of your actual data. So, make sure that your data remains -alive and in the same place while you're using it. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/datatypes.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/datatypes.md deleted file mode 100644 index bc14c8b90..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/datatypes.md +++ /dev/null @@ -1,373 +0,0 @@ -Supporting additional data types {#datatypes} -================================ - -Communication with the database mostly happens in a text format. When you -include an integer value in a query, you use `to_string` to convert it to that -text format. When you get a query result field "as a float," it converts from -the text format to a floating-point type. These conversions are everywhere in -libpqxx. - -The conversion sydstem supports many built-in types, but it is also extensible. -You can "teach" libpqxx (in the scope of your own application) to convert -additional types of values to and from PostgreSQL's string format. - -This is massively useful, but it's not for the faint of heart. You'll need to -specialise some templates. And, **the API for doing this can change with any -major libpqxx release.** - - -Converting types ----------------- - -In your application, a conversion is driven entirely by a C++ type you specify. -The value's SQL type has nothing to do with it, nor is there anything in the -string that would identify its type. - -So, if you've SELECTed a 64-bit integer from the database, and you try to -convert it to a C++ "short," one of two things will happen: either the number -is small enough to fit in your `short` (and it just works), or else it throws a -conversion exception. - -Or, your database table might have a text column, but a given field may contain -a string that _looks_ just like a number. You can convert that value to an -integer type just fine. Or to a floating-point type. All that matters to the -conversion is the actual value, and the type. - -In some cases the templates for these conversions can tell the type from the -arguments you pass them: - - auto x = to_string(99); - -In other cases you may need to instantiate template explicitly: - - auto y = from_string("99"); - - -Supporting a new type ---------------------- - -Let's say you have some other SQL type which you want to be able to store in, -or retrieve from, the database. What would it take to support that? - -Sometimes you do not need _complete_ support. You might need a conversion _to_ -a string but not _from_ a string, for example. The conversion is defined at -compile time, so don't be too afraid to be incomplete. If you leave out one of -these steps, it's not going to crash at run time or mess up your data. The -worst that can happen is that your code won't build. - -So what do you need for a complete conversion? - -First off, of course, you need a C++ type. It may be your own, but it -doesn't have to be. It could be a type from a third-party library, or even one -from the standard library that libpqxx does not yet support. - -You also specialise the `pqxx::type_name` variable to specify the type's name. -This is important for all code which mentions your type in human-readable text, -such as error messages. - -Then, does your type have a built-in null value? You specialise the -`pqxx::nullness` template to specify the details. - -Finally, you specialise the `pqxx::string_traits` template. This is where you -define the actual conversions. - -Let's go through these steps one by one. - - -Your type ---------- - -You'll need a type for which the conversions are not yet defined, because the -C++ type is what determines the right conversion. One type, one set of -conversions. - -The type doesn't have to be one that you create. The conversion logic was -designed such that you can build it around any type. So you can just as -easily build a conversion for a type that's defined somewhere else. There's -no need to include any special methods or other members inside it. That's also -how libpqxx can support converting built-in types like `int`. - -By the way, if the type is an enum, you don't need to do any of this. Just -invoke the preprocessor macro `PQXX_DECLARE_ENUM_CONVERSION`, from the global -namespace near the top of your translation unit, and pass the type as an -argument. - -The library also provides specialisations for `std::optional`, -`std::shared_ptr`, and `std::unique_ptr`. If you have conversions for -`T`, you'll also have conversions for those. - - -Specialise `type_name` ----------------------- - -When errors happen during conversion, libpqxx will compose error messages for -the user. Sometimes these will include the name of the type that's being -converted. - -To tell libpqxx the name of each type, there's a template variable called -`pqxx::type_name`. For any given type `T`, it should have a specialisation -that provides that `T`'s human-readable name: - - namespace pqxx - { - template<> std::string const type_name{"T"}; - } - -(Yes, this means that you need to define something inside the pqxx namespace. -Future versions of libpqxx may move this into a separate namespace.) - -Define this early on in your translation unit, before any code that might cause -libpqxx to need the name. That way, the libpqxx code which needs to know the -type's name can see your definition. - - -Specialise `nullness` ---------------------- - -A struct template `pqxx::nullness` defines whether your type has a natural -"null value" built in. If so, it also provides member functions for producing -and recognising null values. - -The simplest scenario is also the most common: most types don't have a null -value built in. In that case, derive your nullness traits from -`pqxx::no_null`: - - namespace pqxx - { - template<> struct nullness : pqxx::no_null {}; - } - -(Here again you're defining this in the pqxx namespace.) - -If your type does have a natural null value, the definition gets a little more -complex: - - namespace pqxx - { - template<> struct nullness - { - static constexpr bool has_null{true}; - static constexpr bool always_null{false}; - - static bool is_null(T const &value) - { - // Return whether "value" is null. - return ...; - } - - [[nodiscard]] static T null() - { - // Return a null value. - return ...; - } - }; - } - -You may be wondering why there's a function to produce a null value, but also a -function to check whether a value is null. Why not just compare the value to -the result of `null()`? Because two null values may not be equal. `T` may -have several different null values. Or it may override the comparison -operator, similar to SQL where NULL is not equal to NULL. - -As a third case, your type may be one that _always_ represents a null value. -This is the case for `std::nullptr_t` and `std::nullopt_t`. In that case, you -set `nullness::always_null` to `true` (as well as `has_null` of course), -and you won't need to define any actual conversions. - - -Specialise `string_traits` -------------------------- - -This part is more work. (You can skip it for types that are _always_ null, -but those will be rare.) Specialise the `pqxx::string_traits` template: - - namespace pqxx - { - template<> struct string_traits - { - static T from_string(std::string_view text); - static zview to_buf(char *begin, char *end, T const &value); - static char *into_buf(char *begin, char *end, T const &value); - static std::size_t size_buffer(T const &value) noexcept; - }; - } - -You'll also need to write those member functions, or as many of them as needed -to get your code to build. - - -### `from_string` - -We start off simple: `from_string` parses a string as a value of `T`, and -returns that value. - -The string may not be zero-terminated; it's just the `string_view` from -beginning to end (exclusive). In your tests, cover cases where the string -does not end in a zero byte. - -It's perfectly possible that the string isn't actually a `T` value. Mistakes -happen. In that case, throw a `pqxx::conversion_error`. - -(Of course it's also possible that you run into some other error, so it's fine -to throw different exceptions as well. But when it's definitely "this is not -the right format for a `T`," throw `conversion_error`.) - - -### `to_buf` - -In this function, you convert a value of `T` into a string that the postgres -server will understand. - -The caller will provide you with a buffer where you can write the string, if -you need it: from `begin` to `end` exclusive. It's a half-open interval, so -don't access `*end`. - -If the buffer is insufficient for you to do the conversion, throw a -`pqxx::conversion_overrun`. It doesn't have to be exact: you can be a little -pessimistic and demand a bit more space than you need. Just be sure to throw -the exception if there's any risk of overrunning the buffer. - -You don't _have_ to use the buffer for this function though. For example, -`pqxx::string_traits::to_buf` returns a compile-time constant string and -ignores the buffer. - -Even if you do use the buffer, your string does not _have_ to start at the -beginning of the buffer. For example, the integer conversions start by writing -the _least_ significant digit to the _end_ of the buffer, and then writes the -more significant digits before it. It was just more convenient. - -Return a `pqxx::zview`. This is basically a `std::string_view`, but with one -difference: a `zview` guarantees that there will be a valid zero byte right -after the `string_view`. The zero byte is not counted as part of its size, but -it will be there. - -Expressed in code, this rule must hold: - - void invariant(zview z) - { - assert(z[std::size(z)] == 0); - } - -Make sure you write your trailing zero _before_ the `end`. If the trailing -zero doesn't fit in the buffer, then there's just not enough room to perform -the conversion. - -Beware of locales when converting. If you use standard library features like -`sprintf`, they may obey whatever locale is currently set on the system. That -means that a simple integer like 1000000 may come out as "1000000" on your -system, but as "1,000,000" on mine, or as "1.000.000" for somebody else, and on -an Indian system it may be "1,00,000". Values coming from or going to the -database should be in non-localised formats. You can use libpqxx functions for -those conversions: `pqxx::from_string`, `pqxx::to_string`, `pqxx::to_buf`. - - -### `into_buf` - -This is a stricter version of `to_buf`. All the same requirements apply, but -in addition you must write your string into the buffer provided, starting -_exactly_ at `begin`. - -That's why this function returns just a simple pointer: the address right -behind the trailing zero. If the caller wants to use the string, they can -find it at `begin`. If they want to write a different value into the rest of -the buffer, they can start at the location you returned. - - -### `size_buffer` - -Here you estimate how much buffer space you need for converting a `T` to a -string. Be precise if you can, but pessimistic if you must. It's usually -better to waste a few unnecessary bytes than to spend a lot of time computing -the exact buffer space you need. And failing the conversion because you -under-budgeted the buffer is worst of all. - -Include the trailing zero in the buffer size. If your `to_buf` takes more -space than just what's needed to store the result, include that too. - -Make `size_buffer` a `constexpr` function if you can. It can allow the caller -to allocate the buffer on the stack, with a size known at compile time. - - -Optional: Specialise `is_unquoted_safe` ---------------------------------------- - -When converting arrays or composite values to strings, libpqxx may need to -quote values and escape any special characters. This takes time. - -Some types though, such as integral or floating-point types, can never have -any special characters such as quotes, commas, or backslashes in their string -representations. In such cases, there's no need to quote or escape such values -in arrays or composite types. - -If your type is like that, you can tell libpqxx about this by defining: - - namespace pqxx - { - template<> inline constexpr bool is_unquoted_safe{true}; - } - -The code that converts this type of field to strings in an array or a composite -type can then use a simpler, more efficient variant of the code. It's always -safe to leave this out; it's _just_ an optimisation for when you're completely -sure that it's safe. - -Do not do this if a string representation of your type may contain a comma; -semicolon; parenthesis; brace; quote; backslash; newline; or any other -character that might need escaping. - - -Optional: Specialise `param_format` ------------------------------------ - -This one you don't generally need to worry about. Read on if you're writing a -type which represents raw binary data, or if you're writing a template where -_some specialisations_ may contain raw binary data. - -When you call parameterised statements, or prepared statements with parameters, -libpqxx needs to your parameters on to libpq, the underlying C-level PostgreSQL -client library. - -There are two formats for doing that: _text_ and _binary._ In the first, we -represent all values as strings, and the server then converts them into its own -internal binary representation. That's what the string conversions are all -about, and it's what we do for almost all types of parameters. - -But we do it differently when the parameter is a contiguous series of raw bytes -and the corresponding SQL type is `BYTEA`. There is a text format for those, -but we bypass it for efficiency. The server can use the binary data in the -exact same form, without any conversion or extra processing. The binary data -is also twice as compact during transport. - -(People sometimes ask why we can't just treat all types as binary. However the -general case isn't so clear-cut. The binary formats are not documented, there -are no guarantees that they will be platform-independent or that they will -remain stable, and there's no really solid way to detect when we might get the -format wrong. But also, the conversions aren't necessarily as straightforward -and efficient as they sound. So, for the general case, libpqxx sticks with the -text formats. Raw binary data alone stands out as a clear win.) - -Long story short, the machinery for passing parameters needs to know: is this -parameter a binary string, or not? In the normal case it can assume "no," and -that's what it does. The text format is always a safe choice; we just try to -use the binary format where it's faster. - -The `param_format` function template is what makes the decision. We specialise -it for types which may be binary strings, and use the default for all other -types. - -"Types which _may_ be binary"? You might think we know whether a type is a -binary type or not. But there are some complications with generic types. - -Templates like `std::shared_ptr`, `std::optional`, and so on act like -"wrappers" for another type. A `std::optional` is binary if `T` is binary. -Otherwise, it's not. If you're building support for a template of this nature, -you'll probably want to implement `param_format` for it. - -The decision to use binary format is made based on a given object, not -necessarily based on the type in general. Look at `std::variant`. If you have -a `std::variant` type which can hold an `int` or a binary string, is that a -binary parameter? We can't decide without knowing the individual object. - -Containers are another hard case. Should we pass `std::vector` in binary? -Even when `T` is a binary type, we don't currently have any way to pass an -array in binary format, so we always pass it as text. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/escaping.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/escaping.md deleted file mode 100644 index 2ad9fe3db..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/escaping.md +++ /dev/null @@ -1,74 +0,0 @@ -String escaping {#escaping} -=============== - -Writing queries as strings is easy. But sometimes you need a variable in -there: `"SELECT id FROM user WHERE name = '" + name + "'"`. - -This is dangerous. See the bug? If `name` can contain quotes, you may have -an SQL injection vulnerability there, where users can enter nasty stuff like -"`.'; DROP TABLE user`". Or if you're lucky, it's just a nasty bug that you -discover when `name` happens to be "d'Arcy". - -So, you'll need to _escape_ the `name` before you insert it. This is where -quotes and other problematic characters are marked as "this is just a character -in the string, not the end of the string." There are -[several functions](@ref escaping-functions) in libpqxx to do this for you. - - -SQL injection -------------- - -To understand what SQL injection vulnerabilities are and why they should be -prevented, imagine you use the following SQL statement somewhere in your -program: - - TX.exec( - "SELECT number,amount " - "FROM accounts " - "WHERE allowed_to_see('" + userid + "','" + password + "')"); - -This shows a logged-in user important information on all accounts he is -authorized to view. The userid and password strings are variables entered -by the user himself. - -Now, if the user is actually an attacker who knows (or can guess) the -general shape of this SQL statement, imagine he enters the following -password: - - x') OR ('x' = 'x - -Does that make sense to you? Probably not. But if this is inserted into -the SQL string by the C++ code above, the query becomes: - - SELECT number,amount - FROM accounts - WHERE allowed_to_see('user','x') OR ('x' = 'x') - -Is this what you wanted to happen? Probably not! The neat `allowed_to_see()` -clause is completely circumvented by the "`OR ('x' = 'x')`" clause, which is -always `true`. Therefore, the attacker will get to see all accounts in the -database! - - -Using the esc functions ------------------------ - -Here's how you can fix the problem in the example above: - - TX.exec( - "SELECT number,amount " - "FROM accounts " - "WHERE allowed_to_see('" + TX.esc(userid) + "', " - "'" + TX.esc(password) + "')"); - -Now, the quotes embedded in the attacker's string will be neatly escaped so -they can't "break out" of the quoted SQL string they were meant to go into: - - SELECT number,amount - FROM accounts - WHERE allowed_to_see('user', 'x'') OR (''x'' = ''x') - -If you look carefully, you'll see that thanks to the added escape characters -(a single-quote is escaped in SQL by doubling it) all we get is a very -strange-looking password string--but not a change in the SQL statement. - diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/getting-started.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/getting-started.md deleted file mode 100644 index 1b87b881f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/getting-started.md +++ /dev/null @@ -1,142 +0,0 @@ -Getting started {#getting-started} -=============== - -The most basic three types in libpqxx are the _connection_, the _transaction_, -and the _result_. - -They fit together as follows: -* You connect to the database by creating a `pqxx::connection` object (see - @ref connections). - -* You create a transaction object (see @ref transactions) operating on that - connection. You'll usually want the `pqxx::work` variety. - - Once you're done you call the transaction's `commit` function to make its - work final. If you don't call this, the work will be rolled back when the - transaction object is destroyed. - -* Until then, use the transaction's `exec`, `query_value`, and `stream` - functions (and variants) to execute SQL statements. You pass the statements - themselves in as simple strings. (See @ref streams for more about data - streaming). - -* Most of the `exec` functions return a `pqxx::result` object, which acts - as a standard container of rows: `pqxx::row`. - - Each row in a result, in turn, acts as a container of fields: `pqxx::field`. - See @ref accessing-results for more about results, rows, and fields. - -* Each field's data is stored internally as a text string, in a format defined - by PostgreSQL. You can convert field or row values using their `as()` and - `to()` member functions. - -* After you've closed the transaction, the connection is free to run a next - transaction. - -Here's a very basic example. It connects to the default database (you'll -need to have one set up), queries it for a very simple result, converts it to -an `int`, and prints it out. It also contains some basic error handling. - - #include - #include - - int main() - { - try - { - // Connect to the database. In practice we may have to pass some - // arguments to say where the database server is, and so on. - // The constructor parses options exactly like libpq's - // PQconnectdb/PQconnect, see: - // https://www.postgresql.org/docs/10/static/libpq-connect.html - pqxx::connection c; - - // Start a transaction. In libpqxx, you always work in one. - pqxx::work w(c); - - // work::exec1() executes a query returning a single row of data. - // We'll just ask the database to return the number 1 to us. - pqxx::row r = w.exec1("SELECT 1"); - - // Commit your transaction. If an exception occurred before this - // point, execution will have left the block, and the transaction will - // have been destroyed along the way. In that case, the failed - // transaction would implicitly abort instead of getting to this point. - w.commit(); - - // Look at the first and only field in the row, parse it as an integer, - // and print it. - // - // "r[0]" returns the first field, which has an "as<...>()" member - // function template to convert its contents from their string format - // to a type of your choice. - std::cout << r[0].as() << std::endl; - } - catch (std::exception const &e) - { - std::cerr << e.what() << std::endl; - return 1; - } - } - -This prints the number 1. Notice that you can keep the result object around -after you've closed the transaction or even the connection. There are -situations where you can't do it, but generally it's fine. If you're -interested: you can install your own callbacks for receiving error messages -from the database, and in that case you'll have to keep the connection object -alive. But otherwise, it's nice to be able to "fire and forget" your -connection and deal with the data. - -You can also convert an entire row to a series of C++-side types in one go, -using the @c as member function on the row: - - pqxx::connection c; - pqxx::work w(c); - pqxx::row r = w.exec1("SELECT 1, 2, 'Hello'"); - auto [one, two, hello] = r.as(); - std::cout << (one + two) << ' ' << std::strlen(hello) << std::endl; - -Here's a slightly more complicated example. It takes an argument from the -command line and retrieves a string with that value. The interesting part is -that it uses the escaping-and-quoting function `quote` to embed this -string value in SQL safely. It also reads the result field's value as a -plain C-style string using its `c_str` function. - - #include - #include - #include - - int main(int argc, char *argv[]) - { - try - { - if (!argv[1]) throw std::runtime_error("Give me a string!"); - - pqxx::connection c; - pqxx::work w(c); - - // work::exec() returns a full result set, which can consist of any - // number of rows. - pqxx::result r = w.exec("SELECT " + w.quote(argv[1])); - - // End our transaction here. We can still use the result afterwards. - w.commit(); - - // Print the first field of the first row. Read it as a C string, - // just like std::string::c_str() does. - std::cout << r[0][0].c_str() << std::endl; - } - catch (std::exception const &e) - { - std::cerr << e.what() << std::endl; - return 1; - } - } - -You can find more about converting field values to native types, or -converting values to strings for use with libpqxx, under -@ref stringconversion. More about getting to the rows and fields of a -result is under @ref accessing-results. - -If you want to handle exceptions thrown by libpqxx in more detail, for -example to print the SQL contents of a query that failed, see @ref exception. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/mainpage.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/mainpage.md deleted file mode 100644 index 5d4b8f9b2..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/mainpage.md +++ /dev/null @@ -1,28 +0,0 @@ -libpqxx {#mainpage} -======= - -@version 7.7.3 -@author Jeroen T. Vermeulen -@see http://pqxx.org -@see https://github.com/jtv/libpqxx - -Welcome to libpqxx, the C++ API to the PostgreSQL database management system. - -Compiling this package requires PostgreSQL to be installed -- including the -C headers for client development. The library builds on top of PostgreSQL's -standard C API, libpq. The libpq headers are not needed to compile client -programs, however. - -For a quick introduction to installing and using libpqxx, see the README.md -file. The latest information can be found at http://pqxx.org/ - - -Some links that should help you find your bearings: -* @ref getting-started -* @ref thread-safety -* @ref connections -* @ref transactions -* @ref escaping -* @ref performance -* @ref transactor -* @ref datatypes diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/parameters.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/parameters.md deleted file mode 100644 index 7ac792025..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/parameters.md +++ /dev/null @@ -1,90 +0,0 @@ -Statement parameters {#parameters} -==================== - -When you execute a prepared statement (see @ref prepared), or a parameterised -statement (using functions like `pqxx::connection::exec_params`), you may write -special _placeholders_ in the query text. They look like `$1`, `$2`, and so -on. - -If you execute the query and pass parameter values, the call will respectively -substitute the first where it finds `$1`, the second where it finds `$2`, et -cetera. - -Doing this saves you work. If you don't use statement parameters, you'll need -to quote and escape your values (see `connection::quote()` and friends) as you -insert them into your query as literal values. - -Or if you forget to do that, you leave yourself open to horrible -[SQL injection attacks](https://xkcd.com/327/). Trust me, I was born in a town -whose name started with an apostrophe! - -Statement parameters save you this work. With these parameters you can pass -your values as-is, and they will go across the wire to the database in a safe -format. - -In some cases it may even be faster! When a parameter represents binary data -(as in the SQL `BYTEA` type), libpqxx will send it directly as binary, which is -a bit more efficient. If you insert the binary data directly in your query -text, your CPU will have some extra work to do, converting the data into a text -format, escaping it, and adding quotes. - - -Dynamic parameter lists ------------------------ - -In rare cases you may just not know how many parameters you'll pass into your -statement when you call it. - -For these situations, have a look at `params`. It lets you compose your -parameters list on the fly, even add whole ranges of parameters at a time. - -You can pass a `params` into your statement as a normal parameter. It will -fill in all the parameter values it contains into that position of the -statement's overall parameter list. - -So if you call your statement passing a regular parameter `a`, a -`params` containing just a parameter `b`, and another regular parameter `c`, -then your call will pass parameters `a`, `b`, and `c`. Or if the params object -is empty, it will pass just `a` and `c`. If the params object contains `x` and -`y`, your call will pass `a, x, y, c`. - -You can mix static and dynamic parameters freely. Don't go overboard though: -complexity is where bugs happen! - - -Generating placeholders ------------------------ - -If your code gets particularly complex, it may sometimes happen that it becomes -hard to track which parameter value belongs with which placeholder. Did you -intend to pass this numeric value as `$7`, or as `$8`? The answer may depend -on an `if` that happened earlier in a different function. - -(Generally if things get that complex, it's a good idea to look for simpler -solutions. But especially when performance matters, sometimes you can't avoid -complexity like that.) - -There's a little helper class called `placeholders`. You can use it as a -counter which produces those placeholder strings, `$1`, `$2`, `$3`, et cetera. -When you start generating a complex statement, you can create both a `params` -and a `placeholders`: - - pqxx::params values; - pqxx::placeholders name; - -Let's say you've got some complex code to generate the conditions for an SQL -"WHERE" clause. You'll generally want to do these things close together in -your, so that you don't accidentally update one part and forget another: - - if (extra_clause) - { - // Extend the query text, using the current placeholder. - query += " AND x = " + name.get(); - // Add the parameter value. - values.append(my_x); - // Move on to the next placeholder value. - name.next(); - } - -Depending on the starting value of `name`, this might add to `query` a fragment -like "` AND x = $3`" or "` AND x = $5`". diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/performance.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/performance.md deleted file mode 100644 index 6c403684f..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/performance.md +++ /dev/null @@ -1,24 +0,0 @@ -Performance features {#performance} -==================== - -If your program's database interaction is not as efficient as it needs to be, -the first place to look is usually the SQL you're executing. But libpqxx -has a few specialized features to help you squeeze more performance out -of how you issue commands and retrieve data: - -* @ref streams. Use these as a faster way to transfer data between your - code and the database. -* `std::string_view` and `pqxx::zview`. In places where traditional C++ worked - with `std::string`, see whether `std::string_view` or `pqxx::zview` will - do. Of course that means that you'll have to look at the data's lifetime - more carefully, but it'll save the computer a lot of copying. -* @ref prepared. These can be executed many times without the server - parsing and planning them anew each time. They also save you having to - escape string parameters. -* `pqxx::pipeline` lets you send queries to the database in batches, and - continue other processing while they are executing. -* `pqxx::connecting` lets you start setting up a database connection, but - without blocking the thread. - -As always of course, don't risk the quality of your code for optimizations -that you don't need! diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/prepared-statement.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/prepared-statement.md deleted file mode 100644 index 5193866a6..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/prepared-statement.md +++ /dev/null @@ -1,125 +0,0 @@ -Prepared statements {#prepared} -=================== - -Prepared statements are SQL queries that you define once and then invoke -as many times as you like, typically with varying parameters. It's basically -a function that you can define ad hoc. - -If you have an SQL statement that you're going to execute many times in -quick succession, it may be more efficient to prepare it once and reuse it. -This saves the database backend the effort of parsing complex SQL and -figuring out an efficient execution plan. Another nice side effect is that -you don't need to worry about escaping parameters. Some corporate coding -standards require all SQL parameters to be passed in this way, to reduce the -risk of programmer mistakes leaving room for SQL injections. - - -Preparing a statement ---------------------- - -You create a prepared statement by preparing it on the connection (using the -`pqxx::connection::prepare` functions), passing an identifier and its SQL text. - -The identifier is the name by which the prepared statement will be known; it -should consist of ASCII letters, digits, and underscores only, and start with -an ASCII letter. The name is case-sensitive. - -```cxx - void prepare_my_statement(pqxx::connection &c) - { - c.prepare( - "my_statement", - "SELECT * FROM Employee WHERE name = 'Xavier'"); - } -``` - -Once you've done this, you'll be able to call `my_statement` from any -transaction you execute on the same connection. For this, use the -`pqxx::transaction_base::exec_prepared` functions. - -```cxx - pqxx::result execute_my_statement(pqxx::transaction_base &t) - { - return t.exec_prepared("my_statement"); - } -``` - - -Parameters ----------- - -Did I mention that prepared statements can have parameters? The query text -can contain `$1`, `$2` etc. as placeholders for parameter values that you -will provide when you invoke the prepared satement. - -See @ref parameters for more about this. And here's a simple example of -preparing a statement and invoking it with parameters: - -```cxx - void prepare_find(pqxx::connection &c) - { - // Prepare a statement called "find" that looks for employees with a - // given name (parameter 1) whose salary exceeds a given number - // (parameter 2). - c.prepare( - "find", - "SELECT * FROM Employee WHERE name = $1 AND salary > $2"); - } -``` - -This example looks up the prepared statement "find," passes `name` and -`min_salary` as parameters, and invokes the statement with those values: - -```cxx - pqxx::result execute_find( - pqxx::transaction_base &t, std::string name, int min_salary) - { - return t.exec_prepared("find", name, min_salary); - } -``` - - -A special prepared statement ----------------------------- - -There is one special case: the _nameless_ prepared statement. You may prepare -a statement without a name, i.e. whose name is an empty string. The unnamed -statement can be redefined at any time, without un-preparing it first. - - -Performance note ----------------- - -Don't assume that using prepared statements will speed up your application. -There are cases where prepared statements are actually slower than plain SQL. - -The reason is that the backend can often produce a better execution plan when -it knows the statement's actual parameter values. - -For example, say you've got a web application and you're querying for users -with status "inactive" who have email addresses in a given domain name X. If -X is a very popular provider, the best way for the database engine to plan the -query may be to list the inactive users first and then filter for the email -addresses you're looking for. But in other cases, it may be much faster to -find matching email addresses first and then see which of their owners are -"inactive." A prepared statement must be planned to fit either case, but a -direct query will be optimised based on table statistics, partial indexes, etc. - - -Zero bytes ----------- - -@warning Beware of "nul" bytes! - -Any string you pass as a parameter will end at the _first char with value -zero._ If you pass a string that contains a zero byte, the last byte in the -value will be the one just before the zero. - -So, if you need a zero byte in a string, consider that it's really a _binary -string,_ which is not the same thing as a text string. SQL represents binary -data as the `BYTEA` type, or in binary large objects ("blobs"). - -In libpqxx, you represent binary data as a range of `std::byte`. They must be -contiguous in memory, so that libpqxx can pass pointers to the underlying C -library. So you might use `std::basic_string`, or -`std::basic_string_view`, or `std::vector`. diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/streams.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/streams.md deleted file mode 100644 index 3df4d6126..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/streams.md +++ /dev/null @@ -1,107 +0,0 @@ -Streams {#streams} -======= - -Most of the time it's fine to retrieve data from the database using `SELECT` -queries, and store data using `INSERT`. But for those cases where efficiency -matters, there are two classes to help you do this better: `stream_from` and -`stream_to`. They're less flexible than SQL queries, and there's the risk of -losing your connection while you're in mid-stream, but you get some speed and -memory efficiencies in return. - -Both stream classes do data conversion for you: `stream_from` receives values -from the database in PostgreSQL's text format, and converts them to the C++ -types you specify. Likewise, `stream_to` converts C++ values you provide to -PostgreSQL's text format for transfer. (On its end, the database of course -converts values to and from their SQL types.) - - -Null values ------------ - -So how do you deal with nulls? It depends on the C++ type you're using. Some -types may have a built-in null value. For instance, if you have a -`char const *` value and you convert it to an SQL string, then converting a -`nullptr` will produce a NULL SQL value. - -But what do you do about C++ types which don't have a built-in null value, such -as `int`? The trick is to wrap it in `std::optional`. The difference between -`int` and `std::optional` is that the former always has an `int` value, -and the latter doesn't have to. - -Actually it's not just `std::optional`. You can do the same thing with -`std::unique_ptr` or `std::shared_ptr`. A smart pointer is less efficient than -`std::optional` in most situations because they allocate their value on the -heap, but sometimes that's what you want in order to save moving or copying -large values around. - -This part is not generic though. It won't work with just any smart-pointer -type, just the ones which are explicitly supported: `shared_ptr` and -`unique_ptr`. If you really need to, you can build support for additional -wrappers and smart pointers by copying the implementation patterns from the -existing smart-pointer support. - - -stream\_from ------------- - -Use `stream_from` to read data directly from the database. It's faster than -the transaction's `exec` functions if the result contains enough rows. But -also, you won't need to keep your full result set in memory. That can really -matter with larger data sets. - -And, you can start processing your data right after the first row of data comes -in from the server. With `exec()` you need to wait to receive all data, and -then you begin processing. With `stream_from` you can be processing data on -the client side while the server is still sending you the rest. - -You don't actually need to create a `stream_from` object yourself, though you -can. Two shorthand functions, @ref pqxx::transaction_base::stream -and @ref pqxx::transaction_base::for_each, can create the streams for you with -a minimum of overhead. - -Not all kinds of queries will work in a stream. Internally the streams make -use of PostgreSQL's `COPY` command, so see the PostgreSQL documentation for -`COPY` for the exact limitations. Basic `SELECT` and `UPDATE ... RETURNING` -queries should just work. - -As you read a row, the stream converts its fields to a tuple type containing -the value types you ask for: - - auto stream pqxx::stream_from::query( - tx, "SELECT name, points FROM score"); - std::tuple row; - while (stream >> row) - process(row); - stream.complete(); - -As the stream reads each row, it converts that row's data into your tuple, -goes through your loop body, and then promptly forgets that row's data. This -means you can easily process more data than will fit in memory. - - -stream\_to ----------- - -Use `stream_to` to write data directly to a database table. This saves you -having to perform an `INSERT` for every row, and so it can be significantly -faster if you want to insert more than just one or two rows at a time. - -As with `stream_from`, you can specify the table and the columns, and not much -else. You insert tuple-like objects of your choice: - - pqxx::stream_to stream{ - tx, - "score", - std::vector{"name", "points"}}; - for (auto const &entry: scores) - stream << entry; - stream.complete(); - -Each row is processed as you provide it, and not retained in memory after that. - -The call to `complete()` is more important here than it is for `stream_from`. -It's a lot like a "commit" or "abort" at the end of a transaction. If you omit -it, it will be done automatically during the stream's destructor. But since -destructors can't throw exceptions, any failures at that stage won't be visible -in your code. So, always call `complete()` on a `stream_to` to close it off -properly! diff --git a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/thread-safety.md b/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/thread-safety.md deleted file mode 100644 index 07c7f9984..000000000 --- a/ext/libpqxx-7.7.3/install/ubuntu22.04/arm64/share/doc/libpqxx/thread-safety.md +++ /dev/null @@ -1,29 +0,0 @@ -Thread safety {#thread-safety} -============= - -This library does not contain any locking code to protect objects against -simultaneous modification in multi-threaded programs. Therefore it is up -to you, the user of the library, to ensure that your threaded client -programs perform no conflicting operations concurrently. - -Most of the time this isn't hard. Result sets are immutable, so you can -share them between threads without problem. The main rule is: - -@li Treat a connection, together with any and all objects related to it, as -a "world" of its own. You should generally make sure that the same "world" -is never accessed by another thread while you're doing anything non-const -in there. - -That means: don't issue a query on a transaction while you're also opening -a subtransaction, don't access a cursor while you may also be committing, -and so on. - -In particular, cursors are tricky. It's easy to perform a non-const -operation without noticing. So, if you're going to share cursors or -cursor-related objects between threads, lock very conservatively! - -Use `pqxx::describe_thread_safety` to find out at runtime what level of -thread safety is implemented in your build and version of libpqxx. It -returns a `pqxx::thread_safety_model` describing what you can and cannot rely -on. A command-line utility `tools/pqxxthreadsafety` prints out the same -information. diff --git a/ext/libpqxx-7.7.3/libpqxx.pc.in b/ext/libpqxx-7.7.3/libpqxx.pc.in deleted file mode 100644 index eb7dcff49..000000000 --- a/ext/libpqxx-7.7.3/libpqxx.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libpqxx -Description: C++ client API for the PostgreSQL database management system. -Version: @VERSION@ -Libs: -L${libdir} -lpqxx -Cflags: -I${includedir} diff --git a/ext/libpqxx-7.7.3/requirements.json b/ext/libpqxx-7.7.3/requirements.json deleted file mode 100644 index 28f8f8ad1..000000000 --- a/ext/libpqxx-7.7.3/requirements.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "description": "Minimum versions needed of various things.", - "c++": "17", - "libpq": "9.6", - "postgresql": "9.6", - "gcc": "8", - "clang": "11", - "msvc": "2019" -} diff --git a/ext/libpqxx-7.7.3/src/CMakeLists.txt b/ext/libpqxx-7.7.3/src/CMakeLists.txt deleted file mode 100644 index 1d697ab7c..000000000 --- a/ext/libpqxx-7.7.3/src/CMakeLists.txt +++ /dev/null @@ -1,91 +0,0 @@ -if(NOT PostgreSQL_FOUND) - if(POLICY CMP0074) - cmake_policy(PUSH) - # CMP0074 is `OLD` by `cmake_minimum_required(VERSION 3.7)`, - # sets `NEW` to enable support CMake variable `PostgreSQL_ROOT`. - cmake_policy(SET CMP0074 NEW) - endif() - - find_package(PostgreSQL REQUIRED) - - if(POLICY CMP0074) - cmake_policy(POP) - endif() -endif() - -# When setting up the include paths, mention the binary tree's include -# directory *before* the source tree's include directory. If the source tree -# happens to contain autoconf-generated config headers, we should still prefer -# the ones in the binary tree. -macro(library_target_setup tgt) - target_include_directories(${tgt} - PUBLIC - $ - $ - $ - PRIVATE - ${PostgreSQL_INCLUDE_DIRS} - ) - target_link_libraries(${tgt} PRIVATE ${PostgreSQL_LIBRARIES}) - if(WIN32) - target_link_libraries(${tgt} PUBLIC wsock32 ws2_32) - endif() - install(TARGETS ${tgt} EXPORT libpqxx-targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) - - get_target_property(name ${tgt} NAME) - get_target_property(output_name ${tgt} OUTPUT_NAME) - if(NOT CMAKE_HOST_WIN32) - # Create library symlink - get_target_property(target_type ${tgt} TYPE) - if(target_type STREQUAL "SHARED_LIBRARY") - set(library_prefix ${CMAKE_SHARED_LIBRARY_PREFIX}) - set(library_suffix ${CMAKE_SHARED_LIBRARY_SUFFIX}) - elseif(target_type STREQUAL "STATIC_LIBRARY") - set(library_prefix ${CMAKE_STATIC_LIBRARY_PREFIX}) - set(library_suffix ${CMAKE_STATIC_LIBRARY_SUFFIX}) - endif() - - list(APPEND noop_command "${CMAKE_COMMAND}" "-E" "true") - list(APPEND create_symlink_command "${CMAKE_COMMAND}" "-E" "create_symlink" "${library_prefix}${output_name}${library_suffix}" "${library_prefix}${name}${library_suffix}") - # `add_custom_command()` does nothing if the `OUTPUT_NAME` and `NAME` - # properties are equal, otherwise it creates library symlink. - add_custom_command(TARGET ${tgt} POST_BUILD - COMMAND "$,${noop_command},${create_symlink_command}>" - VERBATIM - COMMAND_EXPAND_LISTS - ) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${library_prefix}${name}${library_suffix} - DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) - endif() -endmacro() - -file(GLOB CXX_SOURCES *.cxx) - -add_library(pqxx ${CXX_SOURCES}) - -get_target_property(pqxx_target_type pqxx TYPE) -if(pqxx_target_type STREQUAL "SHARED_LIBRARY") - target_compile_definitions(pqxx PUBLIC PQXX_SHARED) -endif() - -set_target_properties( - pqxx PROPERTIES - OUTPUT_NAME $,pqxx,pqxx-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}> -) -library_target_setup(pqxx) - -# install pkg-config file -set(prefix ${CMAKE_INSTALL_PREFIX}) -set(exec_prefix \${prefix}) -set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}") -set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") -set(VERSION ${PROJECT_VERSION}) -configure_file(${PROJECT_SOURCE_DIR}/libpqxx.pc.in ${PROJECT_BINARY_DIR}/libpqxx.pc) -install(FILES ${PROJECT_BINARY_DIR}/libpqxx.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig -) diff --git a/ext/libpqxx-7.7.3/src/Makefile.am b/ext/libpqxx-7.7.3/src/Makefile.am deleted file mode 100644 index dfd520941..000000000 --- a/ext/libpqxx-7.7.3/src/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -lib_LTLIBRARIES = libpqxx.la -libpqxx_la_SOURCES = \ - array.cxx \ - binarystring.cxx \ - blob.cxx \ - connection.cxx \ - cursor.cxx \ - encodings.cxx \ - errorhandler.cxx \ - except.cxx \ - field.cxx \ - largeobject.cxx \ - notification.cxx \ - params.cxx \ - pipeline.cxx \ - result.cxx \ - robusttransaction.cxx \ - sql_cursor.cxx \ - strconv.cxx \ - stream_from.cxx \ - stream_to.cxx \ - subtransaction.cxx \ - time.cxx \ - transaction.cxx \ - transaction_base.cxx \ - row.cxx \ - util.cxx \ - version.cxx \ - wait.cxx - -libpqxx_version = -release $(PQXX_ABI) - -libpqxx_la_LDFLAGS = $(libpqxx_version) \ - -rpath $(libdir) \ - ${POSTGRES_LIB} - -AM_CPPFLAGS = \ - -I$(top_srcdir)/include -I$(top_builddir)/include ${POSTGRES_INCLUDE} - -# Override automatically generated list of default includes. It contains only -# unnecessary entries, and incorrectly mentions include/pqxx directly. -DEFAULT_INCLUDES= - -MAINTAINERCLEANFILES=Makefile.in diff --git a/ext/libpqxx-7.7.3/src/Makefile.in b/ext/libpqxx-7.7.3/src/Makefile.in deleted file mode 100644 index 3c0152727..000000000 --- a/ext/libpqxx-7.7.3/src/Makefile.in +++ /dev/null @@ -1,809 +0,0 @@ -# Makefile.in generated by automake 1.16.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2021 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ - $(top_srcdir)/config/m4/ltoptions.m4 \ - $(top_srcdir)/config/m4/ltsugar.m4 \ - $(top_srcdir)/config/m4/ltversion.m4 \ - $(top_srcdir)/config/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(libdir)" -LTLIBRARIES = $(lib_LTLIBRARIES) -libpqxx_la_LIBADD = -am_libpqxx_la_OBJECTS = array.lo binarystring.lo blob.lo connection.lo \ - cursor.lo encodings.lo errorhandler.lo except.lo field.lo \ - largeobject.lo notification.lo params.lo pipeline.lo result.lo \ - robusttransaction.lo sql_cursor.lo strconv.lo stream_from.lo \ - stream_to.lo subtransaction.lo time.lo transaction.lo \ - transaction_base.lo row.lo util.lo version.lo wait.lo -libpqxx_la_OBJECTS = $(am_libpqxx_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libpqxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(libpqxx_la_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -depcomp = $(SHELL) $(top_srcdir)/config/depcomp -am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/array.Plo \ - ./$(DEPDIR)/binarystring.Plo ./$(DEPDIR)/blob.Plo \ - ./$(DEPDIR)/connection.Plo ./$(DEPDIR)/cursor.Plo \ - ./$(DEPDIR)/encodings.Plo ./$(DEPDIR)/errorhandler.Plo \ - ./$(DEPDIR)/except.Plo ./$(DEPDIR)/field.Plo \ - ./$(DEPDIR)/largeobject.Plo ./$(DEPDIR)/notification.Plo \ - ./$(DEPDIR)/params.Plo ./$(DEPDIR)/pipeline.Plo \ - ./$(DEPDIR)/result.Plo ./$(DEPDIR)/robusttransaction.Plo \ - ./$(DEPDIR)/row.Plo ./$(DEPDIR)/sql_cursor.Plo \ - ./$(DEPDIR)/strconv.Plo ./$(DEPDIR)/stream_from.Plo \ - ./$(DEPDIR)/stream_to.Plo ./$(DEPDIR)/subtransaction.Plo \ - ./$(DEPDIR)/time.Plo ./$(DEPDIR)/transaction.Plo \ - ./$(DEPDIR)/transaction_base.Plo ./$(DEPDIR)/util.Plo \ - ./$(DEPDIR)/version.Plo ./$(DEPDIR)/wait.Plo -am__mv = mv -f -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_@AM_V@) -am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) -am__v_CXX_0 = @echo " CXX " $@; -am__v_CXX_1 = -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) -am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) -am__v_CXXLD_0 = @echo " CXXLD " $@; -am__v_CXXLD_1 = -SOURCES = $(libpqxx_la_SOURCES) -DIST_SOURCES = $(libpqxx_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp \ - $(top_srcdir)/config/mkinstalldirs -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSCOPE = @CSCOPE@ -CTAGS = @CTAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ETAGS = @ETAGS@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_DOT = @HAVE_DOT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR = @MKDIR@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PG_CONFIG = @PG_CONFIG@ -PKG_CONFIG = @PKG_CONFIG@ -POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ -PQXXVERSION = @PQXXVERSION@ -PQXX_ABI = @PQXX_ABI@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_postgres_lib = @with_postgres_lib@ -lib_LTLIBRARIES = libpqxx.la -libpqxx_la_SOURCES = \ - array.cxx \ - binarystring.cxx \ - blob.cxx \ - connection.cxx \ - cursor.cxx \ - encodings.cxx \ - errorhandler.cxx \ - except.cxx \ - field.cxx \ - largeobject.cxx \ - notification.cxx \ - params.cxx \ - pipeline.cxx \ - result.cxx \ - robusttransaction.cxx \ - sql_cursor.cxx \ - strconv.cxx \ - stream_from.cxx \ - stream_to.cxx \ - subtransaction.cxx \ - time.cxx \ - transaction.cxx \ - transaction_base.cxx \ - row.cxx \ - util.cxx \ - version.cxx \ - wait.cxx - -libpqxx_version = -release $(PQXX_ABI) -libpqxx_la_LDFLAGS = $(libpqxx_version) \ - -rpath $(libdir) \ - ${POSTGRES_LIB} - -AM_CPPFLAGS = \ - -I$(top_srcdir)/include -I$(top_builddir)/include ${POSTGRES_INCLUDE} - - -# Override automatically generated list of default includes. It contains only -# unnecessary entries, and incorrectly mentions include/pqxx directly. -DEFAULT_INCLUDES = -MAINTAINERCLEANFILES = Makefile.in -all: all-am - -.SUFFIXES: -.SUFFIXES: .cxx .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libpqxx.la: $(libpqxx_la_OBJECTS) $(libpqxx_la_DEPENDENCIES) $(EXTRA_libpqxx_la_DEPENDENCIES) - $(AM_V_CXXLD)$(libpqxx_la_LINK) -rpath $(libdir) $(libpqxx_la_OBJECTS) $(libpqxx_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binarystring.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blob.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cursor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encodings.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errorhandler.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/except.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/field.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/largeobject.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notification.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/params.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipeline.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/result.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/robusttransaction.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/row.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_cursor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strconv.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_from.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_to.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subtransaction.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transaction.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transaction_base.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wait.Plo@am__quote@ # am--include-marker - -$(am__depfiles_remade): - @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) - -.cxx.o: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< - -.cxx.obj: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cxx.lo: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: - for dir in "$(DESTDIR)$(libdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - mostlyclean-am - -distclean: distclean-am - -rm -f ./$(DEPDIR)/array.Plo - -rm -f ./$(DEPDIR)/binarystring.Plo - -rm -f ./$(DEPDIR)/blob.Plo - -rm -f ./$(DEPDIR)/connection.Plo - -rm -f ./$(DEPDIR)/cursor.Plo - -rm -f ./$(DEPDIR)/encodings.Plo - -rm -f ./$(DEPDIR)/errorhandler.Plo - -rm -f ./$(DEPDIR)/except.Plo - -rm -f ./$(DEPDIR)/field.Plo - -rm -f ./$(DEPDIR)/largeobject.Plo - -rm -f ./$(DEPDIR)/notification.Plo - -rm -f ./$(DEPDIR)/params.Plo - -rm -f ./$(DEPDIR)/pipeline.Plo - -rm -f ./$(DEPDIR)/result.Plo - -rm -f ./$(DEPDIR)/robusttransaction.Plo - -rm -f ./$(DEPDIR)/row.Plo - -rm -f ./$(DEPDIR)/sql_cursor.Plo - -rm -f ./$(DEPDIR)/strconv.Plo - -rm -f ./$(DEPDIR)/stream_from.Plo - -rm -f ./$(DEPDIR)/stream_to.Plo - -rm -f ./$(DEPDIR)/subtransaction.Plo - -rm -f ./$(DEPDIR)/time.Plo - -rm -f ./$(DEPDIR)/transaction.Plo - -rm -f ./$(DEPDIR)/transaction_base.Plo - -rm -f ./$(DEPDIR)/util.Plo - -rm -f ./$(DEPDIR)/version.Plo - -rm -f ./$(DEPDIR)/wait.Plo - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-libLTLIBRARIES - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/array.Plo - -rm -f ./$(DEPDIR)/binarystring.Plo - -rm -f ./$(DEPDIR)/blob.Plo - -rm -f ./$(DEPDIR)/connection.Plo - -rm -f ./$(DEPDIR)/cursor.Plo - -rm -f ./$(DEPDIR)/encodings.Plo - -rm -f ./$(DEPDIR)/errorhandler.Plo - -rm -f ./$(DEPDIR)/except.Plo - -rm -f ./$(DEPDIR)/field.Plo - -rm -f ./$(DEPDIR)/largeobject.Plo - -rm -f ./$(DEPDIR)/notification.Plo - -rm -f ./$(DEPDIR)/params.Plo - -rm -f ./$(DEPDIR)/pipeline.Plo - -rm -f ./$(DEPDIR)/result.Plo - -rm -f ./$(DEPDIR)/robusttransaction.Plo - -rm -f ./$(DEPDIR)/row.Plo - -rm -f ./$(DEPDIR)/sql_cursor.Plo - -rm -f ./$(DEPDIR)/strconv.Plo - -rm -f ./$(DEPDIR)/stream_from.Plo - -rm -f ./$(DEPDIR)/stream_to.Plo - -rm -f ./$(DEPDIR)/subtransaction.Plo - -rm -f ./$(DEPDIR)/time.Plo - -rm -f ./$(DEPDIR)/transaction.Plo - -rm -f ./$(DEPDIR)/transaction_base.Plo - -rm -f ./$(DEPDIR)/util.Plo - -rm -f ./$(DEPDIR)/version.Plo - -rm -f ./$(DEPDIR)/wait.Plo - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-libLTLIBRARIES - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ - clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ - ctags ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-libLTLIBRARIES install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES - -.PRECIOUS: Makefile - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ext/libpqxx-7.7.3/src/array.cxx b/ext/libpqxx-7.7.3/src/array.cxx deleted file mode 100644 index e35aaddce..000000000 --- a/ext/libpqxx-7.7.3/src/array.cxx +++ /dev/null @@ -1,240 +0,0 @@ -/** Handling of SQL arrays. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/array.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/array-composite.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/util.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace pqxx -{ -/// Scan to next glyph in the buffer. Assumes there is one. -[[nodiscard]] std::string::size_type -array_parser::scan_glyph(std::string::size_type pos) const -{ - return m_scan(std::data(m_input), std::size(m_input), pos); -} - - -/// Scan to next glyph in a substring. Assumes there is one. -std::string::size_type array_parser::scan_glyph( - std::string::size_type pos, std::string::size_type end) const -{ - return m_scan(std::data(m_input), end, pos); -} - - -/// Find the end of a single-quoted SQL string in an SQL array. -/** Call this while pointed at the opening quote. - * - * Returns the offset of the first character after the closing quote. - */ -std::string::size_type array_parser::scan_single_quoted_string() const -{ - assert(m_input[m_pos] == '\''); - auto const sz{std::size(m_input)}; - auto here{pqxx::internal::find_char<'\\', '\''>(m_scan, m_input, m_pos + 1)}; - while (here < sz) - { - char const c{m_input[here]}; - // Consume the slash or quote that we found. - ++here; - if (c == '\'') - { - // Single quote. - - // At end? - if (here >= sz) - return here; - - // SQL escapes single quotes by doubling them. Terrible idea, but it's - // what we have. Inspect the next character to find out whether this - // is the closing quote, or an escaped one inside the string. - if (m_input[here] != '\'') - return here; - // Check against embedded "'" byte in a multichar byte. If we do have a - // multibyte char, then we're still out of the string. - if (scan_glyph(here, sz) > here + 1) - PQXX_UNLIKELY return here; - - // We have a second quote. Consume it as well. - ++here; - } - else - { - assert(c == '\\'); - // Backslash escape. Skip ahead by one more character. - here = scan_glyph(here, sz); - } - // Race on to the next quote or backslash. - here = pqxx::internal::find_char<'\\', '\''>(m_scan, m_input, here); - } - throw argument_error{internal::concat("Null byte in SQL string: ", m_input)}; -} - - -/// Parse a single-quoted SQL string: un-quote it and un-escape it. -std::string -array_parser::parse_single_quoted_string(std::string::size_type end) const -{ - std::string output; - // Maximum output size is same as the input size, minus the opening and - // closing quotes. In the worst case, the real number could be half that. - // Usually it'll be a pretty close estimate. - output.reserve(end - m_pos - 2); - // XXX: find_char<'\\', '\''>(). - for (auto here = m_pos + 1, next = scan_glyph(here, end); here < end - 1; - here = next, next = scan_glyph(here, end)) - { - if (next - here == 1 and (m_input[here] == '\'' or m_input[here] == '\\')) - { - // Skip escape. (Performance-wise, we bet that these are relatively - // rare.) - PQXX_UNLIKELY - here = next; - next = scan_glyph(here, end); - } - - output.append(std::data(m_input) + here, std::data(m_input) + next); - } - - return output; -} - - -/// Find the end of a double-quoted SQL string in an SQL array. -std::string::size_type array_parser::scan_double_quoted_string() const -{ - return pqxx::internal::scan_double_quoted_string( - std::data(m_input), std::size(m_input), m_pos, m_scan); -} - - -/// Parse a double-quoted SQL string: un-quote it and un-escape it. -std::string -array_parser::parse_double_quoted_string(std::string::size_type end) const -{ - return pqxx::internal::parse_double_quoted_string( - std::data(m_input), end, m_pos, m_scan); -} - - -/// Find the end of an unquoted string in an SQL array. -/** Assumes UTF-8 or an ASCII-superset single-byte encoding. - */ -std::string::size_type array_parser::scan_unquoted_string() const -{ - return pqxx::internal::scan_unquoted_string<',', ';', '}'>( - std::data(m_input), std::size(m_input), m_pos, m_scan); -} - - -/// Parse an unquoted SQL string. -/** Here, the special unquoted value NULL means a null value, not a string - * that happens to spell "NULL". - */ -std::string -array_parser::parse_unquoted_string(std::string::size_type end) const -{ - return pqxx::internal::parse_unquoted_string( - std::data(m_input), end, m_pos, m_scan); -} - - -array_parser::array_parser( - std::string_view input, internal::encoding_group enc) : - m_input(input), m_scan(internal::get_glyph_scanner(enc)) -{} - - -std::pair array_parser::get_next() -{ - std::string value; - - if (m_pos >= std::size(m_input)) - return std::make_pair(juncture::done, value); - - juncture found; - std::string::size_type end; - - if (scan_glyph(m_pos) - m_pos > 1) - { - // Non-ASCII unquoted string. - end = scan_unquoted_string(); - value = parse_unquoted_string(end); - found = juncture::string_value; - } - else - switch (m_input[m_pos]) - { - case '\0': throw failure{"Unexpected zero byte in array."}; - case '{': - found = juncture::row_start; - end = scan_glyph(m_pos); - break; - case '}': - found = juncture::row_end; - end = scan_glyph(m_pos); - break; - case '\'': - found = juncture::string_value; - end = scan_single_quoted_string(); - value = parse_single_quoted_string(end); - break; - case '"': - found = juncture::string_value; - end = scan_double_quoted_string(); - value = parse_double_quoted_string(end); - break; - default: - end = scan_unquoted_string(); - value = parse_unquoted_string(end); - if (value == "NULL") - { - // In this one situation, as a special case, NULL means a null field, - // not a string that happens to spell "NULL". - value.clear(); - found = juncture::null_value; - } - else - { - // The normal case: we just parsed an unquoted string. The value is - // what we need. - PQXX_LIKELY - found = juncture::string_value; - } - break; - } - - // Skip a trailing field separator, if present. - if (end < std::size(m_input)) - { - auto next{scan_glyph(end)}; - if (next - end == 1 and (m_input[end] == ',' or m_input[end] == ';')) - PQXX_UNLIKELY - end = next; - } - - m_pos = end; - return std::make_pair(found, value); -} -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/src/binarystring.cxx b/ext/libpqxx-7.7.3/src/binarystring.cxx deleted file mode 100644 index 936437006..000000000 --- a/ext/libpqxx-7.7.3/src/binarystring.cxx +++ /dev/null @@ -1,108 +0,0 @@ -/** Implementation of bytea (binary string) conversions. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include -#include -#include -#include - -extern "C" -{ -#include -} - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/binarystring.hxx" -#include "pqxx/field.hxx" -#include "pqxx/strconv.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace -{ -/// Copy data to a heap-allocated buffer. -std::shared_ptr - PQXX_COLD copy_to_buffer(void const *data, std::size_t len) -{ - void *const output{malloc(len + 1)}; - if (output == nullptr) - throw std::bad_alloc{}; - static_cast(output)[len] = '\0'; - memcpy(static_cast(output), data, len); - return {static_cast(output), std::free}; -} -} // namespace - - -PQXX_COLD pqxx::binarystring::binarystring(field const &F) -{ - unsigned char const *data{ - reinterpret_cast(F.c_str())}; - m_buf = - std::shared_ptr{PQunescapeBytea(data, &m_size), PQfreemem}; - if (m_buf == nullptr) - throw std::bad_alloc{}; -} - - -pqxx::binarystring::binarystring(std::string_view s) : - m_buf{copy_to_buffer(std::data(s), std::size(s))}, m_size{std::size(s)} -{} - - -pqxx::binarystring::binarystring(void const *binary_data, std::size_t len) : - m_buf{copy_to_buffer(binary_data, len)}, m_size{len} -{} - - -bool pqxx::binarystring::operator==(binarystring const &rhs) const noexcept -{ - return (std::size(rhs) == size()) and - (std::memcmp(data(), std::data(rhs), size()) == 0); -} - - -pqxx::binarystring & -pqxx::binarystring::operator=(binarystring const &rhs) = default; - -PQXX_COLD pqxx::binarystring::const_reference -pqxx::binarystring::at(size_type n) const -{ - if (n >= m_size) - { - if (m_size == 0) - throw std::out_of_range{"Accessing empty binarystring"}; - throw std::out_of_range{ - "binarystring index out of range: " + to_string(n) + - " (should be below " + to_string(m_size) + ")"}; - } - return data()[n]; -} - - -PQXX_COLD void pqxx::binarystring::swap(binarystring &rhs) -{ - m_buf.swap(rhs.m_buf); - - // This part very obviously can't go wrong, so do it last - auto const s{m_size}; - m_size = rhs.m_size; - rhs.m_size = s; -} - - -std::string pqxx::binarystring::str() const -{ - return std::string{get(), m_size}; -} diff --git a/ext/libpqxx-7.7.3/src/blob.cxx b/ext/libpqxx-7.7.3/src/blob.cxx deleted file mode 100644 index 1492d9107..000000000 --- a/ext/libpqxx-7.7.3/src/blob.cxx +++ /dev/null @@ -1,337 +0,0 @@ -#include "pqxx-source.hxx" - -#include -#include -#include - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/blob.hxx" -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/gates/connection-largeobject.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace -{ -constexpr int INV_WRITE{0x00020000}, INV_READ{0x00040000}; -} // namespace - - -pqxx::internal::pq::PGconn * -pqxx::blob::raw_conn(pqxx::connection *conn) noexcept -{ - pqxx::internal::gate::connection_largeobject gate{*conn}; - return gate.raw_connection(); -} - - -pqxx::internal::pq::PGconn * -pqxx::blob::raw_conn(pqxx::dbtransaction const &tx) noexcept -{ - return raw_conn(&tx.conn()); -} - - -std::string pqxx::blob::errmsg(connection const *conn) -{ - pqxx::internal::gate::const_connection_largeobject gate{*conn}; - return gate.error_message(); -} - - -pqxx::blob pqxx::blob::open_internal(dbtransaction &tx, oid id, int mode) -{ - auto &conn{tx.conn()}; - int fd{lo_open(raw_conn(&conn), id, mode)}; - if (fd == -1) - throw pqxx::failure{internal::concat( - "Could not open binary large object ", id, ": ", errmsg(&conn))}; - return {conn, fd}; -} - - -pqxx::oid pqxx::blob::create(dbtransaction &tx, oid id) -{ - oid actual_id{lo_create(raw_conn(tx), id)}; - if (actual_id == 0) - throw failure{internal::concat( - "Could not create binary large object: ", errmsg(&tx.conn()))}; - return actual_id; -} - - -void pqxx::blob::remove(dbtransaction &tx, oid id) -{ - if (id == 0) - throw usage_error{"Trying to delete binary large object without an ID."}; - if (lo_unlink(raw_conn(tx), id) == -1) - throw failure{internal::concat( - "Could not delete large object ", id, ": ", errmsg(&tx.conn()))}; -} - - -pqxx::blob pqxx::blob::open_r(dbtransaction &tx, oid id) -{ - return open_internal(tx, id, INV_READ); -} - - -pqxx::blob pqxx::blob::open_w(dbtransaction &tx, oid id) -{ - return open_internal(tx, id, INV_WRITE); -} - - -pqxx::blob pqxx::blob::open_rw(dbtransaction &tx, oid id) -{ - return open_internal(tx, id, INV_READ | INV_WRITE); -} - - -pqxx::blob::blob(blob &&other) : - m_conn{std::exchange(other.m_conn, nullptr)}, - m_fd{std::exchange(other.m_fd, -1)} -{} - - -pqxx::blob &pqxx::blob::operator=(blob &&other) -{ - if (m_fd != -1) - lo_close(raw_conn(m_conn), m_fd); - m_conn = std::exchange(other.m_conn, nullptr); - m_fd = std::exchange(other.m_fd, -1); - return *this; -} - - -pqxx::blob::~blob() -{ - try - { - close(); - } - catch (std::exception const &e) - { - if (m_conn != nullptr) - PQXX_UNLIKELY - m_conn->process_notice(internal::concat( - "Failure while closing binary large object: ", e.what(), "\n")); - } -} - - -void pqxx::blob::close() -{ - if (m_fd != -1) - { - lo_close(raw_conn(m_conn), m_fd); - m_fd = -1; - m_conn = nullptr; - } -} - - -std::size_t pqxx::blob::raw_read(std::byte buf[], std::size_t size) -{ - if (m_conn == nullptr) - throw usage_error{"Attempt to read from a closed binary large object."}; - if (size > chunk_limit) - throw range_error{ - "Reads from a binary large object must be less than 2 GB at once."}; - auto data{reinterpret_cast(buf)}; - int received{lo_read(raw_conn(m_conn), m_fd, data, size)}; - if (received < 0) - throw failure{ - internal::concat("Could not read from binary large object: ", errmsg())}; - return static_cast(received); -} - - -std::size_t -pqxx::blob::read(std::basic_string &buf, std::size_t size) -{ - buf.resize(size); - auto const received{raw_read(std::data(buf), size)}; - buf.resize(received); - return static_cast(received); -} - - -void pqxx::blob::raw_write(std::byte const buf[], std::size_t size) -{ - if (m_conn == nullptr) - throw usage_error{"Attempt to write to a closed binary large object."}; - if (size > chunk_limit) - throw range_error{ - "Writes to a binary large object must be less than 2 GB at once."}; - auto ptr{reinterpret_cast(buf)}; - int written{lo_write(raw_conn(m_conn), m_fd, ptr, size)}; - if (written < 0) - throw failure{ - internal::concat("Write to binary large object failed: ", errmsg())}; -} - - -void pqxx::blob::resize(std::int64_t size) -{ - if (m_conn == nullptr) - throw usage_error{"Attempt to resize a closed binary large object."}; - if (lo_truncate64(raw_conn(m_conn), m_fd, size) < 0) - throw failure{ - internal::concat("Binary large object truncation failed: ", errmsg())}; -} - - -std::int64_t pqxx::blob::tell() const -{ - if (m_conn == nullptr) - throw usage_error{"Attempt to tell() a closed binary large object."}; - std::int64_t offset{lo_tell64(raw_conn(m_conn), m_fd)}; - if (offset < 0) - throw failure{internal::concat( - "Error reading binary large object position: ", errmsg())}; - return offset; -} - - -std::int64_t pqxx::blob::seek(std::int64_t offset, int whence) -{ - if (m_conn == nullptr) - throw usage_error{"Attempt to seek() a closed binary large object."}; - std::int64_t seek_result{lo_lseek64(raw_conn(m_conn), m_fd, offset, whence)}; - if (seek_result < 0) - throw failure{internal::concat( - "Error during seek on binary large object: ", errmsg())}; - return seek_result; -} - - -std::int64_t pqxx::blob::seek_abs(std::int64_t offset) -{ - return this->seek(offset, SEEK_SET); -} - - -std::int64_t pqxx::blob::seek_rel(std::int64_t offset) -{ - return this->seek(offset, SEEK_CUR); -} - - -std::int64_t pqxx::blob::seek_end(std::int64_t offset) -{ - return this->seek(offset, SEEK_END); -} - - -pqxx::oid pqxx::blob::from_buf( - dbtransaction &tx, std::basic_string_view data, oid id) -{ - oid actual_id{create(tx, id)}; - try - { - open_w(tx, actual_id).write(data); - } - catch (std::exception const &) - { - try - { - remove(tx, id); - } - catch (std::exception const &e) - { - try - { - tx.conn().process_notice(internal::concat( - "Could not clean up partially created large object ", id, ": ", - e.what())); - } - catch (std::exception const &) - {} - } - throw; - } - return actual_id; -} - - -void pqxx::blob::append_from_buf( - dbtransaction &tx, std::basic_string_view data, oid id) -{ - if (std::size(data) > chunk_limit) - throw range_error{ - "Writes to a binary large object must be less than 2 GB at once."}; - blob b{open_w(tx, id)}; - b.seek_end(); - b.write(data); -} - - -void pqxx::blob::to_buf( - dbtransaction &tx, oid id, std::basic_string &buf, - std::size_t max_size) -{ - open_r(tx, id).read(buf, max_size); -} - - -std::size_t pqxx::blob::append_to_buf( - dbtransaction &tx, oid id, std::int64_t offset, - std::basic_string &buf, std::size_t append_max) -{ - if (append_max > chunk_limit) - throw range_error{ - "Reads from a binary large object must be less than 2 GB at once."}; - auto b{open_r(tx, id)}; - b.seek_abs(offset); - auto const org_size{std::size(buf)}; - buf.resize(org_size + append_max); - try - { - auto here{reinterpret_cast(std::data(buf) + org_size)}; - auto chunk{static_cast( - lo_read(b.raw_conn(b.m_conn), b.m_fd, here, append_max))}; - buf.resize(org_size + chunk); - return chunk; - } - catch (std::exception const &) - { - buf.resize(org_size); - throw; - } -} - - -pqxx::oid pqxx::blob::from_file(dbtransaction &tx, char const path[]) -{ - auto id{lo_import(raw_conn(tx), path)}; - if (id == 0) - throw failure{internal::concat( - "Could not import '", path, "' as a binary large object: ", errmsg(tx))}; - return id; -} - - -pqxx::oid pqxx::blob::from_file(dbtransaction &tx, char const path[], oid id) -{ - auto actual_id{lo_import_with_oid(raw_conn(tx), path, id)}; - if (actual_id == 0) - throw failure{internal::concat( - "Could not import '", path, "' as binary large object ", id, ": ", - errmsg(tx))}; - return actual_id; -} - - -void pqxx::blob::to_file(dbtransaction &tx, oid id, char const path[]) -{ - if (lo_export(raw_conn(tx), id, path) < 0) - throw failure{internal::concat( - "Could not export binary large object ", id, " to file '", path, - "': ", errmsg(tx))}; -} diff --git a/ext/libpqxx-7.7.3/src/connection.cxx b/ext/libpqxx-7.7.3/src/connection.cxx deleted file mode 100644 index bef8c79aa..000000000 --- a/ext/libpqxx-7.7.3/src/connection.cxx +++ /dev/null @@ -1,1274 +0,0 @@ -/** Implementation of the pqxx::connection class. - * - * pqxx::connection encapsulates a connection to a database. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// For fcntl(). -#if __has_include() -# include -#endif -#if __has_include() -# include -#endif - -// For ioctlsocket(). -#if defined(_WIN32) && __has_include() -# include -#endif - -extern "C" -{ -#include -} - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/binarystring.hxx" -#include "pqxx/internal/wait.hxx" -#include "pqxx/nontransaction.hxx" -#include "pqxx/notification.hxx" -#include "pqxx/pipeline.hxx" -#include "pqxx/result.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/transaction.hxx" - -#include "pqxx/internal/gates/errorhandler-connection.hxx" -#include "pqxx/internal/gates/result-connection.hxx" -#include "pqxx/internal/gates/result-creation.hxx" - -#include "pqxx/internal/header-post.hxx" - - -extern "C" -{ - // The PQnoticeProcessor that receives an error or warning from libpq and - // sends it to the appropriate connection for processing. - void pqxx_notice_processor(void *conn, char const *msg) noexcept - { - reinterpret_cast(conn)->process_notice(msg); - } - - - // There's no way in libpq to disable a connection's notice processor. So, - // set an inert one to get the same effect. - void inert_notice_processor(void *, char const *) noexcept {} -} // extern "C" - -using namespace std::literals; - -std::string PQXX_COLD -pqxx::encrypt_password(char const user[], char const password[]) -{ - std::unique_ptr> p{ - PQencryptPassword(password, user), PQfreemem}; - return {p.get()}; -} - - -pqxx::connection::connection(connection &&rhs) : - m_conn{rhs.m_conn}, m_unique_id{rhs.m_unique_id} -{ - rhs.check_movable(); - rhs.m_conn = nullptr; -} - - -pqxx::connection::connection( - connection::connect_mode, zview connection_string) : - m_conn{PQconnectStart(connection_string.c_str())} -{ - if (m_conn == nullptr) - throw std::bad_alloc{}; - if (status() == CONNECTION_BAD) - throw pqxx::broken_connection{PQerrorMessage(m_conn)}; -} - - -std::pair pqxx::connection::poll_connect() -{ - switch (PQconnectPoll(m_conn)) - { - case PGRES_POLLING_FAILED: - throw pqxx::broken_connection{PQerrorMessage(m_conn)}; - case PGRES_POLLING_READING: return std::make_pair(true, false); - case PGRES_POLLING_WRITING: return std::make_pair(false, true); - case PGRES_POLLING_OK: - if (not is_open()) - throw pqxx::broken_connection{PQerrorMessage(m_conn)}; - return std::make_pair(false, false); - case PGRES_POLLING_ACTIVE: - throw internal_error{ - "Nonblocking connection poll returned obsolete 'active' state."}; - default: - throw internal_error{ - "Nonblocking connection poll returned unknown value."}; - } -} - -void pqxx::connection::complete_init() -{ - if (m_conn == nullptr) - throw std::bad_alloc{}; - try - { - if (not is_open()) - throw broken_connection{PQerrorMessage(m_conn)}; - - set_up_state(); - } - catch (std::exception const &) - { - PQfinish(m_conn); - m_conn = nullptr; - throw; - } -} - - -void pqxx::connection::init(char const options[]) -{ - m_conn = PQconnectdb(options); - complete_init(); -} - - -void pqxx::connection::init(char const *params[], char const *values[]) -{ - m_conn = PQconnectdbParams(params, values, 0); - complete_init(); -} - - -void pqxx::connection::check_movable() const -{ - if (m_trans) - throw pqxx::usage_error{"Moving a connection with a transaction open."}; - if (not std::empty(m_errorhandlers)) - throw pqxx::usage_error{ - "Moving a connection with error handlers registered."}; - if (not std::empty(m_receivers)) - throw pqxx::usage_error{ - "Moving a connection with notification receivers registered."}; -} - - -void pqxx::connection::check_overwritable() const -{ - if (m_trans) - throw pqxx::usage_error{ - "Moving a connection onto one with a transaction open."}; - if (not std::empty(m_errorhandlers)) - throw pqxx::usage_error{ - "Moving a connection onto one with error handlers registered."}; - if (not std::empty(m_receivers)) - throw usage_error{ - "Moving a connection onto one " - "with notification receivers registered."}; -} - - -pqxx::connection &pqxx::connection::operator=(connection &&rhs) -{ - check_overwritable(); - rhs.check_movable(); - - close(); - - m_conn = std::exchange(rhs.m_conn, nullptr); - m_unique_id = rhs.m_unique_id; - - return *this; -} - - -pqxx::result pqxx::connection::make_result( - internal::pq::PGresult *pgr, std::shared_ptr const &query, - std::string_view desc) -{ - if (pgr == nullptr) - { - if (is_open()) - throw failure(err_msg()); - else - throw broken_connection{"Lost connection to the database server."}; - } - internal::encoding_group enc; - try - { - enc = internal::enc_group(encoding_id()); - } - catch (std::exception const &) - { - // Don't let the PGresult leak. - // TODO: Can we just accept a unique_ptr instead? - internal::clear_result(pgr); - throw; - } - auto const r{pqxx::internal::gate::result_creation::create(pgr, query, enc)}; - pqxx::internal::gate::result_creation{r}.check_status(desc); - return r; -} - - -int PQXX_COLD pqxx::connection::backendpid() const &noexcept -{ - return (m_conn == nullptr) ? 0 : PQbackendPID(m_conn); -} - - -namespace -{ -PQXX_PURE int socket_of(::pqxx::internal::pq::PGconn const *c) noexcept -{ - return (c == nullptr) ? -1 : PQsocket(c); -} -} // namespace - - -int pqxx::connection::sock() const &noexcept -{ - return socket_of(m_conn); -} - - -int PQXX_COLD pqxx::connection::protocol_version() const noexcept -{ - return (m_conn == nullptr) ? 0 : PQprotocolVersion(m_conn); -} - - -int PQXX_COLD pqxx::connection::server_version() const noexcept -{ - return PQserverVersion(m_conn); -} - - -void pqxx::connection::set_variable( - std::string_view var, std::string_view value) & -{ - exec(internal::concat("SET ", quote_name(var), "=", value)); -} - - -std::string pqxx::connection::get_variable(std::string_view var) -{ - return exec(internal::concat("SHOW ", quote_name(var))) - .at(0) - .at(0) - .as(std::string{}); -} - - -std::string pqxx::connection::get_var(std::string_view var) -{ - // (Variables can't be null, so far as I can make out.) - return exec(internal::concat("SHOW "sv, quote_name(var)))[0][0] - .as(); -} - - -/** Set up various parts of logical connection state that may need to be - * recovered because the physical connection to the database was lost and is - * being reset, or that may not have been initialized yet. - */ -void pqxx::connection::set_up_state() -{ - if (auto const proto_ver{protocol_version()}; proto_ver < 3) - { - if (proto_ver == 0) - throw broken_connection{"No connection."}; - else - throw feature_not_supported{ - "Unsupported frontend/backend protocol version; 3.0 is the minimum."}; - } - - if (server_version() <= 90000) - throw feature_not_supported{ - "Unsupported server version; 9.0 is the minimum."}; - - // The default notice processor in libpq writes to stderr. Ours does - // nothing. - // If the caller registers an error handler, this gets replaced with an - // error handler that walks down the connection's chain of handlers. We - // don't do that by default because there's a danger: libpq may call the - // notice processor via a result object, even after the connection has been - // destroyed and the handlers list no longer exists. - PQXX_LIKELY - PQsetNoticeProcessor(m_conn, inert_notice_processor, nullptr); -} - - -bool pqxx::connection::is_open() const noexcept -{ - return status() == CONNECTION_OK; -} - - -void pqxx::connection::process_notice_raw(char const msg[]) noexcept -{ - if ((msg == nullptr) or (*msg == '\0')) - return; - auto const rbegin = std::crbegin(m_errorhandlers), - rend = std::crend(m_errorhandlers); - for (auto i{rbegin}; (i != rend) and (**i)(msg); ++i) - ; -} - - -void pqxx::connection::process_notice(char const msg[]) noexcept -{ - if (msg == nullptr) - return; - zview const view{msg}; - if (std::empty(view)) - return; - else if (msg[std::size(view) - 1] == '\n') - process_notice_raw(msg); - else - // Newline is missing. Let the zview version of the code add it. - PQXX_UNLIKELY - process_notice(view); -} - - -void pqxx::connection::process_notice(zview msg) noexcept -{ - if (std::empty(msg)) - return; - else if (msg[std::size(msg) - 1] == '\n') - process_notice_raw(msg.c_str()); - else - try - { - // Add newline. - std::string buf; - buf.reserve(std::size(msg) + 1); - buf.assign(msg); - buf.push_back('\n'); - process_notice_raw(buf.c_str()); - } - catch (std::exception const &) - { - // If nothing else works, try writing the message without the newline. - PQXX_UNLIKELY - process_notice_raw(msg.c_str()); - } -} - - -void PQXX_COLD pqxx::connection::trace(FILE *out) noexcept -{ - if (m_conn) - { - if (out) - PQtrace(m_conn, out); - else - PQuntrace(m_conn); - } -} - - -void PQXX_COLD pqxx::connection::add_receiver(pqxx::notification_receiver *n) -{ - if (n == nullptr) - throw argument_error{"Null receiver registered"}; - - // Add to receiver list and attempt to start listening. - auto const p{m_receivers.find(n->channel())}; - auto const new_value{receiver_list::value_type{n->channel(), n}}; - - if (p == std::end(m_receivers)) - { - // Not listening on this event yet, start doing so. - auto const lq{std::make_shared( - internal::concat("LISTEN ", quote_name(n->channel())))}; - make_result(PQexec(m_conn, lq->c_str()), lq, *lq); - m_receivers.insert(new_value); - } - else - { - m_receivers.insert(p, new_value); - } -} - - -void PQXX_COLD -pqxx::connection::remove_receiver(pqxx::notification_receiver *T) noexcept -{ - if (T == nullptr) - return; - - try - { - auto needle{ - std::pair{T->channel(), T}}; - auto R{m_receivers.equal_range(needle.first)}; - auto i{find(R.first, R.second, needle)}; - - if (i == R.second) - { - PQXX_UNLIKELY - process_notice(internal::concat( - "Attempt to remove unknown receiver '", needle.first, "'")); - } - else - { - // Erase first; otherwise a notification for the same receiver may yet - // come in and wreak havoc. Thanks Dragan Milenkovic. - bool const gone{R.second == ++R.first}; - m_receivers.erase(i); - if (gone) - exec(internal::concat("UNLISTEN ", quote_name(needle.first)).c_str()); - } - } - catch (std::exception const &e) - { - PQXX_UNLIKELY - process_notice(e.what()); - } -} - - -bool pqxx::connection::consume_input() noexcept -{ - return PQconsumeInput(m_conn) != 0; -} - - -bool pqxx::connection::is_busy() const noexcept -{ - return PQisBusy(m_conn) != 0; -} - - -void PQXX_COLD pqxx::connection::cancel_query() -{ - using pointer = std::unique_ptr>; - pointer cancel{PQgetCancel(m_conn), PQfreeCancel}; - if (cancel == nullptr) - PQXX_UNLIKELY - throw std::bad_alloc{}; - - std::array errbuf; - auto const err{errbuf.data()}; - auto const c{ - PQcancel(cancel.get(), err, static_cast(std::size(errbuf)))}; - if (c == 0) - PQXX_UNLIKELY - throw pqxx::sql_error{std::string{err, std::size(errbuf)}, "[cancel]"}; -} - - -namespace -{ -// C++20: std::span? -/// Get error string for a given @c errno value. -template -char const *PQXX_COLD -error_string(int err_num, std::array &buffer) -{ - // Not entirely clear whether strerror_s will be in std or global namespace. - using namespace std; - -#if defined(PQXX_HAVE_STERROR_S) || defined(PQXX_HAVE_STRERROR_R) -# if defined(PQXX_HAVE_STRERROR_S) - auto const err_result{strerror_s(std::data(buffer), BYTES, err_num)}; -# else - auto const err_result{strerror_r(err_num, std::data(buffer), BYTES)}; -# endif - if constexpr (std::is_same_v, char *>) - { - // GNU version of strerror_r; returns the error string, which may or may - // not reside within buffer. - return err_result; - } - else - { - // Either strerror_s or POSIX strerror_r; returns an error code. - // Sorry for being lazy here: Not reporting error string for the case - // where we can't retrieve an error string. - if (err_result == 0) - return std::data(buffer); - else - return "Compound errors."; - } - -#else - // Fallback case, hopefully for no actual platforms out there. - pqxx::ignore_unused(err_num, buffer); - return "(No error information available.)"; -#endif -} -} // namespace - - -#if defined(_WIN32) || __has_include() -void pqxx::connection::set_blocking(bool block) & -{ - auto const fd{sock()}; -# if defined _WIN32 - unsigned long mode{not block}; - if (::ioctlsocket(fd, FIONBIO, &mode) != 0) - { - std::array errbuf; - char const *err{error_string(WSAGetLastError(), errbuf)}; - throw broken_connection{ - internal::concat("Could not set socket's blocking mode: ", err)}; - } -# else // _WIN32 - std::array errbuf; - auto flags{::fcntl(fd, F_GETFL, 0)}; - if (flags == -1) - { - char const *const err{error_string(errno, errbuf)}; - throw broken_connection{ - internal::concat("Could not get socket state: ", err)}; - } - if (block) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - if (::fcntl(fd, F_SETFL, flags) == -1) - { - char const *const err{error_string(errno, errbuf)}; - throw broken_connection{ - internal::concat("Could not set socket's blocking mode: ", err)}; - } -# endif // _WIN32 -} -#endif // defined(_WIN32) || __has_include() - - -void PQXX_COLD -pqxx::connection::set_verbosity(error_verbosity verbosity) &noexcept -{ - PQsetErrorVerbosity(m_conn, static_cast(verbosity)); -} - - -namespace -{ -/// Unique pointer to PGnotify. -using notify_ptr = std::unique_ptr>; - - -/// Get one notification from a connection, or null. -notify_ptr get_notif(pqxx::internal::pq::PGconn *conn) -{ - return notify_ptr(PQnotifies(conn), PQfreemem); -} -} // namespace - - -int pqxx::connection::get_notifs() -{ - if (not consume_input()) - throw broken_connection{"Connection lost."}; - - // Even if somehow we receive notifications during our transaction, don't - // deliver them. - if (m_trans) - PQXX_UNLIKELY - return 0; - - int notifs = 0; - for (auto N{get_notif(m_conn)}; N.get(); N = get_notif(m_conn)) - { - notifs++; - - auto const Hit{m_receivers.equal_range(std::string{N->relname})}; - if (Hit.second != Hit.first) - { - std::string payload{N->extra}; - for (auto i{Hit.first}; i != Hit.second; ++i) try - { - (*i->second)(payload, N->be_pid); - } - catch (std::exception const &e) - { - try - { - process_notice(internal::concat( - "Exception in notification receiver '", i->first, - "': ", e.what(), "\n")); - } - catch (std::bad_alloc const &) - { - // Out of memory. Try to get the message out in a more robust way. - process_notice( - "Exception in notification receiver, " - "and also ran out of memory\n"); - } - catch (std::exception const &) - { - process_notice( - "Exception in notification receiver " - "(compounded by other error)\n"); - } - } - } - - N.reset(); - } - return notifs; -} - - -char const *PQXX_COLD pqxx::connection::dbname() const -{ - return PQdb(m_conn); -} - - -char const *PQXX_COLD pqxx::connection::username() const -{ - return PQuser(m_conn); -} - - -char const *PQXX_COLD pqxx::connection::hostname() const -{ - return PQhost(m_conn); -} - - -char const *PQXX_COLD pqxx::connection::port() const -{ - return PQport(m_conn); -} - - -char const *pqxx::connection::err_msg() const noexcept -{ - return (m_conn == nullptr) ? "No connection to database" : - PQerrorMessage(m_conn); -} - - -void PQXX_COLD pqxx::connection::register_errorhandler(errorhandler *handler) -{ - // Set notice processor on demand, i.e. only when the caller actually - // registers an error handler. - // We do this just to make it less likely that users fall into the trap - // where a result object may hold a notice processor derived from its parent - // connection which has already been destroyed. Our notice processor goes - // through the connection's list of error handlers. If the connection object - // has already been destroyed though, that list no longer exists. - // By setting the notice processor on demand, we absolve users who never - // register an error handler from ahving to care about this nasty subtlety. - if (std::empty(m_errorhandlers)) - PQsetNoticeProcessor(m_conn, pqxx_notice_processor, this); - m_errorhandlers.push_back(handler); -} - - -void PQXX_COLD -pqxx::connection::unregister_errorhandler(errorhandler *handler) noexcept -{ - // The errorhandler itself will take care of nulling its pointer to this - // connection. - m_errorhandlers.remove(handler); - if (std::empty(m_errorhandlers)) - PQsetNoticeProcessor(m_conn, inert_notice_processor, nullptr); -} - - -std::vector - PQXX_COLD pqxx::connection::get_errorhandlers() const -{ - return {std::begin(m_errorhandlers), std::end(m_errorhandlers)}; -} - - -pqxx::result -pqxx::connection::exec(std::string_view query, std::string_view desc) -{ - return exec(std::make_shared(query), desc); -} - - -pqxx::result pqxx::connection::exec( - std::shared_ptr query, std::string_view desc) -{ - auto const res{make_result(PQexec(m_conn, query->c_str()), query, desc)}; - get_notifs(); - return res; -} - - -std::string pqxx::connection::encrypt_password( - char const user[], char const password[], char const *algorithm) -{ -#if defined(PQXX_HAVE_PQENCRYPTPASSWORDCONN) - { - auto const buf{PQencryptPasswordConn(m_conn, password, user, algorithm)}; - std::unique_ptr> ptr{ - buf, [](char const *x) { PQfreemem(const_cast(x)); }}; - return std::string(ptr.get()); - } -#else - { - // No PQencryptPasswordConn. Fall back on the old PQencryptPassword... - // unless the caller selects a different algorithm. - if (algorithm != nullptr and std::strcmp(algorithm, "md5") != 0) - throw feature_not_supported{ - "Could not encrypt password: available libpq version does not support " - "algorithms other than md5."}; -# include "pqxx/internal/ignore-deprecated-pre.hxx" - return pqxx::encrypt_password(user, password); -# include "pqxx/internal/ignore-deprecated-post.hxx" - } -#endif // PQXX_HAVE_PQENCRYPTPASSWORDCONN -} - - -void pqxx::connection::prepare(char const name[], char const definition[]) & -{ - auto const q{std::make_shared( - pqxx::internal::concat("[PREPARE ", name, "]"))}; - - auto const r{ - make_result(PQprepare(m_conn, name, definition, 0, nullptr), q, *q)}; -} - - -void pqxx::connection::prepare(char const definition[]) & -{ - this->prepare("", definition); -} - - -void pqxx::connection::unprepare(std::string_view name) -{ - exec(internal::concat("DEALLOCATE ", quote_name(name))); -} - - -pqxx::result pqxx::connection::exec_prepared( - std::string_view statement, internal::c_params const &args) -{ - auto const q{std::make_shared(statement)}; - auto const pq_result{PQexecPrepared( - m_conn, q->c_str(), - check_cast(std::size(args.values), "exec_prepared"sv), - args.values.data(), args.lengths.data(), - reinterpret_cast(args.formats.data()), - static_cast(format::text))}; - auto const r{make_result(pq_result, q, statement)}; - get_notifs(); - return r; -} - - -void pqxx::connection::close() -{ - try - { - if (m_trans) - PQXX_UNLIKELY - process_notice(internal::concat( - "Closing connection while ", - internal::describe_object("transaction"sv, m_trans->name()), - " is still open.")); - - if (not std::empty(m_receivers)) - { - PQXX_UNLIKELY - process_notice("Closing connection with outstanding receivers."); - m_receivers.clear(); - } - - std::list old_handlers; - m_errorhandlers.swap(old_handlers); - auto const rbegin{std::crbegin(old_handlers)}, - rend{std::crend(old_handlers)}; - for (auto i{rbegin}; i != rend; ++i) - pqxx::internal::gate::errorhandler_connection{**i}.unregister(); - - PQfinish(m_conn); - m_conn = nullptr; - } - catch (std::exception const &) - { - m_conn = nullptr; - throw; - } -} - - -int pqxx::connection::status() const noexcept -{ - return PQstatus(m_conn); -} - - -namespace -{ -/// Return a name for t, if t is non-null and has a name; or empty string. -std::string_view get_name(pqxx::transaction_base const *t) -{ - return (t == nullptr) ? ""sv : t->name(); -} -} // namespace - - -void pqxx::connection::register_transaction(transaction_base *t) -{ - internal::check_unique_register( - m_trans, "transaction", get_name(m_trans), t, "transaction", get_name(t)); - m_trans = t; -} - - -void pqxx::connection::unregister_transaction(transaction_base *t) noexcept -{ - try - { - internal::check_unique_unregister( - m_trans, "transaction", get_name(m_trans), t, "transaction", - get_name(t)); - } - catch (std::exception const &e) - { - process_notice(e.what()); - } - m_trans = nullptr; -} - - -std::pair>, std::size_t> -pqxx::connection::read_copy_line() -{ - char *buf{nullptr}; - - // Allocate once, re-use across invocations. - static auto const q{std::make_shared("[END COPY]")}; - - auto const line_len{PQgetCopyData(m_conn, &buf, false)}; - switch (line_len) - { - case -2: // Error. - throw failure{ - internal::concat("Reading of table data failed: ", err_msg())}; - - case -1: // End of COPY. - make_result(PQgetResult(m_conn), q, *q); - return {}; - - case 0: // "Come back later." - throw internal_error{"table read inexplicably went asynchronous"}; - - default: // Success, got buffer size. - // Line size includes a trailing zero, which we ignore. - auto const text_len{static_cast(line_len) - 1}; - return std::make_pair( - std::unique_ptr>{buf, PQfreemem}, - text_len); - } -} - - -void pqxx::connection::write_copy_line(std::string_view line) -{ - static std::string const err_prefix{"Error writing to table: "}; - auto const size{check_cast( - internal::ssize(line), "Line in stream_to is too long to process."sv)}; - if (PQputCopyData(m_conn, line.data(), size) <= 0) - PQXX_UNLIKELY - throw failure{err_prefix + err_msg()}; - if (PQputCopyData(m_conn, "\n", 1) <= 0) - PQXX_UNLIKELY - throw failure{err_prefix + err_msg()}; -} - - -void pqxx::connection::end_copy_write() -{ - int res{PQputCopyEnd(m_conn, nullptr)}; - switch (res) - { - case -1: - throw failure{internal::concat("Write to table failed: ", err_msg())}; - case 0: throw internal_error{"table write is inexplicably asynchronous"}; - case 1: - // Normal termination. Retrieve result object. - break; - - default: - throw internal_error{ - internal::concat("unexpected result ", res, " from PQputCopyEnd()")}; - } - - static auto const q{std::make_shared("[END COPY]")}; - make_result(PQgetResult(m_conn), q, *q); -} - - -void pqxx::connection::start_exec(char const query[]) -{ - if (PQsendQuery(m_conn, query) == 0) - PQXX_UNLIKELY - throw failure{err_msg()}; -} - - -pqxx::internal::pq::PGresult *pqxx::connection::get_result() -{ - return PQgetResult(m_conn); -} - - -size_t pqxx::connection::esc_to_buf(std::string_view text, char *buf) const -{ - int err{0}; - auto const copied{ - PQescapeStringConn(m_conn, buf, text.data(), std::size(text), &err)}; - if (err) - PQXX_UNLIKELY - throw argument_error{err_msg()}; - return copied; -} - - -std::string pqxx::connection::esc(std::string_view text) const -{ - std::string buf; - buf.resize(2 * std::size(text) + 1); - auto const copied{esc_to_buf(text, buf.data())}; - buf.resize(copied); - return buf; -} - - -std::string PQXX_COLD -pqxx::connection::esc_raw(unsigned char const bin[], std::size_t len) const -{ - return pqxx::internal::esc_bin(binary_cast(bin, len)); -} - - -std::string -pqxx::connection::esc_raw(std::basic_string_view bin) const -{ - return pqxx::internal::esc_bin(bin); -} - - -std::string PQXX_COLD pqxx::connection::unesc_raw(char const text[]) const -{ - if (text[0] == '\\' and text[1] == 'x') - { - // Hex-escaped format. - std::string buf; - buf.resize(pqxx::internal::size_unesc_bin(std::strlen(text))); - pqxx::internal::unesc_bin( - std::string_view{text}, reinterpret_cast(buf.data())); - return buf; - } - else - { - // Legacy escape format. - // TODO: Remove legacy support. - std::size_t len; - auto bytes{const_cast( - reinterpret_cast(text))}; - std::unique_ptr> const - ptr{PQunescapeBytea(bytes, &len), PQfreemem}; - return std::string{ptr.get(), ptr.get() + len}; - } -} - - -std::string PQXX_COLD -pqxx::connection::quote_raw(unsigned char const bin[], std::size_t len) const -{ - return internal::concat("'", esc_raw(binary_cast(bin, len)), "'::bytea"); -} - - -std::string -pqxx::connection::quote_raw(std::basic_string_view bytes) const -{ - return internal::concat("'", esc_raw(bytes), "'::bytea"); -} - - -std::string PQXX_COLD pqxx::connection::quote(binarystring const &b) const -{ - return quote(b.bytes_view()); -} - - -std::string pqxx::connection::quote(std::basic_string_view b) const -{ - return internal::concat("'", esc_raw(b), "'::bytea"); -} - - -std::string pqxx::connection::quote_name(std::string_view identifier) const -{ - std::unique_ptr> buf{ - PQescapeIdentifier(m_conn, identifier.data(), std::size(identifier)), - PQfreemem}; - if (buf.get() == nullptr) - PQXX_UNLIKELY - throw failure{err_msg()}; - return std::string{buf.get()}; -} - - -std::string pqxx::connection::quote_table(std::string_view table_name) const -{ - return this->quote_name(table_name); -} - - -std::string pqxx::connection::quote_table(table_path path) const -{ - return separated_list( - ".", std::begin(path), std::end(path), - [this](auto name) { return this->quote_name(*name); }); -} - - -std::string -pqxx::connection::esc_like(std::string_view text, char escape_char) const -{ - std::string out; - out.reserve(std::size(text)); - internal::for_glyphs( - internal::enc_group(encoding_id()), - [&out, escape_char](char const *gbegin, char const *gend) { - if ((gend - gbegin == 1) and (*gbegin == '_' or *gbegin == '%')) - // We're not expecting a lot of wildcards in a string. Usually. - PQXX_UNLIKELY - out.push_back(escape_char); - - for (; gbegin != gend; ++gbegin) out.push_back(*gbegin); - }, - text.data(), std::size(text)); - return out; -} - - -int pqxx::connection::await_notification() -{ - int notifs = get_notifs(); - if (notifs == 0) - { - PQXX_LIKELY - internal::wait_fd(socket_of(m_conn), true, false, 10, 0); - notifs = get_notifs(); - } - return notifs; -} - - -int pqxx::connection::await_notification( - std::time_t seconds, long microseconds) -{ - int notifs = get_notifs(); - if (notifs == 0) - { - PQXX_LIKELY - internal::wait_fd( - socket_of(m_conn), true, false, - check_cast(seconds, "Seconds out of range."), - check_cast(microseconds, "Microseconds out of range.")); - return get_notifs(); - } - return notifs; -} - - -std::string pqxx::connection::adorn_name(std::string_view n) -{ - auto const id{to_string(++m_unique_id)}; - if (std::empty(n)) - return pqxx::internal::concat("x", id); - else - return pqxx::internal::concat(n, "_", id); -} - - -std::string pqxx::connection::get_client_encoding() const -{ - return internal::name_encoding(encoding_id()); -} - - -void PQXX_COLD pqxx::connection::set_client_encoding(char const encoding[]) & -{ - switch (auto const retval{PQsetClientEncoding(m_conn, encoding)}; retval) - { - case 0: - // OK. - PQXX_LIKELY - break; - case -1: - PQXX_UNLIKELY - if (is_open()) - throw failure{"Setting client encoding failed."}; - else - throw broken_connection{"Lost connection to the database server."}; - default: - PQXX_UNLIKELY - throw internal_error{internal::concat( - "Unexpected result from PQsetClientEncoding: ", retval)}; - } -} - - -int pqxx::connection::encoding_id() const -{ - int const enc{PQclientEncoding(m_conn)}; - if (enc == -1) - { - // PQclientEncoding does not query the database, but it does check for - // broken connections. And unfortunately, we check the encoding right - // *before* checking a query result for failure. So, we need to handle - // connection failure here and it will apply in lots of places. - // TODO: Make pqxx::result::result(...) do all the checking. - PQXX_UNLIKELY - if (is_open()) - throw failure{"Could not obtain client encoding."}; - else - throw broken_connection{"Lost connection to the database server."}; - } - PQXX_LIKELY - return enc; -} - - -pqxx::result pqxx::connection::exec_params( - std::string_view query, internal::c_params const &args) -{ - auto const q{std::make_shared(query)}; - auto const pq_result{PQexecParams( - m_conn, q->c_str(), - check_cast(std::size(args.values), "exec_params"sv), nullptr, - args.values.data(), args.lengths.data(), - reinterpret_cast(args.formats.data()), - static_cast(format::text))}; - auto const r{make_result(pq_result, q)}; - get_notifs(); - return r; -} - - -namespace -{ -/// Get the prevailing default value for a connection parameter. -char const *get_default(PQconninfoOption const &opt) noexcept -{ - if (opt.envvar == nullptr) - { - // There's no environment variable for this setting. The only default is - // the one that was compiled in. - return opt.compiled; - } - // As of C++11, std::getenv() uses thread-local storage, so it should be - // thread-safe. MSVC still warns about it though. -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4996) -#endif - char const *var{std::getenv(opt.envvar)}; -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - if (var == nullptr) - { - // There's an environment variable for this setting, but it's not set. - return opt.compiled; - } - - // The environment variable is the prevailing default. - return var; -} -} // namespace - - -std::string pqxx::connection::connection_string() const -{ - if (m_conn == nullptr) - PQXX_UNLIKELY - throw usage_error{"Can't get connection string: connection is not open."}; - - std::unique_ptr< - PQconninfoOption, std::function> const params{ - PQconninfo(m_conn), PQconninfoFree}; - if (params.get() == nullptr) - PQXX_UNLIKELY - throw std::bad_alloc{}; - - std::string buf; - for (std::size_t i{0}; params.get()[i].keyword != nullptr; ++i) - { - auto const param{params.get()[i]}; - if (param.val != nullptr) - { - auto const default_val{get_default(param)}; - if ( - (default_val == nullptr) or (std::strcmp(param.val, default_val) != 0)) - { - if (not std::empty(buf)) - buf.push_back(' '); - buf += param.keyword; - buf.push_back('='); - buf += param.val; - } - } - } - return buf; -} - - -#if defined(_WIN32) || __has_include() -pqxx::connecting::connecting(zview connection_string) : - m_conn{connection::connect_nonblocking, connection_string} -{} -#endif // defined(_WIN32) || __has_include( - - -#if defined(_WIN32) || __has_include() -void pqxx::connecting::process() & -{ - auto const [reading, writing]{m_conn.poll_connect()}; - m_reading = reading; - m_writing = writing; -} -#endif // defined(_WIN32) || __has_include( - - -#if defined(_WIN32) || __has_include() -pqxx::connection pqxx::connecting::produce() && -{ - if (!done()) - throw usage_error{ - "Tried to produce a nonblocking connection before it was done."}; - m_conn.complete_init(); - return std::move(m_conn); -} -#endif // defined(_WIN32) || __has_include( diff --git a/ext/libpqxx-7.7.3/src/cursor.cxx b/ext/libpqxx-7.7.3/src/cursor.cxx deleted file mode 100644 index 28e8ba42f..000000000 --- a/ext/libpqxx-7.7.3/src/cursor.cxx +++ /dev/null @@ -1,339 +0,0 @@ -/** Implementation of libpqxx STL-style cursor classes. - * - * These classes wrap SQL cursors in STL-like interfaces. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/cursor.hxx" -#include "pqxx/internal/gates/icursor_iterator-icursorstream.hxx" -#include "pqxx/internal/gates/icursorstream-icursor_iterator.hxx" -#include "pqxx/result.hxx" -#include "pqxx/strconv.hxx" -#include "pqxx/transaction.hxx" - -#include "pqxx/internal/header-post.hxx" - - -pqxx::cursor_base::difference_type pqxx::cursor_base::all() noexcept -{ - // Implemented out-of-line so we don't fall afoul of Visual Studio defining - // min() and max() macros, which turn this expression into malformed code: - return std::numeric_limits::max() - 1; -} - - -pqxx::cursor_base::difference_type pqxx::cursor_base::backward_all() noexcept -{ - // Implemented out-of-line so we don't fall afoul of Visual Studio defining - // min() and max() macros, which turn this expression into malformed code: - return std::numeric_limits::min() + 1; -} - - -pqxx::cursor_base::cursor_base( - connection &context, std::string_view Name, bool embellish_name) : - m_name{embellish_name ? context.adorn_name(Name) : Name} -{} - - -pqxx::result::size_type -pqxx::internal::obtain_stateless_cursor_size(sql_cursor &cur) -{ - if (cur.endpos() == -1) - cur.move(cursor_base::all()); - return result::size_type(cur.endpos() - 1); -} - - -pqxx::result pqxx::internal::stateless_cursor_retrieve( - sql_cursor &cur, result::difference_type size, - result::difference_type begin_pos, result::difference_type end_pos) -{ - if (begin_pos < 0 or begin_pos > size) - throw range_error{"Starting position out of range"}; - - if (end_pos < -1) - end_pos = -1; - else if (end_pos > size) - end_pos = size; - - if (begin_pos == end_pos) - return cur.empty_result(); - - int const direction{((begin_pos < end_pos) ? 1 : -1)}; - cur.move((begin_pos - direction) - (cur.pos() - 1)); - return cur.fetch(end_pos - begin_pos); -} - - -pqxx::icursorstream::icursorstream( - transaction_base &context, std::string_view query, std::string_view basename, - difference_type sstride) : - m_cur{ - context, - query, - basename, - cursor_base::forward_only, - cursor_base::read_only, - cursor_base::owned, - false}, - m_stride{sstride}, - m_realpos{0}, - m_reqpos{0}, - m_iterators{nullptr}, - m_done{false} -{ - set_stride(sstride); -} - - -pqxx::icursorstream::icursorstream( - transaction_base &context, field const &cname, difference_type sstride, - cursor_base::ownership_policy op) : - m_cur{context, cname.c_str(), op}, - m_stride{sstride}, - m_realpos{0}, - m_reqpos{0}, - m_iterators{nullptr}, - m_done{false} -{ - set_stride(sstride); -} - - -void pqxx::icursorstream::set_stride(difference_type stride) & -{ - if (stride < 1) - throw argument_error{ - internal::concat("Attempt to set cursor stride to ", stride)}; - m_stride = stride; -} - - -pqxx::result pqxx::icursorstream::fetchblock() -{ - result const r{m_cur.fetch(m_stride)}; - m_realpos += std::size(r); - if (std::empty(r)) - m_done = true; - return r; -} - - -pqxx::icursorstream &pqxx::icursorstream::ignore(std::streamsize n) & -{ - auto offset{m_cur.move(difference_type(n))}; - m_realpos += offset; - if (offset < n) - m_done = true; - return *this; -} - - -pqxx::icursorstream::size_type pqxx::icursorstream::forward(size_type n) -{ - m_reqpos += difference_type(n) * m_stride; - return icursorstream::size_type(m_reqpos); -} - - -void pqxx::icursorstream::insert_iterator(icursor_iterator *i) noexcept -{ - pqxx::internal::gate::icursor_iterator_icursorstream{*i}.set_next( - m_iterators); - if (m_iterators != nullptr) - pqxx::internal::gate::icursor_iterator_icursorstream{*m_iterators} - .set_prev(i); - m_iterators = i; -} - - -void pqxx::icursorstream::remove_iterator(icursor_iterator *i) const noexcept -{ - pqxx::internal::gate::icursor_iterator_icursorstream igate{*i}; - if (i == m_iterators) - { - m_iterators = igate.get_next(); - if (m_iterators != nullptr) - pqxx::internal::gate::icursor_iterator_icursorstream{*m_iterators} - .set_prev(nullptr); - } - else - { - auto prev{igate.get_prev()}, next{igate.get_next()}; - pqxx::internal::gate::icursor_iterator_icursorstream{*prev}.set_next(next); - if (next != nullptr) - pqxx::internal::gate::icursor_iterator_icursorstream{*next}.set_prev( - prev); - } - igate.set_prev(nullptr); - igate.set_next(nullptr); -} - - -void pqxx::icursorstream::service_iterators(difference_type topos) -{ - if (topos < m_realpos) - return; - - using todolist = std::multimap; - todolist todo; - for (icursor_iterator *i{m_iterators}, *next; i != nullptr; i = next) - { - pqxx::internal::gate::icursor_iterator_icursorstream gate{*i}; - auto const ipos{gate.pos()}; - if (ipos >= m_realpos and ipos <= topos) - todo.insert(todolist::value_type(ipos, i)); - next = gate.get_next(); - } - auto const todo_end = std::end(todo); - for (auto i{std::begin(todo)}; i != todo_end;) - { - auto const readpos{i->first}; - if (readpos > m_realpos) - ignore(readpos - m_realpos); - result const r{fetchblock()}; - for (; i != todo_end and i->first == readpos; ++i) - pqxx::internal::gate::icursor_iterator_icursorstream{*i->second}.fill(r); - } -} - - -pqxx::icursor_iterator::icursor_iterator() noexcept : m_pos{0} {} - - -pqxx::icursor_iterator::icursor_iterator(istream_type &s) noexcept : - m_stream{&s}, - m_pos{difference_type( - pqxx::internal::gate::icursorstream_icursor_iterator(s).forward(0))} -{ - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} - .insert_iterator(this); -} - - -pqxx::icursor_iterator::icursor_iterator(icursor_iterator const &rhs) noexcept - : - m_stream{rhs.m_stream}, m_here{rhs.m_here}, m_pos{rhs.m_pos} -{ - if (m_stream != nullptr) - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} - .insert_iterator(this); -} - - -pqxx::icursor_iterator::~icursor_iterator() noexcept -{ - if (m_stream != nullptr) - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} - .remove_iterator(this); -} - - -pqxx::icursor_iterator pqxx::icursor_iterator::operator++(int) -{ - icursor_iterator old{*this}; - m_pos = difference_type( - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream}.forward()); - m_here.clear(); - return old; -} - - -pqxx::icursor_iterator &pqxx::icursor_iterator::operator++() -{ - m_pos = difference_type( - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream}.forward()); - m_here.clear(); - return *this; -} - - -pqxx::icursor_iterator &pqxx::icursor_iterator::operator+=(difference_type n) -{ - if (n <= 0) - { - PQXX_UNLIKELY - if (n == 0) - return *this; - throw argument_error{"Advancing icursor_iterator by negative offset."}; - } - PQXX_LIKELY - m_pos = difference_type( - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream}.forward( - icursorstream::size_type(n))); - m_here.clear(); - return *this; -} - - -pqxx::icursor_iterator & -pqxx::icursor_iterator::operator=(icursor_iterator const &rhs) noexcept -{ - if (rhs.m_stream == m_stream) - { - PQXX_UNLIKELY - m_here = rhs.m_here; - m_pos = rhs.m_pos; - } - else - { - PQXX_LIKELY - if (m_stream != nullptr) - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} - .remove_iterator(this); - m_here = rhs.m_here; - m_pos = rhs.m_pos; - m_stream = rhs.m_stream; - if (m_stream != nullptr) - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} - .insert_iterator(this); - } - return *this; -} - - -bool pqxx::icursor_iterator::operator==(icursor_iterator const &rhs) const -{ - if (m_stream == rhs.m_stream) - return pos() == rhs.pos(); - if (m_stream != nullptr and rhs.m_stream != nullptr) - return false; - refresh(); - rhs.refresh(); - return std::empty(m_here) and std::empty(rhs.m_here); -} - - -bool pqxx::icursor_iterator::operator<(icursor_iterator const &rhs) const -{ - if (m_stream == rhs.m_stream) - return pos() < rhs.pos(); - refresh(); - rhs.refresh(); - return not std::empty(m_here); -} - - -void pqxx::icursor_iterator::refresh() const -{ - if (m_stream != nullptr) - pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} - .service_iterators(pos()); -} - - -void pqxx::icursor_iterator::fill(result const &r) -{ - m_here = r; -} diff --git a/ext/libpqxx-7.7.3/src/encodings.cxx b/ext/libpqxx-7.7.3/src/encodings.cxx deleted file mode 100644 index 99f038724..000000000 --- a/ext/libpqxx-7.7.3/src/encodings.cxx +++ /dev/null @@ -1,839 +0,0 @@ -/** Implementation of string encodings support - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include -#include - -extern "C" -{ -#include -} - - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/encodings.hxx" -#include "pqxx/strconv.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace pqxx -{ -PQXX_DECLARE_ENUM_CONVERSION(pqxx::internal::encoding_group); -} - - -// Internal helper functions -namespace -{ -/// Extract byte from buffer, return as unsigned char. -constexpr PQXX_PURE unsigned char -get_byte(char const buffer[], std::size_t offset) noexcept -{ - return static_cast(buffer[offset]); -} - - -[[noreturn]] void throw_for_encoding_error( - char const *encoding_name, char const buffer[], std::size_t start, - std::size_t count) -{ - std::stringstream s; - s << "Invalid byte sequence for encoding " << encoding_name << " at byte " - << start << ": " << std::hex << std::setw(2) << std::setfill('0'); - for (std::size_t i{0}; i < count; ++i) - { - s << "0x" << static_cast(get_byte(buffer, start + i)); - if (i + 1 < count) - s << " "; - } - throw pqxx::argument_error{s.str()}; -} - - -/// Does value lie between bottom and top, inclusive? -constexpr PQXX_PURE bool -between_inc(unsigned char value, unsigned bottom, unsigned top) -{ - return value >= bottom and value <= top; -} - - -/* -EUC-JP and EUC-JIS-2004 represent slightly different code points but iterate -the same: - * https://en.wikipedia.org/wiki/Extended_Unix_Code#EUC-JP - * http://x0213.org/codetable/index.en.html -*/ -PQXX_PURE std::size_t next_seq_for_euc_jplike( - char const buffer[], std::size_t buffer_len, std::size_t start, - char const encoding_name[]) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error(encoding_name, buffer, start, 1); - - auto const byte2{get_byte(buffer, start + 1)}; - if (byte1 == 0x8e) - { - if (not between_inc(byte2, 0xa1, 0xfe)) - PQXX_UNLIKELY - throw_for_encoding_error(encoding_name, buffer, start, 2); - - return start + 2; - } - - if (between_inc(byte1, 0xa1, 0xfe)) - { - if (not between_inc(byte2, 0xa1, 0xfe)) - PQXX_UNLIKELY - throw_for_encoding_error(encoding_name, buffer, start, 2); - - return start + 2; - } - - if (byte1 == 0x8f and start + 3 <= buffer_len) - { - auto const byte3{get_byte(buffer, start + 2)}; - if ( - not between_inc(byte2, 0xa1, 0xfe) or not between_inc(byte3, 0xa1, 0xfe)) - PQXX_UNLIKELY - throw_for_encoding_error(encoding_name, buffer, start, 3); - - return start + 3; - } - - throw_for_encoding_error(encoding_name, buffer, start, 1); -} - -/* -As far as I can tell, for the purposes of iterating the only difference between -SJIS and SJIS-2004 is increased range in the first byte of two-byte sequences -(0xEF increased to 0xFC). Officially, that is; apparently the version of SJIS -used by Postgres has the same range as SJIS-2004. They both have increased -range over the documented versions, not having the even/odd restriction for the -first byte in 2-byte sequences. -*/ -// https://en.wikipedia.org/wiki/Shift_JIS#Shift_JIS_byte_map -// http://x0213.org/codetable/index.en.html -PQXX_PURE std::size_t next_seq_for_sjislike( - char const buffer[], std::size_t buffer_len, std::size_t start, - char const *encoding_name) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80 or between_inc(byte1, 0xa1, 0xdf)) - return start + 1; - - if ( - not between_inc(byte1, 0x81, 0x9f) and not between_inc(byte1, 0xe0, 0xfc)) - PQXX_UNLIKELY - throw_for_encoding_error(encoding_name, buffer, start, 1); - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error(encoding_name, buffer, start, buffer_len - start); - - auto const byte2{get_byte(buffer, start + 1)}; - if (byte2 == 0x7f) - PQXX_UNLIKELY - throw_for_encoding_error(encoding_name, buffer, start, 2); - - if (between_inc(byte2, 0x40, 0x9e) or between_inc(byte2, 0x9f, 0xfc)) - return start + 2; - - PQXX_UNLIKELY - throw_for_encoding_error(encoding_name, buffer, start, 2); -} -} // namespace - - -// Implement template specializations first. -namespace pqxx::internal -{ -template struct glyph_scanner -{ - PQXX_PURE static std::size_t - call(char const buffer[], std::size_t buffer_len, std::size_t start); -}; - -template<> struct glyph_scanner -{ - static PQXX_PURE constexpr std::size_t - call(char const /* buffer */[], std::size_t buffer_len, std::size_t start) - { - if (start >= buffer_len) - return std::string::npos; - else - return start + 1; - } -}; - -// https://en.wikipedia.org/wiki/Big5#Organization -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (not between_inc(byte1, 0x81, 0xfe) or (start + 2 > buffer_len)) - PQXX_UNLIKELY - throw_for_encoding_error("BIG5", buffer, start, 1); - - auto const byte2{get_byte(buffer, start + 1)}; - if ( - not between_inc(byte2, 0x40, 0x7e) and not between_inc(byte2, 0xa1, 0xfe)) - PQXX_UNLIKELY - throw_for_encoding_error("BIG5", buffer, start, 2); - - return start + 2; -} - -/* -The PostgreSQL documentation claims that the EUC_* encodings are 1-3 bytes -each, but other documents explain that the EUC sets can contain 1-(2,3,4) bytes -depending on the specific extension: - EUC_CN : 1-2 - EUC_JP : 1-3 - EUC_JIS_2004: 1-2 - EUC_KR : 1-2 - EUC_TW : 1-4 -*/ - -// https://en.wikipedia.org/wiki/GB_2312#EUC-CN -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (not between_inc(byte1, 0xa1, 0xf7) or start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("EUC_CN", buffer, start, 1); - - auto const byte2{get_byte(buffer, start + 1)}; - if (not between_inc(byte2, 0xa1, 0xfe)) - PQXX_UNLIKELY - throw_for_encoding_error("EUC_CN", buffer, start, 2); - - return start + 2; -} - - -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - return next_seq_for_euc_jplike(buffer, buffer_len, start, "EUC_JP"); -} - - -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - return next_seq_for_euc_jplike(buffer, buffer_len, start, "EUC_JIS_2004"); -} - - -// https://en.wikipedia.org/wiki/Extended_Unix_Code#EUC-KR -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (not between_inc(byte1, 0xa1, 0xfe) or start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("EUC_KR", buffer, start, 1); - - auto const byte2{get_byte(buffer, start + 1)}; - if (not between_inc(byte2, 0xa1, 0xfe)) - PQXX_UNLIKELY - throw_for_encoding_error("EUC_KR", buffer, start, 1); - - return start + 2; -} - -// https://en.wikipedia.org/wiki/Extended_Unix_Code#EUC-TW -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - PQXX_UNLIKELY - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("EUC_KR", buffer, start, 1); - - auto const byte2{get_byte(buffer, start + 1)}; - if (between_inc(byte1, 0xa1, 0xfe)) - { - if (not between_inc(byte2, 0xa1, 0xfe)) - PQXX_UNLIKELY - throw_for_encoding_error("EUC_KR", buffer, start, 2); - - return start + 2; - } - - if (byte1 != 0x8e or start + 4 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("EUC_KR", buffer, start, 1); - - if ( - between_inc(byte2, 0xa1, 0xb0) and - between_inc(get_byte(buffer, start + 2), 0xa1, 0xfe) and - between_inc(get_byte(buffer, start + 3), 0xa1, 0xfe)) - return start + 4; - - PQXX_UNLIKELY - throw_for_encoding_error("EUC_KR", buffer, start, 4); -} - -// https://en.wikipedia.org/wiki/GB_18030#Mapping -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - if (byte1 == 0x80) - throw_for_encoding_error("GB18030", buffer, start, buffer_len - start); - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("GB18030", buffer, start, buffer_len - start); - - auto const byte2{get_byte(buffer, start + 1)}; - if (between_inc(byte2, 0x40, 0xfe)) - { - if (byte2 == 0x7f) - PQXX_UNLIKELY - throw_for_encoding_error("GB18030", buffer, start, 2); - - return start + 2; - } - - if (start + 4 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("GB18030", buffer, start, buffer_len - start); - - if ( - between_inc(byte2, 0x30, 0x39) and - between_inc(get_byte(buffer, start + 2), 0x81, 0xfe) and - between_inc(get_byte(buffer, start + 3), 0x30, 0x39)) - return start + 4; - - PQXX_UNLIKELY - throw_for_encoding_error("GB18030", buffer, start, 4); -} - -// https://en.wikipedia.org/wiki/GBK_(character_encoding)#Encoding -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("GBK", buffer, start, 1); - - auto const byte2{get_byte(buffer, start + 1)}; - if ( - (between_inc(byte1, 0xa1, 0xa9) and between_inc(byte2, 0xa1, 0xfe)) or - (between_inc(byte1, 0xb0, 0xf7) and between_inc(byte2, 0xa1, 0xfe)) or - (between_inc(byte1, 0x81, 0xa0) and between_inc(byte2, 0x40, 0xfe) and - byte2 != 0x7f) or - (between_inc(byte1, 0xaa, 0xfe) and between_inc(byte2, 0x40, 0xa0) and - byte2 != 0x7f) or - (between_inc(byte1, 0xa8, 0xa9) and between_inc(byte2, 0x40, 0xa0) and - byte2 != 0x7f) or - (between_inc(byte1, 0xaa, 0xaf) and between_inc(byte2, 0xa1, 0xfe)) or - (between_inc(byte1, 0xf8, 0xfe) and between_inc(byte2, 0xa1, 0xfe)) or - (between_inc(byte1, 0xa1, 0xa7) and between_inc(byte2, 0x40, 0xa0) and - byte2 != 0x7f)) - return start + 2; - - PQXX_UNLIKELY - throw_for_encoding_error("GBK", buffer, start, 2); -} - -/* -The PostgreSQL documentation claims that the JOHAB encoding is 1-3 bytes, but -"CJKV Information Processing" describes it (actually just the Hangul portion) -as "three five-bit segments" that reside inside 16 bits (2 bytes). - -CJKV Information Processing by Ken Lunde, pg. 269: - - https://bit.ly/2BEOu5V -*/ -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("JOHAB", buffer, start, 1); - - auto const byte2{get_byte(buffer, start)}; - if ( - (between_inc(byte1, 0x84, 0xd3) and - (between_inc(byte2, 0x41, 0x7e) or between_inc(byte2, 0x81, 0xfe))) or - ((between_inc(byte1, 0xd8, 0xde) or between_inc(byte1, 0xe0, 0xf9)) and - (between_inc(byte2, 0x31, 0x7e) or between_inc(byte2, 0x91, 0xfe)))) - return start + 2; - - PQXX_UNLIKELY - throw_for_encoding_error("JOHAB", buffer, start, 2); -} - -/* -PostgreSQL's MULE_INTERNAL is the emacs rather than Xemacs implementation; -see the server/mb/pg_wchar.h PostgreSQL header file. -This is implemented according to the description in said header file, but I was -unable to get it to successfully iterate a MULE-encoded test CSV generated -using PostgreSQL 9.2.23. Use this at your own risk. -*/ -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("MULE_INTERNAL", buffer, start, 1); - - auto const byte2{get_byte(buffer, start + 1)}; - if (between_inc(byte1, 0x81, 0x8d) and byte2 >= 0xa0) - return start + 2; - - if (start + 3 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("MULE_INTERNAL", buffer, start, 2); - - if ( - ((byte1 == 0x9a and between_inc(byte2, 0xa0, 0xdf)) or - (byte1 == 0x9b and between_inc(byte2, 0xe0, 0xef)) or - (between_inc(byte1, 0x90, 0x99) and byte2 >= 0xa0)) and - (byte2 >= 0xa0)) - return start + 3; - - if (start + 4 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("MULE_INTERNAL", buffer, start, 3); - - if ( - ((byte1 == 0x9c and between_inc(byte2, 0xf0, 0xf4)) or - (byte1 == 0x9d and between_inc(byte2, 0xf5, 0xfe))) and - get_byte(buffer, start + 2) >= 0xa0 and - get_byte(buffer, start + 4) >= 0xa0) - return start + 4; - - PQXX_UNLIKELY - throw_for_encoding_error("MULE_INTERNAL", buffer, start, 4); -} - -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - return next_seq_for_sjislike(buffer, buffer_len, start, "SJIS"); -} - -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - return next_seq_for_sjislike(buffer, buffer_len, start, "SHIFT_JIS_2004"); -} - -// https://en.wikipedia.org/wiki/Unified_Hangul_Code -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("UHC", buffer, start, buffer_len - start); - - auto const byte2{get_byte(buffer, start + 1)}; - if (between_inc(byte1, 0x80, 0xc6)) - { - if ( - between_inc(byte2, 0x41, 0x5a) or between_inc(byte2, 0x61, 0x7a) or - between_inc(byte2, 0x80, 0xfe)) - return start + 2; - - PQXX_UNLIKELY - throw_for_encoding_error("UHC", buffer, start, 2); - } - - if (between_inc(byte1, 0xa1, 0xfe)) - { - if (not between_inc(byte2, 0xa1, 0xfe)) - PQXX_UNLIKELY - throw_for_encoding_error("UHC", buffer, start, 2); - - return start + 2; - } - - throw_for_encoding_error("UHC", buffer, start, 1); -} - -// https://en.wikipedia.org/wiki/UTF-8#Description -template<> -PQXX_PURE std::size_t glyph_scanner::call( - char const buffer[], std::size_t buffer_len, std::size_t start) -{ - if (start >= buffer_len) - return std::string::npos; - - auto const byte1{get_byte(buffer, start)}; - if (byte1 < 0x80) - return start + 1; - - if (start + 2 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("UTF8", buffer, start, buffer_len - start); - - auto const byte2{get_byte(buffer, start + 1)}; - if (between_inc(byte1, 0xc0, 0xdf)) - { - if (not between_inc(byte2, 0x80, 0xbf)) - PQXX_UNLIKELY - throw_for_encoding_error("UTF8", buffer, start, 2); - - return start + 2; - } - - if (start + 3 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("UTF8", buffer, start, buffer_len - start); - - auto const byte3{get_byte(buffer, start + 2)}; - if (between_inc(byte1, 0xe0, 0xef)) - { - if (between_inc(byte2, 0x80, 0xbf) and between_inc(byte3, 0x80, 0xbf)) - return start + 3; - - PQXX_UNLIKELY - throw_for_encoding_error("UTF8", buffer, start, 3); - } - - if (start + 4 > buffer_len) - PQXX_UNLIKELY - throw_for_encoding_error("UTF8", buffer, start, buffer_len - start); - - if (between_inc(byte1, 0xf0, 0xf7)) - { - if ( - between_inc(byte2, 0x80, 0xbf) and between_inc(byte3, 0x80, 0xbf) and - between_inc(get_byte(buffer, start + 3), 0x80, 0xbf)) - return start + 4; - - PQXX_UNLIKELY - throw_for_encoding_error("UTF8", buffer, start, 4); - } - - PQXX_UNLIKELY - throw_for_encoding_error("UTF8", buffer, start, 1); -} - - -PQXX_PURE char const *name_encoding(int encoding_id) -{ - return pg_encoding_to_char(encoding_id); -} - - -encoding_group enc_group(int libpq_enc_id) -{ - return enc_group(name_encoding(libpq_enc_id)); -} - - -encoding_group enc_group(std::string_view encoding_name) -{ - struct mapping - { - std::string_view const name; - encoding_group const group; - constexpr mapping(std::string_view n, encoding_group g) : name{n}, group{g} - {} - constexpr bool operator<(mapping const &rhs) const - { - return name < rhs.name; - } - }; - - // C++20: Once compilers are ready, go full constexpr, leave to the compiler. - auto const sz{std::size(encoding_name)}; - if (sz > 0u) - switch (encoding_name[0]) - { - case 'B': - if (encoding_name == "BIG5"sv) - return encoding_group::BIG5; - PQXX_UNLIKELY - break; - case 'E': - // C++20: Use string_view::starts_with(). - if ((sz >= 6u) and (encoding_name.substr(0, 4) == "EUC_"sv)) - { - auto const subtype{encoding_name.substr(4)}; - static constexpr std::array subtypes{ - mapping{"CN"sv, encoding_group::EUC_CN}, - mapping{"JIS_2004"sv, encoding_group::EUC_JIS_2004}, - mapping{"JP"sv, encoding_group::EUC_JP}, - mapping{"KR"sv, encoding_group::EUC_KR}, - mapping{"TW"sv, encoding_group::EUC_TW}, - }; - for (auto const &m : subtypes) - if (m.name == subtype) - return m.group; - } - PQXX_UNLIKELY - break; - case 'G': - if (encoding_name == "GB18030"sv) - return encoding_group::GB18030; - else if (encoding_name == "GBK"sv) - return encoding_group::GBK; - PQXX_UNLIKELY - break; - case 'I': - // We know iso-8859-X, where 5 <= X < 9. They're all monobyte encodings. - if ((sz == 10) and (encoding_name.substr(0, 9) == "ISO_8859_"sv)) - { - char const subtype{encoding_name[9]}; - if (('5' <= subtype) and (subtype < '9')) - return encoding_group::MONOBYTE; - } - PQXX_UNLIKELY - break; - case 'J': - if (encoding_name == "JOHAB"sv) - return encoding_group::JOHAB; - PQXX_UNLIKELY - break; - case 'K': - if ((encoding_name == "KOI8R"sv) or (encoding_name == "KOI8U"sv)) - return encoding_group::MONOBYTE; - PQXX_UNLIKELY - break; - case 'L': - // We know LATIN1 through LATIN10. - if (encoding_name.substr(0, 5) == "LATIN"sv) - { - auto const subtype{encoding_name.substr(5)}; - if (subtype.size() == 1) - { - char const n{subtype[0]}; - if (('1' <= n) and (n <= '9')) - return encoding_group::MONOBYTE; - } - else if (subtype == "10"sv) - { - return encoding_group::MONOBYTE; - } - } - PQXX_UNLIKELY - break; - case 'M': - if (encoding_name == "MULE_INTERNAL"sv) - return encoding_group::MULE_INTERNAL; - PQXX_UNLIKELY - break; - case 'S': - if (encoding_name == "SHIFT_JIS_2004"sv) - return encoding_group::SHIFT_JIS_2004; - else if (encoding_name == "SJIS"sv) - return encoding_group::SJIS; - else if (encoding_name == "SQL_ASCII"sv) - return encoding_group::MONOBYTE; - PQXX_UNLIKELY - break; - case 'U': - if (encoding_name == "UHC"sv) - return encoding_group::UHC; - else if (encoding_name == "UTF8"sv) - return encoding_group::UTF8; - PQXX_UNLIKELY - break; - case 'W': - if (encoding_name.substr(0, 3) == "WIN"sv) - { - auto const subtype{encoding_name.substr(3)}; - static constexpr std::array subtypes{ - "866"sv, "874"sv, "1250"sv, "1251"sv, "1252"sv, "1253"sv, - "1254"sv, "1255"sv, "1256"sv, "1257"sv, "1258"sv, - }; - for (auto const n : subtypes) - if (n == subtype) - return encoding_group::MONOBYTE; - } - PQXX_UNLIKELY - break; - default: PQXX_UNLIKELY break; - } - PQXX_UNLIKELY - throw std::invalid_argument{ - internal::concat("Unrecognized encoding: '", encoding_name, "'.")}; -} - - -/// Look up instantiation @c T::call at runtime. -/** Here, "T" is a struct template with a static member function "call", whose - * type is "F". - * - * The return value is a pointer to the "call" member function for the - * instantiation of T for encoding group enc. - */ -template class T, typename F> -constexpr inline F *for_encoding(encoding_group enc) -{ -#define CASE_GROUP(ENC) \ - case encoding_group::ENC: return T::call - - switch (enc) - { - PQXX_LIKELY CASE_GROUP(MONOBYTE); - CASE_GROUP(BIG5); - CASE_GROUP(EUC_CN); - CASE_GROUP(EUC_JP); - CASE_GROUP(EUC_JIS_2004); - CASE_GROUP(EUC_KR); - CASE_GROUP(EUC_TW); - CASE_GROUP(GB18030); - CASE_GROUP(GBK); - CASE_GROUP(JOHAB); - CASE_GROUP(MULE_INTERNAL); - CASE_GROUP(SJIS); - CASE_GROUP(SHIFT_JIS_2004); - CASE_GROUP(UHC); - PQXX_LIKELY CASE_GROUP(UTF8); - } - PQXX_UNLIKELY - throw pqxx::usage_error{ - internal::concat("Unsupported encoding group code ", enc, ".")}; - -#undef CASE_GROUP -} - - -PQXX_PURE glyph_scanner_func *get_glyph_scanner(encoding_group enc) -{ - return for_encoding(enc); -} - - -template struct char_finder -{ - constexpr static PQXX_PURE std::size_t - call(std::string_view haystack, char needle, std::size_t start) - { - auto const buffer{std::data(haystack)}; - auto const size{std::size(haystack)}; - for (auto here{start}; here + 1 <= size; - here = glyph_scanner::call(buffer, size, here)) - { - if (haystack[here] == needle) - return here; - } - return std::string::npos; - } -}; - - -template struct string_finder -{ - PQXX_PURE constexpr static PQXX_PURE std::size_t - call(std::string_view haystack, std::string_view needle, std::size_t start) - { - auto const buffer{std::data(haystack)}; - auto const size{std::size(haystack)}; - auto const needle_size{std::size(needle)}; - for (auto here{start}; here + needle_size <= size; - here = glyph_scanner::call(buffer, size, here)) - { - if (std::memcmp(buffer + here, std::data(needle), needle_size) == 0) - return here; - } - return std::string::npos; - } -}; - -#undef DISPATCH_ENCODING_OPERATION -} // namespace pqxx::internal diff --git a/ext/libpqxx-7.7.3/src/errorhandler.cxx b/ext/libpqxx-7.7.3/src/errorhandler.cxx deleted file mode 100644 index de120ff3d..000000000 --- a/ext/libpqxx-7.7.3/src/errorhandler.cxx +++ /dev/null @@ -1,43 +0,0 @@ -/** Implementation of pqxx::errorhandler and helpers. - * - * pqxx::errorhandler allows programs to receive errors and warnings. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/connection.hxx" -#include "pqxx/errorhandler.hxx" -#include "pqxx/internal/gates/connection-errorhandler.hxx" - -#include "pqxx/internal/header-post.hxx" - - -pqxx::errorhandler::errorhandler(connection &conn) : m_home{&conn} -{ - pqxx::internal::gate::connection_errorhandler{*m_home}.register_errorhandler( - this); -} - - -pqxx::errorhandler::~errorhandler() -{ - unregister(); -} - - -void pqxx::errorhandler::unregister() noexcept -{ - if (m_home != nullptr) - { - pqxx::internal::gate::connection_errorhandler connection_gate{*m_home}; - m_home = nullptr; - connection_gate.unregister_errorhandler(this); - } -} diff --git a/ext/libpqxx-7.7.3/src/except.cxx b/ext/libpqxx-7.7.3/src/except.cxx deleted file mode 100644 index 4974e8ac0..000000000 --- a/ext/libpqxx-7.7.3/src/except.cxx +++ /dev/null @@ -1,126 +0,0 @@ -/** Implementation of libpqxx exception classes. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" - -#include "pqxx/internal/header-post.hxx" - -pqxx::failure::failure(std::string const &whatarg) : - std::runtime_error{whatarg} -{} - - -pqxx::broken_connection::broken_connection() : - failure{"Connection to database failed."} -{} - - -pqxx::broken_connection::broken_connection(std::string const &whatarg) : - failure{whatarg} -{} - - -pqxx::variable_set_to_null::variable_set_to_null() : - variable_set_to_null{ - "Attempt to set a variable to null. This is not allowed."} -{} - - -pqxx::variable_set_to_null::variable_set_to_null(std::string const &whatarg) : - failure{whatarg} -{} - - -pqxx::sql_error::sql_error( - std::string const &whatarg, std::string const &Q, char const sqlstate[]) : - failure{whatarg}, m_query{Q}, m_sqlstate{sqlstate ? sqlstate : ""} -{} - - -pqxx::sql_error::~sql_error() noexcept = default; - - -PQXX_PURE std::string const &pqxx::sql_error::query() const noexcept -{ - return m_query; -} - - -PQXX_PURE std::string const &pqxx::sql_error::sqlstate() const noexcept -{ - return m_sqlstate; -} - - -pqxx::in_doubt_error::in_doubt_error(std::string const &whatarg) : - failure{whatarg} -{} - - -pqxx::transaction_rollback::transaction_rollback( - std::string const &whatarg, std::string const &q, char const sqlstate[]) : - sql_error{whatarg, q, sqlstate} -{} - - -pqxx::serialization_failure::serialization_failure( - std::string const &whatarg, std::string const &q, char const sqlstate[]) : - transaction_rollback{whatarg, q, sqlstate} -{} - - -pqxx::statement_completion_unknown::statement_completion_unknown( - std::string const &whatarg, std::string const &q, char const sqlstate[]) : - transaction_rollback{whatarg, q, sqlstate} -{} - - -pqxx::deadlock_detected::deadlock_detected( - std::string const &whatarg, std::string const &q, char const sqlstate[]) : - transaction_rollback{whatarg, q, sqlstate} -{} - - -pqxx::internal_error::internal_error(std::string const &whatarg) : - std::logic_error{internal::concat("libpqxx internal error: ", whatarg)} -{} - - -pqxx::usage_error::usage_error(std::string const &whatarg) : - std::logic_error{whatarg} -{} - - -pqxx::argument_error::argument_error(std::string const &whatarg) : - invalid_argument{whatarg} -{} - - -pqxx::conversion_error::conversion_error(std::string const &whatarg) : - domain_error{whatarg} -{} - - -pqxx::conversion_overrun::conversion_overrun(std::string const &whatarg) : - conversion_error{whatarg} -{} - - -pqxx::range_error::range_error(std::string const &whatarg) : - out_of_range{whatarg} -{} - - -pqxx::blob_already_exists::blob_already_exists(std::string const &whatarg) : - failure{whatarg} -{} diff --git a/ext/libpqxx-7.7.3/src/field.cxx b/ext/libpqxx-7.7.3/src/field.cxx deleted file mode 100644 index f5026ced2..000000000 --- a/ext/libpqxx-7.7.3/src/field.cxx +++ /dev/null @@ -1,80 +0,0 @@ -/** Implementation of the pqxx::field class. - * - * pqxx::field refers to a field in a query result. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/field.hxx" -#include "pqxx/internal/libpq-forward.hxx" -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" - -#include "pqxx/internal/header-post.hxx" - - -pqxx::field::field(pqxx::row const &r, pqxx::row::size_type c) noexcept : - m_col{c}, m_home{r.m_result}, m_row{r.m_index} -{} - - -bool PQXX_COLD pqxx::field::operator==(field const &rhs) const -{ - if (is_null() and rhs.is_null()) - return true; - if (is_null() != rhs.is_null()) - return false; - auto const s{size()}; - return (s == std::size(rhs)) and (std::memcmp(c_str(), rhs.c_str(), s) == 0); -} - - -char const *pqxx::field::name() const & -{ - return home().column_name(col()); -} - - -pqxx::oid pqxx::field::type() const -{ - return home().column_type(col()); -} - - -pqxx::oid pqxx::field::table() const -{ - return home().column_table(col()); -} - - -pqxx::row::size_type pqxx::field::table_column() const -{ - return home().table_column(col()); -} - - -char const *pqxx::field::c_str() const & -{ - return home().get_value(idx(), col()); -} - - -bool pqxx::field::is_null() const noexcept -{ - return home().get_is_null(idx(), col()); -} - - -pqxx::field::size_type pqxx::field::size() const noexcept -{ - return home().get_length(idx(), col()); -} diff --git a/ext/libpqxx-7.7.3/src/largeobject.cxx b/ext/libpqxx-7.7.3/src/largeobject.cxx deleted file mode 100644 index c57de3c73..000000000 --- a/ext/libpqxx-7.7.3/src/largeobject.cxx +++ /dev/null @@ -1,322 +0,0 @@ -/** Implementation of the Large Objects interface. - * - * Allows direct access to large objects, as well as though I/O streams. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include - -extern "C" -{ -#include -} - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/connection.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/gates/connection-largeobject.hxx" -#include "pqxx/largeobject.hxx" - -#include "pqxx/internal/header-post.hxx" - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - -namespace -{ -constexpr inline int PQXX_COLD std_mode_to_pq_mode(std::ios::openmode mode) -{ - /// Mode bits, copied from libpq-fs.h so that we no longer need that header. - constexpr int INV_WRITE{0x00020000}, INV_READ{0x00040000}; - - return ((mode & std::ios::in) ? INV_READ : 0) | - ((mode & std::ios::out) ? INV_WRITE : 0); -} - - -constexpr int PQXX_COLD std_dir_to_pq_dir(std::ios::seekdir dir) noexcept -{ - if constexpr ( - static_cast(std::ios::beg) == int(SEEK_SET) and - static_cast(std::ios::cur) == int(SEEK_CUR) and - static_cast(std::ios::end) == int(SEEK_END)) - { - // Easy optimisation: they're the same constants. This is actually the - // case for the gcc I'm using. - return dir; - } - else - switch (dir) - { - case std::ios::beg: return SEEK_SET; break; - case std::ios::cur: return SEEK_CUR; break; - case std::ios::end: return SEEK_END; break; - - // Shouldn't happen, but may silence compiler warning. - default: return dir; break; - } -} -} // namespace - - -PQXX_COLD pqxx::largeobject::largeobject(dbtransaction &t) -{ - // (Mode is ignored as of postgres 8.1.) - m_id = lo_creat(raw_connection(t), 0); - if (m_id == oid_none) - { - int const err{errno}; - if (err == ENOMEM) - throw std::bad_alloc{}; - throw failure{internal::concat( - "Could not create large object: ", reason(t.conn(), err))}; - } -} - - -PQXX_COLD -pqxx::largeobject::largeobject(dbtransaction &t, std::string_view file) -{ - m_id = lo_import(raw_connection(t), std::data(file)); - if (m_id == oid_none) - { - int const err{errno}; - if (err == ENOMEM) - throw std::bad_alloc{}; - throw failure{internal::concat( - "Could not import file '", file, - "' to large object: ", reason(t.conn(), err))}; - } -} - - -PQXX_COLD pqxx::largeobject::largeobject(largeobjectaccess const &o) noexcept : - m_id{o.id()} -{} - - -void PQXX_COLD -pqxx::largeobject::to_file(dbtransaction &t, std::string_view file) const -{ - if (id() == oid_none) - throw usage_error{"No object selected."}; - if (lo_export(raw_connection(t), id(), std::data(file)) == -1) - { - int const err{errno}; - if (err == ENOMEM) - throw std::bad_alloc{}; - throw failure{internal::concat( - "Could not export large object ", m_id, " to file '", file, - "': ", reason(t.conn(), err))}; - } -} - - -void PQXX_COLD pqxx::largeobject::remove(dbtransaction &t) const -{ - if (id() == oid_none) - throw usage_error{"No object selected."}; - if (lo_unlink(raw_connection(t), id()) == -1) - { - int const err{errno}; - if (err == ENOMEM) - throw std::bad_alloc{}; - throw failure{internal::concat( - "Could not delete large object ", m_id, ": ", reason(t.conn(), err))}; - } -} - - -pqxx::internal::pq::PGconn *PQXX_COLD -pqxx::largeobject::raw_connection(dbtransaction const &t) -{ - return pqxx::internal::gate::connection_largeobject{t.conn()} - .raw_connection(); -} - - -std::string PQXX_COLD -pqxx::largeobject::reason(connection const &c, int err) const -{ - if (err == ENOMEM) - return "Out of memory"; - return pqxx::internal::gate::const_connection_largeobject{c}.error_message(); -} - - -PQXX_COLD -pqxx::largeobjectaccess::largeobjectaccess(dbtransaction &t, openmode mode) : - largeobject{t}, m_trans{t} -{ - open(mode); -} - - -PQXX_COLD pqxx::largeobjectaccess::largeobjectaccess( - dbtransaction &t, oid o, openmode mode) : - largeobject{o}, m_trans{t} -{ - open(mode); -} - - -PQXX_COLD pqxx::largeobjectaccess::largeobjectaccess( - dbtransaction &t, largeobject o, openmode mode) : - largeobject{o}, m_trans{t} -{ - open(mode); -} - - -PQXX_COLD pqxx::largeobjectaccess::largeobjectaccess( - dbtransaction &t, std::string_view file, openmode mode) : - largeobject{t, file}, m_trans{t} -{ - open(mode); -} - - -pqxx::largeobjectaccess::size_type PQXX_COLD -pqxx::largeobjectaccess::seek(size_type dest, seekdir dir) -{ - auto const res{cseek(dest, dir)}; - if (res == -1) - { - int const err{errno}; - if (err == ENOMEM) - throw std::bad_alloc{}; - if (id() == oid_none) - throw usage_error{"No object selected."}; - throw failure{ - internal::concat("Error seeking in large object: ", reason(err))}; - } - - return res; -} - - -pqxx::largeobjectaccess::pos_type PQXX_COLD -pqxx::largeobjectaccess::cseek(off_type dest, seekdir dir) noexcept -{ - return lo_lseek64(raw_connection(), m_fd, dest, std_dir_to_pq_dir(dir)); -} - - -pqxx::largeobjectaccess::pos_type PQXX_COLD -pqxx::largeobjectaccess::cwrite(char const buf[], std::size_t len) noexcept -{ - return std::max(lo_write(raw_connection(), m_fd, buf, len), -1); -} - - -pqxx::largeobjectaccess::pos_type PQXX_COLD -pqxx::largeobjectaccess::cread(char buf[], std::size_t len) noexcept -{ - return std::max(lo_read(raw_connection(), m_fd, buf, len), -1); -} - - -pqxx::largeobjectaccess::pos_type PQXX_COLD -pqxx::largeobjectaccess::ctell() const noexcept -{ - return lo_tell64(raw_connection(), m_fd); -} - - -void PQXX_COLD -pqxx::largeobjectaccess::write(char const buf[], std::size_t len) -{ - if (id() == oid_none) - throw usage_error{"No object selected."}; - if (auto const bytes{cwrite(buf, len)}; internal::cmp_less(bytes, len)) - { - int const err{errno}; - if (err == ENOMEM) - throw std::bad_alloc{}; - if (bytes < 0) - throw failure{internal::concat( - "Error writing to large object #", id(), ": ", reason(err))}; - if (bytes == 0) - throw failure{internal::concat( - "Could not write to large object #", id(), ": ", reason(err))}; - - throw failure{internal::concat( - "Wanted to write ", len, " bytes to large object #", id(), - "; could only write ", bytes, ".")}; - } -} - - -pqxx::largeobjectaccess::size_type PQXX_COLD -pqxx::largeobjectaccess::read(char buf[], std::size_t len) -{ - if (id() == oid_none) - throw usage_error{"No object selected."}; - auto const bytes{cread(buf, len)}; - if (bytes < 0) - { - int const err{errno}; - if (err == ENOMEM) - throw std::bad_alloc{}; - throw failure{internal::concat( - "Error reading from large object #", id(), ": ", reason(err))}; - } - return bytes; -} - - -void PQXX_COLD pqxx::largeobjectaccess::open(openmode mode) -{ - if (id() == oid_none) - throw usage_error{"No object selected."}; - m_fd = lo_open(raw_connection(), id(), std_mode_to_pq_mode(mode)); - if (m_fd < 0) - { - int const err{errno}; - if (err == ENOMEM) - throw std::bad_alloc{}; - throw failure{internal::concat( - "Could not open large object ", id(), ": ", reason(err))}; - } -} - - -void PQXX_COLD pqxx::largeobjectaccess::close() noexcept -{ - if (m_fd >= 0) - lo_close(raw_connection(), m_fd); -} - - -pqxx::largeobjectaccess::size_type PQXX_COLD -pqxx::largeobjectaccess::tell() const -{ - auto const res{ctell()}; - if (res == -1) - throw failure{reason(errno)}; - return res; -} - - -std::string PQXX_COLD pqxx::largeobjectaccess::reason(int err) const -{ - if (m_fd == -1) - return "No object opened."; - return largeobject::reason(m_trans.conn(), err); -} - - -void PQXX_COLD pqxx::largeobjectaccess::process_notice(zview s) noexcept -{ - m_trans.process_notice(s); -} - -#include "pqxx/internal/ignore-deprecated-post.hxx" diff --git a/ext/libpqxx-7.7.3/src/notification.cxx b/ext/libpqxx-7.7.3/src/notification.cxx deleted file mode 100644 index eb8d5e1a1..000000000 --- a/ext/libpqxx-7.7.3/src/notification.cxx +++ /dev/null @@ -1,35 +0,0 @@ -/** Implementation of the pqxx::notification_receiever class. - * - * pqxx::notification_receiver processes notifications. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/internal/gates/connection-notification_receiver.hxx" -#include "pqxx/notification.hxx" - -#include "pqxx/internal/header-post.hxx" - - -pqxx::notification_receiver::notification_receiver( - connection &c, std::string_view channel) : - m_conn{c}, m_channel{channel} -{ - pqxx::internal::gate::connection_notification_receiver{c}.add_receiver(this); -} - - -pqxx::notification_receiver::~notification_receiver() -{ - pqxx::internal::gate::connection_notification_receiver{this->conn()} - .remove_receiver(this); -} diff --git a/ext/libpqxx-7.7.3/src/params.cxx b/ext/libpqxx-7.7.3/src/params.cxx deleted file mode 100644 index bd3fc108c..000000000 --- a/ext/libpqxx-7.7.3/src/params.cxx +++ /dev/null @@ -1,122 +0,0 @@ -/* Implementations related to prepared and parameterised statements. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/params.hxx" - -#include "pqxx/internal/header-post.hxx" - - -void pqxx::internal::c_params::reserve(std::size_t n) & -{ - values.reserve(n); - lengths.reserve(n); - formats.reserve(n); -} - - -void pqxx::params::reserve(std::size_t n) & -{ - m_params.reserve(n); -} - - -void pqxx::params::append() & -{ - m_params.emplace_back(nullptr); -} - - -void pqxx::params::append(zview value) & -{ - m_params.emplace_back(value); -} - - -void pqxx::params::append(std::string const &value) & -{ - m_params.emplace_back(value); -} - - -void pqxx::params::append(std::string &&value) & -{ - m_params.emplace_back(std::move(value)); -} - - -void pqxx::params::append(params const &value) & -{ - this->reserve(std::size(value.m_params) + std::size(this->m_params)); - for (auto const ¶m : value.m_params) m_params.emplace_back(param); -} - - -void pqxx::params::append(std::basic_string_view value) & -{ - m_params.emplace_back(value); -} - - -void pqxx::params::append(std::basic_string const &value) & -{ - m_params.emplace_back(value); -} - - -void pqxx::params::append(std::basic_string &&value) & -{ - m_params.emplace_back(std::move(value)); -} - - -void PQXX_COLD pqxx::params::append(binarystring const &value) & -{ - m_params.push_back(entry{value.bytes_view()}); -} - - -void pqxx::params::append(params &&value) & -{ - this->reserve(std::size(value.m_params) + std::size(this->m_params)); - for (auto const ¶m : value.m_params) - m_params.emplace_back(std::move(param)); - value.m_params.clear(); -} - - -pqxx::internal::c_params pqxx::params::make_c_params() const -{ - pqxx::internal::c_params p; - p.reserve(std::size(m_params)); - for (auto const ¶m : m_params) - std::visit( - [&p](auto const &value) { - using T = strip_t; - - if constexpr (std::is_same_v) - { - p.values.push_back(nullptr); - p.lengths.push_back(0); - } - else - { - p.values.push_back(reinterpret_cast(std::data(value))); - p.lengths.push_back( - check_cast(internal::ssize(value), s_overflow)); - } - - p.formats.push_back(param_format(value)); - }, - param); - - return p; -} diff --git a/ext/libpqxx-7.7.3/src/pipeline.cxx b/ext/libpqxx-7.7.3/src/pipeline.cxx deleted file mode 100644 index 854b1a70e..000000000 --- a/ext/libpqxx-7.7.3/src/pipeline.cxx +++ /dev/null @@ -1,448 +0,0 @@ -/** Implementation of the pqxx::pipeline class. - * - * Throughput-optimized query interface. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/dbtransaction.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/gates/connection-pipeline.hxx" -#include "pqxx/internal/gates/result-creation.hxx" -#include "pqxx/internal/gates/result-pipeline.hxx" -#include "pqxx/pipeline.hxx" -#include "pqxx/separated_list.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace -{ -std::string const theSeparator{"; "}; -std::string const theDummyValue{"1"}; -std::string const theDummyQuery{"SELECT " + theDummyValue + theSeparator}; -} // namespace - - -void pqxx::pipeline::init() -{ - m_encoding = internal::enc_group(m_trans.conn().encoding_id()); - m_issuedrange = make_pair(std::end(m_queries), std::end(m_queries)); - attach(); -} - - -pqxx::pipeline::~pipeline() noexcept -{ - try - { - cancel(); - } - catch (std::exception const &) - {} - detach(); -} - - -void pqxx::pipeline::attach() -{ - if (not registered()) - register_me(); -} - - -void pqxx::pipeline::detach() -{ - if (registered()) - unregister_me(); -} - - -pqxx::pipeline::query_id pqxx::pipeline::insert(std::string_view q) & -{ - attach(); - query_id const qid{generate_id()}; - auto const i{m_queries.insert(std::make_pair(qid, Query(q))).first}; - - if (m_issuedrange.second == std::end(m_queries)) - { - m_issuedrange.second = i; - if (m_issuedrange.first == std::end(m_queries)) - m_issuedrange.first = i; - } - m_num_waiting++; - - if (m_num_waiting > m_retain) - { - if (have_pending()) - receive_if_available(); - if (not have_pending()) - issue(); - } - - return qid; -} - - -void pqxx::pipeline::complete() -{ - if (have_pending()) - receive(m_issuedrange.second); - if (m_num_waiting and (m_error == qid_limit())) - { - issue(); - receive(std::end(m_queries)); - } - detach(); -} - - -void pqxx::pipeline::flush() -{ - if (not std::empty(m_queries)) - { - if (have_pending()) - receive(m_issuedrange.second); - m_issuedrange.first = m_issuedrange.second = std::end(m_queries); - m_num_waiting = 0; - m_dummy_pending = false; - m_queries.clear(); - } - detach(); -} - - -void PQXX_COLD pqxx::pipeline::cancel() -{ - while (have_pending()) - { - pqxx::internal::gate::connection_pipeline(m_trans.conn()).cancel_query(); - auto canceled_query{m_issuedrange.first}; - ++m_issuedrange.first; - m_queries.erase(canceled_query); - } -} - - -bool pqxx::pipeline::is_finished(pipeline::query_id q) const -{ - if (m_queries.find(q) == std::end(m_queries)) - throw std::logic_error{ - internal::concat("Requested status for unknown query '", q, "'.")}; - return (QueryMap::const_iterator(m_issuedrange.first) == - std::end(m_queries)) or - (q < m_issuedrange.first->first and q < m_error); -} - - -std::pair pqxx::pipeline::retrieve() -{ - if (std::empty(m_queries)) - throw std::logic_error{"Attempt to retrieve result from empty pipeline."}; - return retrieve(std::begin(m_queries)); -} - - -int pqxx::pipeline::retain(int retain_max) & -{ - if (retain_max < 0) - throw range_error{internal::concat( - "Attempt to make pipeline retain ", retain_max, " queries")}; - - int const oldvalue{m_retain}; - m_retain = retain_max; - - if (m_num_waiting >= m_retain) - resume(); - - return oldvalue; -} - - -void pqxx::pipeline::resume() & -{ - if (have_pending()) - receive_if_available(); - if (not have_pending() and m_num_waiting) - { - issue(); - receive_if_available(); - } -} - - -pqxx::pipeline::query_id pqxx::pipeline::generate_id() -{ - if (m_q_id == qid_limit()) - throw std::overflow_error{"Too many queries went through pipeline."}; - ++m_q_id; - return m_q_id; -} - - -void pqxx::pipeline::issue() -{ - // Retrieve that null result for the last query, if needed. - obtain_result(); - - // Don't issue anything if we've encountered an error. - if (m_error < qid_limit()) - return; - - // Start with oldest query (lowest id) not in previous issue range. - auto oldest{m_issuedrange.second}; - - // Construct cumulative query string for entire batch. - auto cum{separated_list( - theSeparator, oldest, std::end(m_queries), - [](QueryMap::const_iterator i) { return i->second.query; })}; - auto const num_issued{ - QueryMap::size_type(std::distance(oldest, std::end(m_queries)))}; - bool const prepend_dummy{num_issued > 1}; - if (prepend_dummy) - cum = theDummyQuery + cum; - - pqxx::internal::gate::connection_pipeline{m_trans.conn()}.start_exec( - cum.c_str()); - - // Since we managed to send out these queries, update state to reflect this. - m_dummy_pending = prepend_dummy; - m_issuedrange.first = oldest; - m_issuedrange.second = std::end(m_queries); - m_num_waiting -= check_cast(num_issued, "pipeline issue()"sv); -} - - -void PQXX_COLD pqxx::pipeline::internal_error(std::string const &err) -{ - set_error_at(0); - throw pqxx::internal_error{err}; -} - - -bool pqxx::pipeline::obtain_result(bool expect_none) -{ - pqxx::internal::gate::connection_pipeline gate{m_trans.conn()}; - auto const r{gate.get_result()}; - if (r == nullptr) - { - if (have_pending() and not expect_none) - { - PQXX_UNLIKELY - set_error_at(m_issuedrange.first->first); - m_issuedrange.second = m_issuedrange.first; - } - return false; - } - - result const res{pqxx::internal::gate::result_creation::create( - r, std::begin(m_queries)->second.query, m_encoding)}; - - if (not have_pending()) - { - PQXX_UNLIKELY - set_error_at(std::begin(m_queries)->first); - throw std::logic_error{ - "Got more results from pipeline than there were queries."}; - } - - // Must be the result for the oldest pending query. - if (not std::empty(m_issuedrange.first->second.res)) - PQXX_UNLIKELY - internal_error("Multiple results for one query."); - - m_issuedrange.first->second.res = res; - ++m_issuedrange.first; - - return true; -} - - -void pqxx::pipeline::obtain_dummy() -{ - // Allocate once, re-use across invocations. - static auto const text{ - std::make_shared("[DUMMY PIPELINE QUERY]")}; - - pqxx::internal::gate::connection_pipeline gate{m_trans.conn()}; - auto const r{gate.get_result()}; - m_dummy_pending = false; - - if (r == nullptr) - PQXX_UNLIKELY - internal_error("Pipeline got no result from backend when it expected one."); - - result R{pqxx::internal::gate::result_creation::create(r, text, m_encoding)}; - - bool OK{false}; - try - { - pqxx::internal::gate::result_creation{R}.check_status(); - OK = true; - } - catch (sql_error const &) - {} - if (OK) - { - PQXX_LIKELY - if (std::size(R) > 1) - PQXX_UNLIKELY - internal_error("Unexpected result for dummy query in pipeline."); - - if (R.at(0).at(0).as() != theDummyValue) - PQXX_UNLIKELY - internal_error("Dummy query in pipeline returned unexpected value."); - return; - } - - // TODO: Can we actually re-issue statements after a failure? - /* Execution of this batch failed. - * - * When we send multiple statements in one go, the backend treats them as a - * single transaction. So the entire batch was effectively rolled back. - * - * Since none of the queries in the batch were actually executed, we can - * afford to replay them one by one until we find the exact query that - * caused the error. This gives us not only a more specific error message - * to report, but also tells us which query to report it for. - */ - // First, give the whole batch the same syntax error message, in case all - // else is going to fail. - for (auto i{m_issuedrange.first}; i != m_issuedrange.second; ++i) - i->second.res = R; - - // Remember where the end of this batch was - auto const stop{m_issuedrange.second}; - - // Retrieve that null result for the last query, if needed - obtain_result(true); - - // Reset internal state to forget botched batch attempt - m_num_waiting += check_cast( - std::distance(m_issuedrange.first, stop), "pipeline obtain_dummy()"sv); - m_issuedrange.second = m_issuedrange.first; - - // Issue queries in failed batch one at a time. - unregister_me(); - try - { - do { - m_num_waiting--; - auto const query{*m_issuedrange.first->second.query}; - auto &holder{m_issuedrange.first->second}; - holder.res = m_trans.exec(query); - pqxx::internal::gate::result_creation{holder.res}.check_status(); - ++m_issuedrange.first; - } while (m_issuedrange.first != stop); - } - catch (std::exception const &) - { - auto const thud{m_issuedrange.first->first}; - ++m_issuedrange.first; - m_issuedrange.second = m_issuedrange.first; - auto q{m_issuedrange.first}; - set_error_at((q == std::end(m_queries)) ? thud + 1 : q->first); - } -} - - -std::pair -pqxx::pipeline::retrieve(pipeline::QueryMap::iterator q) -{ - if (q == std::end(m_queries)) - throw std::logic_error{"Attempt to retrieve result for unknown query."}; - - if (q->first >= m_error) - throw std::runtime_error{ - "Could not complete query in pipeline due to error in earlier query."}; - - // If query hasn't issued yet, do it now. - if ( - m_issuedrange.second != std::end(m_queries) and - (q->first >= m_issuedrange.second->first)) - { - if (have_pending()) - receive(m_issuedrange.second); - if (m_error == qid_limit()) - issue(); - } - - // If result not in yet, get it; else get at least whatever's convenient. - if (have_pending()) - { - if (q->first >= m_issuedrange.first->first) - { - auto suc{q}; - ++suc; - receive(suc); - } - else - { - receive_if_available(); - } - } - - if (q->first >= m_error) - throw std::runtime_error{ - "Could not complete query in pipeline due to error in earlier query."}; - - // Don't leave the backend idle if there are queries waiting to be issued. - if (m_num_waiting and not have_pending() and (m_error == qid_limit())) - issue(); - - result const R{q->second.res}; - auto const P{std::make_pair(q->first, R)}; - - m_queries.erase(q); - - pqxx::internal::gate::result_creation{R}.check_status(); - return P; -} - - -void pqxx::pipeline::get_further_available_results() -{ - pqxx::internal::gate::connection_pipeline gate{m_trans.conn()}; - while (not gate.is_busy() and obtain_result()) - if (not gate.consume_input()) - throw broken_connection{}; -} - - -void pqxx::pipeline::receive_if_available() -{ - pqxx::internal::gate::connection_pipeline gate{m_trans.conn()}; - if (not gate.consume_input()) - throw broken_connection{}; - if (gate.is_busy()) - return; - - if (m_dummy_pending) - obtain_dummy(); - if (have_pending()) - get_further_available_results(); -} - - -void pqxx::pipeline::receive(pipeline::QueryMap::const_iterator stop) -{ - if (m_dummy_pending) - obtain_dummy(); - - while (obtain_result() and - QueryMap::const_iterator{m_issuedrange.first} != stop) - ; - - // Also haul in any remaining "targets of opportunity". - if (QueryMap::const_iterator{m_issuedrange.first} == stop) - get_further_available_results(); -} diff --git a/ext/libpqxx-7.7.3/src/pqxx-source.hxx b/ext/libpqxx-7.7.3/src/pqxx-source.hxx deleted file mode 100644 index 1a8f5fb11..000000000 --- a/ext/libpqxx-7.7.3/src/pqxx-source.hxx +++ /dev/null @@ -1,30 +0,0 @@ -/* Compiler settings for compiling libpqxx itself. - * - * Include this header in every source file that goes into the libpqxx library - * binary, and nowhere else. - * - * To ensure this, include this file once, as the very first header, in each - * compilation unit for the library. - * - * DO NOT INCLUDE THIS FILE when building client programs. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ - -// Workarounds & definitions needed to compile libpqxx into a library. -#include "pqxx/config-internal-compiler.h" - -#ifdef _WIN32 - -# ifdef PQXX_SHARED -// We're building libpqxx as a shared library. -# undef PQXX_LIBEXPORT -# define PQXX_LIBEXPORT __declspec(dllexport) -# define PQXX_PRIVATE __declspec() -# endif // PQXX_SHARED - -#endif // _WIN32 diff --git a/ext/libpqxx-7.7.3/src/result.cxx b/ext/libpqxx-7.7.3/src/result.cxx deleted file mode 100644 index 86a739004..000000000 --- a/ext/libpqxx-7.7.3/src/result.cxx +++ /dev/null @@ -1,536 +0,0 @@ -/** Implementation of the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include - -extern "C" -{ -#include -} - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/result_iterator.hxx" -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace pqxx -{ -PQXX_DECLARE_ENUM_CONVERSION(ExecStatusType); -} - -std::string const pqxx::result::s_empty_string; - - -/// C++ wrapper for libpq's PQclear. -void pqxx::internal::clear_result(pq::PGresult const *data) -{ - PQclear(const_cast(data)); -} - - -pqxx::result::result( - pqxx::internal::pq::PGresult *rhs, std::shared_ptr query, - internal::encoding_group enc) : - m_data{make_data_pointer(rhs)}, m_query{query}, m_encoding(enc) -{} - - -bool pqxx::result::operator==(result const &rhs) const noexcept -{ - if (&rhs == this) - PQXX_UNLIKELY return true; - auto const s{size()}; - if (std::size(rhs) != s) - return false; - for (size_type i{0}; i < s; ++i) - if ((*this)[i] != rhs[i]) - return false; - return true; -} - - -pqxx::result::const_reverse_iterator pqxx::result::rbegin() const -{ - return const_reverse_iterator{end()}; -} - - -pqxx::result::const_reverse_iterator pqxx::result::crbegin() const -{ - return rbegin(); -} - - -pqxx::result::const_reverse_iterator pqxx::result::rend() const -{ - return const_reverse_iterator{begin()}; -} - - -pqxx::result::const_reverse_iterator pqxx::result::crend() const -{ - return rend(); -} - - -pqxx::result::const_iterator pqxx::result::begin() const noexcept -{ - return {this, 0}; -} - - -pqxx::result::const_iterator pqxx::result::cbegin() const noexcept -{ - return begin(); -} - - -pqxx::result::size_type pqxx::result::size() const noexcept -{ - return (m_data.get() == nullptr) ? - 0 : - static_cast(PQntuples(m_data.get())); -} - - -bool pqxx::result::empty() const noexcept -{ - return (m_data.get() == nullptr) or (PQntuples(m_data.get()) == 0); -} - - -pqxx::result::reference pqxx::result::front() const noexcept -{ - return row{*this, 0, columns()}; -} - - -pqxx::result::reference pqxx::result::back() const noexcept -{ - return row{*this, size() - 1, columns()}; -} - - -void pqxx::result::swap(result &rhs) noexcept -{ - m_data.swap(rhs.m_data); - m_query.swap(rhs.m_query); -} - - -pqxx::row pqxx::result::operator[](result_size_type i) const noexcept -{ - return row{*this, i, columns()}; -} - - -#if defined(PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT) -pqxx::field pqxx::result::operator[]( - result_size_type row_num, row_size_type col_num) const noexcept -{ - return {*this, row_num, field_num}; -} -#endif - - -pqxx::row pqxx::result::at(pqxx::result::size_type i) const -{ - if (i >= size()) - throw range_error{"Row number out of range."}; - return operator[](i); -} - - -pqxx::field pqxx::result::at( - pqxx::result_size_type row_num, pqxx::row_size_type col_num) const -{ - if (row_num >= size()) - throw range_error{"Row number out of range."}; - if (col_num >= columns()) - throw range_error{"Column out of range."}; - return {*this, row_num, col_num}; -} - - -namespace -{ -/// C string comparison. -inline bool equal(char const lhs[], char const rhs[]) -{ - return strcmp(lhs, rhs) == 0; -} -} // namespace - -void PQXX_COLD pqxx::result::throw_sql_error( - std::string const &Err, std::string const &Query) const -{ - // Try to establish more precise error type, and throw corresponding - // type of exception. - char const *const code{PQresultErrorField(m_data.get(), PG_DIAG_SQLSTATE)}; - if (code == nullptr) - { - // No SQLSTATE at all. Can this even happen? - // Let's assume the connection is no longer usable. - throw broken_connection{Err}; - } - - switch (code[0]) - { - PQXX_UNLIKELY - case '\0': - // SQLSTATE is empty. We may have seen this happen in one - // circumstance: a client-side socket timeout (while using the - // tcp_user_timeout connection option). Unfortunately in that case the - // connection was just fine, so we had no real way of detecting the - // problem. (Trying to continue to use the connection does break - // though, so I feel justified in panicking.) - throw broken_connection{Err}; - - case '0': - switch (code[1]) - { - case 'A': throw feature_not_supported{Err, Query, code}; - case '8': throw broken_connection{Err}; - case 'L': - case 'P': throw insufficient_privilege{Err, Query, code}; - } - break; - case '2': - switch (code[1]) - { - case '2': throw data_exception{Err, Query, code}; - case '3': - if (equal(code, "23001")) - throw restrict_violation{Err, Query, code}; - if (equal(code, "23502")) - throw not_null_violation{Err, Query, code}; - if (equal(code, "23503")) - throw foreign_key_violation{Err, Query, code}; - if (equal(code, "23505")) - throw unique_violation{Err, Query, code}; - if (equal(code, "23514")) - throw check_violation{Err, Query, code}; - throw integrity_constraint_violation{Err, Query, code}; - case '4': throw invalid_cursor_state{Err, Query, code}; - case '6': throw invalid_sql_statement_name{Err, Query, code}; - } - break; - case '3': - switch (code[1]) - { - case '4': throw invalid_cursor_name{Err, Query, code}; - } - break; - case '4': - switch (code[1]) - { - case '0': - if (equal(code, "40000")) - throw transaction_rollback{Err, Query, code}; - if (equal(code, "40001")) - throw serialization_failure{Err, Query, code}; - if (equal(code, "40003")) - throw statement_completion_unknown{Err, Query, code}; - if (equal(code, "40P01")) - throw deadlock_detected{Err, Query, code}; - break; - case '2': - if (equal(code, "42501")) - throw insufficient_privilege{Err, Query}; - if (equal(code, "42601")) - throw syntax_error{Err, Query, code, errorposition()}; - if (equal(code, "42703")) - throw undefined_column{Err, Query, code}; - if (equal(code, "42883")) - throw undefined_function{Err, Query, code}; - if (equal(code, "42P01")) - throw undefined_table{Err, Query, code}; - } - break; - case '5': - switch (code[1]) - { - case '3': - if (equal(code, "53100")) - throw disk_full{Err, Query, code}; - if (equal(code, "53200")) - throw out_of_memory{Err, Query, code}; - if (equal(code, "53300")) - throw too_many_connections{Err}; - throw insufficient_resources{Err, Query, code}; - } - break; - - case 'P': - if (equal(code, "P0001")) - throw plpgsql_raise{Err, Query, code}; - if (equal(code, "P0002")) - throw plpgsql_no_data_found{Err, Query, code}; - if (equal(code, "P0003")) - throw plpgsql_too_many_rows{Err, Query, code}; - throw plpgsql_error{Err, Query, code}; - } - - // Unknown error code. - throw sql_error{Err, Query, code}; -} - -void pqxx::result::check_status(std::string_view desc) const -{ - if (auto err{status_error()}; not std::empty(err)) - { - PQXX_UNLIKELY - if (not std::empty(desc)) - err = pqxx::internal::concat("Failure during '", desc, "': ", err); - throw_sql_error(err, query()); - } -} - - -std::string pqxx::result::status_error() const -{ - if (m_data.get() == nullptr) - throw failure{"No result set given."}; - - std::string err; - - switch (PQresultStatus(m_data.get())) - { - case PGRES_EMPTY_QUERY: // The string sent to the backend was empty. - case PGRES_COMMAND_OK: // Successful completion, no result data. - case PGRES_TUPLES_OK: // The query successfully executed. - break; - - case PGRES_COPY_OUT: // Copy Out (from server) data transfer started. - case PGRES_COPY_IN: // Copy In (to server) data transfer started. - break; - - case PGRES_BAD_RESPONSE: // The server's response was not understood. - case PGRES_NONFATAL_ERROR: - case PGRES_FATAL_ERROR: err = PQresultErrorMessage(m_data.get()); break; - - default: - throw internal_error{internal::concat( - "pqxx::result: Unrecognized response code ", - PQresultStatus(m_data.get()))}; - } - return err; -} - - -char const *pqxx::result::cmd_status() const noexcept -{ - return PQcmdStatus(const_cast(m_data.get())); -} - - -std::string const &pqxx::result::query() const &noexcept -{ - return (m_query.get() == nullptr) ? s_empty_string : *m_query; -} - - -pqxx::oid pqxx::result::inserted_oid() const -{ - if (m_data.get() == nullptr) - throw usage_error{ - "Attempt to read oid of inserted row without an INSERT result"}; - return PQoidValue(const_cast(m_data.get())); -} - - -pqxx::result::size_type pqxx::result::affected_rows() const -{ - auto const rows_str{ - PQcmdTuples(const_cast(m_data.get()))}; - return (rows_str[0] == '\0') ? 0 : size_type(atoi(rows_str)); -} - - -char const *pqxx::result::get_value( - pqxx::result::size_type row, pqxx::row::size_type col) const -{ - return PQgetvalue(m_data.get(), row, col); -} - - -bool pqxx::result::get_is_null( - pqxx::result::size_type row, pqxx::row::size_type col) const -{ - return PQgetisnull(m_data.get(), row, col) != 0; -} - -pqxx::field::size_type pqxx::result::get_length( - pqxx::result::size_type row, pqxx::row::size_type col) const noexcept -{ - return static_cast( - PQgetlength(m_data.get(), row, col)); -} - - -pqxx::oid pqxx::result::column_type(row::size_type col_num) const -{ - oid const t{PQftype(m_data.get(), col_num)}; - if (t == oid_none) - throw argument_error{internal::concat( - "Attempt to retrieve type of nonexistent column ", col_num, - " of query result.")}; - return t; -} - - -pqxx::row::size_type pqxx::result::column_number(zview col_name) const -{ - auto const n{PQfnumber( - const_cast(m_data.get()), col_name.c_str())}; - if (n == -1) - throw argument_error{ - internal::concat("Unknown column name: '", col_name, "'.")}; - - return static_cast(n); -} - - -pqxx::oid pqxx::result::column_table(row::size_type col_num) const -{ - oid const t{PQftable(m_data.get(), col_num)}; - - /* If we get oid_none, it may be because the column is computed, or because - * we got an invalid row number. - */ - if (t == oid_none and col_num >= columns()) - throw argument_error{internal::concat( - "Attempt to retrieve table ID for column ", col_num, " out of ", - columns())}; - - return t; -} - - -pqxx::row::size_type pqxx::result::table_column(row::size_type col_num) const -{ - auto const n{row::size_type(PQftablecol(m_data.get(), col_num))}; - if (n != 0) - PQXX_LIKELY - return n - 1; - - // Failed. Now find out why, so we can throw a sensible exception. - auto const col_str{to_string(col_num)}; - if (col_num > columns()) - throw range_error{ - internal::concat("Invalid column index in table_column(): ", col_str)}; - - if (m_data.get() == nullptr) - throw usage_error{internal::concat( - "Can't query origin of column ", col_str, - ": result is not initialized.")}; - - throw usage_error{internal::concat( - "Can't query origin of column ", col_str, - ": not derived from table column.")}; -} - - -int pqxx::result::errorposition() const -{ - int pos{-1}; - if (m_data.get()) - { - auto const p{PQresultErrorField( - const_cast(m_data.get()), - PG_DIAG_STATEMENT_POSITION)}; - if (p) - pos = from_string(p); - } - return pos; -} - - -char const *pqxx::result::column_name(pqxx::row::size_type number) const & -{ - auto const n{PQfname(m_data.get(), number)}; - if (n == nullptr) - { - PQXX_UNLIKELY - if (m_data.get() == nullptr) - throw usage_error{"Queried column name on null result."}; - throw range_error{internal::concat( - "Invalid column number: ", number, " (maximum is ", (columns() - 1), - ").")}; - } - return n; -} - - -pqxx::row::size_type pqxx::result::columns() const noexcept -{ - auto ptr{const_cast(m_data.get())}; - return (ptr == nullptr) ? 0 : row::size_type(PQnfields(ptr)); -} - - -// const_result_iterator - -pqxx::const_result_iterator pqxx::const_result_iterator::operator++(int) -{ - const_result_iterator old{*this}; - m_index++; - return old; -} - - -pqxx::const_result_iterator pqxx::const_result_iterator::operator--(int) -{ - const_result_iterator old{*this}; - m_index--; - return old; -} - - -pqxx::result::const_iterator -pqxx::result::const_reverse_iterator::base() const noexcept -{ - iterator_type tmp{*this}; - return ++tmp; -} - - -pqxx::const_reverse_result_iterator -pqxx::const_reverse_result_iterator::operator++(int) -{ - const_reverse_result_iterator tmp{*this}; - iterator_type::operator--(); - return tmp; -} - - -pqxx::const_reverse_result_iterator -pqxx::const_reverse_result_iterator::operator--(int) -{ - const_reverse_result_iterator tmp{*this}; - iterator_type::operator++(); - return tmp; -} - - -template<> std::string pqxx::to_string(field const &value) -{ - return {value.c_str(), std::size(value)}; -} diff --git a/ext/libpqxx-7.7.3/src/robusttransaction.cxx b/ext/libpqxx-7.7.3/src/robusttransaction.cxx deleted file mode 100644 index 5bbfd64f8..000000000 --- a/ext/libpqxx-7.7.3/src/robusttransaction.cxx +++ /dev/null @@ -1,221 +0,0 @@ -/** Implementation of the pqxx::robusttransaction class. - * - * pqxx::robusttransaction is a slower but safer transaction class. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/connection.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/wait.hxx" -#include "pqxx/nontransaction.hxx" -#include "pqxx/result.hxx" -#include "pqxx/robusttransaction.hxx" - -#include "pqxx/internal/header-post.hxx" - - -using namespace std::literals; - -namespace -{ -using pqxx::operator"" _zv; - -/// Statuses in which we may find our transaction. -/** There's also "in the future," but it manifests as an error, not as an - * actual status. - */ -enum tx_stat -{ - tx_unknown, - tx_committed, - tx_aborted, - tx_in_progress, -}; - - -constexpr auto committed{"committed"_zv}, aborted{"aborted"_zv}, - in_progress{"in progress"_zv}; - - -/// Parse a nonempty transaction status string. -constexpr tx_stat parse_status(std::string_view text) noexcept -{ - switch (text[0]) - { - case 'a': - if (text == aborted) - PQXX_LIKELY return tx_aborted; - break; - case 'c': - if (text == committed) - PQXX_LIKELY return tx_committed; - break; - case 'i': - if (text == in_progress) - PQXX_LIKELY return tx_in_progress; - break; - } - return tx_unknown; -} - - -tx_stat query_status(std::string const &xid, std::string const &conn_str) -{ - static std::string const name{"robusttxck"sv}; - auto const query{pqxx::internal::concat("SELECT txid_status(", xid, ")")}; - pqxx::connection c{conn_str}; - pqxx::nontransaction w{c, name}; - auto const status_row{w.exec1(query)}; - auto const status_field{status_row[0]}; - if (std::size(status_field) == 0) - throw pqxx::internal_error{"Transaction status string is empty."}; - auto const status{parse_status(status_field.as())}; - if (status == tx_unknown) - throw pqxx::internal_error{pqxx::internal::concat( - "Unknown transaction status string: ", status_field.view())}; - return status; -} -} // namespace - - -void pqxx::internal::basic_robusttransaction::init(zview begin_command) -{ - static auto const txid_q{ - std::make_shared("SELECT txid_current()"sv)}; - m_backendpid = conn().backendpid(); - direct_exec(begin_command); - direct_exec(txid_q)[0][0].to(m_xid); -} - - -pqxx::internal::basic_robusttransaction::basic_robusttransaction( - connection &c, zview begin_command, std::string_view tname) : - dbtransaction(c, tname), m_conn_string{c.connection_string()} -{ - init(begin_command); -} - - -pqxx::internal::basic_robusttransaction::basic_robusttransaction( - connection &c, zview begin_command) : - dbtransaction(c), m_conn_string{c.connection_string()} -{ - init(begin_command); -} - - -pqxx::internal::basic_robusttransaction::~basic_robusttransaction() = default; - - -void pqxx::internal::basic_robusttransaction::do_commit() -{ - static auto const check_constraints_q{ - std::make_shared("SET CONSTRAINTS ALL IMMEDIATE"sv)}, - commit_q{std::make_shared("COMMIT"sv)}; - // Check constraints before sending the COMMIT to the database, so as to - // minimise our in-doubt window. - try - { - direct_exec(check_constraints_q); - } - catch (std::exception const &) - { - do_abort(); - throw; - } - - // Here comes the in-doubt window. If we lose our connection here, we'll be - // left clueless as to what happened on the backend. It may have received - // the commit command and completed the transaction, and ended up with a - // success it could not report back to us. Or it may have noticed the broken - // connection and aborted the transaction. It may even still be executing - // the commit, only to fail later. - // - // All this uncertainty requires some special handling, and that s what makes - // robusttransaction what it is. - try - { - direct_exec(commit_q); - - // If we make it here, great. Normal, successful commit. - return; - } - catch (broken_connection const &) - { - // Oops, lost connection at the crucial moment. Fall through to in-doubt - // handling below. - } - catch (std::exception const &) - { - if (conn().is_open()) - { - // Commit failed, for some other reason. - do_abort(); - throw; - } - // Otherwise, fall through to in-doubt handling. - } - - // If we get here, we're in doubt. Figure out what happened. - - int const max_attempts{500}; - static_assert(max_attempts > 0); - - tx_stat stat; - for (int attempts{0}; attempts < max_attempts; - ++attempts, pqxx::internal::wait_for(300u)) - { - stat = tx_unknown; - try - { - stat = query_status(m_xid, m_conn_string); - } - catch (pqxx::broken_connection const &) - { - // Swallow the error. Pause and retry. - } - switch (stat) - { - case tx_unknown: - // We were unable to reconnect and query transaction status. - // Stay in it for another attempt. - return; - case tx_committed: - // Success! We're done. - return; - case tx_aborted: - // Aborted. We're done. - do_abort(); - return; - case tx_in_progress: - // The transaction is still running. Stick around until we know what - // transpires. - break; - } - } - - // Okay, this has taken too long. Give up, report in-doubt state. - throw in_doubt_error{internal::concat( - "Transaction ", name(), " (with transaction ID ", m_xid, - ") " - "lost connection while committing. It's impossible to tell whether " - "it committed, or aborted, or is still running. " - "Attempts to find out its outcome have failed. " - "The backend process on the server had process ID ", - m_backendpid, - ". " - "You may be able to check what happened to that process.")}; -} diff --git a/ext/libpqxx-7.7.3/src/row.cxx b/ext/libpqxx-7.7.3/src/row.cxx deleted file mode 100644 index f0974c839..000000000 --- a/ext/libpqxx-7.7.3/src/row.cxx +++ /dev/null @@ -1,250 +0,0 @@ -/** Implementation of the pqxx::result class and support classes. - * - * pqxx::result represents the set of result rows from a database query. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include - -extern "C" -{ -#include -} - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/except.hxx" -#include "pqxx/result.hxx" -#include "pqxx/row.hxx" - -#include "pqxx/internal/header-post.hxx" - - -pqxx::row::row( - result const &r, result::size_type index, size_type cols) noexcept : - m_result{r}, m_index{index}, m_end{cols} -{} - - -pqxx::row::const_iterator pqxx::row::begin() const noexcept -{ - return {*this, m_begin}; -} - - -pqxx::row::const_iterator pqxx::row::cbegin() const noexcept -{ - return begin(); -} - - -pqxx::row::const_iterator pqxx::row::end() const noexcept -{ - return {*this, m_end}; -} - - -pqxx::row::const_iterator pqxx::row::cend() const noexcept -{ - return end(); -} - - -pqxx::row::reference pqxx::row::front() const noexcept -{ - return field{m_result, m_index, m_begin}; -} - - -pqxx::row::reference pqxx::row::back() const noexcept -{ - return field{m_result, m_index, m_end - 1}; -} - - -pqxx::row::const_reverse_iterator pqxx::row::rbegin() const -{ - return const_reverse_row_iterator{end()}; -} - - -pqxx::row::const_reverse_iterator pqxx::row::crbegin() const -{ - return rbegin(); -} - - -pqxx::row::const_reverse_iterator pqxx::row::rend() const -{ - return const_reverse_row_iterator{begin()}; -} - - -pqxx::row::const_reverse_iterator pqxx::row::crend() const -{ - return rend(); -} - - -bool pqxx::row::operator==(row const &rhs) const noexcept -{ - if (&rhs == this) - return true; - auto const s{size()}; - if (std::size(rhs) != s) - return false; - for (size_type i{0}; i < s; ++i) - if ((*this)[i] != rhs[i]) - return false; - return true; -} - - -pqxx::row::reference pqxx::row::operator[](size_type i) const noexcept -{ - return field{m_result, m_index, m_begin + i}; -} - - -pqxx::row::reference pqxx::row::operator[](zview col_name) const -{ - return at(col_name); -} - - -void pqxx::row::swap(row &rhs) noexcept -{ - auto const i{m_index}; - auto const b{m_begin}; - auto const e{m_end}; - m_result.swap(rhs.m_result); - m_index = rhs.m_index; - m_begin = rhs.m_begin; - m_end = rhs.m_end; - rhs.m_index = i; - rhs.m_begin = b; - rhs.m_end = e; -} - - -pqxx::field pqxx::row::at(zview col_name) const -{ - return {m_result, m_index, m_begin + column_number(col_name)}; -} - - -pqxx::field pqxx::row::at(pqxx::row::size_type i) const -{ - if (i >= size()) - throw range_error{"Invalid field number."}; - - return operator[](i); -} - - -pqxx::oid pqxx::row::column_type(size_type col_num) const -{ - return m_result.column_type(m_begin + col_num); -} - - -pqxx::oid pqxx::row::column_table(size_type col_num) const -{ - return m_result.column_table(m_begin + col_num); -} - - -pqxx::row::size_type pqxx::row::table_column(size_type col_num) const -{ - return m_result.table_column(m_begin + col_num); -} - - -pqxx::row::size_type pqxx::row::column_number(zview col_name) const -{ - auto const n{m_result.column_number(col_name)}; - if (n >= m_end) - throw argument_error{ - "Column '" + std::string{col_name} + "' falls outside slice."}; - if (n >= m_begin) - return n - m_begin; - - // This deals with a really nasty possibility: that the column name occurs - // twice - once before the beginning of the slice, and once inside the slice. - char const *const adapted_name{m_result.column_name(n)}; - for (auto i{m_begin}; i < m_end; ++i) - if (strcmp(adapted_name, m_result.column_name(i)) == 0) - return i - m_begin; - - // Didn't find any? Recurse just to produce the same error message. - return result{}.column_number(col_name); -} - - -pqxx::row PQXX_COLD pqxx::row::slice(size_type sbegin, size_type send) const -{ - if (sbegin > send or send > size()) - throw range_error{"Invalid field range."}; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - row res{*this}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - res.m_begin = m_begin + sbegin; - res.m_end = m_begin + send; - return res; -} - - -bool PQXX_COLD pqxx::row::empty() const noexcept -{ - return m_begin == m_end; -} - - -pqxx::const_row_iterator pqxx::const_row_iterator::operator++(int) -{ - auto const old{*this}; - m_col++; - return old; -} - - -pqxx::const_row_iterator pqxx::const_row_iterator::operator--(int) -{ - auto const old{*this}; - m_col--; - return old; -} - - -pqxx::const_row_iterator -pqxx::const_reverse_row_iterator::base() const noexcept -{ - iterator_type tmp{*this}; - return ++tmp; -} - - -pqxx::const_reverse_row_iterator -pqxx::const_reverse_row_iterator::operator++(int) -{ - auto tmp{*this}; - operator++(); - return tmp; -} - - -pqxx::const_reverse_row_iterator -pqxx::const_reverse_row_iterator::operator--(int) -{ - auto tmp{*this}; - operator--(); - return tmp; -} diff --git a/ext/libpqxx-7.7.3/src/sql_cursor.cxx b/ext/libpqxx-7.7.3/src/sql_cursor.cxx deleted file mode 100644 index 1e5d6a790..000000000 --- a/ext/libpqxx-7.7.3/src/sql_cursor.cxx +++ /dev/null @@ -1,276 +0,0 @@ -/** Implementation of libpqxx STL-style cursor classes. - * - * These classes wrap SQL cursors in STL-like interfaces. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/cursor.hxx" -#include "pqxx/internal/encodings.hxx" -#include "pqxx/internal/gates/connection-sql_cursor.hxx" -#include "pqxx/internal/gates/transaction-sql_cursor.hxx" - -#include "pqxx/internal/header-post.hxx" - - -using namespace std::literals; - -namespace -{ -/// Is this character a "useless trailing character" in a query? -/** A character is "useless" at the end of a query if it is either whitespace - * or a semicolon. - */ -inline bool useless_trail(char c) -{ - return isspace(c) or c == ';'; -} - - -/// Find end of nonempty query, stripping off any trailing semicolon. -/** When executing a normal query, a trailing semicolon is meaningless but - * won't hurt. That's why we can't rule out that some code may include one. - * - * But for cursor queries, a trailing semicolon is a problem. The query gets - * embedded in a larger statement, which a semicolon would break into two. - * We'll have to remove it if present. - * - * A trailing semicolon may not actually be at the end. It could be masked by - * subsequent whitespace. If there's also a comment though, that's the - * caller's own lookout. We can't guard against every possible mistake, and - * text processing is actually remarkably sensitive to mistakes in a - * multi-encoding world. - * - * If there is a trailing semicolon, this function returns its offset. If - * there are more than one, it returns the offset of the first one. If there - * is no trailing semicolon, it returns the length of the query string. - * - * The query must be nonempty. - */ -std::string::size_type -find_query_end(std::string_view query, pqxx::internal::encoding_group enc) -{ - auto const text{std::data(query)}; - auto const size{std::size(query)}; - std::string::size_type end; - if (enc == pqxx::internal::encoding_group::MONOBYTE) - { - // This is an encoding where we can scan backwards from the end. - for (end = std::size(query); end > 0 and useless_trail(text[end - 1]); - --end) - ; - } - else - { - // Complex encoding. We only know how to iterate forwards, so start from - // the beginning. - end = 0; - - pqxx::internal::for_glyphs( - enc, - [text, &end](char const *gbegin, char const *gend) { - if (gend - gbegin > 1 or not useless_trail(*gbegin)) - end = std::string::size_type(gend - text); - }, - text, size); - } - - return end; -} -} // namespace - - -pqxx::internal::sql_cursor::sql_cursor( - transaction_base &t, std::string_view query, std::string_view cname, - cursor_base::access_policy ap, cursor_base::update_policy up, - cursor_base::ownership_policy op, bool hold) : - cursor_base{t.conn(), cname}, - m_home{t.conn()}, - m_adopted{false}, - m_at_end{-1}, - m_pos{0} -{ - if (&t.conn() != &m_home) - throw internal_error{"Cursor in wrong connection"}; - - if (std::empty(query)) - throw usage_error{"Cursor has empty query."}; - auto const enc{enc_group(t.conn().encoding_id())}; - auto const qend{find_query_end(query, enc)}; - if (qend == 0) - throw usage_error{"Cursor has effectively empty query."}; - query.remove_suffix(std::size(query) - qend); - - std::string const cq{internal::concat( - "DECLARE "sv, t.quote_name(name()), " "sv, - ((ap == cursor_base::forward_only) ? "NO "sv : ""sv), "SCROLL CURSOR "sv, - (hold ? "WITH HOLD "sv : ""sv), "FOR "sv, query, " "sv, - ((up == cursor_base::update) ? "FOR UPDATE "sv : "FOR READ ONLY "sv))}; - - t.exec(cq); - - // Now that we're here in the starting position, keep a copy of an empty - // result. That may come in handy later, because we may not be able to - // construct an empty result with all the right metadata due to the weird - // meaning of "FETCH 0." - init_empty_result(t); - - m_ownership = op; -} - - -pqxx::internal::sql_cursor::sql_cursor( - transaction_base &t, std::string_view cname, - cursor_base::ownership_policy op) : - cursor_base{t.conn(), cname, false}, - m_home{t.conn()}, - m_empty_result{}, - m_adopted{true}, - m_at_end{0}, - m_pos{-1} -{ - m_adopted = true; - m_ownership = op; -} - - -void pqxx::internal::sql_cursor::close() noexcept -{ - if (m_ownership == cursor_base::owned) - { - try - { - gate::connection_sql_cursor{m_home}.exec( - internal::concat("CLOSE "sv, m_home.quote_name(name())).c_str()); - } - catch (std::exception const &) - {} - m_ownership = cursor_base::loose; - } -} - - -void pqxx::internal::sql_cursor::init_empty_result(transaction_base &t) -{ - if (pos() != 0) - throw internal_error{"init_empty_result() from bad pos()."}; - m_empty_result = - t.exec(internal::concat("FETCH 0 IN "sv, m_home.quote_name(name()))); -} - - -/// Compute actual displacement based on requested and reported displacements. -pqxx::internal::sql_cursor::difference_type pqxx::internal::sql_cursor::adjust( - difference_type hoped, difference_type actual) -{ - if (actual < 0) - throw internal_error{"Negative rows in cursor movement."}; - if (hoped == 0) - return 0; - int const direction{((hoped < 0) ? -1 : 1)}; - bool hit_end{false}; - if (actual != labs(hoped)) - { - if (actual > labs(hoped)) - throw internal_error{"Cursor displacement larger than requested."}; - - // If we see fewer rows than requested, then we've hit an end (on either - // side) of the result set. Wether we make an extra step to a one-past-end - // position or whether we're already there depends on where we were - // previously: if our last move was in the same direction and also fell - // short, we're already at a one-past-end row. - if (m_at_end != direction) - ++actual; - - // If we hit the beginning, make sure our position calculation ends up - // at zero (even if we didn't previously know where we were!), and if we - // hit the other end, register the fact that we now know where the end - // of the result set is. - if (direction > 0) - hit_end = true; - else if (m_pos == -1) - m_pos = actual; - else if (m_pos != actual) - throw internal_error{internal::concat( - "Moved back to beginning, but wrong position: hoped=", hoped, - ", actual=", actual, ", m_pos=", m_pos, ", direction=", direction, - ".")}; - - m_at_end = direction; - } - else - { - m_at_end = 0; - } - - if (m_pos >= 0) - m_pos += direction * actual; - if (hit_end) - { - if (m_endpos >= 0 and m_pos != m_endpos) - throw internal_error{"Inconsistent cursor end positions."}; - m_endpos = m_pos; - } - return direction * actual; -} - - -pqxx::result pqxx::internal::sql_cursor::fetch( - difference_type rows, difference_type &displacement) -{ - if (rows == 0) - { - displacement = 0; - return m_empty_result; - } - auto const query{pqxx::internal::concat( - "FETCH "sv, stridestring(rows), " IN "sv, m_home.quote_name(name()))}; - auto const r{gate::connection_sql_cursor{m_home}.exec(query.c_str())}; - displacement = adjust(rows, difference_type(std::size(r))); - return r; -} - - -pqxx::cursor_base::difference_type pqxx::internal::sql_cursor::move( - difference_type rows, difference_type &displacement) -{ - if (rows == 0) - { - displacement = 0; - return 0; - } - - auto const query{pqxx::internal::concat( - "MOVE "sv, stridestring(rows), " IN "sv, m_home.quote_name(name()))}; - auto const r{gate::connection_sql_cursor{m_home}.exec(query.c_str())}; - auto d{static_cast(r.affected_rows())}; - displacement = adjust(rows, d); - return d; -} - - -std::string pqxx::internal::sql_cursor::stridestring(difference_type n) -{ - /* Some special-casing for ALL and BACKWARD ALL here. We used to use numeric - * "infinities" for difference_type for this (the highest and lowest possible - * values for "long"), but for PostgreSQL 8.0 at least, the backend appears - * to expect a 32-bit number and fails to parse large 64-bit numbers. We - * could change the alias to match this behaviour, but that would break - * if/when Postgres is changed to accept 64-bit displacements. - */ - static std::string const All{"ALL"}, BackAll{"BACKWARD ALL"}; - if (n >= cursor_base::all()) - return All; - else if (n <= cursor_base::backward_all()) - return BackAll; - return to_string(n); -} diff --git a/ext/libpqxx-7.7.3/src/strconv.cxx b/ext/libpqxx-7.7.3/src/strconv.cxx deleted file mode 100644 index 2bd206b2a..000000000 --- a/ext/libpqxx-7.7.3/src/strconv.cxx +++ /dev/null @@ -1,785 +0,0 @@ -/** Implementation of string conversions. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/except.hxx" -#include "pqxx/strconv.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace -{ -#if !defined(PQXX_HAVE_CHARCONV_FLOAT) -/// Do we have fully functional thread_local support? -/** When building with libcxxrt on clang, you can't create thread_local objects - * of non-POD types. Any attempt will result in a link error. - */ -constexpr bool have_thread_local -{ -# if defined(PQXX_HAVE_THREAD_LOCAL) - true -# else - false -# endif -}; -#endif - - -/// String comparison between string_view. -constexpr inline bool equal(std::string_view lhs, std::string_view rhs) -{ - return lhs.compare(rhs) == 0; -} - - -/// The lowest possible value of integral type T. -template constexpr T bottom{std::numeric_limits::min()}; - -/// The highest possible value of integral type T. -template constexpr T top{std::numeric_limits::max()}; - -/// Write nonnegative integral value at end of buffer. Return start. -/** Assumes a sufficiently large buffer. - * - * Includes a single trailing null byte, right before @c *end. - */ -template constexpr inline char *nonneg_to_buf(char *end, T value) -{ - char *pos = end; - *--pos = '\0'; - do { - *--pos = pqxx::internal::number_to_digit(int(value % 10)); - value = T(value / 10); - } while (value > 0); - return pos; -} - - -/// Write negative version of value at end of buffer. Return start. -/** Like @c nonneg_to_buf, but prefixes a minus sign. - */ -template constexpr inline char *neg_to_buf(char *end, T value) -{ - char *pos = nonneg_to_buf(end, value); - *--pos = '-'; - return pos; -} - - -/// Write lowest possible negative value at end of buffer. -/** Like @c neg_to_buf, but for the special case of the bottom value. - */ -template constexpr inline char *bottom_to_buf(char *end) -{ - static_assert(std::is_signed_v); - - // This is the hard case. In two's-complement systems, which includes - // any modern-day system I can think of, a signed type's bottom value - // has no positive equivalent. Luckily the C++ standards committee can't - // think of any exceptions either, so it's the required representation as - // of C++20. We'll assume it right now, while still on C++17. - static_assert(-(bottom + 1) == top); - - // The unsigned version of T does have the unsigned version of bottom. - using unsigned_t = std::make_unsigned_t; - - // Careful though. If we tried to negate value in order to promote to - // unsigned_t, the value will overflow, which means behaviour is - // undefined. Promotion of a negative value to an unsigned type is - // well-defined, given a representation, so let's do that: - constexpr auto positive{static_cast(bottom)}; - - // As luck would have it, in two's complement, this gives us exactly the - // value we want. - static_assert(positive == top / 2 + 1); - - // So the only thing we need to do differently from the regular negative - // case is to skip that overflowing negation and promote to an unsigned type! - return neg_to_buf(end, positive); -} - - -#if defined(PQXX_HAVE_CHARCONV_INT) || defined(PQXX_HAVE_CHARCONV_FLOAT) -/// Call to_chars, report errors as exceptions, add zero, return pointer. -template -[[maybe_unused]] inline char * -wrap_to_chars(char *begin, char *end, T const &value) -{ - auto res{std::to_chars(begin, end - 1, value)}; - if (res.ec != std::errc()) - PQXX_UNLIKELY - switch (res.ec) - { - case std::errc::value_too_large: - throw pqxx::conversion_overrun{ - "Could not convert " + pqxx::type_name + - " to string: " - "buffer too small (" + - pqxx::to_string(end - begin) + " bytes)."}; - default: - throw pqxx::conversion_error{ - "Could not convert " + pqxx::type_name + " to string."}; - } - // No need to check for overrun here: we never even told to_chars about that - // last byte in the buffer, so it didn't get used up. - *res.ptr++ = '\0'; - return res.ptr; -} -#endif -} // namespace - - -namespace pqxx::internal -{ -template -zview integral_traits::to_buf(char *begin, char *end, T const &value) -{ - static_assert(std::is_integral_v); - auto const space{end - begin}, - need{static_cast(size_buffer(value))}; - if (space < need) - throw conversion_overrun{ - "Could not convert " + type_name + - " to string: " - "buffer too small. " + - pqxx::internal::state_buffer_overrun(space, need)}; - - char *pos; - if constexpr (std::is_unsigned_v) - pos = nonneg_to_buf(end, value); - else if (value >= 0) - pos = nonneg_to_buf(end, value); - else if (value > bottom) - pos = neg_to_buf(end, -value); - else - pos = bottom_to_buf(end); - - return {pos, end - pos - 1}; -} - - -template zview integral_traits::to_buf(char *, char *, short const &); -template zview integral_traits::to_buf( - char *, char *, unsigned short const &); -template zview integral_traits::to_buf(char *, char *, int const &); -template zview -integral_traits::to_buf(char *, char *, unsigned const &); -template zview integral_traits::to_buf(char *, char *, long const &); -template zview -integral_traits::to_buf(char *, char *, unsigned long const &); -template zview -integral_traits::to_buf(char *, char *, long long const &); -template zview integral_traits::to_buf( - char *, char *, unsigned long long const &); - - -template -char *integral_traits::into_buf(char *begin, char *end, T const &value) -{ -#if defined(PQXX_HAVE_CHARCONV_INT) - // This is exactly what to_chars is good at. Trust standard library - // implementers to optimise better than we can. - return wrap_to_chars(begin, end, value); -#else - return generic_into_buf(begin, end, value); -#endif -} - - -template char *integral_traits::into_buf(char *, char *, short const &); -template char *integral_traits::into_buf( - char *, char *, unsigned short const &); -template char *integral_traits::into_buf(char *, char *, int const &); -template char * -integral_traits::into_buf(char *, char *, unsigned const &); -template char *integral_traits::into_buf(char *, char *, long const &); -template char *integral_traits::into_buf( - char *, char *, unsigned long const &); -template char * -integral_traits::into_buf(char *, char *, long long const &); -template char *integral_traits::into_buf( - char *, char *, unsigned long long const &); -} // namespace pqxx::internal - - -namespace pqxx::internal -{ -std::string demangle_type_name(char const raw[]) -{ -#if defined(PQXX_HAVE_CXA_DEMANGLE) - // We've got __cxa_demangle. Use it to get a friendlier type name. - int status{0}; - - // We've seen this fail on FreeBSD 11.3 (see #361). Trying to throw a - // meaningful exception only made things worse. So in case of error, just - // fall back to the raw name. - // - // When __cxa_demangle fails, it's guaranteed to return null. - char *demangled{abi::__cxa_demangle(raw, nullptr, nullptr, &status)}; -#else - static constexpr char *demangled{nullptr}; -#endif - std::string const name{(demangled == nullptr) ? raw : demangled}; - - // Check for nullness to work around jemalloc bug (see #508). - if (demangled != nullptr) - std::free(demangled); - return name; -} - -void PQXX_COLD throw_null_conversion(std::string const &type) -{ - throw conversion_error{"Attempt to convert null to " + type + "."}; -} - - -std::string PQXX_COLD state_buffer_overrun(int have_bytes, int need_bytes) -{ - // We convert these in standard library terms, not for the localisation - // so much as to avoid "error cycles," if these values in turn should fail - // to get enough buffer space. - std::stringstream have, need; - have << have_bytes; - need << need_bytes; - return "Have " + have.str() + " bytes, need " + need.str() + "."; -} -} // namespace pqxx::internal - - -namespace -{ -#if defined(PQXX_HAVE_CHARCONV_INT) || defined(PQXX_HAVE_CHARCONV_FLOAT) -template -[[maybe_unused]] inline TYPE from_string_arithmetic(std::string_view in) -{ - char const *here; - auto const end{std::data(in) + std::size(in)}; - - // Skip whitespace. This is not the proper way to do it, but I see no way - // that any of the supported encodings could ever produce a valid character - // whose byte sequence would confuse this code. - for (here = std::data(in); here < end and (*here == ' ' or *here == '\t'); - ++here) - ; - - TYPE out{}; - auto const res{std::from_chars(here, end, out)}; - if (res.ec == std::errc() and res.ptr == end) - PQXX_LIKELY - return out; - - std::string msg; - if (res.ec == std::errc()) - { - msg = "Could not parse full string."; - } - else - { - switch (res.ec) - { - case std::errc::result_out_of_range: msg = "Value out of range."; break; - case std::errc::invalid_argument: msg = "Invalid argument."; break; - default: break; - } - } - - auto const base{ - "Could not convert '" + std::string(in) + - "' " - "to " + - pqxx::type_name}; - if (std::empty(msg)) - throw pqxx::conversion_error{base + "."}; - else - throw pqxx::conversion_error{base + ": " + msg}; -} -#endif -} // namespace - - -namespace -{ -#if !defined(PQXX_HAVE_CHARCONV_INT) -[[noreturn, maybe_unused]] void PQXX_COLD report_overflow() -{ - throw pqxx::conversion_error{ - "Could not convert string to integer: value out of range."}; -} - -template struct numeric_ten -{ - static inline constexpr T value = 10; -}; - -template struct numeric_high_threshold -{ - static inline constexpr T value = - (std::numeric_limits::max)() / numeric_ten::value; -}; - -template struct numeric_low_threshold -{ - static inline constexpr T value = - (std::numeric_limits::min)() / numeric_ten::value; -}; - -/// Return 10*n, or throw exception if it overflows. -template -[[maybe_unused]] constexpr inline T safe_multiply_by_ten(T n) -{ - using limits = std::numeric_limits; - - if (n > numeric_high_threshold::value) - PQXX_UNLIKELY - report_overflow(); - if constexpr (limits::is_signed) - { - if (numeric_low_threshold::value > n) - PQXX_UNLIKELY - report_overflow(); - } - return T(n * numeric_ten::value); -} - - -/// Add digit d to nonnegative n, or throw exception if it overflows. -template -[[maybe_unused]] constexpr inline T safe_add_digit(T n, T d) -{ - T const high_threshold{static_cast(std::numeric_limits::max() - d)}; - if (n > high_threshold) - PQXX_UNLIKELY - report_overflow(); - return static_cast(n + d); -} - - -/// Subtract digit d to nonpositive n, or throw exception if it overflows. -template -[[maybe_unused]] constexpr inline T safe_sub_digit(T n, T d) -{ - T const low_threshold{static_cast(std::numeric_limits::min() + d)}; - if (n < low_threshold) - PQXX_UNLIKELY - report_overflow(); - return static_cast(n - d); -} - - -/// For use in string parsing: add new numeric digit to intermediate value. -template -[[maybe_unused]] constexpr inline L absorb_digit_positive(L value, R digit) -{ - return safe_add_digit(safe_multiply_by_ten(value), L(digit)); -} - - -/// For use in string parsing: subtract digit from intermediate value. -template -[[maybe_unused]] constexpr inline L absorb_digit_negative(L value, R digit) -{ - return safe_sub_digit(safe_multiply_by_ten(value), L(digit)); -} - - -template -[[maybe_unused]] constexpr T from_string_integer(std::string_view text) -{ - if (std::size(text) == 0) - throw pqxx::conversion_error{ - "Attempt to convert empty string to " + pqxx::type_name + "."}; - - char const *const data{std::data(text)}; - std::size_t i{0}; - - // Skip whitespace. This is not the proper way to do it, but I see no way - // that any of the supported encodings could ever produce a valid character - // whose byte sequence would confuse this code. - // - // Why skip whitespace? Because that's how integral conversions are meant to - // work _for composite types._ I see no clean way to support leading - // whitespace there without putting the code in here. A shame about the - // overhead, modest as it is, for the normal case. - for (; i < std::size(text) and (data[i] == ' ' or data[i] == '\t'); ++i) - ; - if (i == std::size(text)) - throw pqxx::conversion_error{ - "Converting string to " + pqxx::type_name + - ", but it contains only whitespace."}; - - char const initial{data[i]}; - T result{0}; - - if (pqxx::internal::is_digit(initial)) - { - for (; pqxx::internal::is_digit(data[i]); ++i) - result = absorb_digit_positive( - result, pqxx::internal::digit_to_number(data[i])); - } - else if (initial == '-') - { - if constexpr (not std::is_signed_v) - throw pqxx::conversion_error{ - "Attempt to convert negative value to " + pqxx::type_name + "."}; - - ++i; - if (i >= std::size(text)) - throw pqxx::conversion_error{ - "Converting string to " + pqxx::type_name + - ", but it contains only a sign."}; - for (; i < std::size(text) and pqxx::internal::is_digit(data[i]); ++i) - result = absorb_digit_negative( - result, pqxx::internal::digit_to_number(data[i])); - } - else - { - throw pqxx::conversion_error{ - "Could not convert string to " + pqxx::type_name + - ": " - "'" + - std::string{text} + "'."}; - } - - if (i < std::size(text)) - throw pqxx::conversion_error{ - "Unexpected text after " + pqxx::type_name + - ": " - "'" + - std::string{text} + "'."}; - - return result; -} -#endif // !PQXX_HAVE_CHARCONV_INT -} // namespace - - -namespace -{ -[[maybe_unused]] constexpr bool -valid_infinity_string(std::string_view text) noexcept -{ - return equal("infinity", text) or equal("Infinity", text) or - equal("INFINITY", text) or equal("inf", text); -} -} // namespace - - -#if !defined(PQXX_HAVE_CHARCONV_FLOAT) -namespace -{ -/// Wrapper for std::stringstream with C locale. -/** We use this to work around missing std::to_chars for floating-point types. - * - * Initialising the stream (including locale and tweaked precision) seems to - * be expensive. So, create thread-local instances which we re-use. It's a - * lockless way of keeping global variables thread-safe, basically. - * - * The stream initialisation happens once per thread, in the constructor. - * And that's why we need to wrap this in a class. We can't just do it at the - * call site, or we'd still be doing it for every call. - */ -template class dumb_stringstream : public std::stringstream -{ -public: - // Do not initialise the base-class object using "stringstream{}" (with curly - // braces): that breaks on Visual C++. The classic "stringstream()" syntax - // (with parentheses) does work. - PQXX_COLD dumb_stringstream() - { - this->imbue(std::locale::classic()); - this->precision(std::numeric_limits::max_digits10); - } -}; - - -template -inline bool PQXX_COLD from_dumb_stringstream( - dumb_stringstream &s, F &result, std::string_view text) -{ - s.str(std::string{text}); - return static_cast(s >> result); -} - - -// These are hard, and some popular compilers still lack std::from_chars. -template -inline T PQXX_COLD from_string_awful_float(std::string_view text) -{ - if (std::empty(text)) - throw pqxx::conversion_error{ - "Trying to convert empty string to " + pqxx::type_name + "."}; - - bool ok{false}; - T result; - - switch (text[0]) - { - case 'N': - case 'n': - // Accept "NaN," "nan," etc. - ok = - (std::size(text) == 3 and (text[1] == 'A' or text[1] == 'a') and - (text[2] == 'N' or text[2] == 'n')); - result = std::numeric_limits::quiet_NaN(); - break; - - case 'I': - case 'i': - ok = valid_infinity_string(text); - result = std::numeric_limits::infinity(); - break; - - default: - if (text[0] == '-' and valid_infinity_string(text.substr(1))) - { - ok = true; - result = -std::numeric_limits::infinity(); - } - else - { - PQXX_LIKELY - if constexpr (have_thread_local) - { - thread_local dumb_stringstream S; - // Visual Studio 2017 seems to fail on repeated conversions if the - // clear() is done before the seekg(). Still don't know why! See #124 - // and #125. - S.seekg(0); - S.clear(); - ok = from_dumb_stringstream(S, result, text); - } - else - { - dumb_stringstream S; - ok = from_dumb_stringstream(S, result, text); - } - } - break; - } - - if (not ok) - throw pqxx::conversion_error{ - "Could not convert string to numeric value: '" + std::string{text} + - "'."}; - - return result; -} -} // namespace -#endif // !PQXX_HAVE_CHARCONV_FLOAT - - -namespace pqxx::internal -{ -/// Floating-point to_buf implemented in terms of to_string. -template -zview float_traits::to_buf(char *begin, char *end, T const &value) -{ -#if defined(PQXX_HAVE_CHARCONV_FLOAT) - { - // Definitely prefer to let the standard library handle this! - auto const ptr{wrap_to_chars(begin, end, value)}; - return zview{begin, std::size_t(ptr - begin - 1)}; - } -#else - { - // Implement it ourselves. Weird detail: since this workaround is based on - // std::stringstream, which produces a std::string, it's actually easier to - // build the to_buf() on top of the to_string() than the other way around. - if (std::isnan(value)) - return "nan"_zv; - if (std::isinf(value)) - return (value > 0) ? "infinity"_zv : "-infinity"_zv; - auto text{to_string_float(value)}; - auto have{end - begin}; - auto need{std::size(text) + 1}; - if (need > std::size_t(have)) - throw conversion_error{ - "Could not convert floating-point number to string: " - "buffer too small. " + - state_buffer_overrun(have, need)}; - text.copy(begin, need); - return zview{begin, std::size(text)}; - } -#endif -} - - -template zview float_traits::to_buf(char *, char *, float const &); -template zview float_traits::to_buf(char *, char *, double const &); -template zview -float_traits::to_buf(char *, char *, long double const &); - - -template -char *float_traits::into_buf(char *begin, char *end, T const &value) -{ -#if defined(PQXX_HAVE_CHARCONV_FLOAT) - return wrap_to_chars(begin, end, value); -#else - return generic_into_buf(begin, end, value); -#endif -} - - -template char *float_traits::into_buf(char *, char *, float const &); -template char *float_traits::into_buf(char *, char *, double const &); -template char * -float_traits::into_buf(char *, char *, long double const &); - - -#if !defined(PQXX_HAVE_CHARCONV_FLOAT) -template -inline std::string PQXX_COLD -to_dumb_stringstream(dumb_stringstream &s, F value) -{ - s.str(""); - s << value; - return s.str(); -} -#endif - - -/// Floating-point implementations for @c pqxx::to_string(). -template std::string to_string_float(T value) -{ -#if defined(PQXX_HAVE_CHARCONV_FLOAT) - { - static constexpr auto space{float_traits::size_buffer(value)}; - std::string buf; - buf.resize(space); - std::string_view const view{ - float_traits::to_buf(std::data(buf), std::data(buf) + space, value)}; - buf.resize(static_cast(std::end(view) - std::begin(view))); - return buf; - } -#else - { - // In this rare case, we can convert to std::string but not to a simple - // buffer. So, implement to_buf in terms of to_string instead of the other - // way around. - if constexpr (have_thread_local) - { - thread_local dumb_stringstream s; - return to_dumb_stringstream(s, value); - } - else - { - dumb_stringstream s; - return to_dumb_stringstream(s, value); - } - } -#endif -} -} // namespace pqxx::internal - - -namespace pqxx::internal -{ -template T integral_traits::from_string(std::string_view text) -{ -#if defined(PQXX_HAVE_CHARCONV_INT) - return from_string_arithmetic(text); -#else - return from_string_integer(text); -#endif -} - -template short integral_traits::from_string(std::string_view); -template unsigned short - integral_traits::from_string(std::string_view); -template int integral_traits::from_string(std::string_view); -template unsigned integral_traits::from_string(std::string_view); -template long integral_traits::from_string(std::string_view); -template unsigned long - integral_traits::from_string(std::string_view); -template long long integral_traits::from_string(std::string_view); -template unsigned long long - integral_traits::from_string(std::string_view); - - -template T float_traits::from_string(std::string_view text) -{ -#if defined(PQXX_HAVE_CHARCONV_FLOAT) - return from_string_arithmetic(text); -#else - return from_string_awful_float(text); -#endif -} - - -template float float_traits::from_string(std::string_view); -template double float_traits::from_string(std::string_view); -template long double float_traits::from_string(std::string_view); - - -template std::string to_string_float(float); -template std::string to_string_float(double); -template std::string to_string_float(long double); -} // namespace pqxx::internal - - -bool pqxx::string_traits::from_string(std::string_view text) -{ - std::optional result; - - switch (std::size(text)) - { - case 0: result = false; break; - - case 1: - switch (text[0]) - { - case 'f': - case 'F': - case '0': result = false; break; - - case 't': - case 'T': - case '1': result = true; break; - - default: break; - } - break; - - case 4: - if (equal(text, "true") or equal(text, "TRUE")) - result = true; - break; - - case 5: - if (equal(text, "false") or equal(text, "FALSE")) - result = false; - break; - - default: break; - } - - if (result) - return *result; - else - throw conversion_error{ - "Failed conversion to bool: '" + std::string{text} + "'."}; -} diff --git a/ext/libpqxx-7.7.3/src/stream_from.cxx b/ext/libpqxx-7.7.3/src/stream_from.cxx deleted file mode 100644 index f710300ea..000000000 --- a/ext/libpqxx-7.7.3/src/stream_from.cxx +++ /dev/null @@ -1,327 +0,0 @@ -/** Implementation of the pqxx::stream_from class. - * - * pqxx::stream_from enables optimized batch reads from a database table. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/internal/encodings.hxx" -#include "pqxx/internal/gates/connection-stream_from.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/transaction_base.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace -{ -pqxx::internal::glyph_scanner_func * -get_scanner(pqxx::transaction_base const &tx) -{ - auto const group{pqxx::internal::enc_group(tx.conn().encoding_id())}; - return pqxx::internal::get_glyph_scanner(group); -} - - -constexpr std::string_view class_name{"stream_from"}; -} // namespace - - -pqxx::stream_from::stream_from( - transaction_base &tx, from_query_t, std::string_view query) : - transaction_focus{tx, class_name}, m_glyph_scanner{get_scanner(tx)} -{ - tx.exec0(internal::concat("COPY ("sv, query, ") TO STDOUT"sv)); - register_me(); -} - - -pqxx::stream_from::stream_from( - transaction_base &tx, from_table_t, std::string_view table) : - transaction_focus{tx, class_name, table}, - m_glyph_scanner{get_scanner(tx)} -{ - tx.exec0(internal::concat("COPY "sv, tx.quote_name(table), " TO STDOUT"sv)); - register_me(); -} - - -pqxx::stream_from::stream_from( - transaction_base &tx, std::string_view table, std::string_view columns, - from_table_t) : - transaction_focus{tx, class_name, table}, - m_glyph_scanner{get_scanner(tx)} -{ - if (std::empty(columns)) - PQXX_UNLIKELY - tx.exec0(internal::concat("COPY "sv, table, " TO STDOUT"sv)); - else PQXX_LIKELY tx.exec0( - internal::concat("COPY "sv, table, "("sv, columns, ") TO STDOUT"sv)); - register_me(); -} - - -pqxx::stream_from::stream_from( - transaction_base &tx, std::string_view unquoted_table, - std::string_view columns, from_table_t, int) : - stream_from{ - tx, tx.conn().quote_table(unquoted_table), columns, from_table} -{} - - -pqxx::stream_from pqxx::stream_from::raw_table( - transaction_base &tx, std::string_view path, std::string_view columns) -{ - return {tx, path, columns, from_table}; -} - - -pqxx::stream_from pqxx::stream_from::table( - transaction_base &tx, table_path path, - std::initializer_list columns) -{ - auto const &conn{tx.conn()}; - return raw_table(tx, conn.quote_table(path), conn.quote_columns(columns)); -} - - -pqxx::stream_from::~stream_from() noexcept -{ - try - { - close(); - } - catch (std::exception const &e) - { - reg_pending_error(e.what()); - } -} - - -pqxx::stream_from::raw_line pqxx::stream_from::get_raw_line() -{ - if (*this) - { - internal::gate::connection_stream_from gate{m_trans.conn()}; - try - { - raw_line line{gate.read_copy_line()}; - if (line.first.get() == nullptr) - close(); - return line; - } - catch (std::exception const &) - { - close(); - throw; - } - } - else - { - return {}; - } -} - - -void pqxx::stream_from::close() -{ - if (not m_finished) - { - PQXX_UNLIKELY - m_finished = true; - unregister_me(); - } -} - - -void pqxx::stream_from::complete() -{ - if (m_finished) - return; - try - { - // Flush any remaining lines - libpq will automatically close the stream - // when it hits the end. - bool done{false}; - while (not done) - { - auto [line, size] = get_raw_line(); - ignore_unused(size); - done = not line.get(); - } - } - catch (broken_connection const &) - { - close(); - throw; - } - catch (std::exception const &e) - { - reg_pending_error(e.what()); - } - close(); -} - - -void pqxx::stream_from::parse_line() -{ - if (m_finished) - PQXX_UNLIKELY - return; - auto const next_seq{m_glyph_scanner}; - - m_fields.clear(); - - auto const [line, line_size] = get_raw_line(); - if (line.get() == nullptr) - { - m_finished = true; - return; - } - - if (line_size >= (std::numeric_limits::max() / 2)) - throw range_error{"Stream produced a ridiculously long line."}; - - // Make room for unescaping the line. It's a pessimistic size. - // Unusually, we're storing terminating zeroes *inside* the string. - // This is the only place where we modify m_row. MAKE SURE THE BUFFER DOES - // NOT GET RESIZED while we're working, because we're working with views into - // its buffer. - m_row.resize(line_size + 1); - - char const *line_begin{line.get()}; - char const *line_end{line_begin + line_size}; - char const *read{line_begin}; - - // Output iterator for unescaped text. - char *write{m_row.data()}; - - // The pointer cannot be null at this point. But we initialise field_begin - // with this value, and carry it around the loop, and it can later become - // null. Static analysis in clang-tidy then likes to assume a case where - // field_begin is null, and deduces from this that "write" must have been - // null -- and so it marks "*write" as a null pointer dereference. - // - // This assertion tells clang-tidy just what it needs in order to deduce - // that *write never dereferences a null pointer. - assert(write != nullptr); - - // Beginning of current field in m_row, or nullptr for null fields. - char const *field_begin{write}; - - while (read < line_end) - { - auto const offset{static_cast(read - line_begin)}; - auto const glyph_end{line_begin + next_seq(line_begin, line_size, offset)}; - // XXX: find_char<'\t', '\\'>(). - if (glyph_end == read + 1) - { - // Single-byte character. - char c{*read++}; - switch (c) - { - case '\t': // Field separator. - // End the field. - if (field_begin == nullptr) - { - m_fields.emplace_back(); - } - else - { - // Would love to emplace_back() here, but gcc 9.1 warns about the - // constructor not throwing. It suggests adding "noexcept." Which - // we can hardly do, without std::string_view guaranteeing it. - m_fields.push_back(zview{field_begin, write - field_begin}); - *write++ = '\0'; - } - field_begin = write; - break; - - PQXX_UNLIKELY - case '\\': { - // Escape sequence. - if (read >= line_end) - throw failure{"Row ends in backslash"}; - - c = *read++; - switch (c) - { - case 'N': - // Null value. - if (write != field_begin) - throw failure{"Null sequence found in nonempty field"}; - field_begin = nullptr; - // (If there's any characters _after_ the null we'll just crash.) - break; - - case 'b': // Backspace. - PQXX_UNLIKELY - *write++ = '\b'; - break; - case 'f': // Form feed - PQXX_UNLIKELY - *write++ = '\f'; - break; - case 'n': // Line feed. - *write++ = '\n'; - break; - case 'r': // Carriage return. - *write++ = '\r'; - break; - case 't': // Horizontal tab. - *write++ = '\t'; - break; - case 'v': // Vertical tab. - *write++ = '\v'; - break; - - default: - PQXX_LIKELY - // Regular character ("self-escaped"). - *write++ = c; - break; - } - } - break; - - PQXX_LIKELY - default: *write++ = c; break; - } - } - else - { - // Multi-byte sequence. Never treated specially, so just append. - while (read < glyph_end) *write++ = *read++; - } - } - - // End the last field here. - if (field_begin == nullptr) - { - m_fields.emplace_back(); - } - else - { - m_fields.push_back(zview{field_begin, write - field_begin}); - *write++ = '\0'; - } - - // DO NOT shrink m_row to fit. We're carrying string_views pointing into - // the buffer. (Also, how useful would shrinking really be?) -} - - -std::vector const *pqxx::stream_from::read_row() & -{ - parse_line(); - return m_finished ? nullptr : &m_fields; -} diff --git a/ext/libpqxx-7.7.3/src/stream_to.cxx b/ext/libpqxx-7.7.3/src/stream_to.cxx deleted file mode 100644 index 1693ba377..000000000 --- a/ext/libpqxx-7.7.3/src/stream_to.cxx +++ /dev/null @@ -1,170 +0,0 @@ -/** Implementation of the pqxx::stream_to class. - * - * pqxx::stream_to enables optimized batch updates to a database table. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/gates/connection-stream_to.hxx" -#include "pqxx/stream_from.hxx" -#include "pqxx/stream_to.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace -{ -using namespace std::literals; - -void begin_copy( - pqxx::transaction_base &tx, std::string_view table, std::string_view columns) -{ - tx.exec0( - std::empty(columns) ? - pqxx::internal::concat("COPY "sv, table, " FROM STDIN"sv) : - pqxx::internal::concat( - "COPY "sv, table, "("sv, columns, ") FROM STDIN"sv)); -} -} // namespace - - -pqxx::stream_to::~stream_to() noexcept -{ - try - { - complete(); - } - catch (std::exception const &e) - { - reg_pending_error(e.what()); - } -} - - -void pqxx::stream_to::write_raw_line(std::string_view text) -{ - internal::gate::connection_stream_to{m_trans.conn()}.write_copy_line(text); -} - - -void pqxx::stream_to::write_buffer() -{ - if (not std::empty(m_buffer)) - { - // In append_to_buffer() we write a tab after each field. We only want a - // tab _between_ fields. Remove that last one. - assert(m_buffer[std::size(m_buffer) - 1] == '\t'); - m_buffer.resize(std::size(m_buffer) - 1); - } - write_raw_line(m_buffer); - m_buffer.clear(); -} - - -pqxx::stream_to &pqxx::stream_to::operator<<(stream_from &tr) -{ - while (tr) - { - const auto [line, size] = tr.get_raw_line(); - if (line.get() == nullptr) - break; - write_raw_line(std::string_view{line.get(), size}); - } - return *this; -} - - -pqxx::stream_to::stream_to( - transaction_base &tx, std::string_view path, std::string_view columns) : - transaction_focus{tx, s_classname, path}, - m_scanner{get_glyph_scanner( - pqxx::internal::enc_group(tx.conn().encoding_id()))} -{ - begin_copy(tx, path, columns); - register_me(); -} - - -void pqxx::stream_to::complete() -{ - if (!m_finished) - { - m_finished = true; - unregister_me(); - internal::gate::connection_stream_to{m_trans.conn()}.end_copy_write(); - } -} - - -/// Return escape letter for c's backslash sequence, or 0 if not needed. -/** The API is a bit weird: you pass the width of the character, and its first - * byte. That's because we never need to escape a multibyte character anyway. - */ -constexpr char escape(std::size_t width, char c) -{ - if (width == 1u) - switch (c) - { - case '\b': return 'b'; - case '\f': return 'f'; - case '\n': return 'n'; - case '\r': return 'r'; - case '\t': return 't'; - case '\v': return 'v'; - case '\\': return '\\'; - } - - PQXX_LIKELY - return '\0'; -} - - -void pqxx::stream_to::escape_field_to_buffer(std::string_view data) -{ - if (not std::empty(data)) - { - // Mark the beginning of a stretch that we can copy into our buffer in one - // go. It feels like a waste to invoke generic multi-byte copies for every - // individual character in this loop, most of them actually probably only - // one byte long. - std::size_t begin_stretch{0}; - - std::size_t begin_char{0}, end; - // XXX: find_char<'\b', '\f', '\n', '\r', '\t', \v', '\\'>(). - for (end = m_scanner(std::data(data), std::size(data), begin_char); - begin_char < std::size(data); begin_char = end, - end = m_scanner(std::data(data), std::size(data), begin_char)) - { - // Escape sequence letter, if needed. - char const esc{escape(end - begin_char, data[begin_char])}; - if (esc != '\0') - { - // This character needs escaping. So, it ends any trivially copyable - // stretch that we may have been having. - - // Copy the stretch we've built up into our buffer. - m_buffer.append( - std::data(data) + begin_stretch, begin_char - begin_stretch); - - // Escape the current character. - m_buffer.push_back('\\'); - m_buffer.push_back(esc); - - // Start a new stretch, right after the current character. - begin_stretch = end; - } - } - // Copy the final stretch. - m_buffer.append( - std::data(data) + begin_stretch, begin_char - begin_stretch); - } - m_buffer.push_back('\t'); -} diff --git a/ext/libpqxx-7.7.3/src/subtransaction.cxx b/ext/libpqxx-7.7.3/src/subtransaction.cxx deleted file mode 100644 index 186ad13e8..000000000 --- a/ext/libpqxx-7.7.3/src/subtransaction.cxx +++ /dev/null @@ -1,68 +0,0 @@ -/** Implementation of the pqxx::subtransaction class. - * - * pqxx::transaction is a nested transaction, i.e. one within a transaction - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/connection.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/subtransaction.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace -{ -using namespace std::literals; -constexpr std::string_view class_name{"subtransaction"sv}; -} // namespace - - -pqxx::subtransaction::subtransaction( - dbtransaction &t, std::string_view tname) : - transaction_focus{t, class_name, t.conn().adorn_name(tname)}, - // We can't initialise the rollback command here, because we don't yet - // have a full object to implement quoted_name(). - dbtransaction{t.conn(), tname, std::shared_ptr{}} -{ - set_rollback_cmd(std::make_shared( - internal::concat("ROLLBACK TO SAVEPOINT ", quoted_name()))); - direct_exec(std::make_shared( - internal::concat("SAVEPOINT ", quoted_name()))); -} - - -namespace -{ -using dbtransaction_ref = pqxx::dbtransaction &; -} - - -pqxx::subtransaction::subtransaction( - subtransaction &t, std::string_view tname) : - subtransaction(dbtransaction_ref(t), tname) -{} - - -pqxx::subtransaction::~subtransaction() noexcept -{ - close(); -} - - -void pqxx::subtransaction::do_commit() -{ - direct_exec(std::make_shared( - internal::concat("RELEASE SAVEPOINT ", quoted_name()))); -} diff --git a/ext/libpqxx-7.7.3/src/time.cxx b/ext/libpqxx-7.7.3/src/time.cxx deleted file mode 100644 index 6b3ffdb1c..000000000 --- a/ext/libpqxx-7.7.3/src/time.cxx +++ /dev/null @@ -1,226 +0,0 @@ -/** Implementation of date/time support. - */ -#include "pqxx-source.hxx" - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/time.hxx" - -#include "pqxx/internal/header-post.hxx" - -// std::chrono::year_month_day is C++20, so let's worry a bit less about C++17 -// compatibility in this file. -#if defined(PQXX_HAVE_YEAR_MONTH_DAY) -namespace -{ -using namespace std::literals; - - -/// Render the numeric part of a year value into a buffer. -/** Converts the year from "common era" (with a Year Zero) to "anno domini" - * (without a Year Zero). - * - * Doesn't render the sign. When you're rendering a date, you indicate a - * negative year by suffixing "BC" at the very end. - * - * Where @c string_traits::into_buf() returns a pointer to the position right - * after the terminating zero, this function returns a pointer to the character - * right after the last digit. (It may or may not write a terminating zero at - * that position itself.) - */ -inline char * -year_into_buf(char *begin, char *end, std::chrono::year const &value) -{ - int const y{value}; - if (y == int{(std::chrono::year::min)()}) - { - // This is an evil special case: C++ year -32767 translates to 32768 BC, - // which is a number we can't fit into a short. At the moment postgres - // doesn't handle years before 4713 BC, but who knows, right? - static_assert(int{(std::chrono::year::min)()} == -32767); - constexpr auto hardcoded{"32768"sv}; - PQXX_UNLIKELY - begin += hardcoded.copy(begin, std::size(hardcoded)); - } - else - { - // C++ std::chrono::year has a year zero. PostgreSQL does not. So, C++ - // year zero is 1 BC in the postgres calendar; C++ 1 BC is postgres 2 BC, - // and so on. - auto const absy{static_cast(std::abs(y) + int{y <= 0})}; - - // PostgreSQL requires year input to be at least 3 digits long, or it - // won't be able to deduce the date format correctly. However on output - // it always writes years as at least 4 digits, and we'll do the same. - // Dates and times are a dirty, dirty business. - if (absy < 1000) - { - PQXX_UNLIKELY - *begin++ = '0'; - if (absy < 100) - *begin++ = '0'; - if (absy < 10) - *begin++ = '0'; - } - begin = pqxx::string_traits::into_buf(begin, end, absy) - 1; - } - return begin; -} - - -/// Parse the numeric part of a year value. -inline int year_from_buf(std::string_view text) -{ - if (std::size(text) < 4) - throw pqxx::conversion_error{ - pqxx::internal::concat("Year field is too small: '", text, "'.")}; - // Parse as int, so we can accommodate 32768 BC which won't fit in a short - // as-is, but equates to 32767 BCE which will. - int const year{pqxx::string_traits::from_string(text)}; - if (year <= 0) - throw pqxx::conversion_error{ - pqxx::internal::concat("Bad year: '", text, "'.")}; - return year; -} - - -/// Render a valid 1-based month number into a buffer. -/* Where @c string_traits::into_buf() returns a pointer to the position right - * after the terminating zero, this function returns a pointer to the character - * right after the last digit. (It may or may not write a terminating zero at - * that position itself.) - */ -inline static char * -month_into_buf(char *begin, std::chrono::month const &value) -{ - unsigned const m{value}; - if (m >= 10) - *begin = '1'; - else - *begin = '0'; - ++begin; - *begin++ = pqxx::internal::number_to_digit(static_cast(m % 10)); - return begin; -} - - -/// Parse a 1-based month value. -inline std::chrono::month month_from_string(std::string_view text) -{ - if ( - not pqxx::internal::is_digit(text[0]) or - not pqxx::internal::is_digit(text[1])) - throw pqxx::conversion_error{ - pqxx::internal::concat("Invalid month: '", text, "'.")}; - return std::chrono::month{unsigned( - (10 * pqxx::internal::digit_to_number(text[0])) + - pqxx::internal::digit_to_number(text[1]))}; -} - - -/// Render a valid 1-based day-of-month value into a buffer. -inline char *day_into_buf(char *begin, std::chrono::day const &value) -{ - unsigned d{value}; - *begin++ = pqxx::internal::number_to_digit(static_cast(d / 10)); - *begin++ = pqxx::internal::number_to_digit(static_cast(d % 10)); - return begin; -} - - -/// Parse a 1-based day-of-month value. -inline std::chrono::day day_from_string(std::string_view text) -{ - if ( - not pqxx::internal::is_digit(text[0]) or - not pqxx::internal::is_digit(text[1])) - throw pqxx::conversion_error{ - pqxx::internal::concat("Bad day in date: '", text, "'.")}; - std::chrono::day const d{unsigned( - (10 * pqxx::internal::digit_to_number(text[0])) + - pqxx::internal::digit_to_number(text[1]))}; - if (not d.ok()) - throw pqxx::conversion_error{ - pqxx::internal::concat("Bad day in date: '", text, "'.")}; - return d; -} - - -/// Look for the dash separating year and month. -/** Assumes that @c text is nonempty. - */ -inline std::size_t find_year_month_separator(std::string_view text) noexcept -{ - // We're looking for a dash. PostgreSQL won't output a negative year, so - // no worries about a leading dash. We could start searching at offset 4, - // but starting at the beginning produces more helpful error messages for - // malformed years. - std::size_t here; - for (here = 0; here < std::size(text) and text[here] != '-'; ++here) - ; - return here; -} - - -/// Componse generic "invalid date" message for given (invalid) date text. -std::string make_parse_error(std::string_view text) -{ - return pqxx::internal::concat("Invalid date: '", text, "'."); -} -} // namespace - - -namespace pqxx -{ -char *string_traits::into_buf( - char *begin, char *end, std::chrono::year_month_day const &value) -{ - if (std::size_t(end - begin) < size_buffer(value)) - throw conversion_overrun{"Not enough room in buffer for date."}; - begin = year_into_buf(begin, end, value.year()); - *begin++ = '-'; - begin = month_into_buf(begin, value.month()); - *begin++ = '-'; - begin = day_into_buf(begin, value.day()); - if (int{value.year()} <= 0) - { - PQXX_UNLIKELY - begin += s_bc.copy(begin, std::size(s_bc)); - } - *begin++ = '\0'; - return begin; -} - - -std::chrono::year_month_day -string_traits::from_string(std::string_view text) -{ - // We can't just re-use the std::chrono::year conversions, because the "BC" - // suffix comes at the very end. - if (std::size(text) < 9) - throw conversion_error{make_parse_error(text)}; - bool const is_bc{text.ends_with(s_bc)}; - if (is_bc) - PQXX_UNLIKELY - text = text.substr(0, std::size(text) - std::size(s_bc)); - auto const ymsep{find_year_month_separator(text)}; - if ((std::size(text) - ymsep) != 6) - throw conversion_error{make_parse_error(text)}; - auto const base_year{ - year_from_buf(std::string_view{std::data(text), ymsep})}; - if (base_year == 0) - throw conversion_error{"Year zero conversion."}; - std::chrono::year const y{is_bc ? (-base_year + 1) : base_year}; - auto const m{month_from_string(text.substr(ymsep + 1, 2))}; - if (text[ymsep + 3] != '-') - throw conversion_error{make_parse_error(text)}; - auto const d{day_from_string(text.substr(ymsep + 4, 2))}; - std::chrono::year_month_day const date{y, m, d}; - if (not date.ok()) - throw conversion_error{make_parse_error(text)}; - return date; -} -} // namespace pqxx -#endif diff --git a/ext/libpqxx-7.7.3/src/transaction.cxx b/ext/libpqxx-7.7.3/src/transaction.cxx deleted file mode 100644 index 61ed29ef7..000000000 --- a/ext/libpqxx-7.7.3/src/transaction.cxx +++ /dev/null @@ -1,107 +0,0 @@ -/** Implementation of the pqxx::transaction class. - * - * pqxx::transaction represents a regular database transaction. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/connection.hxx" -#include "pqxx/result.hxx" -#include "pqxx/transaction.hxx" - -#include "pqxx/internal/header-post.hxx" - - -pqxx::internal::basic_transaction::basic_transaction( - connection &c, zview begin_command, std::string_view tname) : - dbtransaction(c, tname) -{ - register_transaction(); - direct_exec(begin_command); -} - - -pqxx::internal::basic_transaction::basic_transaction( - connection &c, zview begin_command, std::string &&tname) : - dbtransaction(c, std::move(tname)) -{ - register_transaction(); - direct_exec(begin_command); -} - - -pqxx::internal::basic_transaction::basic_transaction( - connection &c, zview begin_command) : - dbtransaction(c) -{ - register_transaction(); - direct_exec(begin_command); -} - - -// This should stop the compiler from generating the same vtables and -// destructor in multiple translation units. More importantly, if we don't do -// this, the sanitisers in g++ 7 and clang++ 6 complain about pointers to -// dbtransaction actually pointing to basic_transaction. Which is odd, in that -// any basic_transaction pointer should also be a dbtransaction pointer. But, -// apparently the vtable isn't the right one. -pqxx::internal::basic_transaction::~basic_transaction() noexcept = default; - - -void pqxx::internal::basic_transaction::do_commit() -{ - static auto const commit_q{std::make_shared("COMMIT"sv)}; - try - { - direct_exec(commit_q); - } - catch (statement_completion_unknown const &e) - { - // Outcome of "commit" is unknown. This is a disaster: we don't know the - // resulting state of the database. - process_notice(internal::concat(e.what(), "\n")); - - std::string msg{internal::concat( - "WARNING: Commit of transaction '", name(), - "' is unknown. " - "There is no way to tell whether the transaction succeeded " - "or was aborted except to check manually.\n")}; - process_notice(msg); - // Strip newline. It was only needed for process_notice(). - msg.pop_back(); - throw in_doubt_error{std::move(msg)}; - } - catch (std::exception const &e) - { - if (not conn().is_open()) - { - // We've lost the connection while committing. There is just no way of - // telling what happened on the other end. >8-O - process_notice(internal::concat(e.what(), "\n")); - - auto msg{internal::concat( - "WARNING: Connection lost while committing transaction '", name(), - "'. There is no way to tell whether the transaction succeeded " - "or was aborted except to check manually.\n")}; - process_notice(msg); - // Strip newline. It was only needed for process_notice(). - msg.pop_back(); - throw in_doubt_error{std::move(msg)}; - } - else - { - // Commit failed--probably due to a constraint violation or something - // similar. - throw; - } - } -} diff --git a/ext/libpqxx-7.7.3/src/transaction_base.cxx b/ext/libpqxx-7.7.3/src/transaction_base.cxx deleted file mode 100644 index c7d01ac08..000000000 --- a/ext/libpqxx-7.7.3/src/transaction_base.cxx +++ /dev/null @@ -1,539 +0,0 @@ -/** Common code and definitions for the transaction classes. - * - * pqxx::transaction_base defines the interface for any abstract class that - * represents a database transaction. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/connection.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/internal/encodings.hxx" -#include "pqxx/internal/gates/connection-transaction.hxx" -#include "pqxx/internal/gates/transaction-transaction_focus.hxx" -#include "pqxx/result.hxx" -#include "pqxx/transaction_base.hxx" -#include "pqxx/transaction_focus.hxx" - -#include "pqxx/internal/header-post.hxx" - - -using namespace std::literals; - -namespace -{ -/// Return a query pointer for the command "ROLLBACK". -/** Concentrates constructions so as to minimise the number of allocations. - * This way, the string gets allocated once and then all subsequent invocations - * copy shared_ptr instances to the same string. - */ -std::shared_ptr make_rollback_cmd() -{ - static auto const cmd{std::make_shared("ROLLBACK")}; - return cmd; -} -} // namespace - -pqxx::transaction_base::transaction_base(connection &c) : - m_conn{c}, m_rollback_cmd{make_rollback_cmd()} -{} - - -pqxx::transaction_base::transaction_base( - connection &c, std::string_view tname) : - m_conn{c}, m_name{tname}, m_rollback_cmd{make_rollback_cmd()} -{} - - -pqxx::transaction_base::~transaction_base() -{ - try - { - if (not std::empty(m_pending_error)) - PQXX_UNLIKELY - process_notice( - internal::concat("UNPROCESSED ERROR: ", m_pending_error, "\n")); - - if (m_registered) - { - m_conn.process_notice( - internal::concat(description(), " was never closed properly!\n")); - pqxx::internal::gate::connection_transaction{conn()} - .unregister_transaction(this); - } - } - catch (std::exception const &e) - { - try - { - process_notice(internal::concat(e.what(), "\n")); - } - catch (std::exception const &) - { - process_notice(e.what()); - } - } -} - - -void pqxx::transaction_base::register_transaction() -{ - pqxx::internal::gate::connection_transaction{conn()}.register_transaction( - this); - m_registered = true; -} - - -void pqxx::transaction_base::commit() -{ - check_pending_error(); - - // Check previous status code. Caller should only call this function if - // we're in "implicit" state, but multiple commits are silently accepted. - switch (m_status) - { - case status::active: // Just fine. This is what we expect. - break; - - case status::aborted: - throw usage_error{internal::concat( - "Attempt to commit previously aborted ", description())}; - - case status::committed: - // Transaction has been committed already. This is not exactly proper - // behaviour, but throwing an exception here would only give the impression - // that an abort is needed--which would only confuse things further at this - // stage. - // Therefore, multiple commits are accepted, though under protest. - m_conn.process_notice( - internal::concat(description(), " committed more than once.\n")); - return; - - case status::in_doubt: - // Transaction may or may not have been committed. The only thing we can - // really do is keep telling the caller that the transaction is in doubt. - throw in_doubt_error{internal::concat( - description(), " committed again while in an indeterminate state.")}; - - default: throw internal_error{"pqxx::transaction: invalid status code."}; - } - - // Tricky one. If stream is nested in transaction but inside the same scope, - // the commit() will come before the stream is closed. Which means the - // commit is premature. Punish this swiftly and without fail to discourage - // the habit from forming. - if (m_focus != nullptr) - throw failure{internal::concat( - "Attempt to commit ", description(), " with ", m_focus->description(), - " still open.")}; - - // Check that we're still connected (as far as we know--this is not an - // absolute thing!) before trying to commit. If the connection was broken - // already, the commit would fail anyway but this way at least we don't - // remain in-doubt as to whether the backend got the commit order at all. - if (not m_conn.is_open()) - throw broken_connection{ - "Broken connection to backend; cannot complete transaction."}; - - try - { - do_commit(); - m_status = status::committed; - } - catch (in_doubt_error const &) - { - m_status = status::in_doubt; - throw; - } - catch (std::exception const &) - { - m_status = status::aborted; - throw; - } - - close(); -} - - -void pqxx::transaction_base::do_abort() -{ - if (m_rollback_cmd) - direct_exec(m_rollback_cmd); -} - - -void pqxx::transaction_base::abort() -{ - // Check previous status code. Quietly accept multiple aborts to - // simplify emergency bailout code. - switch (m_status) - { - case status::active: - try - { - do_abort(); - } - catch (std::exception const &e) - { - m_conn.process_notice(internal::concat(e.what(), "\n")); - } - break; - - case status::aborted: return; - - case status::committed: - throw usage_error{internal::concat( - "Attempt to abort previously committed ", description())}; - - case status::in_doubt: - // Aborting an in-doubt transaction is probably a reasonably sane response - // to an insane situation. Log it, but do not fail. - m_conn.process_notice(internal::concat( - "Warning: ", description(), - " aborted after going into indeterminate state; " - "it may have been executed anyway.\n")); - return; - - default: throw internal_error{"Invalid transaction status."}; - } - - m_status = status::aborted; - close(); -} - - -std::string PQXX_COLD pqxx::transaction_base::quote_raw(zview bin) const -{ - return conn().quote(binary_cast(bin)); -} - - -namespace -{ -/// Guard command execution against clashes with pipelines and such. -/** A transaction can have only one focus at a time. Command execution is the - * most basic example of a transaction focus. - */ -class PQXX_PRIVATE command : pqxx::transaction_focus -{ -public: - command(pqxx::transaction_base &tx, std::string_view oname) : - transaction_focus{tx, "command"sv, oname} - { - register_me(); - } - - ~command() { unregister_me(); } -}; -} // namespace - -pqxx::result -pqxx::transaction_base::exec(std::string_view query, std::string_view desc) -{ - check_pending_error(); - - command cmd{*this, desc}; - - switch (m_status) - { - case status::active: break; - - case status::committed: - case status::aborted: - case status::in_doubt: { - std::string const n{ - std::empty(desc) ? "" : internal::concat("'", desc, "' ")}; - - throw usage_error{internal::concat( - "Could not execute command ", n, ": transaction is already closed.")}; - } - - default: throw internal_error{"pqxx::transaction: invalid status code."}; - } - - return direct_exec(query, desc); -} - - -pqxx::result pqxx::transaction_base::exec_n( - result::size_type rows, zview query, std::string_view desc) -{ -#include "pqxx/internal/ignore-deprecated-pre.hxx" - result const r{exec(query, desc)}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - if (std::size(r) != rows) - { - std::string const N{ - std::empty(desc) ? "" : internal::concat("'", desc, "'")}; - throw unexpected_rows{internal::concat( - "Expected ", rows, " row(s) of data from query ", N, ", got ", - std::size(r), ".")}; - } - return r; -} - - -void pqxx::transaction_base::check_rowcount_prepared( - zview statement, result::size_type expected_rows, - result::size_type actual_rows) -{ - if (actual_rows != expected_rows) - throw unexpected_rows{internal::concat( - "Expected ", expected_rows, " row(s) of data from prepared statement '", - statement, "', got ", actual_rows, ".")}; -} - - -void pqxx::transaction_base::check_rowcount_params( - std::size_t expected_rows, std::size_t actual_rows) -{ - if (actual_rows != expected_rows) - throw unexpected_rows{internal::concat( - "Expected ", expected_rows, - " row(s) of data from parameterised query, got ", actual_rows, ".")}; -} - - -pqxx::result pqxx::transaction_base::internal_exec_prepared( - zview statement, internal::c_params const &args) -{ - command cmd{*this, statement}; - return pqxx::internal::gate::connection_transaction{conn()}.exec_prepared( - statement, args); -} - - -pqxx::result pqxx::transaction_base::internal_exec_params( - zview query, internal::c_params const &args) -{ - command cmd{*this, query}; - return pqxx::internal::gate::connection_transaction{conn()}.exec_params( - query, args); -} - - -void pqxx::transaction_base::set_variable( - std::string_view var, std::string_view value) -{ -#include "pqxx/internal/ignore-deprecated-pre.hxx" - conn().set_variable(var, value); -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -std::string pqxx::transaction_base::get_variable(std::string_view var) -{ -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return conn().get_variable(var); -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -void pqxx::transaction_base::close() noexcept -{ - try - { - try - { - check_pending_error(); - } - catch (std::exception const &e) - { - m_conn.process_notice(e.what()); - } - - if (m_registered) - { - m_registered = false; - pqxx::internal::gate::connection_transaction{conn()} - .unregister_transaction(this); - } - - if (m_status != status::active) - return; - - if (m_focus != nullptr) - PQXX_UNLIKELY - m_conn.process_notice(internal::concat( - "Closing ", description(), " with ", m_focus->description(), - " still open.\n")); - - try - { - abort(); - } - catch (std::exception const &e) - { - m_conn.process_notice(e.what()); - } - } - catch (std::exception const &e) - { - try - { - m_conn.process_notice(e.what()); - } - catch (std::exception const &) - {} - } -} - - -namespace -{ -[[nodiscard]] std::string_view -get_classname(pqxx::transaction_focus const *focus) -{ - return (focus == nullptr) ? ""sv : focus->classname(); -} - - -[[nodiscard]] std::string_view -get_obj_name(pqxx::transaction_focus const *focus) -{ - return (focus == nullptr) ? ""sv : focus->name(); -} -} // namespace - - -void pqxx::transaction_base::register_focus(transaction_focus *new_focus) -{ - internal::check_unique_register( - m_focus, get_classname(m_focus), get_obj_name(m_focus), new_focus, - get_classname(new_focus), get_obj_name(new_focus)); - m_focus = new_focus; -} - - -void pqxx::transaction_base::unregister_focus( - transaction_focus *new_focus) noexcept -{ - try - { - pqxx::internal::check_unique_unregister( - m_focus, get_classname(m_focus), get_obj_name(m_focus), new_focus, - get_classname(new_focus), get_obj_name(new_focus)); - m_focus = nullptr; - } - catch (std::exception const &e) - { - m_conn.process_notice(internal::concat(e.what(), "\n")); - } -} - - -pqxx::result pqxx::transaction_base::direct_exec( - std::string_view cmd, std::string_view desc) -{ - check_pending_error(); - return pqxx::internal::gate::connection_transaction{conn()}.exec(cmd, desc); -} - - -pqxx::result pqxx::transaction_base::direct_exec( - std::shared_ptr cmd, std::string_view desc) -{ - check_pending_error(); - return pqxx::internal::gate::connection_transaction{conn()}.exec(cmd, desc); -} - - -void pqxx::transaction_base::register_pending_error(zview err) noexcept -{ - if (std::empty(m_pending_error) and not std::empty(err)) - { - try - { - m_pending_error = err; - } - catch (std::exception const &e) - { - try - { - PQXX_UNLIKELY - process_notice("UNABLE TO PROCESS ERROR\n"); - process_notice(e.what()); - process_notice("ERROR WAS:"); - process_notice(err); - } - catch (...) - {} - } - } -} - - -void pqxx::transaction_base::register_pending_error(std::string &&err) noexcept -{ - if (std::empty(m_pending_error) and not std::empty(err)) - { - try - { - m_pending_error = std::move(err); - } - catch (std::exception const &e) - { - try - { - PQXX_UNLIKELY - process_notice("UNABLE TO PROCESS ERROR\n"); - process_notice(e.what()); - process_notice("ERROR WAS:"); - process_notice(err); - } - catch (...) - {} - } - } -} - - -void pqxx::transaction_base::check_pending_error() -{ - if (not std::empty(m_pending_error)) - { - std::string err; - err.swap(m_pending_error); - throw failure{err}; - } -} - - -std::string pqxx::transaction_base::description() const -{ - return internal::describe_object("transaction", name()); -} - - -void pqxx::transaction_focus::register_me() -{ - pqxx::internal::gate::transaction_transaction_focus{m_trans}.register_focus( - this); - m_registered = true; -} - - -void pqxx::transaction_focus::unregister_me() noexcept -{ - pqxx::internal::gate::transaction_transaction_focus{m_trans} - .unregister_focus(this); - m_registered = false; -} - - -void pqxx::transaction_focus::reg_pending_error( - std::string const &err) noexcept -{ - pqxx::internal::gate::transaction_transaction_focus{m_trans} - .register_pending_error(err); -} diff --git a/ext/libpqxx-7.7.3/src/util.cxx b/ext/libpqxx-7.7.3/src/util.cxx deleted file mode 100644 index fe859bd2a..000000000 --- a/ext/libpqxx-7.7.3/src/util.cxx +++ /dev/null @@ -1,194 +0,0 @@ -/** Various utility functions. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include -#include -#include -#include -#include - -extern "C" -{ -#include -} - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/except.hxx" -#include "pqxx/internal/concat.hxx" -#include "pqxx/util.hxx" - -#include "pqxx/internal/header-post.hxx" - - -using namespace std::literals; - -pqxx::thread_safety_model PQXX_COLD pqxx::describe_thread_safety() -{ - thread_safety_model model; - model.safe_libpq = (PQisthreadsafe() != 0); - // Sadly I'm not aware of any way to avoid this just yet. - model.safe_kerberos = false; - - model.description = internal::concat( - (model.safe_libpq ? ""sv : - "Using a libpq build that is not thread-safe.\n"sv), - (model.safe_kerberos ? - ""sv : - "Kerberos is not thread-safe. If your application uses Kerberos, " - "protect all calls to Kerberos or libpqxx using a global lock.\n"sv)); - return model; -} - - -std::string pqxx::internal::describe_object( - std::string_view class_name, std::string_view obj_name) -{ - if (std::empty(obj_name)) - return std::string{class_name}; - else - return pqxx::internal::concat(class_name, " '", obj_name, "'"); -} - - -void pqxx::internal::check_unique_register( - void const *old_guest, std::string_view old_class, std::string_view old_name, - void const *new_guest, std::string_view new_class, std::string_view new_name) -{ - if (new_guest == nullptr) - throw internal_error{"Null pointer registered."}; - - if (old_guest != nullptr) - throw usage_error{ - (old_guest == new_guest) ? - concat("Started twice: ", describe_object(old_class, old_name), ".") : - concat( - "Started new ", describe_object(new_class, new_name), " while ", - describe_object(new_class, new_name), " was still active.")}; -} - - -void pqxx::internal::check_unique_unregister( - void const *old_guest, std::string_view old_class, std::string_view old_name, - void const *new_guest, std::string_view new_class, std::string_view new_name) -{ - if (new_guest != old_guest) - { - PQXX_UNLIKELY - if (new_guest == nullptr) - throw usage_error{concat( - "Expected to close ", describe_object(old_class, old_name), - ", but got null pointer instead.")}; - if (old_guest == nullptr) - throw usage_error{concat( - "Closed while not open: ", describe_object(new_class, new_name))}; - else - throw usage_error{concat( - "Closed ", describe_object(new_class, new_name), - "; expected to close ", describe_object(old_class, old_name))}; - } -} - - -namespace -{ -constexpr char hex_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - - -/// Translate a number (must be between 0 and 16 exclusive) to a hex digit. -constexpr char hex_digit(int c) noexcept -{ - return hex_digits[c]; -} - - -/// Translate a hex digit to a nibble. Return -1 if it's not a valid digit. -constexpr int nibble(int c) noexcept -{ - if (c >= '0' and c <= '9') - PQXX_LIKELY - return c - '0'; - else if (c >= 'a' and c <= 'f') return 10 + (c - 'a'); - else if (c >= 'A' and c <= 'F') return 10 + (c - 'A'); - else return -1; -} -} // namespace - - -void pqxx::internal::esc_bin( - std::basic_string_view binary_data, char buffer[]) noexcept -{ - auto here{buffer}; - *here++ = '\\'; - *here++ = 'x'; - - for (auto const byte : binary_data) - { - auto uc{static_cast(byte)}; - *here++ = hex_digit(uc >> 4); - *here++ = hex_digit(uc & 0x0f); - } - - // (No need to increment further. Facebook's "infer" complains if we do.) - *here = '\0'; -} - - -std::string -pqxx::internal::esc_bin(std::basic_string_view binary_data) -{ - auto const bytes{size_esc_bin(std::size(binary_data))}; - std::string buf; - buf.resize(bytes); - esc_bin(binary_data, buf.data()); - // Strip off the trailing zero. - buf.resize(bytes - 1); - return buf; -} - - -void pqxx::internal::unesc_bin( - std::string_view escaped_data, std::byte buffer[]) -{ - auto const in_size{std::size(escaped_data)}; - if (in_size < 2) - throw pqxx::failure{"Binary data appears truncated."}; - if ((in_size % 2) != 0) - throw pqxx::failure{"Invalid escaped binary length."}; - char const *in{escaped_data.data()}; - char const *const end{in + in_size}; - if (*in++ != '\\' or *in++ != 'x') - throw pqxx::failure( - "Escaped binary data did not start with '\\x'`. Is the server or libpq " - "too old?"); - auto out{buffer}; - while (in != end) - { - int hi{nibble(*in++)}; - if (hi < 0) - throw pqxx::failure{"Invalid hex-escaped data."}; - int lo{nibble(*in++)}; - if (lo < 0) - throw pqxx::failure{"Invalid hex-escaped data."}; - *out++ = static_cast((hi << 4) | lo); - } -} - - -std::basic_string -pqxx::internal::unesc_bin(std::string_view escaped_data) -{ - auto const bytes{size_unesc_bin(std::size(escaped_data))}; - std::basic_string buf; - buf.resize(bytes); - unesc_bin(escaped_data, buf.data()); - return buf; -} diff --git a/ext/libpqxx-7.7.3/src/version.cxx b/ext/libpqxx-7.7.3/src/version.cxx deleted file mode 100644 index e216ecd4f..000000000 --- a/ext/libpqxx-7.7.3/src/version.cxx +++ /dev/null @@ -1,27 +0,0 @@ -/** Version check. - * - * Copyright (c) 2000-2022, Jeroen T. Vermeulen. - * - * See COPYING for copyright license. If you did not receive a file called - * COPYING with this source code, please notify the distributor of this - * mistake, or contact the author. - */ -#include "pqxx-source.hxx" - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/version.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace pqxx::internal -{ -// One, single definition of this function. If a call fails to link, and -// (some) other calls do link, then the libpqxx binary was built against a -// different libpqxx version than the code which is being linked against it. -PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept -{ - return 0; -} -} // namespace pqxx::internal diff --git a/ext/libpqxx-7.7.3/src/wait.cxx b/ext/libpqxx-7.7.3/src/wait.cxx deleted file mode 100644 index 276d9659e..000000000 --- a/ext/libpqxx-7.7.3/src/wait.cxx +++ /dev/null @@ -1,136 +0,0 @@ -/** Functions that wait. - */ -#include "pqxx-source.hxx" - -// The header is still broken on MinGW. :-( -#if defined(PQXX_HAVE_SLEEP_FOR) -# include -#endif - -// For WSAPoll(): -#if __has_include() -# include -# define PQXX_HAVE_SELECT -#endif -#if __has_include() -# include -#endif -#if __has_include() -# include -#endif - -// For poll(): -#if __has_include() -# include -#endif - -// For select() on recent POSIX systems. -#if __has_include() -# include -# define PQXX_HAVE_SELECT -#endif - -// For select() on some older POSIX systems. -#if __has_include() -# include -# define PQXX_HAVE_SELECT -#endif -#if __has_include() -# include -#endif -#if __has_include() -# include -#endif - - -#include "pqxx/internal/header-pre.hxx" - -#include "pqxx/internal/wait.hxx" -#include "pqxx/util.hxx" - -#include "pqxx/internal/header-post.hxx" - - -namespace -{ -template T to_milli(unsigned seconds, unsigned microseconds) -{ - return pqxx::check_cast( - (seconds * 1000) + (microseconds / 1000), - "Wait timeout value out of bounds."); -} - - -#if defined(PQXX_HAVE_SELECT) -/// Set a bit on an fd_set. -[[maybe_unused]] void set_fdbit(fd_set &bits, int fd) -{ -# ifdef _MSC_VER -// Suppress pointless, unfixable warnings in Visual Studio. -# pragma warning(push) -# pragma warning(disable : 4389) // Signed/unsigned mismatch. -# pragma warning(disable : 4127) // Conditional expression is constant. -# endif - FD_SET(fd, &bits); -# ifdef _MSV_VER -// Restore prevalent warning settings. -# pragma warning(pop) -# endif -} -#endif -} // namespace - - -void pqxx::internal::wait_fd( - int fd, bool for_read, bool for_write, unsigned seconds, - unsigned microseconds) -{ -// WSAPoll is available in winsock2.h only for versions of Windows >= 0x0600 -#if defined(_WIN32) && (_WIN32_WINNT >= 0x0600) - short const events{static_cast( - (for_read ? POLLRDNORM : 0) | (for_write ? POLLWRNORM : 0))}; - WSAPOLLFD fdarray{SOCKET(fd), events, 0}; - WSAPoll(&fdarray, 1u, to_milli(seconds, microseconds)); - // TODO: Check for errors. -#elif defined(PQXX_HAVE_POLL) - auto const events{static_cast( - POLLERR | POLLHUP | POLLNVAL | (for_read ? POLLIN : 0) | - (for_write ? POLLOUT : 0))}; - pollfd pfd{fd, events, 0}; - poll(&pfd, 1, to_milli(seconds, microseconds)); - // TODO: Check for errors. -#else - // No poll()? Our last option is select(). - fd_set read_fds; - FD_ZERO(&read_fds); - if (for_read) - set_fdbit(read_fds, fd); - - fd_set write_fds; - FD_ZERO(&write_fds); - if (for_write) - set_fdbit(write_fds, fd); - - fd_set except_fds; - FD_ZERO(&except_fds); - set_fdbit(except_fds, fd); - - timeval tv = {seconds, microseconds}; - select(fd + 1, &read_fds, &write_fds, &except_fds, &tv); - // TODO: Check for errors. -#endif -} - - -void PQXX_COLD pqxx::internal::wait_for(unsigned int microseconds) -{ -#if defined(PQXX_HAVE_SLEEP_FOR) - std::this_thread::sleep_for(std::chrono::microseconds{microseconds}); -#else - // MinGW still does not have a functioning header. Work around this - // using select(). - // Not worth optimising for though -- they'll have to fix it at some point. - timeval tv{microseconds / 1'000'000u, microseconds % 1'000'000u}; - select(0, nullptr, nullptr, nullptr, &tv); -#endif -} diff --git a/ext/libpqxx-7.7.3/test/CMakeLists.txt b/ext/libpqxx-7.7.3/test/CMakeLists.txt deleted file mode 100644 index 331631145..000000000 --- a/ext/libpqxx-7.7.3/test/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -enable_testing() - -if(NOT PostgreSQL_FOUND) - find_package(PostgreSQL REQUIRED) -endif() - -file(GLOB TEST_SOURCES test*.cxx unit/test_*.cxx runner.cxx) - -add_executable(runner ${TEST_SOURCES}) -target_link_libraries(runner PUBLIC pqxx) -target_include_directories(runner PRIVATE ${PostgreSQL_INCLUDE_DIRS}) -add_test( - NAME runner - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMAND runner -) - -if(INSTALL_TEST) - install( - PROGRAMS runner - TYPE BIN - RENAME libpqxx-test-runner - ) -endif() diff --git a/ext/libpqxx-7.7.3/test/Makefile.am b/ext/libpqxx-7.7.3/test/Makefile.am deleted file mode 100644 index e3ce4be7b..000000000 --- a/ext/libpqxx-7.7.3/test/Makefile.am +++ /dev/null @@ -1,129 +0,0 @@ -# ############################################################################## -# AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. -# -# This file is generated automatically by libpqxx's template2mak.py script, and -# will be rewritten from time to time. -# -# If you modify this file, chances are your modifications will be lost. -# -# The template2mak.py script should be available in the tools directory of the -# libpqxx source archive. -# -# Generated from template './test/Makefile.am.template'. -# ############################################################################## -# Makefile.am is generated automatically for automake whenever test programs are -# added to libpqxx. - -EXTRA_DIST = Makefile.am.template - -# Use the serial test runner, so tests don't get run in parallel. Otherwise, -# output from test failures will be hidden away in log files where we can't -# see them when running in a build slave. -AUTOMAKE_OPTIONS=serial-tests - - -AM_CPPFLAGS=-I$(top_builddir)/include -I$(top_srcdir)/include - -# Override automatically generated list of default includes. It contains only -# unnecessary entries, and incorrectly mentions include/pqxx directly. -DEFAULT_INCLUDES= - -noinst_HEADERS = test_helpers.hxx - -CLEANFILES=pqxxlo.txt -MAINTAINERCLEANFILES=Makefile.in - -#TESTS_ENVIRONMENT=PGDATABASE=libpqxx -# PGDATABASE, PGHOST, PGPORT, PGUSER - -runner_SOURCES = \ - test00.cxx \ - test01.cxx \ - test02.cxx \ - test04.cxx \ - test07.cxx \ - test10.cxx \ - test11.cxx \ - test13.cxx \ - test14.cxx \ - test16.cxx \ - test17.cxx \ - test18.cxx \ - test20.cxx \ - test21.cxx \ - test26.cxx \ - test29.cxx \ - test30.cxx \ - test32.cxx \ - test37.cxx \ - test39.cxx \ - test46.cxx \ - test56.cxx \ - test60.cxx \ - test61.cxx \ - test62.cxx \ - test69.cxx \ - test70.cxx \ - test71.cxx \ - test72.cxx \ - test74.cxx \ - test75.cxx \ - test76.cxx \ - test77.cxx \ - test78.cxx \ - test79.cxx \ - test82.cxx \ - test84.cxx \ - test87.cxx \ - test88.cxx \ - test89.cxx \ - test90.cxx \ - unit/test_array.cxx \ - unit/test_binarystring.cxx \ - unit/test_blob.cxx \ - unit/test_cancel_query.cxx \ - unit/test_column.cxx \ - unit/test_composite.cxx \ - unit/test_connection.cxx \ - unit/test_cursor.cxx \ - unit/test_encodings.cxx \ - unit/test_error_verbosity.cxx \ - unit/test_errorhandler.cxx \ - unit/test_escape.cxx \ - unit/test_exceptions.cxx \ - unit/test_field.cxx \ - unit/test_float.cxx \ - unit/test_largeobject.cxx \ - unit/test_nonblocking_connect.cxx \ - unit/test_notification.cxx \ - unit/test_pipeline.cxx \ - unit/test_prepared_statement.cxx \ - unit/test_range.cxx \ - unit/test_read_transaction.cxx \ - unit/test_result_iteration.cxx \ - unit/test_result_slicing.cxx \ - unit/test_row.cxx \ - unit/test_separated_list.cxx \ - unit/test_simultaneous_transactions.cxx \ - unit/test_sql_cursor.cxx \ - unit/test_stateless_cursor.cxx \ - unit/test_strconv.cxx \ - unit/test_stream_from.cxx \ - unit/test_stream_to.cxx \ - unit/test_string_conversion.cxx \ - unit/test_subtransaction.cxx \ - unit/test_test_helpers.cxx \ - unit/test_thread_safety_model.cxx \ - unit/test_time.cxx \ - unit/test_transaction.cxx \ - unit/test_transaction_base.cxx \ - unit/test_transaction_focus.cxx \ - unit/test_transactor.cxx \ - unit/test_type_name.cxx \ - unit/test_zview.cxx \ - runner.cxx - -runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} - -TESTS = runner -check_PROGRAMS = ${TESTS} diff --git a/ext/libpqxx-7.7.3/test/Makefile.am.template b/ext/libpqxx-7.7.3/test/Makefile.am.template deleted file mode 100644 index 2a21f6ef7..000000000 --- a/ext/libpqxx-7.7.3/test/Makefile.am.template +++ /dev/null @@ -1,38 +0,0 @@ -# Makefile.am is generated automatically for automake whenever test programs are -# added to libpqxx. - -EXTRA_DIST = Makefile.am.template - -# Use the serial test runner, so tests don't get run in parallel. Otherwise, -# output from test failures will be hidden away in log files where we can't -# see them when running in a build slave. -AUTOMAKE_OPTIONS=serial-tests - - -AM_CPPFLAGS=-I$(top_builddir)/include -I$(top_srcdir)/include - -# Override automatically generated list of default includes. It contains only -# unnecessary entries, and incorrectly mentions include/pqxx directly. -DEFAULT_INCLUDES= - -noinst_HEADERS = test_helpers.hxx - -CLEANFILES=pqxxlo.txt -MAINTAINERCLEANFILES=Makefile.in - -#TESTS_ENVIRONMENT=PGDATABASE=libpqxx -# PGDATABASE, PGHOST, PGPORT, PGUSER - -runner_SOURCES = \ -###MAKTEMPLATE:FOREACH test/test*.cxx - ###BASENAME###.cxx \ -###MAKTEMPLATE:ENDFOREACH -###MAKTEMPLATE:FOREACH test/unit/test_*.cxx - unit/###BASENAME###.cxx \ -###MAKTEMPLATE:ENDFOREACH - runner.cxx - -runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} - -TESTS = runner -check_PROGRAMS = ${TESTS} diff --git a/ext/libpqxx-7.7.3/test/Makefile.in b/ext/libpqxx-7.7.3/test/Makefile.in deleted file mode 100644 index 8ffcca06c..000000000 --- a/ext/libpqxx-7.7.3/test/Makefile.in +++ /dev/null @@ -1,1302 +0,0 @@ -# Makefile.in generated by automake 1.16.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2021 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# ############################################################################## -# AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. -# -# This file is generated automatically by libpqxx's template2mak.py script, and -# will be rewritten from time to time. -# -# If you modify this file, chances are your modifications will be lost. -# -# The template2mak.py script should be available in the tools directory of the -# libpqxx source archive. -# -# Generated from template './test/Makefile.am.template'. -# ############################################################################## -# Makefile.am is generated automatically for automake whenever test programs are -# added to libpqxx. - -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -TESTS = runner$(EXEEXT) -check_PROGRAMS = $(am__EXEEXT_1) -subdir = test -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ - $(top_srcdir)/config/m4/ltoptions.m4 \ - $(top_srcdir)/config/m4/ltsugar.m4 \ - $(top_srcdir)/config/m4/ltversion.m4 \ - $(top_srcdir)/config/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ - $(am__DIST_COMMON) -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -am__EXEEXT_1 = runner$(EXEEXT) -am__dirstamp = $(am__leading_dot)dirstamp -am_runner_OBJECTS = test00.$(OBJEXT) test01.$(OBJEXT) test02.$(OBJEXT) \ - test04.$(OBJEXT) test07.$(OBJEXT) test10.$(OBJEXT) \ - test11.$(OBJEXT) test13.$(OBJEXT) test14.$(OBJEXT) \ - test16.$(OBJEXT) test17.$(OBJEXT) test18.$(OBJEXT) \ - test20.$(OBJEXT) test21.$(OBJEXT) test26.$(OBJEXT) \ - test29.$(OBJEXT) test30.$(OBJEXT) test32.$(OBJEXT) \ - test37.$(OBJEXT) test39.$(OBJEXT) test46.$(OBJEXT) \ - test56.$(OBJEXT) test60.$(OBJEXT) test61.$(OBJEXT) \ - test62.$(OBJEXT) test69.$(OBJEXT) test70.$(OBJEXT) \ - test71.$(OBJEXT) test72.$(OBJEXT) test74.$(OBJEXT) \ - test75.$(OBJEXT) test76.$(OBJEXT) test77.$(OBJEXT) \ - test78.$(OBJEXT) test79.$(OBJEXT) test82.$(OBJEXT) \ - test84.$(OBJEXT) test87.$(OBJEXT) test88.$(OBJEXT) \ - test89.$(OBJEXT) test90.$(OBJEXT) unit/test_array.$(OBJEXT) \ - unit/test_binarystring.$(OBJEXT) unit/test_blob.$(OBJEXT) \ - unit/test_cancel_query.$(OBJEXT) unit/test_column.$(OBJEXT) \ - unit/test_composite.$(OBJEXT) unit/test_connection.$(OBJEXT) \ - unit/test_cursor.$(OBJEXT) unit/test_encodings.$(OBJEXT) \ - unit/test_error_verbosity.$(OBJEXT) \ - unit/test_errorhandler.$(OBJEXT) unit/test_escape.$(OBJEXT) \ - unit/test_exceptions.$(OBJEXT) unit/test_field.$(OBJEXT) \ - unit/test_float.$(OBJEXT) unit/test_largeobject.$(OBJEXT) \ - unit/test_nonblocking_connect.$(OBJEXT) \ - unit/test_notification.$(OBJEXT) unit/test_pipeline.$(OBJEXT) \ - unit/test_prepared_statement.$(OBJEXT) \ - unit/test_range.$(OBJEXT) unit/test_read_transaction.$(OBJEXT) \ - unit/test_result_iteration.$(OBJEXT) \ - unit/test_result_slicing.$(OBJEXT) unit/test_row.$(OBJEXT) \ - unit/test_separated_list.$(OBJEXT) \ - unit/test_simultaneous_transactions.$(OBJEXT) \ - unit/test_sql_cursor.$(OBJEXT) \ - unit/test_stateless_cursor.$(OBJEXT) \ - unit/test_strconv.$(OBJEXT) unit/test_stream_from.$(OBJEXT) \ - unit/test_stream_to.$(OBJEXT) \ - unit/test_string_conversion.$(OBJEXT) \ - unit/test_subtransaction.$(OBJEXT) \ - unit/test_test_helpers.$(OBJEXT) \ - unit/test_thread_safety_model.$(OBJEXT) \ - unit/test_time.$(OBJEXT) unit/test_transaction.$(OBJEXT) \ - unit/test_transaction_base.$(OBJEXT) \ - unit/test_transaction_focus.$(OBJEXT) \ - unit/test_transactor.$(OBJEXT) unit/test_type_name.$(OBJEXT) \ - unit/test_zview.$(OBJEXT) runner.$(OBJEXT) -runner_OBJECTS = $(am_runner_OBJECTS) -runner_DEPENDENCIES = $(top_builddir)/src/libpqxx.la -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -depcomp = $(SHELL) $(top_srcdir)/config/depcomp -am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/runner.Po ./$(DEPDIR)/test00.Po \ - ./$(DEPDIR)/test01.Po ./$(DEPDIR)/test02.Po \ - ./$(DEPDIR)/test04.Po ./$(DEPDIR)/test07.Po \ - ./$(DEPDIR)/test10.Po ./$(DEPDIR)/test11.Po \ - ./$(DEPDIR)/test13.Po ./$(DEPDIR)/test14.Po \ - ./$(DEPDIR)/test16.Po ./$(DEPDIR)/test17.Po \ - ./$(DEPDIR)/test18.Po ./$(DEPDIR)/test20.Po \ - ./$(DEPDIR)/test21.Po ./$(DEPDIR)/test26.Po \ - ./$(DEPDIR)/test29.Po ./$(DEPDIR)/test30.Po \ - ./$(DEPDIR)/test32.Po ./$(DEPDIR)/test37.Po \ - ./$(DEPDIR)/test39.Po ./$(DEPDIR)/test46.Po \ - ./$(DEPDIR)/test56.Po ./$(DEPDIR)/test60.Po \ - ./$(DEPDIR)/test61.Po ./$(DEPDIR)/test62.Po \ - ./$(DEPDIR)/test69.Po ./$(DEPDIR)/test70.Po \ - ./$(DEPDIR)/test71.Po ./$(DEPDIR)/test72.Po \ - ./$(DEPDIR)/test74.Po ./$(DEPDIR)/test75.Po \ - ./$(DEPDIR)/test76.Po ./$(DEPDIR)/test77.Po \ - ./$(DEPDIR)/test78.Po ./$(DEPDIR)/test79.Po \ - ./$(DEPDIR)/test82.Po ./$(DEPDIR)/test84.Po \ - ./$(DEPDIR)/test87.Po ./$(DEPDIR)/test88.Po \ - ./$(DEPDIR)/test89.Po ./$(DEPDIR)/test90.Po \ - unit/$(DEPDIR)/test_array.Po \ - unit/$(DEPDIR)/test_binarystring.Po \ - unit/$(DEPDIR)/test_blob.Po \ - unit/$(DEPDIR)/test_cancel_query.Po \ - unit/$(DEPDIR)/test_column.Po unit/$(DEPDIR)/test_composite.Po \ - unit/$(DEPDIR)/test_connection.Po \ - unit/$(DEPDIR)/test_cursor.Po unit/$(DEPDIR)/test_encodings.Po \ - unit/$(DEPDIR)/test_error_verbosity.Po \ - unit/$(DEPDIR)/test_errorhandler.Po \ - unit/$(DEPDIR)/test_escape.Po \ - unit/$(DEPDIR)/test_exceptions.Po unit/$(DEPDIR)/test_field.Po \ - unit/$(DEPDIR)/test_float.Po \ - unit/$(DEPDIR)/test_largeobject.Po \ - unit/$(DEPDIR)/test_nonblocking_connect.Po \ - unit/$(DEPDIR)/test_notification.Po \ - unit/$(DEPDIR)/test_pipeline.Po \ - unit/$(DEPDIR)/test_prepared_statement.Po \ - unit/$(DEPDIR)/test_range.Po \ - unit/$(DEPDIR)/test_read_transaction.Po \ - unit/$(DEPDIR)/test_result_iteration.Po \ - unit/$(DEPDIR)/test_result_slicing.Po \ - unit/$(DEPDIR)/test_row.Po \ - unit/$(DEPDIR)/test_separated_list.Po \ - unit/$(DEPDIR)/test_simultaneous_transactions.Po \ - unit/$(DEPDIR)/test_sql_cursor.Po \ - unit/$(DEPDIR)/test_stateless_cursor.Po \ - unit/$(DEPDIR)/test_strconv.Po \ - unit/$(DEPDIR)/test_stream_from.Po \ - unit/$(DEPDIR)/test_stream_to.Po \ - unit/$(DEPDIR)/test_string_conversion.Po \ - unit/$(DEPDIR)/test_subtransaction.Po \ - unit/$(DEPDIR)/test_test_helpers.Po \ - unit/$(DEPDIR)/test_thread_safety_model.Po \ - unit/$(DEPDIR)/test_time.Po unit/$(DEPDIR)/test_transaction.Po \ - unit/$(DEPDIR)/test_transaction_base.Po \ - unit/$(DEPDIR)/test_transaction_focus.Po \ - unit/$(DEPDIR)/test_transactor.Po \ - unit/$(DEPDIR)/test_type_name.Po unit/$(DEPDIR)/test_zview.Po -am__mv = mv -f -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_@AM_V@) -am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) -am__v_CXX_0 = @echo " CXX " $@; -am__v_CXX_1 = -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) -am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) -am__v_CXXLD_0 = @echo " CXXLD " $@; -am__v_CXXLD_1 = -SOURCES = $(runner_SOURCES) -DIST_SOURCES = $(runner_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -HEADERS = $(noinst_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -am__tty_colors_dummy = \ - mgn= red= grn= lgn= blu= brg= std=; \ - am__color_tests=no -am__tty_colors = { \ - $(am__tty_colors_dummy); \ - if test "X$(AM_COLOR_TESTS)" = Xno; then \ - am__color_tests=no; \ - elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ - am__color_tests=yes; \ - elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ - am__color_tests=yes; \ - fi; \ - if test $$am__color_tests = yes; then \ - red=''; \ - grn=''; \ - lgn=''; \ - blu=''; \ - mgn=''; \ - brg=''; \ - std=''; \ - fi; \ -} -am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp \ - $(top_srcdir)/config/mkinstalldirs -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSCOPE = @CSCOPE@ -CTAGS = @CTAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ETAGS = @ETAGS@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_DOT = @HAVE_DOT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR = @MKDIR@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PG_CONFIG = @PG_CONFIG@ -PKG_CONFIG = @PKG_CONFIG@ -POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ -PQXXVERSION = @PQXXVERSION@ -PQXX_ABI = @PQXX_ABI@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_postgres_lib = @with_postgres_lib@ -EXTRA_DIST = Makefile.am.template - -# Use the serial test runner, so tests don't get run in parallel. Otherwise, -# output from test failures will be hidden away in log files where we can't -# see them when running in a build slave. -AUTOMAKE_OPTIONS = serial-tests -AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include - -# Override automatically generated list of default includes. It contains only -# unnecessary entries, and incorrectly mentions include/pqxx directly. -DEFAULT_INCLUDES = -noinst_HEADERS = test_helpers.hxx -CLEANFILES = pqxxlo.txt -MAINTAINERCLEANFILES = Makefile.in - -#TESTS_ENVIRONMENT=PGDATABASE=libpqxx -# PGDATABASE, PGHOST, PGPORT, PGUSER -runner_SOURCES = \ - test00.cxx \ - test01.cxx \ - test02.cxx \ - test04.cxx \ - test07.cxx \ - test10.cxx \ - test11.cxx \ - test13.cxx \ - test14.cxx \ - test16.cxx \ - test17.cxx \ - test18.cxx \ - test20.cxx \ - test21.cxx \ - test26.cxx \ - test29.cxx \ - test30.cxx \ - test32.cxx \ - test37.cxx \ - test39.cxx \ - test46.cxx \ - test56.cxx \ - test60.cxx \ - test61.cxx \ - test62.cxx \ - test69.cxx \ - test70.cxx \ - test71.cxx \ - test72.cxx \ - test74.cxx \ - test75.cxx \ - test76.cxx \ - test77.cxx \ - test78.cxx \ - test79.cxx \ - test82.cxx \ - test84.cxx \ - test87.cxx \ - test88.cxx \ - test89.cxx \ - test90.cxx \ - unit/test_array.cxx \ - unit/test_binarystring.cxx \ - unit/test_blob.cxx \ - unit/test_cancel_query.cxx \ - unit/test_column.cxx \ - unit/test_composite.cxx \ - unit/test_connection.cxx \ - unit/test_cursor.cxx \ - unit/test_encodings.cxx \ - unit/test_error_verbosity.cxx \ - unit/test_errorhandler.cxx \ - unit/test_escape.cxx \ - unit/test_exceptions.cxx \ - unit/test_field.cxx \ - unit/test_float.cxx \ - unit/test_largeobject.cxx \ - unit/test_nonblocking_connect.cxx \ - unit/test_notification.cxx \ - unit/test_pipeline.cxx \ - unit/test_prepared_statement.cxx \ - unit/test_range.cxx \ - unit/test_read_transaction.cxx \ - unit/test_result_iteration.cxx \ - unit/test_result_slicing.cxx \ - unit/test_row.cxx \ - unit/test_separated_list.cxx \ - unit/test_simultaneous_transactions.cxx \ - unit/test_sql_cursor.cxx \ - unit/test_stateless_cursor.cxx \ - unit/test_strconv.cxx \ - unit/test_stream_from.cxx \ - unit/test_stream_to.cxx \ - unit/test_string_conversion.cxx \ - unit/test_subtransaction.cxx \ - unit/test_test_helpers.cxx \ - unit/test_thread_safety_model.cxx \ - unit/test_time.cxx \ - unit/test_transaction.cxx \ - unit/test_transaction_base.cxx \ - unit/test_transaction_focus.cxx \ - unit/test_transactor.cxx \ - unit/test_type_name.cxx \ - unit/test_zview.cxx \ - runner.cxx - -runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} -all: all-am - -.SUFFIXES: -.SUFFIXES: .cxx .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu test/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu test/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list -unit/$(am__dirstamp): - @$(MKDIR_P) unit - @: > unit/$(am__dirstamp) -unit/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) unit/$(DEPDIR) - @: > unit/$(DEPDIR)/$(am__dirstamp) -unit/test_array.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_binarystring.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_blob.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_cancel_query.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_column.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_composite.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_connection.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_cursor.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_encodings.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_error_verbosity.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_errorhandler.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_escape.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_exceptions.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_field.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_float.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_largeobject.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_nonblocking_connect.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_notification.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_pipeline.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_prepared_statement.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_range.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_read_transaction.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_result_iteration.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_result_slicing.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_row.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_separated_list.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_simultaneous_transactions.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_sql_cursor.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_stateless_cursor.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_strconv.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_stream_from.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_stream_to.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_string_conversion.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_subtransaction.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_test_helpers.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_thread_safety_model.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_time.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_transaction.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_transaction_base.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_transaction_focus.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_transactor.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_type_name.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) -unit/test_zview.$(OBJEXT): unit/$(am__dirstamp) \ - unit/$(DEPDIR)/$(am__dirstamp) - -runner$(EXEEXT): $(runner_OBJECTS) $(runner_DEPENDENCIES) $(EXTRA_runner_DEPENDENCIES) - @rm -f runner$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(runner_OBJECTS) $(runner_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -rm -f unit/*.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runner.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test00.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test01.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test02.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test04.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test07.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test10.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test11.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test13.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test14.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test16.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test17.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test18.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test20.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test21.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test26.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test29.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test30.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test32.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test37.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test39.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test46.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test56.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test60.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test61.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test62.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test69.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test70.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test71.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test72.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test74.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test75.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test76.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test77.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test78.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test79.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test82.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test84.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test87.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test88.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test89.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test90.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_array.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_binarystring.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_blob.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_cancel_query.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_column.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_composite.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_connection.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_cursor.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_encodings.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_error_verbosity.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_errorhandler.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_escape.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_exceptions.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_field.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_float.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_largeobject.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_nonblocking_connect.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_notification.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_pipeline.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_prepared_statement.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_range.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_read_transaction.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_result_iteration.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_result_slicing.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_row.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_separated_list.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_simultaneous_transactions.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_sql_cursor.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_stateless_cursor.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_strconv.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_stream_from.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_stream_to.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_string_conversion.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_subtransaction.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_test_helpers.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_thread_safety_model.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_time.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_transaction.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_transaction_base.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_transaction_focus.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_transactor.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_type_name.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_zview.Po@am__quote@ # am--include-marker - -$(am__depfiles_remade): - @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) - -.cxx.o: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< - -.cxx.obj: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cxx.lo: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -check-TESTS: $(TESTS) - @failed=0; all=0; xfail=0; xpass=0; skip=0; \ - srcdir=$(srcdir); export srcdir; \ - list=' $(TESTS) '; \ - $(am__tty_colors); \ - if test -n "$$list"; then \ - for tst in $$list; do \ - if test -f ./$$tst; then dir=./; \ - elif test -f $$tst; then dir=; \ - else dir="$(srcdir)/"; fi; \ - if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xpass=`expr $$xpass + 1`; \ - failed=`expr $$failed + 1`; \ - col=$$red; res=XPASS; \ - ;; \ - *) \ - col=$$grn; res=PASS; \ - ;; \ - esac; \ - elif test $$? -ne 77; then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xfail=`expr $$xfail + 1`; \ - col=$$lgn; res=XFAIL; \ - ;; \ - *) \ - failed=`expr $$failed + 1`; \ - col=$$red; res=FAIL; \ - ;; \ - esac; \ - else \ - skip=`expr $$skip + 1`; \ - col=$$blu; res=SKIP; \ - fi; \ - echo "$${col}$$res$${std}: $$tst"; \ - done; \ - if test "$$all" -eq 1; then \ - tests="test"; \ - All=""; \ - else \ - tests="tests"; \ - All="All "; \ - fi; \ - if test "$$failed" -eq 0; then \ - if test "$$xfail" -eq 0; then \ - banner="$$All$$all $$tests passed"; \ - else \ - if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ - banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ - fi; \ - else \ - if test "$$xpass" -eq 0; then \ - banner="$$failed of $$all $$tests failed"; \ - else \ - if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ - banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ - fi; \ - fi; \ - dashes="$$banner"; \ - skipped=""; \ - if test "$$skip" -ne 0; then \ - if test "$$skip" -eq 1; then \ - skipped="($$skip test was not run)"; \ - else \ - skipped="($$skip tests were not run)"; \ - fi; \ - test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$skipped"; \ - fi; \ - report=""; \ - if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ - report="Please report to $(PACKAGE_BUGREPORT)"; \ - test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$report"; \ - fi; \ - dashes=`echo "$$dashes" | sed s/./=/g`; \ - if test "$$failed" -eq 0; then \ - col="$$grn"; \ - else \ - col="$$red"; \ - fi; \ - echo "$${col}$$dashes$${std}"; \ - echo "$${col}$$banner$${std}"; \ - test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ - test -z "$$report" || echo "$${col}$$report$${std}"; \ - echo "$${col}$$dashes$${std}"; \ - test "$$failed" -eq 0; \ - else :; fi -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) - $(MAKE) $(AM_MAKEFLAGS) check-TESTS -check: check-am -all-am: Makefile $(HEADERS) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -rm -f unit/$(DEPDIR)/$(am__dirstamp) - -rm -f unit/$(am__dirstamp) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ - mostlyclean-am - -distclean: distclean-am - -rm -f ./$(DEPDIR)/runner.Po - -rm -f ./$(DEPDIR)/test00.Po - -rm -f ./$(DEPDIR)/test01.Po - -rm -f ./$(DEPDIR)/test02.Po - -rm -f ./$(DEPDIR)/test04.Po - -rm -f ./$(DEPDIR)/test07.Po - -rm -f ./$(DEPDIR)/test10.Po - -rm -f ./$(DEPDIR)/test11.Po - -rm -f ./$(DEPDIR)/test13.Po - -rm -f ./$(DEPDIR)/test14.Po - -rm -f ./$(DEPDIR)/test16.Po - -rm -f ./$(DEPDIR)/test17.Po - -rm -f ./$(DEPDIR)/test18.Po - -rm -f ./$(DEPDIR)/test20.Po - -rm -f ./$(DEPDIR)/test21.Po - -rm -f ./$(DEPDIR)/test26.Po - -rm -f ./$(DEPDIR)/test29.Po - -rm -f ./$(DEPDIR)/test30.Po - -rm -f ./$(DEPDIR)/test32.Po - -rm -f ./$(DEPDIR)/test37.Po - -rm -f ./$(DEPDIR)/test39.Po - -rm -f ./$(DEPDIR)/test46.Po - -rm -f ./$(DEPDIR)/test56.Po - -rm -f ./$(DEPDIR)/test60.Po - -rm -f ./$(DEPDIR)/test61.Po - -rm -f ./$(DEPDIR)/test62.Po - -rm -f ./$(DEPDIR)/test69.Po - -rm -f ./$(DEPDIR)/test70.Po - -rm -f ./$(DEPDIR)/test71.Po - -rm -f ./$(DEPDIR)/test72.Po - -rm -f ./$(DEPDIR)/test74.Po - -rm -f ./$(DEPDIR)/test75.Po - -rm -f ./$(DEPDIR)/test76.Po - -rm -f ./$(DEPDIR)/test77.Po - -rm -f ./$(DEPDIR)/test78.Po - -rm -f ./$(DEPDIR)/test79.Po - -rm -f ./$(DEPDIR)/test82.Po - -rm -f ./$(DEPDIR)/test84.Po - -rm -f ./$(DEPDIR)/test87.Po - -rm -f ./$(DEPDIR)/test88.Po - -rm -f ./$(DEPDIR)/test89.Po - -rm -f ./$(DEPDIR)/test90.Po - -rm -f unit/$(DEPDIR)/test_array.Po - -rm -f unit/$(DEPDIR)/test_binarystring.Po - -rm -f unit/$(DEPDIR)/test_blob.Po - -rm -f unit/$(DEPDIR)/test_cancel_query.Po - -rm -f unit/$(DEPDIR)/test_column.Po - -rm -f unit/$(DEPDIR)/test_composite.Po - -rm -f unit/$(DEPDIR)/test_connection.Po - -rm -f unit/$(DEPDIR)/test_cursor.Po - -rm -f unit/$(DEPDIR)/test_encodings.Po - -rm -f unit/$(DEPDIR)/test_error_verbosity.Po - -rm -f unit/$(DEPDIR)/test_errorhandler.Po - -rm -f unit/$(DEPDIR)/test_escape.Po - -rm -f unit/$(DEPDIR)/test_exceptions.Po - -rm -f unit/$(DEPDIR)/test_field.Po - -rm -f unit/$(DEPDIR)/test_float.Po - -rm -f unit/$(DEPDIR)/test_largeobject.Po - -rm -f unit/$(DEPDIR)/test_nonblocking_connect.Po - -rm -f unit/$(DEPDIR)/test_notification.Po - -rm -f unit/$(DEPDIR)/test_pipeline.Po - -rm -f unit/$(DEPDIR)/test_prepared_statement.Po - -rm -f unit/$(DEPDIR)/test_range.Po - -rm -f unit/$(DEPDIR)/test_read_transaction.Po - -rm -f unit/$(DEPDIR)/test_result_iteration.Po - -rm -f unit/$(DEPDIR)/test_result_slicing.Po - -rm -f unit/$(DEPDIR)/test_row.Po - -rm -f unit/$(DEPDIR)/test_separated_list.Po - -rm -f unit/$(DEPDIR)/test_simultaneous_transactions.Po - -rm -f unit/$(DEPDIR)/test_sql_cursor.Po - -rm -f unit/$(DEPDIR)/test_stateless_cursor.Po - -rm -f unit/$(DEPDIR)/test_strconv.Po - -rm -f unit/$(DEPDIR)/test_stream_from.Po - -rm -f unit/$(DEPDIR)/test_stream_to.Po - -rm -f unit/$(DEPDIR)/test_string_conversion.Po - -rm -f unit/$(DEPDIR)/test_subtransaction.Po - -rm -f unit/$(DEPDIR)/test_test_helpers.Po - -rm -f unit/$(DEPDIR)/test_thread_safety_model.Po - -rm -f unit/$(DEPDIR)/test_time.Po - -rm -f unit/$(DEPDIR)/test_transaction.Po - -rm -f unit/$(DEPDIR)/test_transaction_base.Po - -rm -f unit/$(DEPDIR)/test_transaction_focus.Po - -rm -f unit/$(DEPDIR)/test_transactor.Po - -rm -f unit/$(DEPDIR)/test_type_name.Po - -rm -f unit/$(DEPDIR)/test_zview.Po - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/runner.Po - -rm -f ./$(DEPDIR)/test00.Po - -rm -f ./$(DEPDIR)/test01.Po - -rm -f ./$(DEPDIR)/test02.Po - -rm -f ./$(DEPDIR)/test04.Po - -rm -f ./$(DEPDIR)/test07.Po - -rm -f ./$(DEPDIR)/test10.Po - -rm -f ./$(DEPDIR)/test11.Po - -rm -f ./$(DEPDIR)/test13.Po - -rm -f ./$(DEPDIR)/test14.Po - -rm -f ./$(DEPDIR)/test16.Po - -rm -f ./$(DEPDIR)/test17.Po - -rm -f ./$(DEPDIR)/test18.Po - -rm -f ./$(DEPDIR)/test20.Po - -rm -f ./$(DEPDIR)/test21.Po - -rm -f ./$(DEPDIR)/test26.Po - -rm -f ./$(DEPDIR)/test29.Po - -rm -f ./$(DEPDIR)/test30.Po - -rm -f ./$(DEPDIR)/test32.Po - -rm -f ./$(DEPDIR)/test37.Po - -rm -f ./$(DEPDIR)/test39.Po - -rm -f ./$(DEPDIR)/test46.Po - -rm -f ./$(DEPDIR)/test56.Po - -rm -f ./$(DEPDIR)/test60.Po - -rm -f ./$(DEPDIR)/test61.Po - -rm -f ./$(DEPDIR)/test62.Po - -rm -f ./$(DEPDIR)/test69.Po - -rm -f ./$(DEPDIR)/test70.Po - -rm -f ./$(DEPDIR)/test71.Po - -rm -f ./$(DEPDIR)/test72.Po - -rm -f ./$(DEPDIR)/test74.Po - -rm -f ./$(DEPDIR)/test75.Po - -rm -f ./$(DEPDIR)/test76.Po - -rm -f ./$(DEPDIR)/test77.Po - -rm -f ./$(DEPDIR)/test78.Po - -rm -f ./$(DEPDIR)/test79.Po - -rm -f ./$(DEPDIR)/test82.Po - -rm -f ./$(DEPDIR)/test84.Po - -rm -f ./$(DEPDIR)/test87.Po - -rm -f ./$(DEPDIR)/test88.Po - -rm -f ./$(DEPDIR)/test89.Po - -rm -f ./$(DEPDIR)/test90.Po - -rm -f unit/$(DEPDIR)/test_array.Po - -rm -f unit/$(DEPDIR)/test_binarystring.Po - -rm -f unit/$(DEPDIR)/test_blob.Po - -rm -f unit/$(DEPDIR)/test_cancel_query.Po - -rm -f unit/$(DEPDIR)/test_column.Po - -rm -f unit/$(DEPDIR)/test_composite.Po - -rm -f unit/$(DEPDIR)/test_connection.Po - -rm -f unit/$(DEPDIR)/test_cursor.Po - -rm -f unit/$(DEPDIR)/test_encodings.Po - -rm -f unit/$(DEPDIR)/test_error_verbosity.Po - -rm -f unit/$(DEPDIR)/test_errorhandler.Po - -rm -f unit/$(DEPDIR)/test_escape.Po - -rm -f unit/$(DEPDIR)/test_exceptions.Po - -rm -f unit/$(DEPDIR)/test_field.Po - -rm -f unit/$(DEPDIR)/test_float.Po - -rm -f unit/$(DEPDIR)/test_largeobject.Po - -rm -f unit/$(DEPDIR)/test_nonblocking_connect.Po - -rm -f unit/$(DEPDIR)/test_notification.Po - -rm -f unit/$(DEPDIR)/test_pipeline.Po - -rm -f unit/$(DEPDIR)/test_prepared_statement.Po - -rm -f unit/$(DEPDIR)/test_range.Po - -rm -f unit/$(DEPDIR)/test_read_transaction.Po - -rm -f unit/$(DEPDIR)/test_result_iteration.Po - -rm -f unit/$(DEPDIR)/test_result_slicing.Po - -rm -f unit/$(DEPDIR)/test_row.Po - -rm -f unit/$(DEPDIR)/test_separated_list.Po - -rm -f unit/$(DEPDIR)/test_simultaneous_transactions.Po - -rm -f unit/$(DEPDIR)/test_sql_cursor.Po - -rm -f unit/$(DEPDIR)/test_stateless_cursor.Po - -rm -f unit/$(DEPDIR)/test_strconv.Po - -rm -f unit/$(DEPDIR)/test_stream_from.Po - -rm -f unit/$(DEPDIR)/test_stream_to.Po - -rm -f unit/$(DEPDIR)/test_string_conversion.Po - -rm -f unit/$(DEPDIR)/test_subtransaction.Po - -rm -f unit/$(DEPDIR)/test_test_helpers.Po - -rm -f unit/$(DEPDIR)/test_thread_safety_model.Po - -rm -f unit/$(DEPDIR)/test_time.Po - -rm -f unit/$(DEPDIR)/test_transaction.Po - -rm -f unit/$(DEPDIR)/test_transaction_base.Po - -rm -f unit/$(DEPDIR)/test_transaction_focus.Po - -rm -f unit/$(DEPDIR)/test_transactor.Po - -rm -f unit/$(DEPDIR)/test_type_name.Po - -rm -f unit/$(DEPDIR)/test_zview.Po - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: check-am install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ - check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ - cscopelist-am ctags ctags-am distclean distclean-compile \ - distclean-generic distclean-libtool distclean-tags distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - -.PRECIOUS: Makefile - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ext/libpqxx-7.7.3/test/runner.cxx b/ext/libpqxx-7.7.3/test/runner.cxx deleted file mode 100644 index 38c9849d8..000000000 --- a/ext/libpqxx-7.7.3/test/runner.cxx +++ /dev/null @@ -1,203 +0,0 @@ -/* libpqxx test runner. - */ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "test_helpers.hxx" - -namespace -{ -inline std::string deref_field(pqxx::field const &f) -{ - return f.c_str(); -} -} // namespace - - -namespace pqxx::test -{ -test_failure::test_failure( - std::string const &ffile, int fline, std::string const &desc) : - std::logic_error(desc), m_file(ffile), m_line(fline) -{} - -test_failure::~test_failure() noexcept = default; - - -/// Drop table, if it exists. -inline void drop_table(transaction_base &t, std::string const &table) -{ - t.exec("DROP TABLE IF EXISTS " + table); -} - - -[[noreturn]] void -check_notreached(char const file[], int line, std::string desc) -{ - throw test_failure(file, line, desc); -} - - -void check( - char const file[], int line, bool condition, char const text[], - std::string const &desc) -{ - if (not condition) - throw test_failure( - file, line, desc + " (failed expression: " + text + ")"); -} - - -void expected_exception(std::string const &message) -{ - std::cout << "(Expected) " << message << std::endl; -} - - -std::string list_row(row Obj) -{ - return separated_list(", ", std::begin(Obj), std::end(Obj), deref_field); -} - - -std::string list_result(result Obj) -{ - if (std::empty(Obj)) - return ""; - return "{" + - separated_list( - "}\n{", std::begin(Obj), std::end(Obj), - [](row r) { return list_row(r); }) + - "}"; -} - - -std::string list_result_iterator(result::const_iterator Obj) -{ - return ""; -} - - -void create_pqxxevents(transaction_base &t) -{ - t.exec( - "CREATE TEMP TABLE pqxxevents(year integer, event varchar) " - "ON COMMIT PRESERVE ROWS"); - t.exec("INSERT INTO pqxxevents(year, event) VALUES (71, 'jtv')"); - t.exec("INSERT INTO pqxxevents(year, event) VALUES (38, 'time_t overflow')"); - t.exec( - "INSERT INTO pqxxevents(year, event) VALUES (1, '''911'' WTC attack')"); - t.exec("INSERT INTO pqxxevents(year, event) VALUES (81, 'C:\\>')"); - t.exec( - "INSERT INTO pqxxevents(year, event) VALUES (1978, 'bloody\t\tcold')"); - t.exec("INSERT INTO pqxxevents(year, event) VALUES (99, '')"); - t.exec("INSERT INTO pqxxevents(year, event) VALUES (2002, 'libpqxx')"); - t.exec( - "INSERT INTO pqxxevents(year, event) " - "VALUES (1989, 'Ode an die Freiheit')"); - t.exec( - "INSERT INTO pqxxevents(year, event) VALUES (2001, 'New millennium')"); - t.exec("INSERT INTO pqxxevents(year, event) VALUES (1974, '')"); - t.exec("INSERT INTO pqxxevents(year, event) VALUES (97, 'Asian crisis')"); - t.exec( - "INSERT INTO pqxxevents(year, event) VALUES (2001, 'A Space Odyssey')"); -} -} // namespace pqxx::test - - -namespace -{ -std::map *all_tests{nullptr}; -} // namespace - - -namespace pqxx::test -{ -void register_test(char const name[], pqxx::test::testfunc func) -{ - if (all_tests == nullptr) - { - all_tests = new std::map(); - } - else - { - assert(all_tests->find(name) == all_tests->end()); - } - (*all_tests)[name] = func; -} -} // namespace pqxx::test - - -int main(int argc, char const *argv[]) -{ - char const *const test_name{(argc > 1) ? argv[1] : nullptr}; - - int test_count = 0; - std::list failed; - for (auto const &i : *all_tests) - if (test_name == nullptr or std::string{test_name} == std::string{i.first}) - { - std::cout << std::endl << "Running: " << i.first << std::endl; - - bool success = false; - try - { - i.second(); - success = true; - } - catch (pqxx::test::test_failure const &e) - { - std::cerr << "Test failure in " + e.file() + " line " + - pqxx::to_string(e.line()) - << ": " << e.what() << std::endl; - } - catch (std::bad_alloc const &) - { - std::cerr << "Out of memory!" << std::endl; - } - catch (pqxx::feature_not_supported const &e) - { - std::cerr << "Not testing unsupported feature: " << e.what() - << std::endl; - success = true; - --test_count; - } - catch (pqxx::sql_error const &e) - { - std::cerr << "SQL error: " << e.what() << std::endl - << "Query was: " << e.query() << std::endl; - } - catch (std::exception const &e) - { - std::cerr << "Exception: " << e.what() << std::endl; - } - catch (...) - { - std::cerr << "Unknown exception" << std::endl; - } - - if (not success) - { - std::cerr << "FAILED: " << i.first << std::endl; - failed.emplace_back(i.first); - } - ++test_count; - } - - std::cout << "Ran " << test_count << " test(s).\n"; - - if (not std::empty(failed)) - { - std::cerr << "*** " << std::size(failed) << " test(s) failed: ***\n"; - for (auto const &i : failed) std::cerr << "\t" << i << '\n'; - } - - return int(std::size(failed)); -} diff --git a/ext/libpqxx-7.7.3/test/test00.cxx b/ext/libpqxx-7.7.3/test/test00.cxx deleted file mode 100644 index 698c9b81b..000000000 --- a/ext/libpqxx-7.7.3/test/test00.cxx +++ /dev/null @@ -1,114 +0,0 @@ -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Initial test program for libpqxx. Test functionality that doesn't require a -// running database. - -namespace -{ -template -inline void -strconv(std::string const &type, T const &Obj, std::string const &expected) -{ - std::string const Objstr{to_string(Obj)}; - - PQXX_CHECK_EQUAL(Objstr, expected, "String mismatch for " + type + "."); - T NewObj; - from_string(Objstr, NewObj); - PQXX_CHECK_EQUAL( - to_string(NewObj), expected, "String mismatch for recycled " + type + "."); -} - -// There's no from_string()... -inline void -strconv(std::string const &type, char const Obj[], std::string const &expected) -{ - std::string const Objstr(to_string(Obj)); - PQXX_CHECK_EQUAL(Objstr, expected, "String mismatch for " + type + "."); -} - -constexpr double not_a_number{std::numeric_limits::quiet_NaN()}; - -struct intderef -{ - template int operator()(ITER i) const noexcept - { - return int(*i); - } -}; - - -void test_000() -{ - PQXX_CHECK_EQUAL( - oid_none, 0u, - "InvalidIod is not zero as it used to be. This may conceivably " - "cause problems in libpqxx."); - - PQXX_CHECK( - cursor_base::prior() < 0 and cursor_base::backward_all() < 0, - "cursor_base::difference_type appears to be unsigned."); - - constexpr char weird[]{"foo\t\n\0bar"}; - std::string const weirdstr(weird, std::size(weird) - 1); - - // Test string conversions - strconv("char const[]", "", ""); - strconv("char const[]", "foo", "foo"); - strconv("int", 0, "0"); - strconv("int", 100, "100"); - strconv("int", -1, "-1"); - -#if defined(_MSC_VER) - long const long_min{LONG_MIN}, long_max{LONG_MAX}; -#else - long const long_min{std::numeric_limits::min()}, - long_max{std::numeric_limits::max()}; -#endif - - std::stringstream lminstr, lmaxstr, llminstr, llmaxstr, ullmaxstr; - lminstr.imbue(std::locale("C")); - lmaxstr.imbue(std::locale("C")); - llminstr.imbue(std::locale("C")); - llmaxstr.imbue(std::locale("C")); - ullmaxstr.imbue(std::locale("C")); - - lminstr << long_min; - lmaxstr << long_max; - - auto const ullong_max{std::numeric_limits::max()}; - auto const llong_max{std::numeric_limits::max()}, - llong_min{std::numeric_limits::min()}; - - llminstr << llong_min; - llmaxstr << llong_max; - ullmaxstr << ullong_max; - - strconv("long", 0, "0"); - strconv("long", long_min, lminstr.str()); - strconv("long", long_max, lmaxstr.str()); - strconv("double", not_a_number, "nan"); - strconv("string", std::string{}, ""); - strconv("string", weirdstr, weirdstr); - strconv("long long", 0LL, "0"); - strconv("long long", llong_min, llminstr.str()); - strconv("long long", llong_max, llmaxstr.str()); - strconv("unsigned long long", 0ULL, "0"); - strconv("unsigned long long", ullong_max, ullmaxstr.str()); - - std::stringstream ss; - strconv("empty stringstream", ss, ""); - ss << -3.1415; - strconv("stringstream", ss, ss.str()); -} - - -PQXX_REGISTER_TEST(test_000); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test01.cxx b/ext/libpqxx-7.7.3/test/test01.cxx deleted file mode 100644 index 84b7f3b78..000000000 --- a/ext/libpqxx-7.7.3/test/test01.cxx +++ /dev/null @@ -1,33 +0,0 @@ -#include - -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -namespace -{ -// Simple test program for libpqxx. Open connection to database, start -// a transaction, and perform a query inside it. -void test_001() -{ - connection conn; - - // Begin a transaction acting on our current connection. Give it a human- - // readable name so the library can include it in error messages. - work tx{conn, "test1"}; - - // Perform a query on the database, storing result rows in R. - result r(tx.exec("SELECT * FROM pg_tables")); - - // We're expecting to find some tables... - PQXX_CHECK(not std::empty(r), "No tables found."); - - tx.commit(); -} - - -PQXX_REGISTER_TEST(test_001); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test02.cxx b/ext/libpqxx-7.7.3/test/test02.cxx deleted file mode 100644 index f98e18d08..000000000 --- a/ext/libpqxx-7.7.3/test/test02.cxx +++ /dev/null @@ -1,76 +0,0 @@ -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Example/test program for libpqxx. Perform a query and enumerate its output -// using array indexing. - -namespace -{ -void bad_connect() -{ - connection conn{"totally#invalid@connect$string!?"}; -} - -void test_002() -{ - // Before we really connect, test the expected behaviour of the default - // connection type, where a failure to connect results in an immediate - // exception rather than a silent retry. - PQXX_CHECK_THROWS_EXCEPTION( - bad_connect(), "Invalid connection string did not cause exception."); - - // Set up connection to database - std::string ConnectString; - connection C{ConnectString}; - - // Start transaction within context of connection. - work T{C, "test2"}; - - // Perform query within transaction. - result R(T.exec("SELECT * FROM pg_tables")); - - // Let's keep the database waiting as briefly as possible: commit now, - // before we start processing results. We could do this later, or since - // we're not making any changes in the database that need to be committed, - // we could in this case even omit it altogether. - T.commit(); - - // Ah, this version of postgres will tell you which table a column in a - // result came from. Let's just test that functionality... - oid const rtable{R.column_table(0)}; - PQXX_CHECK_EQUAL( - rtable, R.column_table(pqxx::row::size_type(0)), - "Inconsistent answers from column_table()"); - - std::string const rcol{R.column_name(0)}; - oid const crtable{R.column_table(rcol)}; - PQXX_CHECK_EQUAL( - crtable, rtable, "Field looked up by name gives different origin."); - - // Now we've got all that settled, let's process our results. - for (auto const &f : R) - { - oid const ftable{f[0].table()}; - PQXX_CHECK_EQUAL(ftable, rtable, "field::table() is broken."); - - oid const ttable{f.column_table(0)}; - - PQXX_CHECK_EQUAL( - ttable, f.column_table(pqxx::row::size_type(0)), - "Inconsistent pqxx::row::column_table()."); - - PQXX_CHECK_EQUAL(ttable, rtable, "Inconsistent result::column_table()."); - - oid const cttable{f.column_table(rcol)}; - - PQXX_CHECK_EQUAL(cttable, rtable, "pqxx::row::column_table() is broken."); - } -} - - -PQXX_REGISTER_TEST(test_002); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test04.cxx b/ext/libpqxx-7.7.3/test/test04.cxx deleted file mode 100644 index 623446398..000000000 --- a/ext/libpqxx-7.7.3/test/test04.cxx +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - -// Example program for libpqxx. Send notification to self. - -namespace -{ -int Backend_PID{0}; - - -// Sample implementation of notification receiver. -class TestListener final : public notification_receiver -{ - bool m_done; - -public: - explicit TestListener(connection &conn) : - notification_receiver(conn, "listen"), m_done(false) - {} - - virtual void operator()(std::string const &, int be_pid) override - { - m_done = true; - PQXX_CHECK_EQUAL( - be_pid, Backend_PID, "Notification came from wrong backend process."); - } - - bool done() const { return m_done; } -}; - - -void test_004() -{ - connection conn; - - TestListener L{conn}; - // Trigger our notification receiver. - perform([&conn, &L] { - work tx(conn); - tx.exec0("NOTIFY " + conn.quote_name(L.channel())); - Backend_PID = conn.backendpid(); - tx.commit(); - }); - - int notifs{0}; - for (int i{0}; (i < 20) and not L.done(); ++i) - { - PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notifications."); - // Sleep for one second. I'm not proud of this, but how does one inject - // a change to the built-in clock in a static language? - pqxx::internal::wait_for(1'000'000u); - notifs = conn.get_notifs(); - } - - PQXX_CHECK_NOT_EQUAL(L.done(), false, "No notification received."); - PQXX_CHECK_EQUAL(notifs, 1, "Got too many notifications."); -} - - -PQXX_REGISTER_TEST(test_004); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test07.cxx b/ext/libpqxx-7.7.3/test/test07.cxx deleted file mode 100644 index 875ee8d50..000000000 --- a/ext/libpqxx-7.7.3/test/test07.cxx +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Example program for libpqxx. Modify the database, retaining transactional -// integrity using the transactor framework. -// -// This assumes the existence of a database table "pqxxevents" containing a -// 2-digit "year" field, which is extended to a 4-digit format by assuming all -// year numbers of 70 or higher are in the 20th century, and all others in the -// 21st, and that no years before 1970 are possible. - -namespace -{ -// Convert year to 4-digit format. -int To4Digits(int Y) -{ - int Result{Y}; - - PQXX_CHECK(Y >= 0, "Negative year: " + to_string(Y)); - if (Y < 70) - Result += 2000; - else if (Y < 100) - Result += 1900; - else if (Y < 1970) - PQXX_CHECK_NOTREACHED("Unexpected year: " + to_string(Y)); - - return Result; -} - - -void test_007() -{ - connection conn; - conn.set_client_encoding("SQL_ASCII"); - - { - work tx{conn}; - test::create_pqxxevents(tx); - tx.commit(); - } - - // Perform (an instantiation of) the UpdateYears transactor we've defined - // in the code above. This is where the work gets done. - std::map conversions; - perform([&conversions, &conn] { - work tx{conn}; - // First select all different years occurring in the table. - result R(tx.exec("SELECT year FROM pqxxevents")); - - // See if we get reasonable type identifier for this column. - oid const rctype{R.column_type(0)}; - PQXX_CHECK_EQUAL( - R.column_type(pqxx::row::size_type(0)), rctype, - "Inconsistent result::column_type()."); - - std::string const rct{to_string(rctype)}; - PQXX_CHECK(rctype > 0, "Got strange type ID for column: " + rct); - - std::string const rcol{R.column_name(0)}; - PQXX_CHECK(not std::empty(rcol), "Didn't get a name for column."); - - oid const rcctype{R.column_type(rcol)}; - PQXX_CHECK_EQUAL( - rcctype, rctype, "Column type is not what it is by name."); - - oid const rawrcctype{R.column_type(rcol)}; - PQXX_CHECK_EQUAL( - rawrcctype, rctype, "Column type by C-style name is different."); - - // Note all different years currently occurring in the table, writing - // them and their correct mappings to conversions. - for (auto const &r : R) - { - int Y{0}; - - // Read year, and if it is non-null, note its converted value - if (r[0] >> Y) - conversions[Y] = To4Digits(Y); - - // See if type identifiers are consistent - oid const tctype{r.column_type(0)}; - - PQXX_CHECK_EQUAL( - tctype, r.column_type(pqxx::row::size_type(0)), - "Inconsistent pqxx::row::column_type()"); - - PQXX_CHECK_EQUAL( - tctype, rctype, - "pqxx::row::column_type() is inconsistent with " - "result::column_type()."); - - oid const ctctype{r.column_type(rcol)}; - - PQXX_CHECK_EQUAL( - ctctype, rctype, "Column type lookup by column name is broken."); - - oid const rawctctype{r.column_type(rcol)}; - - PQXX_CHECK_EQUAL( - rawctctype, rctype, "Column type lookup by C-style name is broken."); - - oid const fctype{r[0].type()}; - PQXX_CHECK_EQUAL(fctype, rctype, "Field type lookup is broken."); - } - - // For each occurring year, write converted date back to whereever it may - // occur in the table. Since we're in a transaction, any changes made by - // others at the same time will not affect us. - for (auto const &c : conversions) - { - auto const query{ - "UPDATE pqxxevents " - "SET year=" + - to_string(c.second) + - " " - "WHERE year=" + - to_string(c.first)}; - R = tx.exec0(query); - } - }); -} - - -PQXX_REGISTER_TEST(test_007); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test10.cxx b/ext/libpqxx-7.7.3/test/test10.cxx deleted file mode 100644 index 4cb4aaba1..000000000 --- a/ext/libpqxx-7.7.3/test/test10.cxx +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include - -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Open connection to database, start a transaction, -// abort it, and verify that it "never happened." - -namespace -{ -// Let's take a boring year that is not going to be in the "pqxxevents" table -constexpr int BoringYear{1977}; - -std::string const Table("pqxxevents"); - - -// Count events, and boring events, in table -std::pair CountEvents(transaction_base &T) -{ - std::string const events_query{"SELECT count(*) FROM " + Table}; - std::string const boring_query{ - events_query + " WHERE year=" + to_string(BoringYear)}; - return std::make_pair( - T.query_value(events_query), T.query_value(boring_query)); -} - - -// Try adding a record, then aborting it, and check whether the abort was -// performed correctly. -void Test(connection &C, bool ExplicitAbort) -{ - std::pair EventCounts; - - // First run our doomed transaction. This will refuse to run if an event - // exists for our Boring Year. - { - // Begin a transaction acting on our current connection; we'll abort it - // later though. - work Doomed{C, "Doomed"}; - - // Verify that our Boring Year was not yet in the events table - EventCounts = CountEvents(Doomed); - - PQXX_CHECK_EQUAL( - EventCounts.second, 0, "Can't run, boring year is already in table."); - - // Now let's try to introduce a row for our Boring Year - Doomed.exec0( - "INSERT INTO " + Table + - "(year, event) " - "VALUES (" + - to_string(BoringYear) + ", 'yawn')"); - - auto const Recount{CountEvents(Doomed)}; - PQXX_CHECK_EQUAL( - Recount.second, 1, "Wrong # events for " + to_string(BoringYear)); - - PQXX_CHECK_EQUAL( - Recount.first, EventCounts.first + 1, "Number of events changed."); - - // Okay, we've added an entry but we don't really want to. Abort it - // explicitly if requested, or simply let the Transaction object "expire." - if (ExplicitAbort) - Doomed.abort(); - - // If now explicit abort requested, Doomed Transaction still ends here - } - - // Now check that we're back in the original state. Note that this may go - // wrong if somebody managed to change the table between our two - // transactions. - work Checkup(C, "Checkup"); - - auto const NewEvents{CountEvents(Checkup)}; - PQXX_CHECK_EQUAL( - NewEvents.first, EventCounts.first, - "Number of events changed. This may be due to a bug in libpqxx, " - "or the test table was modified by some other process."); - - PQXX_CHECK_EQUAL( - NewEvents.second, 0, - "Found unexpected events. This may be due to a bug in libpqxx, " - "or the test table was modified by some other process."); -} - - -void test_abort() -{ - connection conn; - nontransaction t{conn}; - test::create_pqxxevents(t); - connection &c(t.conn()); - t.commit(); - Test(c, true); - Test(c, false); -} - - -PQXX_REGISTER_TEST(test_abort); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test11.cxx b/ext/libpqxx-7.7.3/test/test11.cxx deleted file mode 100644 index 4b42a66d5..000000000 --- a/ext/libpqxx-7.7.3/test/test11.cxx +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include - -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Query a table and report its metadata. -namespace -{ -void test_011() -{ - connection conn; - work tx{conn}; - std::string const Table{"pg_tables"}; - - result R(tx.exec("SELECT * FROM " + Table)); - - // Print column names - for (pqxx::row::size_type c{0}; c < R.columns(); ++c) - { - std::string N{R.column_name(c)}; - PQXX_CHECK_EQUAL(R.column_number(N), c, "Inconsistent column numbers."); - } - - // If there are rows in R, compare their metadata to R's. - if (not std::empty(R)) - { - PQXX_CHECK_EQUAL(R[0].rownumber(), 0, "Row 0 has wrong number."); - - if (std::size(R) >= 2) - PQXX_CHECK_EQUAL(R[1].rownumber(), 1, "Row 1 has wrong number."); - - // Test result::iterator::swap() - pqxx::result::const_iterator const T1(R[0]), T2(R[1]); - PQXX_CHECK_NOT_EQUAL(T1, T2, "Values are identical--can't test swap()."); - pqxx::result::const_iterator T1s(T1), T2s(T2); - PQXX_CHECK_EQUAL(T1s, T1, "Result iterator copy-construction is wrong."); - PQXX_CHECK_EQUAL( - T2s, T2, "Result iterator copy-construction is inconsistently wrong."); - T1s.swap(T2s); - PQXX_CHECK_NOT_EQUAL(T1s, T1, "Result iterator swap doesn't work."); - PQXX_CHECK_NOT_EQUAL( - T2s, T2, "Result iterator swap inconsistently wrong."); - PQXX_CHECK_EQUAL(T2s, T1, "Result iterator swap is asymmetric."); - PQXX_CHECK_EQUAL( - T1s, T2, "Result iterator swap is inconsistently asymmetric."); - - for (pqxx::row::size_type c{0}; c < std::size(R[0]); ++c) - { - std::string N{R.column_name(c)}; - - PQXX_CHECK_EQUAL( - std::string{R[0].at(c).c_str()}, R[0].at(N).c_str(), - "Field by name != field by number."); - - PQXX_CHECK_EQUAL( - std::string{R[0][c].c_str()}, R[0][N].c_str(), - "at() is inconsistent with operator[]."); - - PQXX_CHECK_EQUAL(R[0][c].name(), N, "Field names are inconsistent."); - - PQXX_CHECK_EQUAL( - std::size(R[0][c]), strlen(R[0][c].c_str()), - "Field size is not what we expected."); - } - } -} - - -PQXX_REGISTER_TEST(test_011); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test13.cxx b/ext/libpqxx-7.7.3/test/test13.cxx deleted file mode 100644 index b3577a5d3..000000000 --- a/ext/libpqxx-7.7.3/test/test13.cxx +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Verify abort behaviour of transactor. -// -// The program will attempt to add an entry to a table called "pqxxevents", -// with a key column called "year"--and then abort the change. -// -// Note for the superstitious: the numbering for this test program is pure -// coincidence. -namespace -{ -// Let's take a boring year that is not going to be in the "pqxxevents" table -constexpr unsigned int BoringYear = 1977; - - -// Count events and specifically events occurring in Boring Year, leaving the -// former count in the result pair's first member, and the latter in second. -std::pair count_events(connection &conn, std::string const &table) -{ - work tx{conn}; - std::string const count_query{"SELECT count(*) FROM " + table}; - return std::make_pair( - tx.query_value(count_query), - tx.query_value(count_query + " WHERE year=" + to_string(BoringYear))); -} - - -struct deliberate_error : std::exception -{}; - - -void failed_insert(connection &C, std::string const &table) -{ - work tx(C); - result R = tx.exec0( - "INSERT INTO " + table + " VALUES (" + to_string(BoringYear) + - ", " - "'yawn')"); - - PQXX_CHECK_EQUAL(R.affected_rows(), 1, "Bad affected_rows()."); - throw deliberate_error(); -} - - -void test_013() -{ - connection conn; - { - work tx{conn}; - test::create_pqxxevents(tx); - tx.commit(); - } - - std::string const Table{"pqxxevents"}; - - auto const Before{ - perform([&conn, &Table] { return count_events(conn, Table); })}; - PQXX_CHECK_EQUAL( - Before.second, 0, - "Already have event for " + to_string(BoringYear) + "--can't test."); - - quiet_errorhandler d(conn); - PQXX_CHECK_THROWS( - perform([&conn, &Table] { failed_insert(conn, Table); }), deliberate_error, - "Failing transactor failed to throw correct exception."); - - auto const After{ - perform([&conn, &Table] { return count_events(conn, Table); })}; - - PQXX_CHECK_EQUAL( - After.first, Before.first, "abort() didn't reset event count."); - - PQXX_CHECK_EQUAL( - After.second, Before.second, - "abort() didn't reset event count for " + to_string(BoringYear)); -} - - -PQXX_REGISTER_TEST(test_013); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test14.cxx b/ext/libpqxx-7.7.3/test/test14.cxx deleted file mode 100644 index c82f2323c..000000000 --- a/ext/libpqxx-7.7.3/test/test14.cxx +++ /dev/null @@ -1,36 +0,0 @@ -#include - -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test nontransaction. - -namespace -{ -void test_014() -{ - connection conn; - - // Begin a "non-transaction" acting on our current connection. This is - // really all the transactional integrity we need since we're only - // performing one query which does not modify the database. - nontransaction tx{conn, "test14"}; - - // The transaction class family also has process_notice() functions. - // These simply pass the notice through to their connection, but this may - // be more convenient in some cases. All process_notice() functions accept - // C++ strings as well as C strings. - tx.process_notice(std::string{"Started nontransaction\n"}); - - // "Commit" the non-transaction. This doesn't really do anything since - // nontransaction doesn't start a backend transaction. - tx.commit(); -} - - -PQXX_REGISTER_TEST(test_014); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test16.cxx b/ext/libpqxx-7.7.3/test/test16.cxx deleted file mode 100644 index 211bbba6a..000000000 --- a/ext/libpqxx-7.7.3/test/test16.cxx +++ /dev/null @@ -1,46 +0,0 @@ -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test robusttransaction. -namespace -{ -void test_016() -{ - connection conn; - robusttransaction<> tx{conn}; - result R{tx.exec("SELECT * FROM pg_tables")}; - - result::const_iterator c; - for (c = std::begin(R); c != std::end(R); ++c) - ; - - // See if back() and row comparison work properly - PQXX_CHECK( - std::size(R) >= 2, "Not enough rows in pg_tables to test, sorry!"); - - --c; - - PQXX_CHECK_EQUAL( - c->size(), std::size(R.back()), - "Size mismatch between row iterator and back()."); - - std::string const nullstr; - for (pqxx::row::size_type i{0}; i < c->size(); ++i) - PQXX_CHECK_EQUAL( - c[i].as(nullstr), R.back()[i].as(nullstr), "Value mismatch in back()."); - PQXX_CHECK(*c == R.back(), "Row equality is broken."); - PQXX_CHECK(not(*c != R.back()), "Row inequality is broken."); - - tx.commit(); -} - - -PQXX_REGISTER_TEST(test_016); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test17.cxx b/ext/libpqxx-7.7.3/test/test17.cxx deleted file mode 100644 index 7c99a35cc..000000000 --- a/ext/libpqxx-7.7.3/test/test17.cxx +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#include -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Simple test program for libpqxx. Open connection to database, start -// a dummy transaction to gain nontransactional access, and perform a query. -namespace -{ -void test_017() -{ - connection conn; - perform([&conn] { - nontransaction tx{conn}; - auto const r{tx.exec("SELECT * FROM generate_series(1, 4)")}; - PQXX_CHECK_EQUAL(std::size(r), 4, "Weird query result."); - tx.commit(); - }); -} - - -PQXX_REGISTER_TEST(test_017); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test18.cxx b/ext/libpqxx-7.7.3/test/test18.cxx deleted file mode 100644 index 9718d2daa..000000000 --- a/ext/libpqxx-7.7.3/test/test18.cxx +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Verify abort behaviour of RobustTransaction. -// -// The program will attempt to add an entry to a table called "pqxxevents", -// with a key column called "year"--and then abort the change. -namespace -{ -// Let's take a boring year that is not going to be in the "pqxxevents" table -constexpr long BoringYear{1977}; - - -// Count events and specifically events occurring in Boring Year, leaving the -// former count in the result pair's first member, and the latter in second. -std::pair count_events(connection &conn, std::string const &table) -{ - nontransaction tx{conn}; - std::string const count_query{"SELECT count(*) FROM " + table}; - return std::make_pair( - tx.query_value(count_query), - tx.query_value(count_query + " WHERE year=" + to_string(BoringYear))); -} - - -struct deliberate_error : std::exception -{}; - - -void test_018() -{ - connection conn; - { - work tx{conn}; - test::create_pqxxevents(tx); - tx.commit(); - } - - std::string const Table{"pqxxevents"}; - - auto const Before{ - perform([&conn, &Table] { return count_events(conn, Table); })}; - PQXX_CHECK_EQUAL( - Before.second, 0, - "Already have event for " + to_string(BoringYear) + ", cannot run."); - - { - quiet_errorhandler d{conn}; - PQXX_CHECK_THROWS( - perform([&conn, Table] { - robusttransaction tx{conn}; - tx.exec0( - "INSERT INTO " + Table + " VALUES (" + to_string(BoringYear) + - ", '" + tx.esc("yawn") + "')"); - - throw deliberate_error(); - }), - deliberate_error, - "Not getting expected exception from failing transactor."); - } - - auto const After{ - perform([&conn, &Table] { return count_events(conn, Table); })}; - - PQXX_CHECK_EQUAL(After.first, Before.first, "Event count changed."); - PQXX_CHECK_EQUAL( - After.second, Before.second, - "Event count for " + to_string(BoringYear) + " changed."); -} - - -PQXX_REGISTER_TEST(test_018); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test20.cxx b/ext/libpqxx-7.7.3/test/test20.cxx deleted file mode 100644 index 1ddd4b09a..000000000 --- a/ext/libpqxx-7.7.3/test/test20.cxx +++ /dev/null @@ -1,95 +0,0 @@ -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test: nontransaction changes are not rolled back on abort. -namespace -{ -constexpr unsigned long BoringYear{1977}; - - -void test_020() -{ - connection conn; - nontransaction t1{conn}; - test::create_pqxxevents(t1); - - std::string const Table{"pqxxevents"}; - - // Verify our start condition before beginning: there must not be a 1977 - // record already. - result R(t1.exec(("SELECT * FROM " + Table + - " " - "WHERE year=" + - to_string(BoringYear)) - .c_str())); - PQXX_CHECK_EQUAL( - std::size(R), 0, - "Already have a row for " + to_string(BoringYear) + ", cannot test."); - - // (Not needed, but verify that clear() works on empty containers) - R.clear(); - PQXX_CHECK(std::empty(R), "result::clear() is broken."); - - // OK. Having laid that worry to rest, add a record for 1977. - t1.exec0( - "INSERT INTO " + Table + - " VALUES" - "(" + - to_string(BoringYear) + - "," - "'Yawn'" - ")"); - - // Abort T1. Since T1 is a nontransaction, which provides only the - // transaction class interface without providing any form of transactional - // integrity, this is not going to undo our work. - t1.abort(); - - // Verify that our record was added, despite the Abort() - nontransaction t2{conn, "t2"}; - R = t2.exec(("SELECT * FROM " + Table + - " " - "WHERE year=" + - to_string(BoringYear)) - .c_str()); - - PQXX_CHECK_EQUAL( - std::size(R), 1, - "Found wrong number of rows for " + to_string(BoringYear) + "."); - - PQXX_CHECK(R.capacity() >= std::size(R), "Result's capacity is too small."); - - R.clear(); - PQXX_CHECK(std::empty(R), "result::clear() doesn't work."); - - // Now remove our record again - t2.exec0( - "DELETE FROM " + Table + - " " - "WHERE year=" + - to_string(BoringYear)); - - t2.commit(); - - // And again, verify results - nontransaction t3{conn, "t3"}; - - R = t3.exec(("SELECT * FROM " + Table + - " " - "WHERE year=" + - to_string(BoringYear)) - .c_str()); - - PQXX_CHECK_EQUAL(std::size(R), 0, "Record still found after removal."); -} - - -PQXX_REGISTER_TEST(test_020); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test21.cxx b/ext/libpqxx-7.7.3/test/test21.cxx deleted file mode 100644 index 1090050d9..000000000 --- a/ext/libpqxx-7.7.3/test/test21.cxx +++ /dev/null @@ -1,70 +0,0 @@ -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Simple test program for libpqxx. Open a connection to database, start a -// transaction, and perform a query inside it. -namespace -{ -void test_021() -{ - connection conn; - - std::string const HostName{ - ((conn.hostname() == nullptr) ? "" : conn.hostname())}; - conn.process_notice( - std::string{} + "database=" + conn.dbname() + - ", " - "username=" + - conn.username() + - ", " - "hostname=" + - HostName + - ", " - "port=" + - to_string(conn.port()) + - ", " - "backendpid=" + - to_string(conn.backendpid()) + "\n"); - - work tx{conn, "test_021"}; - - // By now our connection should really have been created - conn.process_notice("Printing details on actual connection\n"); - conn.process_notice( - std::string{} + "database=" + conn.dbname() + - ", " - "username=" + - conn.username() + - ", " - "hostname=" + - HostName + - ", " - "port=" + - to_string(conn.port()) + - ", " - "backendpid=" + - to_string(conn.backendpid()) + "\n"); - - std::string P; - from_string(conn.port(), P); - PQXX_CHECK_EQUAL( - P, to_string(conn.port()), "Port string conversion is broken."); - PQXX_CHECK_EQUAL(to_string(P), P, "Port string conversion is broken."); - - result R(tx.exec("SELECT * FROM pg_tables")); - - tx.process_notice(pqxx::internal::concat( - to_string(std::size(R)), " result row in transaction ", tx.name(), "\n")); - tx.commit(); -} - - -PQXX_REGISTER_TEST(test_021); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test26.cxx b/ext/libpqxx-7.7.3/test/test26.cxx deleted file mode 100644 index 69b04d839..000000000 --- a/ext/libpqxx-7.7.3/test/test26.cxx +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -#include -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Example program for libpqxx. Modify the database, retaining transactional -// integrity using the transactor framework. -namespace -{ -// Convert year to 4-digit format. -int To4Digits(int Y) -{ - int Result{Y}; - - PQXX_CHECK(Y >= 0, "Negative year: " + to_string(Y)); - - if (Y < 70) - Result += 2000; - else if (Y < 100) - Result += 1900; - else - PQXX_CHECK(Y >= 1970, "Unexpected year: " + to_string(Y)); - return Result; -} - - -// Transaction definition for year-field update. Returns conversions done. -std::map update_years(connection &C) -{ - std::map conversions; - work tx{C}; - - // Note all different years currently occurring in the table, writing them - // and their correct mappings to m_conversions - for (auto const &[y] : - tx.stream>("SELECT year FROM pqxxevents")) - { - // Read year, and if it is non-null, note its converted value - if (bool(y)) - conversions[y.value()] = To4Digits(y.value()); - } - - // For each occurring year, write converted date back to whereever it may - // occur in the table. Since we're in a transaction, any changes made by - // others at the same time will not affect us. - for (auto const &c : conversions) - tx.exec0( - "UPDATE pqxxevents " - "SET year=" + - to_string(c.second) + - " " - "WHERE year=" + - to_string(c.first)); - - tx.commit(); - - return conversions; -} - - -void test_026() -{ - connection conn; - { - nontransaction tx{conn}; - test::create_pqxxevents(tx); - tx.commit(); - } - - // Perform (an instantiation of) the UpdateYears transactor we've defined - // in the code above. This is where the work gets done. - auto const conversions{perform([&conn] { return update_years(conn); })}; - - PQXX_CHECK(not std::empty(conversions), "No conversions done!"); -} - - -PQXX_REGISTER_TEST(test_026); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test29.cxx b/ext/libpqxx-7.7.3/test/test29.cxx deleted file mode 100644 index 4547523f1..000000000 --- a/ext/libpqxx-7.7.3/test/test29.cxx +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Open connection to database, start a transaction, -// abort it, and verify that it "never happened." -// -// The program will attempt to add an entry to a table called "pqxxevents", -// with a key column called "year"--and then abort the change. -namespace -{ -// Let's take a boring year that is not going to be in the "pqxxevents" table -constexpr int BoringYear{1977}; - -std::string const Table{"pqxxevents"}; - - -// Count events, and boring events, in table -std::pair CountEvents(transaction_base &tx) -{ - std::string const events_query{"SELECT count(*) FROM " + Table}; - std::string const boring_query{ - events_query + " WHERE year=" + to_string(BoringYear)}; - - return std::make_pair( - tx.query_value(events_query), tx.query_value(boring_query)); -} - - -// Try adding a record, then aborting it, and check whether the abort was -// performed correctly. -void Test(connection &conn, bool ExplicitAbort) -{ - std::vector BoringRow{to_string(BoringYear), "yawn"}; - - std::pair EventCounts; - - // First run our doomed transaction. This will refuse to run if an event - // exists for our Boring Year. - { - // Begin a transaction acting on our current connection; we'll abort it - // later though. - work Doomed(conn, "Doomed"); - - // Verify that our Boring Year was not yet in the events table - EventCounts = CountEvents(Doomed); - - PQXX_CHECK_EQUAL( - EventCounts.second, 0, - "Can't run; " + to_string(BoringYear) + " is already in the table."); - - // Now let's try to introduce a row for our Boring Year - Doomed.exec0( - "INSERT INTO " + Table + - "(year, event) " - "VALUES (" + - to_string(BoringYear) + ", 'yawn')"); - - auto Recount{CountEvents(Doomed)}; - PQXX_CHECK_EQUAL(Recount.second, 1, "Unexpected number of events."); - PQXX_CHECK_EQUAL( - Recount.first, EventCounts.first + 1, "Number of events changed."); - - // Okay, we've added an entry but we don't really want to. Abort it - // explicitly if requested, or simply let the Transaction object "expire." - if (ExplicitAbort) - Doomed.abort(); - - // If now explicit abort requested, Doomed Transaction still ends here - } - - // Now check that we're back in the original state. Note that this may go - // wrong if somebody managed to change the table between our two - // transactions. - work Checkup(conn, "Checkup"); - - auto NewEvents{CountEvents(Checkup)}; - PQXX_CHECK_EQUAL( - NewEvents.first, EventCounts.first, "Wrong number of events."); - - PQXX_CHECK_EQUAL(NewEvents.second, 0, "Found unexpected events."); -} - - -void test_029() -{ - connection conn; - { - nontransaction tx{conn}; - test::create_pqxxevents(tx); - } - - // Test abort semantics, both with explicit and implicit abort - Test(conn, true); - Test(conn, false); -} - - -PQXX_REGISTER_TEST(test_029); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test30.cxx b/ext/libpqxx-7.7.3/test/test30.cxx deleted file mode 100644 index fb6a05da0..000000000 --- a/ext/libpqxx-7.7.3/test/test30.cxx +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include - -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Query a table and report its metadata. -namespace -{ -void test_030() -{ - std::string const Table{"pg_tables"}; - - connection conn; - work tx{conn, "test30"}; - - result R(tx.exec(("SELECT * FROM " + Table).c_str())); - PQXX_CHECK(not std::empty(R), "Table " + Table + " is empty, cannot test."); - - // Print column names - for (pqxx::row::size_type c{0}; c < R.columns(); ++c) - { - std::string N{R.column_name(c)}; - - PQXX_CHECK_EQUAL( - R[0].column_number(N), R.column_number(N), - "row::column_number() is inconsistent with result::column_number()."); - - PQXX_CHECK_EQUAL(R[0].column_number(N), c, "Inconsistent column numbers."); - } - - // If there are rows in R, compare their metadata to R's. - if (std::empty(R)) - { - std::cout << "(Table is empty.)\n"; - return; - } - - PQXX_CHECK_EQUAL(R[0].rownumber(), 0, "Row 0 reports wrong number."); - - if (std::size(R) < 2) - std::cout << "(Only one row in table.)\n"; - else - PQXX_CHECK_EQUAL(R[1].rownumber(), 1, "Row 1 reports wrong number."); - - for (pqxx::row::size_type c{0}; c < std::size(R[0]); ++c) - { - std::string N{R.column_name(c)}; - - PQXX_CHECK_EQUAL( - std::string{R[0].at(c).c_str()}, R[0].at(N).c_str(), - "Different field values by name and by number."); - - PQXX_CHECK_EQUAL( - std::string{R[0][c].c_str()}, R[0][N].c_str(), - "at() is inconsistent with operator[]."); - - PQXX_CHECK_EQUAL(R[0][c].name(), N, "Inconsistent field names."); - - PQXX_CHECK_EQUAL( - std::size(R[0][c]), std::strlen(R[0][c].c_str()), - "Inconsistent field lengths."); - } -} - - -PQXX_REGISTER_TEST(test_030); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test32.cxx b/ext/libpqxx-7.7.3/test/test32.cxx deleted file mode 100644 index 90f0db68c..000000000 --- a/ext/libpqxx-7.7.3/test/test32.cxx +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Verify abort behaviour of transactor. -// -// The program will attempt to add an entry to a table called "pqxxevents", -// with a key column called "year"--and then abort the change. -// -// Note for the superstitious: the numbering for this test program is pure -// coincidence. - -namespace -{ -// Let's take a boring year that is not going to be in the "pqxxevents" table -constexpr int BoringYear{1977}; - -std::pair count_events(connection &conn, std::string const &table) -{ - std::string const count_query{"SELECT count(*) FROM " + table}; - work tx{conn}; - return std::make_pair( - tx.query_value(count_query), - tx.query_value(count_query + " WHERE year=" + to_string(BoringYear))); -} - - -struct deliberate_error : std::exception -{}; - - -void test_032() -{ - connection conn; - { - nontransaction tx{conn}; - test::create_pqxxevents(tx); - } - - std::string const Table{"pqxxevents"}; - - std::pair const Before{ - perform([&conn, &Table] { return count_events(conn, Table); })}; - PQXX_CHECK_EQUAL( - Before.second, 0, - "Already have event for " + to_string(BoringYear) + ", cannot test."); - - { - quiet_errorhandler d(conn); - PQXX_CHECK_THROWS( - perform([&conn, &Table] { - work{conn}.exec0( - "INSERT INTO " + Table + " VALUES (" + to_string(BoringYear) + - ", " - "'yawn')"); - throw deliberate_error(); - }), - deliberate_error, - "Did not get expected exception from failing transactor."); - } - - std::pair const After{ - perform([&conn, &Table] { return count_events(conn, Table); })}; - - PQXX_CHECK_EQUAL(After.first, Before.first, "Event count changed."); - PQXX_CHECK_EQUAL( - After.second, Before.second, - "Event count for " + to_string(BoringYear) + " changed."); -} - - -PQXX_REGISTER_TEST(test_032); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test37.cxx b/ext/libpqxx-7.7.3/test/test37.cxx deleted file mode 100644 index fe231d39b..000000000 --- a/ext/libpqxx-7.7.3/test/test37.cxx +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Verify abort behaviour of RobustTransaction. -// -// The program will attempt to add an entry to a table called "pqxxevents", -// with a key column called "year"--and then abort the change. -namespace -{ -// Let's take a boring year that is not going to be in the "pqxxevents" table -constexpr int BoringYear{1977}; - -// Count events and specifically events occurring in Boring Year, leaving the -// former count in the result pair's first member, and the latter in second. -std::pair count_events(connection &conn, std::string const &table) -{ - std::string const count_query{"SELECT count(*) FROM " + table}; - nontransaction tx{conn}; - return std::make_pair( - tx.query_value(count_query), - tx.query_value(count_query + " WHERE year=" + to_string(BoringYear))); -} - - -struct deliberate_error : std::exception -{}; - - -void test_037() -{ - connection conn; - { - nontransaction tx{conn}; - test::create_pqxxevents(tx); - } - - std::string const Table{"pqxxevents"}; - - auto const Before{ - perform([&conn, &Table] { return count_events(conn, Table); })}; - PQXX_CHECK_EQUAL( - Before.second, 0, - "Already have event for " + to_string(BoringYear) + ", cannot test."); - - { - quiet_errorhandler d(conn); - PQXX_CHECK_THROWS( - perform([&conn, &Table] { - robusttransaction<> tx{conn}; - tx.exec0( - "INSERT INTO " + Table + " VALUES (" + to_string(BoringYear) + - ", " - "'yawn')"); - - throw deliberate_error(); - }), - deliberate_error, - "Did not get expected exception from failing transactor."); - } - - auto const After{ - perform([&conn, &Table] { return count_events(conn, Table); })}; - - PQXX_CHECK_EQUAL(After.first, Before.first, "Number of events changed."); - PQXX_CHECK_EQUAL( - After.second, Before.second, - "Number of events for " + to_string(BoringYear) + " changed."); -} - - -PQXX_REGISTER_TEST(test_037); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test39.cxx b/ext/libpqxx-7.7.3/test/test39.cxx deleted file mode 100644 index d26855811..000000000 --- a/ext/libpqxx-7.7.3/test/test39.cxx +++ /dev/null @@ -1,89 +0,0 @@ -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test: nontransaction changes are committed immediately. -namespace -{ -int BoringYear{1977}; - - -void test_039() -{ - connection conn; - nontransaction tx1{conn}; - test::create_pqxxevents(tx1); - std::string const Table{"pqxxevents"}; - - // Verify our start condition before beginning: there must not be a 1977 - // record already. - result R(tx1.exec( - "SELECT * FROM " + Table + - " " - "WHERE year=" + - to_string(BoringYear))); - - PQXX_CHECK_EQUAL( - std::size(R), 0, - "Already have a row for " + to_string(BoringYear) + ", cannot test."); - - // (Not needed, but verify that clear() works on empty containers) - R.clear(); - PQXX_CHECK(std::empty(R), "Result is non-empty after clear()."); - - // OK. Having laid that worry to rest, add a record for 1977. - tx1.exec0( - "INSERT INTO " + Table + - " VALUES" - "(" + - to_string(BoringYear) + - "," - "'Yawn'" - ")"); - - // Abort tx1. Since tx1 is a nontransaction, which provides only the - // transaction class interface without providing any form of transactional - // integrity, this is not going to undo our work. - tx1.abort(); - - // Verify that our record was added, despite the Abort() - nontransaction tx2(conn, "tx2"); - R = tx2.exec( - "SELECT * FROM " + Table + - " " - "WHERE year=" + - to_string(BoringYear)); - PQXX_CHECK_EQUAL(std::size(R), 1, "Unexpected result size."); - - PQXX_CHECK(R.capacity() >= std::size(R), "Result's capacity is too small."); - - R.clear(); - PQXX_CHECK(std::empty(R), "result::clear() is broken."); - - // Now remove our record again - tx2.exec0( - "DELETE FROM " + Table + - " " - "WHERE year=" + - to_string(BoringYear)); - - tx2.commit(); - - // And again, verify results - nontransaction tx3(conn, "tx3"); - - R = tx3.exec( - "SELECT * FROM " + Table + - " " - "WHERE year=" + - to_string(BoringYear)); - - PQXX_CHECK_EQUAL(std::size(R), 0, "Record is not gone as expected."); -} - - -PQXX_REGISTER_TEST(test_039); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test46.cxx b/ext/libpqxx-7.7.3/test/test46.cxx deleted file mode 100644 index 0fa88915a..000000000 --- a/ext/libpqxx-7.7.3/test/test46.cxx +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include - -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Streams test program for libpqxx. Insert a result field into various -// types of streams. -namespace -{ -void test_046() -{ - connection conn; - work tx{conn}; - - row R{tx.exec1("SELECT count(*) FROM pg_tables")}; - - // Read the value into a stringstream. - std::stringstream I; - I << R[0]; - - // Now convert the stringstream into a numeric type - long L{}, L2{}; - I >> L; - - R[0].to(L2); - PQXX_CHECK_EQUAL(L, L2, "Inconsistency between conversion methods."); - - float F{}, F2{}; - std::stringstream I2; - I2 << R[0]; - I2 >> F; - R[0].to(F2); - PQXX_CHECK_BOUNDS(F2, F - 0.01, F + 0.01, "Bad floating-point result."); - - auto F3{from_string(R[0].c_str())}; - PQXX_CHECK_BOUNDS(F3, F - 0.01, F + 0.01, "Bad float from from_string."); - - auto D{from_string(R[0].c_str())}; - PQXX_CHECK_BOUNDS(D, F - 0.01, F + 0.01, "Bad double from from_string."); - - auto LD{from_string(R[0].c_str())}; - PQXX_CHECK_BOUNDS( - LD, F - 0.01, F + 0.01, "Bad long double from from_string."); - - auto S{from_string(R[0].c_str())}, - S2{from_string(std::string{R[0].c_str()})}, - S3{from_string(R[0])}; - - PQXX_CHECK_EQUAL( - S2, S, - "from_string(char const[], std::string &) " - "is inconsistent with " - "from_string(std::string const &, std::string &)."); - - PQXX_CHECK_EQUAL( - S3, S2, - "from_string(result::field const &, std::string &) " - "is inconsistent with " - "from_string(std::string const &, std::string &)."); - - PQXX_CHECK(tx.query_value("SELECT 1=1"), "1=1 doesn't yield 'true.'"); - - PQXX_CHECK(not tx.query_value("SELECT 2+2=5"), "2+2=5 yields 'true.'"); -} - - -PQXX_REGISTER_TEST(test_046); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test56.cxx b/ext/libpqxx-7.7.3/test/test56.cxx deleted file mode 100644 index 3aef757bb..000000000 --- a/ext/libpqxx-7.7.3/test/test56.cxx +++ /dev/null @@ -1,24 +0,0 @@ -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Simple test program for libpqxx. Issue invalid query and handle error. -namespace -{ -void test_056() -{ - connection conn; - work tx{conn}; - quiet_errorhandler d(conn); - - PQXX_CHECK_THROWS( - tx.exec("DELIBERATELY INVALID TEST QUERY..."), sql_error, - "SQL syntax error did not raise expected exception."); -} - - -PQXX_REGISTER_TEST(test_056); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test60.cxx b/ext/libpqxx-7.7.3/test/test60.cxx deleted file mode 100644 index a29ce9ff7..000000000 --- a/ext/libpqxx-7.7.3/test/test60.cxx +++ /dev/null @@ -1,85 +0,0 @@ -#include - -#include -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Example program for libpqxx. Test session variable functionality. -namespace -{ -std::string GetDatestyle(connection &conn) -{ - return conn.get_var("DATESTYLE"); -} - - -std::string SetDatestyle(connection &conn, std::string style) -{ - conn.set_session_var("DATESTYLE", style); - std::string const fullname{GetDatestyle(conn)}; - PQXX_CHECK( - not std::empty(fullname), - "Setting datestyle to " + style + " makes it an empty string."); - - return fullname; -} - - -void CheckDatestyle(connection &conn, std::string expected) -{ - PQXX_CHECK_EQUAL(GetDatestyle(conn), expected, "Got wrong datestyle."); -} - - -void RedoDatestyle( - connection &conn, std::string const &style, std::string const &expected) -{ - PQXX_CHECK_EQUAL( - SetDatestyle(conn, style), expected, "Set wrong datestyle."); -} - - -void ActivationTest( - connection &conn, std::string const &style, std::string const &expected) -{ - RedoDatestyle(conn, style, expected); - CheckDatestyle(conn, expected); -} - - -void test_060() -{ - connection conn; - - PQXX_CHECK(not std::empty(GetDatestyle(conn)), "Initial datestyle not set."); - - std::string const ISOname{SetDatestyle(conn, "ISO")}; - std::string const SQLname{SetDatestyle(conn, "SQL")}; - - PQXX_CHECK_NOT_EQUAL(ISOname, SQLname, "Same datestyle in SQL and ISO."); - - RedoDatestyle(conn, "SQL", SQLname); - - ActivationTest(conn, "ISO", ISOname); - ActivationTest(conn, "SQL", SQLname); - - PQXX_CHECK_THROWS( - conn.set_session_var("bonjour_name", std::optional{}), - pqxx::variable_set_to_null, - "Setting a variable to null did not report the error correctly."); - - // Prove that setting an unknown variable causes an error, as expected - quiet_errorhandler d{conn}; - PQXX_CHECK_THROWS( - conn.set_session_var("NONEXISTENT_VARIABLE_I_HOPE", 1), sql_error, - "Setting unknown variable failed to fail."); -} - - -PQXX_REGISTER_TEST(test_060); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test61.cxx b/ext/libpqxx-7.7.3/test/test61.cxx deleted file mode 100644 index a9c871bdb..000000000 --- a/ext/libpqxx-7.7.3/test/test61.cxx +++ /dev/null @@ -1,61 +0,0 @@ -#include - -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Example program for libpqxx. Test local variable functionality. -namespace -{ -std::string GetDatestyle(transaction_base &T) -{ - return T.conn().get_var("DATESTYLE"); -} - - -std::string SetDatestyle(transaction_base &T, std::string style) -{ - T.conn().set_session_var("DATESTYLE", style); - std::string const fullname{GetDatestyle(T)}; - PQXX_CHECK( - not std::empty(fullname), - "Setting datestyle to " + style + " makes it an empty string."); - - return fullname; -} - - -void RedoDatestyle( - transaction_base &T, std::string const &style, std::string const &expected) -{ - PQXX_CHECK_EQUAL(SetDatestyle(T, style), expected, "Set wrong datestyle."); -} - - -void test_061() -{ - connection conn; - work tx{conn}; - - PQXX_CHECK(not std::empty(GetDatestyle(tx)), "Initial datestyle not set."); - - std::string const ISOname{SetDatestyle(tx, "ISO")}; - std::string const SQLname{SetDatestyle(tx, "SQL")}; - - PQXX_CHECK_NOT_EQUAL(ISOname, SQLname, "Same datestyle in SQL and ISO."); - - RedoDatestyle(tx, "SQL", SQLname); - - // Prove that setting an unknown variable causes an error, as expected - quiet_errorhandler d(tx.conn()); - PQXX_CHECK_THROWS( - conn.set_session_var("NONEXISTENT_VARIABLE_I_HOPE", 1), sql_error, - "Setting unknown variable failed to fail."); -} - - -PQXX_REGISTER_TEST(test_061); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test62.cxx b/ext/libpqxx-7.7.3/test/test62.cxx deleted file mode 100644 index d23e49e5a..000000000 --- a/ext/libpqxx-7.7.3/test/test62.cxx +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include - -#include "test_helpers.hxx" - - -using namespace pqxx; - - -// Example program for libpqxx. Test binary string functionality. -namespace -{ -void test_062() -{ - connection conn; - work tx{conn}; - - std::string const TestStr{ - "Nasty\n\030Test\n\t String with \200\277 weird bytes " - "\r\0 and Trailer\\\\\0"}; - - tx.exec0("CREATE TEMP TABLE pqxxbin (binfield bytea)"); - - std::string const Esc{tx.esc_raw(std::basic_string{ - reinterpret_cast(std::data(TestStr)), - std::size(TestStr)})}; - - tx.exec0("INSERT INTO pqxxbin VALUES ('" + Esc + "')"); - - result R{tx.exec("SELECT * from pqxxbin")}; - tx.exec0("DELETE FROM pqxxbin"); - - auto const B{R.at(0).at(0).as>()}; - - PQXX_CHECK(not std::empty(B), "Binary string became empty in conversion."); - - PQXX_CHECK_EQUAL( - std::size(B), std::size(TestStr), "Binary string was mangled."); - - std::basic_string::const_iterator c; - std::basic_string::size_type i; - for (i = 0, c = std::begin(B); i < std::size(B); ++i, ++c) - { - PQXX_CHECK(c != std::end(B), "Premature end to binary string."); - - char const x{TestStr.at(i)}, y{char(B.at(i))}, z{char(std::data(B)[i])}; - - PQXX_CHECK_EQUAL( - std::string(&x, 1), std::string(&y, 1), "Binary string byte changed."); - - PQXX_CHECK_EQUAL( - std::string(&y, 1), std::string(&z, 1), - "Inconsistent byte at offset " + to_string(i) + "."); - } -} - - -PQXX_REGISTER_TEST(test_062); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test69.cxx b/ext/libpqxx-7.7.3/test/test69.cxx deleted file mode 100644 index d15ff1489..000000000 --- a/ext/libpqxx-7.7.3/test/test69.cxx +++ /dev/null @@ -1,55 +0,0 @@ -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Issue a query repeatedly through a pipeline, and -// compare results. -namespace -{ -void TestPipeline(pipeline &P, int numqueries) -{ - std::string const Q{"SELECT 99"}; - - for (int i{numqueries}; i > 0; --i) P.insert(Q); - - PQXX_CHECK( - (numqueries == 0) or not std::empty(P), "pipeline::empty() is broken."); - - int res{0}; - for (int i{numqueries}; i > 0; --i) - { - PQXX_CHECK( - not std::empty(P), "Got wrong number of queries from pipeline."); - - auto R{P.retrieve()}; - - if (res != 0) - PQXX_CHECK_EQUAL( - R.second[0][0].as(), res, - "Got unexpected result out of pipeline."); - - res = R.second[0][0].as(); - } - - PQXX_CHECK(std::empty(P), "Pipeline not empty after retrieval."); -} - - -void test_069() -{ - connection conn; - work tx{conn}; - pipeline P(tx); - PQXX_CHECK(std::empty(P), "Pipeline is not empty initially."); - for (int i{0}; i < 5; ++i) TestPipeline(P, i); -} - - -PQXX_REGISTER_TEST(test_069); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/test70.cxx b/ext/libpqxx-7.7.3/test/test70.cxx deleted file mode 100644 index 0f72089f1..000000000 --- a/ext/libpqxx-7.7.3/test/test70.cxx +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -namespace -{ -void TestPipeline(pipeline &P, int numqueries) -{ - std::string const Q{"SELECT * FROM generate_series(1, 10)"}; - result const Empty; - PQXX_CHECK(std::empty(Empty), "Default-constructed result is not empty."); - PQXX_CHECK( - std::empty(Empty.query()), "Default-constructed result has query"); - - P.retain(); - for (int i{numqueries}; i > 0; --i) P.insert(Q); - P.resume(); - - PQXX_CHECK( - (numqueries == 0) || not std::empty(P), "pipeline::empty() is broken."); - - int res{0}; - result Prev; - PQXX_CHECK_EQUAL(Prev, Empty, "Default-constructed results are not equal."); - - for (int i{numqueries}; i > 0; --i) - { - PQXX_CHECK(not std::empty(P), "Got no results from pipeline."); - - auto R{P.retrieve()}; - - PQXX_CHECK_NOT_EQUAL(R.second, Empty, "Got empty result."); - if (Prev != Empty) - PQXX_CHECK_EQUAL(R.second, Prev, "Results to same query are different."); - - Prev = R.second; - PQXX_CHECK_EQUAL(Prev, R.second, "Assignment breaks result equality."); - PQXX_CHECK_EQUAL(R.second.query(), Q, "Result is for unexpected query."); - - if (res != 0) - PQXX_CHECK_EQUAL(Prev[0][0].as(), res, "Bad result from pipeline."); - - res = Prev[0][0].as(); - } - - PQXX_CHECK(std::empty(P), "Pipeline was not empty after retrieval."); -} - - -// Test program for libpqxx. Issue a query repeatedly through a pipeline, and -// compare results. Use retain() and resume() for performance. -void test_070() -{ - connection conn; - work tx{conn}; - pipeline P(tx); - - PQXX_CHECK(std::empty(P), "Pipeline is not empty initially."); - - // Try to confuse the pipeline by feeding it a query and flushing - P.retain(); - std::string const Q{"SELECT * FROM pg_tables"}; - P.insert(Q); - P.flush(); - - PQXX_CHECK(std::empty(P), "Pipeline was not empty after flush()."); - - // See if complete() breaks retain() as it should - P.retain(); - P.insert(Q); - PQXX_CHECK(not std::empty(P), "Pipeline was empty after insert()."); - P.complete(); - PQXX_CHECK(not std::empty(P), "complete() emptied pipeline."); - - PQXX_CHECK_EQUAL( - P.retrieve().second.query(), Q, "Result is for wrong query."); - - PQXX_CHECK(std::empty(P), "Pipeline not empty after retrieve()."); - - // See if retrieve() breaks retain() when it needs to - P.retain(); - P.insert(Q); - PQXX_CHECK_EQUAL( - P.retrieve().second.query(), Q, "Got result for wrong query."); - - // See if regular retain()/resume() works - for (int i{0}; i < 5; ++i) TestPipeline(P, i); - - // See if retrieve() fails on an empty pipeline, as it should - quiet_errorhandler d(conn); - PQXX_CHECK_THROWS_EXCEPTION( - P.retrieve(), "Empty pipeline allows retrieve()."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_070); diff --git a/ext/libpqxx-7.7.3/test/test71.cxx b/ext/libpqxx-7.7.3/test/test71.cxx deleted file mode 100644 index e669d9ad5..000000000 --- a/ext/libpqxx-7.7.3/test/test71.cxx +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Issue queries through a pipeline, and retrieve -// results both in-order and out-of-order. -namespace -{ -using Exp = std::map; - -template void checkresult(pipeline &P, PAIR c) -{ - result const r{P.retrieve(c.first)}; - int const val{r.at(0).at(0).as(int(0))}; - PQXX_CHECK_EQUAL(val, c.second, "Wrong result from pipeline."); -} - - -void test_071() -{ - connection conn; - work tx{conn}; - pipeline P(tx); - - // Keep expected result for every query we issue - Exp values; - - // Insert queries returning various numbers. - for (int i{1}; i < 10; ++i) values[P.insert("SELECT " + to_string(i))] = i; - - // Retrieve results in query_id order, and compare to expected values - for (auto &c : values) checkresult(P, c); - - PQXX_CHECK(std::empty(P), "Pipeline was not empty retrieving all results."); - - values.clear(); - - // Insert more queries returning various numbers - P.retain(20); - for (int i{100}; i > 90; --i) values[P.insert("SELECT " + to_string(i))] = i; - - P.resume(); - - // Retrieve results in reverse order - for (auto c{std::rbegin(values)}; c != std::rend(values); ++c) - checkresult(P, *c); - - values.clear(); - P.retain(10); - for (int i{1010}; i > 1000; --i) - values[P.insert("SELECT " + to_string(i))] = i; - for (auto &c : values) - { - if (P.is_finished(c.first)) - std::cout << "Query #" << c.first << " completed despite retain()" - << std::endl; - } - - // See that all results are retrieved by complete() - P.complete(); - for (auto &c : values) - PQXX_CHECK(P.is_finished(c.first), "Query not finished after complete()."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_071); diff --git a/ext/libpqxx-7.7.3/test/test72.cxx b/ext/libpqxx-7.7.3/test/test72.cxx deleted file mode 100644 index 716081ed7..000000000 --- a/ext/libpqxx-7.7.3/test/test72.cxx +++ /dev/null @@ -1,53 +0,0 @@ -#include - -#include -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Test error handling for pipeline. -namespace -{ -void test_072() -{ - connection conn; - work tx{conn}; - pipeline P{tx}; - - // Ensure all queries are issued at once to make the test more interesting - P.retain(); - - // The middle query should fail; the surrounding two should succeed - auto const id_1{P.insert("SELECT 1")}; - auto const id_f{P.insert("SELECT * FROM pg_nonexist")}; - auto const id_2{P.insert("SELECT 2")}; - - // See that we can process the queries without stumbling over the error - P.complete(); - - // We should be able to get the first result, which preceeds the error - auto const res_1{P.retrieve(id_1).at(0).at(0).as()}; - PQXX_CHECK_EQUAL(res_1, 1, "Got wrong result from pipeline."); - - // We should *not* get a result for the query behind the error - { - quiet_errorhandler d{conn}; - PQXX_CHECK_THROWS( - P.retrieve(id_2).at(0).at(0).as(), std::runtime_error, - "Pipeline wrongly resumed after SQL error."); - } - - // Now see that we get an exception when we touch the failed result - { - quiet_errorhandler d{conn}; - PQXX_CHECK_THROWS( - P.retrieve(id_f), sql_error, "Pipeline failed to register SQL error."); - } -} -} // namespace - - -PQXX_REGISTER_TEST(test_072); diff --git a/ext/libpqxx-7.7.3/test/test74.cxx b/ext/libpqxx-7.7.3/test/test74.cxx deleted file mode 100644 index ff1abd993..000000000 --- a/ext/libpqxx-7.7.3/test/test74.cxx +++ /dev/null @@ -1,72 +0,0 @@ -#include - -#include - -#include "test_helpers.hxx" - -using namespace pqxx; - - -// Test program for libpqxx. Test fieldstream. -namespace -{ -void test_074() -{ - connection conn; - work tx{conn}; - - result R{tx.exec("SELECT * FROM pg_tables")}; - std::string const sval{R.at(0).at(1).c_str()}; - std::string sval2; - fieldstream fs1(R.front()[1]); - fs1 >> sval2; - PQXX_CHECK_EQUAL(sval2, sval, "fieldstream returned wrong value."); - - R = tx.exec("SELECT count(*) FROM pg_tables"); - int ival; - fieldstream fs2(R.at(0).at(0)); - fs2 >> ival; - PQXX_CHECK_EQUAL( - ival, R.front().front().as(), "fieldstream::front() is broken."); - - double dval; - (fieldstream(R.at(0).at(0))) >> dval; - PQXX_CHECK_BOUNDS( - dval, R[0][0].as() - 0.1, R[0][0].as() + 0.1, - "Got wrong double from fieldstream."); - - auto const roughpi{static_cast(3.1415926435)}; - R = tx.exec("SELECT " + to_string(roughpi)); - float pival; - (fieldstream(R.at(0).at(0))) >> pival; - PQXX_CHECK_BOUNDS( - pival, roughpi - 0.001, roughpi + 0.001, - "Pi approximation came back wrong from fieldstream."); - - PQXX_CHECK_EQUAL( - to_string(R[0][0]), R[0][0].c_str(), - "to_string(result::field) is inconsistent with c_str()."); - - float float_pi; - from_string(to_string(roughpi), float_pi); - PQXX_CHECK_BOUNDS( - float_pi, roughpi - 0.00001, roughpi + 0.00001, - "Float changed in conversion."); - - double double_pi; - pqxx::from_string(pqxx::to_string(static_cast(roughpi)), double_pi); - PQXX_CHECK_BOUNDS( - double_pi, roughpi - 0.00001, roughpi + 0.00001, - "Double changed in conversion."); - - long double const ld{roughpi}; - long double long_double_pi; - from_string(to_string(ld), long_double_pi); - PQXX_CHECK_BOUNDS( - long_double_pi, roughpi - 0.00001, roughpi + 0.00001, - "long double changed in conversion."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_074); diff --git a/ext/libpqxx-7.7.3/test/test75.cxx b/ext/libpqxx-7.7.3/test/test75.cxx deleted file mode 100644 index 07f00141e..000000000 --- a/ext/libpqxx-7.7.3/test/test75.cxx +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include - -#include "test_helpers.hxx" - - -// Test program for libpqxx. Compare const_reverse_iterator iteration of a -// result to a regular, const_iterator iteration. -namespace -{ -void test_075() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - pqxx::test::create_pqxxevents(tx); - auto const R(tx.exec("SELECT year FROM pqxxevents")); - PQXX_CHECK(not std::empty(R), "No events found, cannot test."); - - PQXX_CHECK_EQUAL(R[0], R.at(0), "Inconsistent result indexing."); - PQXX_CHECK(not(R[0] != R.at(0)), "result::row::operator!=() is broken."); - - PQXX_CHECK_EQUAL(R[0][0], R[0].at(0), "Inconsistent row indexing."); - PQXX_CHECK( - not(R[0][0] != R[0].at(0)), "result::field::operator!=() is broken."); - - std::vector contents; - for (auto const &i : R) contents.push_back(i.at(0).as()); - - PQXX_CHECK_EQUAL( - std::size(contents), std::vector::size_type(std::size(R)), - "Number of values does not match result size."); - - for (pqxx::result::size_type i{0}; i < std::size(R); ++i) - PQXX_CHECK_EQUAL( - contents[static_cast(i)], R.at(i).at(0).c_str(), - "Inconsistent iteration."); - - // Thorough test for result::const_reverse_iterator - pqxx::result::const_reverse_iterator ri1(std::rbegin(R)), ri2(ri1), - ri3(std::end(R)); - ri2 = std::rbegin(R); - - PQXX_CHECK(ri2 == ri1, "reverse_iterator copy constructor is broken."); - PQXX_CHECK(ri3 == ri2, "result::end() does not generate rbegin()."); - PQXX_CHECK_EQUAL( - ri2 - ri3, 0, - "const_reverse_iterator is at nonzero distance from its own copy."); - - PQXX_CHECK(ri2 == ri3 + 0, "reverse_iterator+0 gives strange result."); - PQXX_CHECK(ri2 == ri3 - 0, "reverse_iterator-0 gives strange result."); - PQXX_CHECK(not(ri3 < ri2), "operator<() breaks on equal reverse_iterators."); - PQXX_CHECK(ri2 <= ri3, "operator<=() breaks on equal reverse_iterators."); - - PQXX_CHECK(ri3++ == ri2, "reverse_iterator post-increment is broken."); - - PQXX_CHECK_EQUAL(ri3 - ri2, 1, "Wrong nonzero reverse_iterator distance."); - PQXX_CHECK(ri3 > ri2, "reverse_iterator operator>() is broken."); - PQXX_CHECK(ri3 >= ri2, "reverse_iterator operator>=() is broken."); - PQXX_CHECK(ri2 < ri3, "reverse_iterator operator<() is broken."); - PQXX_CHECK(ri2 <= ri3, "reverse_iterator operator<=() is broken."); - PQXX_CHECK(ri3 == ri2 + 1, "Adding int to reverse_iterator is broken."); - PQXX_CHECK( - ri2 == ri3 - 1, "Subtracting int from reverse_iterator is broken."); - - PQXX_CHECK(ri3 == ++ri2, "reverse_iterator pre-increment is broken."); - PQXX_CHECK(ri3 >= ri2, "operator>=() breaks on equal reverse_iterators."); - PQXX_CHECK(ri3 >= ri2, "operator<=() breaks on equal reverse_iterators."); - - PQXX_CHECK( - *ri3.base() == R.back(), "reverse_iterator does not arrive at back()."); - - PQXX_CHECK( - ri1->at(0) == (*ri1).at(0), - "reverse_iterator operator->() is inconsistent with operator*()."); - - PQXX_CHECK(ri2-- == ri3, "reverse_iterator post-decrement is broken."); - PQXX_CHECK(ri2 == --ri3, "reverse_iterator pre-decrement is broken."); - PQXX_CHECK(ri2 == std::rbegin(R), "reverse_iterator decrement is broken."); - - ri2 += 1; - ri3 -= -1; - - PQXX_CHECK( - ri2 != std::rbegin(R), "Adding to reverse_iterator does not work."); - PQXX_CHECK( - ri3 == ri2, "reverse_iterator operator-=() breaks on negative distances."); - - ri2 -= 1; - PQXX_CHECK( - ri2 == std::rbegin(R), - "reverse_iterator operator+=() and operator-=() do not cancel out."); - - // Now verify that reverse iterator also sees the same results... - auto l{std::rbegin(contents)}; - for (auto i{std::rbegin(R)}; i != std::rend(R); ++i, ++l) - PQXX_CHECK_EQUAL(*l, i->at(0).c_str(), "Inconsistent reverse iteration."); - - PQXX_CHECK(l == std::rend(contents), "Reverse iteration ended too soon."); - - PQXX_CHECK(not std::empty(R), "No events found in table, cannot test."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_075); diff --git a/ext/libpqxx-7.7.3/test/test76.cxx b/ext/libpqxx-7.7.3/test/test76.cxx deleted file mode 100644 index 122c0445c..000000000 --- a/ext/libpqxx-7.7.3/test/test76.cxx +++ /dev/null @@ -1,52 +0,0 @@ -#include - -#include "test_helpers.hxx" - -// Simple test program for libpqxx. Test string conversion routines. -namespace -{ -void test_076() -{ - pqxx::connection conn; - pqxx::nontransaction tx{conn}; - - auto RFalse{tx.exec1("SELECT 1=0")}, RTrue{tx.exec1("SELECT 1=1")}; - auto False{pqxx::from_string(RFalse[0])}, - True{pqxx::from_string(RTrue[0])}; - PQXX_CHECK(not False, "False bool converted to true."); - PQXX_CHECK(True, "True bool converted to false."); - - RFalse = tx.exec1("SELECT " + pqxx::to_string(False)); - RTrue = tx.exec1("SELECT " + pqxx::to_string(True)); - False = pqxx::from_string(RFalse[0]); - True = pqxx::from_string(RTrue[0]); - PQXX_CHECK(not False, "False bool converted to true."); - PQXX_CHECK(True, "True bool converted to false."); - - short const svals[]{-1, 1, 999, -32767, -32768, 32767, 0}; - for (int i{0}; svals[i] != 0; ++i) - { - auto s{pqxx::from_string(pqxx::to_string(svals[i]))}; - PQXX_CHECK_EQUAL(s, svals[i], "short/string conversion not bijective."); - s = pqxx::from_string( - tx.exec1("SELECT " + pqxx::to_string(svals[i]))[0].c_str()); - PQXX_CHECK_EQUAL(s, svals[i], "Roundtrip through backend changed short."); - } - - unsigned short const uvals[]{1, 999, 32767, 32768, 65535, 0}; - for (int i{0}; uvals[i] != 0; ++i) - { - auto u{pqxx::from_string(pqxx::to_string(uvals[i]))}; - PQXX_CHECK_EQUAL( - u, uvals[i], "unsigned short/string conversion not bijective."); - - u = pqxx::from_string( - tx.exec1("SELECT " + pqxx::to_string(uvals[i]))[0].c_str()); - PQXX_CHECK_EQUAL( - u, uvals[i], "Roundtrip through backend changed unsigned short."); - } -} -} // namespace - - -PQXX_REGISTER_TEST(test_076); diff --git a/ext/libpqxx-7.7.3/test/test77.cxx b/ext/libpqxx-7.7.3/test/test77.cxx deleted file mode 100644 index 88e83c26d..000000000 --- a/ext/libpqxx-7.7.3/test/test77.cxx +++ /dev/null @@ -1,28 +0,0 @@ -#include - -#include "test_helpers.hxx" - - -// Test program for libpqxx. Test result::swap() -namespace -{ -void test_077() -{ - pqxx::connection conn; - pqxx::nontransaction tx{conn}; - - auto RFalse{tx.exec("SELECT 1=0")}, RTrue{tx.exec("SELECT 1=1")}; - auto f{pqxx::from_string(RFalse[0][0])}; - auto t{pqxx::from_string(RTrue[0][0])}; - PQXX_CHECK( - not f and t, "Booleans converted incorrectly; can't trust this test."); - - RFalse.swap(RTrue); - f = pqxx::from_string(RFalse[0][0]); - t = pqxx::from_string(RTrue[0][0]); - PQXX_CHECK(f and not t, "result::swap() is broken."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_077); diff --git a/ext/libpqxx-7.7.3/test/test78.cxx b/ext/libpqxx-7.7.3/test/test78.cxx deleted file mode 100644 index f970cc926..000000000 --- a/ext/libpqxx-7.7.3/test/test78.cxx +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include "test_helpers.hxx" - - -// Example program for libpqxx. Send notification to self, using a -// notification name with unusal characters, and without polling. -namespace -{ -// Sample implementation of notification receiver. -class TestListener : public pqxx::notification_receiver -{ - bool m_done; - -public: - explicit TestListener(pqxx::connection &conn, std::string const &Name) : - pqxx::notification_receiver(conn, Name), m_done(false) - {} - - void operator()(std::string const &, int be_pid) override - { - m_done = true; - PQXX_CHECK_EQUAL( - be_pid, conn().backendpid(), - "Got notification from wrong backend process."); - - std::cout << "Received notification: " << channel() << " pid=" << be_pid - << std::endl; - } - - bool done() const { return m_done; } -}; - - -void test_078() -{ - pqxx::connection conn; - - std::string const NotifName{"my listener"}; - TestListener L{conn, NotifName}; - - pqxx::perform([&conn, &L] { - pqxx::work tx{conn}; - tx.exec0("NOTIFY " + tx.quote_name(L.channel())); - tx.commit(); - }); - - int notifs{0}; - for (int i{0}; (i < 20) and not L.done(); ++i) - { - PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notifications."); - std::cout << "."; - notifs = conn.await_notification(); - } - std::cout << std::endl; - - PQXX_CHECK(L.done(), "No notification received."); - PQXX_CHECK_EQUAL(notifs, 1, "Got unexpected number of notifications."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_078); diff --git a/ext/libpqxx-7.7.3/test/test79.cxx b/ext/libpqxx-7.7.3/test/test79.cxx deleted file mode 100644 index 761e5f3c3..000000000 --- a/ext/libpqxx-7.7.3/test/test79.cxx +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include "test_helpers.hxx" - - -// Example program for libpqxx. Test waiting for notification with timeout. -namespace -{ -// Sample implementation of notification receiver. -class TestListener final : public pqxx::notification_receiver -{ - bool m_done; - -public: - explicit TestListener(pqxx::connection &conn, std::string const &Name) : - pqxx::notification_receiver(conn, Name), m_done(false) - {} - - void operator()(std::string const &, int be_pid) override - { - m_done = true; - PQXX_CHECK_EQUAL( - be_pid, conn().backendpid(), "Notification came from wrong backend."); - - std::cout << "Received notification: " << channel() << " pid=" << be_pid - << std::endl; - } - - bool done() const { return m_done; } -}; - - -void test_079() -{ - pqxx::connection conn; - - std::string const NotifName{"mylistener"}; - TestListener L(conn, NotifName); - - // First see if the timeout really works: we're not expecting any notifs - int notifs{conn.await_notification(0, 1)}; - PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notification."); - - pqxx::perform([&conn, &L] { - pqxx::work tx{conn}; - tx.exec0("NOTIFY " + L.channel()); - tx.commit(); - }); - - for (int i{0}; (i < 20) and not L.done(); ++i) - { - PQXX_CHECK_EQUAL(notifs, 0, "Got notifications, but no handler called."); - std::cout << "."; - notifs = conn.await_notification(1, 0); - } - std::cout << std::endl; - - PQXX_CHECK(L.done(), "No notifications received."); - PQXX_CHECK_EQUAL(notifs, 1, "Got unexpected notifications."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_079); diff --git a/ext/libpqxx-7.7.3/test/test82.cxx b/ext/libpqxx-7.7.3/test/test82.cxx deleted file mode 100644 index e7b2769c7..000000000 --- a/ext/libpqxx-7.7.3/test/test82.cxx +++ /dev/null @@ -1,154 +0,0 @@ -#include - -#include - -#include "test_helpers.hxx" - - -// Test program for libpqxx. Read and print table using row iterators. -namespace -{ -void test_082() -{ - pqxx::connection conn; - pqxx::nontransaction tx{conn}; - - pqxx::test::create_pqxxevents(tx); - std::string const Table{"pqxxevents"}; - pqxx::result R{tx.exec("SELECT * FROM " + Table)}; - - PQXX_CHECK(not std::empty(R), "Got empty result."); - - std::string const nullstr("[null]"); - - for (auto const &r : R) - { - pqxx::row::const_iterator f2(r[0]); - for (auto const &f : r) - { - PQXX_CHECK_EQUAL( - (*f2).as(nullstr), f.as(nullstr), "Inconsistent iteration result."); - ++f2; - } - - PQXX_CHECK( - std::begin(r) + pqxx::row::difference_type(std::size(r)) == std::end(r), - "Row end() appears to be in the wrong place."); - PQXX_CHECK( - pqxx::row::difference_type(std::size(r)) + std::begin(r) == std::end(r), - "Row iterator addition is not commutative."); - PQXX_CHECK_EQUAL( - std::begin(r)->num(), 0, "Wrong column number at begin()."); - - pqxx::row::const_iterator f3(r[std::size(r)]); - - PQXX_CHECK(f3 == std::end(r), "Did not get end() at end of row."); - - PQXX_CHECK( - f3 > std::begin(r), "Row end() appears to precede its begin()."); - - PQXX_CHECK( - f3 >= std::end(r) and std::begin(r) < f3, - "Row iterator operator<() is broken."); - - PQXX_CHECK(f3 > std::begin(r), "Row end() not greater than begin()."); - - pqxx::row::const_iterator f4{r, std::size(r)}; - PQXX_CHECK(f4 == f3, "Row iterator constructor with offset is broken."); - - --f3; - f4 -= 1; - - PQXX_CHECK(f3 < std::end(r), "Last field in row is not before end()."); - PQXX_CHECK(f3 >= std::begin(r), "Last field in row precedes begin()."); - PQXX_CHECK( - f3 == std::end(r) - 1, "Back from end() doese not yield end()-1."); - PQXX_CHECK_EQUAL( - std::end(r) - f3, 1, "Wrong distance from last row to end()."); - - PQXX_CHECK(f4 == f3, "Row iterator operator-=() is broken."); - f4 += 1; - PQXX_CHECK(f4 == std::end(r), "Row iterator operator+=() is broken."); - - for (auto fr = std::rbegin(r); fr != std::rend(r); ++fr, --f3) - PQXX_CHECK_EQUAL( - *fr, *f3, - "Reverse traversal is not consistent with forward traversal."); - } - - // Thorough test for row::const_reverse_iterator - pqxx::row::const_reverse_iterator ri1(std::rbegin(R.front())), ri2(ri1), - ri3(std::end(R.front())); - ri2 = std::rbegin(R.front()); - - PQXX_CHECK( - ri1 == ri2, "Copy-constructed reverse_iterator is not equal to original."); - - PQXX_CHECK(ri2 == ri3, "result::end() does not generate rbegin()."); - PQXX_CHECK_EQUAL( - ri2 - ri3, 0, - "Distance between identical const_reverse_iterators was nonzero."); - - PQXX_CHECK( - pqxx::row::const_reverse_iterator(ri1.base()) == ri1, - "Back-conversion of reverse_iterator base() fails."); - - PQXX_CHECK(ri2 == ri3 + 0, "reverse_iterator+0 gives strange result."); - PQXX_CHECK(ri2 == ri3 - 0, "reverse_iterator-0 gives strange result."); - - PQXX_CHECK( - not(ri3 < ri2), - "reverse_iterator operator<() breaks on identical iterators."); - PQXX_CHECK( - ri2 <= ri3, - "reverse_iterator operator<=() breaks on identical iterators."); - PQXX_CHECK(ri3++ == ri2, "reverse_iterator post-increment is broken."); - - PQXX_CHECK_EQUAL(ri3 - ri2, 1, "Wrong reverse_iterator distance."); - PQXX_CHECK(ri3 > ri2, "reverse_iterator operator>() is broken."); - PQXX_CHECK(ri3 >= ri2, "reverse_iterator operator>=() is broken."); - PQXX_CHECK(ri2 < ri3, "reverse_iterator operator<() is broken."); - PQXX_CHECK(ri2 <= ri3, "reverse_iterator operator<=() is broken."); - PQXX_CHECK(ri3 == ri2 + 1, "Adding number to reverse_iterator goes wrong."); - PQXX_CHECK(ri2 == ri3 - 1, "Subtracting from reverse_iterator goes wrong."); - - PQXX_CHECK( - ri3 == ++ri2, "reverse_iterator pre-incremen returns wrong result."); - - PQXX_CHECK( - ri3 >= ri2, "reverse_iterator operator>=() breaks on equal iterators."); - PQXX_CHECK( - ri3 >= ri2, "reverse_iterator operator<=() breaks on equal iterators."); - PQXX_CHECK( - *ri3.base() == R.front().back(), - "reverse_iterator does not arrive at back()."); - PQXX_CHECK( - ri1->c_str()[0] == (*ri1).c_str()[0], - "reverse_iterator operator->() is inconsistent with operator*()."); - PQXX_CHECK( - ri2-- == ri3, "reverse_iterator post-decrement returns wrong result."); - PQXX_CHECK( - ri2 == --ri3, "reverse_iterator pre-increment returns wrong result."); - PQXX_CHECK( - ri2 == std::rbegin(R.front()), - "Moving iterator back and forth doesn't get it back to origin."); - - ri2 += 1; - ri3 -= -1; - - PQXX_CHECK( - ri2 != std::rbegin(R.front()), "Adding to reverse_iterator doesn't work."); - PQXX_CHECK( - ri2 != std::rbegin(R.front()), "Adding to reverse_iterator doesn't work."); - PQXX_CHECK( - ri3 == ri2, "reverse_iterator operator-=() breaks on negative numbers."); - - ri2 -= 1; - PQXX_CHECK( - ri2 == std::rbegin(R.front()), - "reverse_iterator operator+=() and operator-=() do not cancel out"); -} -} // namespace - - -PQXX_REGISTER_TEST(test_082); diff --git a/ext/libpqxx-7.7.3/test/test84.cxx b/ext/libpqxx-7.7.3/test/test84.cxx deleted file mode 100644 index d35dc521b..000000000 --- a/ext/libpqxx-7.7.3/test/test84.cxx +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include "test_helpers.hxx" - - -// "Adopted SQL Cursor" test program for libpqxx. Create SQL cursor, wrap it -// in a cursor stream, then use it to fetch data and check for consistent -// results. Compare results against an icursor_iterator so that is tested as -// well. -namespace -{ -void test_084() -{ - pqxx::connection conn; - pqxx::transaction tx{conn}; - - std::string const Table{"pg_tables"}, Key{"tablename"}; - - // Count rows. - pqxx::result R(tx.exec("SELECT count(*) FROM " + Table)); - - PQXX_CHECK( - R.at(0).at(0).as() > 20, - "Not enough rows in " + Table + ", cannot test."); - - // Create an SQL cursor and, for good measure, muddle up its state a bit. - std::string const CurName{"MYCUR"}, - Query{"SELECT * FROM " + Table + " ORDER BY " + Key}; - constexpr int InitialSkip{2}, GetRows{3}; - - tx.exec0("DECLARE " + tx.quote_name(CurName) + " CURSOR FOR " + Query); - tx.exec0( - "MOVE " + pqxx::to_string(InitialSkip * GetRows) + - " " - "IN " + - tx.quote_name(CurName)); - - // Wrap cursor in cursor stream. Apply some trickery to get its name inside - // a result field for this purpose. This isn't easy because it's not - // supposed to be easy; normally we'd only construct streams around existing - // SQL cursors if they were being returned by functions. - pqxx::icursorstream C{ - tx, tx.exec("SELECT '" + tx.esc(CurName) + "'")[0][0], GetRows}; - - // Create parallel cursor to check results - pqxx::icursorstream C2{tx, Query, "CHECKCUR", GetRows}; - pqxx::icursor_iterator i2{C2}; - - // Remember, our adopted cursor is at position (InitialSkip*GetRows) - pqxx::icursor_iterator i3(i2); - - PQXX_CHECK( - (i3 == i2) and not(i3 != i2), - "Equality on copy-constructed icursor_iterator is broken."); - PQXX_CHECK( - not(i3 > i2) and not(i3 < i2) and (i3 <= i2) and (i3 >= i2), - "Comparison on identical icursor_iterators is broken."); - - i3 += InitialSkip; - - PQXX_CHECK(not(i3 <= i2), "icursor_iterator operator<=() is broken."); - - pqxx::icursor_iterator iend, i4; - PQXX_CHECK(i3 != iend, "Early end to icursor_iterator iteration."); - i4 = iend; - PQXX_CHECK(i4 == iend, "Assigning empty icursor_iterator fails."); - - // Now start testing our new Cursor. - C >> R; - i2 = i3; - pqxx::result R2(*i2++); - - PQXX_CHECK_EQUAL( - std::size(R), static_cast(GetRows), - "Got unexpected number of rows."); - - PQXX_CHECK_EQUAL(R, R2, "Unexpected result at [1]"); - - C.get(R); - R2 = *i2; - PQXX_CHECK_EQUAL(R, R2, "Unexpected result at [2]"); - i2 += 1; - - C.ignore(GetRows); - C.get(R); - R2 = *++i2; - - PQXX_CHECK_EQUAL(R, R2, "Unexpected result at [3]"); - - ++i2; - R2 = *i2++; - for (int i{1}; C.get(R) and i2 != iend; R2 = *i2++, ++i) - PQXX_CHECK_EQUAL( - R, R2, "Unexpected result in iteration at " + pqxx::to_string(i)); - - PQXX_CHECK(i2 == iend, "Adopted cursor terminated early."); - PQXX_CHECK(not(C >> R), "icursor_iterator terminated early."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_084); diff --git a/ext/libpqxx-7.7.3/test/test87.cxx b/ext/libpqxx-7.7.3/test/test87.cxx deleted file mode 100644 index 3a9a58b16..000000000 --- a/ext/libpqxx-7.7.3/test/test87.cxx +++ /dev/null @@ -1,83 +0,0 @@ -#include "pqxx/config-public-compiler.h" -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include - -#include "test_helpers.hxx" - - -// Test program for libpqxx. Send notification to self, and wait on the -// socket's connection for it to come in. In a simple situation you'd use -// connection::await_notification() for this, but that won't let you wait for -// multiple sockets. -namespace -{ -// Sample implementation of notification receiver. -class TestListener final : public pqxx::notification_receiver -{ - bool m_done; - -public: - explicit TestListener(pqxx::connection &conn, std::string Name) : - pqxx::notification_receiver(conn, Name), m_done(false) - {} - - void operator()(std::string const &, int be_pid) override - { - m_done = true; - PQXX_CHECK_EQUAL( - be_pid, conn().backendpid(), - "Notification came from wrong backend process."); - - std::cout << "Received notification: " << channel() << " pid=" << be_pid - << std::endl; - } - - bool done() const { return m_done; } -}; - - -void test_087() -{ - pqxx::connection conn; - - std::string const NotifName{"my notification"}; - TestListener L{conn, NotifName}; - - pqxx::perform([&conn, &L] { - pqxx::work tx{conn}; - tx.exec0("NOTIFY " + tx.quote_name(L.channel())); - tx.commit(); - }); - - int notifs{0}; - for (int i{0}; (i < 20) and not L.done(); ++i) - { - PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notifications."); - - std::cout << "."; - - pqxx::internal::wait_fd(conn.sock(), true, false); - notifs = conn.get_notifs(); - } - std::cout << std::endl; - - PQXX_CHECK(L.done(), "No notification received."); - PQXX_CHECK_EQUAL(notifs, 1, "Got unexpected number of notifications."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_087); diff --git a/ext/libpqxx-7.7.3/test/test88.cxx b/ext/libpqxx-7.7.3/test/test88.cxx deleted file mode 100644 index d5deaea75..000000000 --- a/ext/libpqxx-7.7.3/test/test88.cxx +++ /dev/null @@ -1,91 +0,0 @@ -#include - -#include -#include - -#include "test_helpers.hxx" - - -// Test program for libpqxx. Attempt to perform nested transactions. -namespace -{ -void test_088() -{ - pqxx::connection conn; - - pqxx::work tx0{conn}; - pqxx::test::create_pqxxevents(tx0); - - // Trivial test: create subtransactions, and commit/abort - std::cout << tx0.exec1("SELECT 'tx0 starts'")[0].c_str() << std::endl; - - pqxx::subtransaction T0a(static_cast(tx0), "T0a"); - T0a.commit(); - - pqxx::subtransaction T0b(static_cast(tx0), "T0b"); - T0b.abort(); - std::cout << tx0.exec1("SELECT 'tx0 ends'")[0].c_str() << std::endl; - tx0.commit(); - - // Basic functionality: perform query in subtransaction; abort, continue - pqxx::work tx1{conn, "tx1"}; - std::cout << tx1.exec1("SELECT 'tx1 starts'")[0].c_str() << std::endl; - pqxx::subtransaction tx1a{tx1, "tx1a"}; - std::cout << tx1a.exec1("SELECT ' a'")[0].c_str() << std::endl; - tx1a.commit(); - pqxx::subtransaction tx1b{tx1, "tx1b"}; - std::cout << tx1b.exec1("SELECT ' b'")[0].c_str() << std::endl; - tx1b.abort(); - pqxx::subtransaction tx1c{tx1, "tx1c"}; - std::cout << tx1c.exec1("SELECT ' c'")[0].c_str() << std::endl; - tx1c.commit(); - std::cout << tx1.exec1("SELECT 'tx1 ends'")[0].c_str() << std::endl; - tx1.commit(); - - // Commit/rollback functionality - pqxx::work tx2{conn, "tx2"}; - std::string const Table{"test088"}; - tx2.exec0("CREATE TEMP TABLE " + Table + "(no INTEGER, text VARCHAR)"); - - tx2.exec0("INSERT INTO " + Table + " VALUES(1,'tx2')"); - - pqxx::subtransaction tx2a{tx2, "tx2a"}; - tx2a.exec0("INSERT INTO " + Table + " VALUES(2,'tx2a')"); - tx2a.commit(); - pqxx::subtransaction tx2b{tx2, "tx2b"}; - tx2b.exec0("INSERT INTO " + Table + " VALUES(3,'tx2b')"); - tx2b.abort(); - pqxx::subtransaction tx2c{tx2, "tx2c"}; - tx2c.exec0("INSERT INTO " + Table + " VALUES(4,'tx2c')"); - tx2c.commit(); - auto const R{tx2.exec("SELECT * FROM " + Table + " ORDER BY no")}; - for (auto const &i : R) - std::cout << '\t' << i[0].c_str() << '\t' << i[1].c_str() << std::endl; - - PQXX_CHECK_EQUAL(std::size(R), 3, "Wrong number of results."); - - int expected[3]{1, 2, 4}; - for (pqxx::result::size_type n{0}; n < std::size(R); ++n) - PQXX_CHECK_EQUAL( - R[n][0].as(), expected[n], "Hit unexpected row number."); - - tx2.abort(); - - // Auto-abort should only roll back the subtransaction. - pqxx::work tx3{conn, "tx3"}; - pqxx::subtransaction tx3a(tx3, "tx3a"); - PQXX_CHECK_THROWS( - tx3a.exec("SELECT * FROM nonexistent_table WHERE nonattribute=0"), - pqxx::sql_error, "Bogus query did not fail."); - - // Subtransaction can only be aborted now, because there was an error. - tx3a.abort(); - // We're back in our top-level transaction. This did not abort. - tx3.exec1("SELECT count(*) FROM pqxxevents"); - // Make sure we can commit exactly one more level of transaction. - tx3.commit(); -} -} // namespace - - -PQXX_REGISTER_TEST(test_088); diff --git a/ext/libpqxx-7.7.3/test/test89.cxx b/ext/libpqxx-7.7.3/test/test89.cxx deleted file mode 100644 index 2b96dfcd2..000000000 --- a/ext/libpqxx-7.7.3/test/test89.cxx +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include -#include - -#include "test_helpers.hxx" - -// Test program for libpqxx. Attempt to perform nested queries on various -// types of connections. -namespace -{ -void test_089() -{ - pqxx::connection C; - - // Trivial test: create subtransactions, and commit/abort - pqxx::work T0(C, "T0"); - T0.exec1("SELECT 'T0 starts'"); - pqxx::subtransaction T0a(T0, "T0a"); - T0a.commit(); - pqxx::subtransaction T0b(T0, "T0b"); - T0b.abort(); - T0.exec1("SELECT 'T0 ends'"); - T0.commit(); - - // Basic functionality: perform query in subtransaction; abort, continue - pqxx::work T1(C, "T1"); - T1.exec1("SELECT 'T1 starts'"); - pqxx::subtransaction T1a(T1, "T1a"); - T1a.exec1("SELECT ' a'"); - T1a.commit(); - pqxx::subtransaction T1b(T1, "T1b"); - T1b.exec1("SELECT ' b'"); - T1b.abort(); - pqxx::subtransaction T1c(T1, "T1c"); - T1c.exec1("SELECT ' c'"); - T1c.commit(); - T1.exec1("SELECT 'T1 ends'"); - T1.commit(); -} -} // namespace - - -PQXX_REGISTER_TEST(test_089); diff --git a/ext/libpqxx-7.7.3/test/test90.cxx b/ext/libpqxx-7.7.3/test/test90.cxx deleted file mode 100644 index d7d97f9f3..000000000 --- a/ext/libpqxx-7.7.3/test/test90.cxx +++ /dev/null @@ -1,23 +0,0 @@ -#include - -#include "test_helpers.hxx" - -// Test program for libpqxx. Test adorn_name. - -namespace -{ -void test_090() -{ - pqxx::connection conn; - - // Test connection's adorn_name() function for uniqueness - std::string const nametest{"basename"}; - - PQXX_CHECK_NOT_EQUAL( - conn.adorn_name(nametest), conn.adorn_name(nametest), - "\"Unique\" names are not unique."); -} -} // namespace - - -PQXX_REGISTER_TEST(test_090); diff --git a/ext/libpqxx-7.7.3/test/test_helpers.hxx b/ext/libpqxx-7.7.3/test/test_helpers.hxx deleted file mode 100644 index 6db3ab971..000000000 --- a/ext/libpqxx-7.7.3/test/test_helpers.hxx +++ /dev/null @@ -1,305 +0,0 @@ -#include -#include - -#include -#include - -namespace pqxx -{ -namespace test -{ -class test_failure : public std::logic_error -{ - std::string const m_file; - int m_line; - -public: - test_failure(std::string const &ffile, int fline, std::string const &desc); - - ~test_failure() noexcept override; - - std::string const &file() const noexcept { return m_file; } - int line() const noexcept { return m_line; } -}; - - -/// Drop a table, if it exists. -void drop_table(transaction_base &, std::string const &table); - - -using testfunc = void (*)(); - - -void register_test(char const name[], testfunc func); - - -/// Register a test while not inside a function. -struct registrar -{ - registrar(char const name[], testfunc func) - { - pqxx::test::register_test(name, func); - } -}; - - -// Register a test function, so the runner will run it. -#define PQXX_REGISTER_TEST(func) \ - pqxx::test::registrar tst_##func { #func, func } - - -// Unconditional test failure. -#define PQXX_CHECK_NOTREACHED(desc) \ - pqxx::test::check_notreached(__FILE__, __LINE__, (desc)) -[[noreturn]] void -check_notreached(char const file[], int line, std::string desc); - -// Verify that a condition is met, similar to assert() -#define PQXX_CHECK(condition, desc) \ - pqxx::test::check(__FILE__, __LINE__, (condition), #condition, (desc)) -void check( - char const file[], int line, bool condition, char const text[], - std::string const &desc); - -// Verify that variable has the expected value. -#define PQXX_CHECK_EQUAL(actual, expected, desc) \ - pqxx::test::check_equal( \ - __FILE__, __LINE__, (actual), #actual, (expected), #expected, (desc)) -template -inline void check_equal( - char const file[], int line, ACTUAL actual, char const actual_text[], - EXPECTED expected, char const expected_text[], std::string const &desc) -{ - if (expected == actual) - return; - std::string const fulldesc = desc + " (" + actual_text + " <> " + - expected_text + - ": " - "actual=" + - to_string(actual) + - ", " - "expected=" + - to_string(expected) + ")"; - throw test_failure(file, line, fulldesc); -} - -// Verify that two values are not equal. -#define PQXX_CHECK_NOT_EQUAL(value1, value2, desc) \ - pqxx::test::check_not_equal( \ - __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc)) -template -inline void check_not_equal( - char const file[], int line, VALUE1 value1, char const text1[], - VALUE2 value2, char const text2[], std::string const &desc) -{ - if (value1 != value2) - return; - std::string const fulldesc = desc + " (" + text1 + " == " + text2 + - ": " - "both are " + - to_string(value2) + ")"; - throw test_failure(file, line, fulldesc); -} - - -// Verify that value1 is less than value2. -#define PQXX_CHECK_LESS(value1, value2, desc) \ - pqxx::test::check_less( \ - __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc)) -// Verify that value1 is greater than value2. -#define PQXX_CHECK_GREATER(value2, value1, desc) \ - pqxx::test::check_less( \ - __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc)) -template -inline void check_less( - char const file[], int line, VALUE1 value1, char const text1[], - VALUE2 value2, char const text2[], std::string const &desc) -{ - if (value1 < value2) - return; - std::string const fulldesc = desc + " (" + text1 + " >= " + text2 + - ": " - "\"lower\"=" + - to_string(value1) + - ", " - "\"upper\"=" + - to_string(value2) + ")"; - throw test_failure(file, line, fulldesc); -} - - -// Verify that value1 is less than or equal to value2. -#define PQXX_CHECK_LESS_EQUAL(value1, value2, desc) \ - pqxx::test::check_less_equal( \ - __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc)) -// Verify that value1 is greater than or equal to value2. -#define PQXX_CHECK_GREATER_EQUAL(value2, value1, desc) \ - pqxx::test::check_less_equal( \ - __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc)) -template -inline void check_less_equal( - char const file[], int line, VALUE1 value1, char const text1[], - VALUE2 value2, char const text2[], std::string const &desc) -{ - if (value1 <= value2) - return; - std::string const fulldesc = desc + " (" + text1 + " > " + text2 + - ": " - "\"lower\"=" + - to_string(value1) + - ", " - "\"upper\"=" + - to_string(value2) + ")"; - throw test_failure(file, line, fulldesc); -} - - -struct failure_to_fail -{}; - - -namespace internal -{ -/// Syntactic placeholder: require (and accept) semicolon after block. -inline void end_of_statement() {} -} // namespace internal - - -// Verify that "action" does not throw an exception. -#define PQXX_CHECK_SUCCEEDS(action, desc) \ - { \ - try \ - { \ - action; \ - } \ - catch (std::exception const &e) \ - { \ - PQXX_CHECK_NOTREACHED( \ - std::string{desc} + " - \"" + \ - #action "\" threw exception: " + e.what()); \ - } \ - catch (...) \ - { \ - PQXX_CHECK_NOTREACHED( \ - std::string{desc} + " - \"" + #action "\" threw a non-exception!"); \ - } \ - } \ - pqxx::test::internal::end_of_statement() - -// Verify that "action" throws an exception, of any std::exception-based type. -#define PQXX_CHECK_THROWS_EXCEPTION(action, desc) \ - { \ - try \ - { \ - action; \ - throw pqxx::test::failure_to_fail(); \ - } \ - catch (pqxx::test::failure_to_fail const &) \ - { \ - PQXX_CHECK_NOTREACHED( \ - std::string{desc} + " (\"" #action "\" did not throw)"); \ - } \ - catch (std::exception const &) \ - {} \ - catch (...) \ - { \ - PQXX_CHECK_NOTREACHED( \ - std::string{desc} + " (\"" #action "\" threw non-exception type)"); \ - } \ - } \ - pqxx::test::internal::end_of_statement() - -// Verify that "action" throws "exception_type" (which is not std::exception). -#define PQXX_CHECK_THROWS(action, exception_type, desc) \ - { \ - try \ - { \ - action; \ - throw pqxx::test::failure_to_fail(); \ - } \ - catch (pqxx::test::failure_to_fail const &) \ - { \ - PQXX_CHECK_NOTREACHED( \ - std::string{desc} + " (\"" #action \ - "\" did not throw " #exception_type ")"); \ - } \ - catch (exception_type const &) \ - {} \ - catch (std::exception const &e) \ - { \ - PQXX_CHECK_NOTREACHED( \ - std::string{desc} + \ - " (\"" #action \ - "\" " \ - "threw exception other than " #exception_type ": " + \ - e.what() + ")"); \ - } \ - catch (...) \ - { \ - PQXX_CHECK_NOTREACHED( \ - std::string{desc} + " (\"" #action "\" threw non-exception type)"); \ - } \ - } \ - pqxx::test::internal::end_of_statement() - -#define PQXX_CHECK_BOUNDS(value, lower, upper, desc) \ - pqxx::test::check_bounds( \ - __FILE__, __LINE__, (value), #value, (lower), #lower, (upper), #upper, \ - (desc)) -template -inline void check_bounds( - char const file[], int line, VALUE value, char const text[], LOWER lower, - char const lower_text[], UPPER upper, char const upper_text[], - std::string const &desc) -{ - std::string const range_check = std::string{lower_text} + " < " + upper_text, - lower_check = - std::string{"!("} + text + " < " + lower_text + ")", - upper_check = std::string{text} + " < " + upper_text; - - pqxx::test::check( - file, line, lower < upper, range_check.c_str(), - desc + " (acceptable range is empty; value was " + text + ")"); - pqxx::test::check( - file, line, not(value < lower), lower_check.c_str(), - desc + " (" + text + " is below lower bound " + lower_text + ")"); - pqxx::test::check( - file, line, value < upper, upper_check.c_str(), - desc + " (" + text + " is not below upper bound " + upper_text + ")"); -} - - -// Report expected exception -void expected_exception(std::string const &); - - -// Represent result row as string. -std::string list_row(row); -// Represent result as string. -std::string list_result(result); -// Represent result iterator as string. -std::string list_result_iterator(result::const_iterator); - - -// @deprecated Set up test data for legacy tests. -void create_pqxxevents(transaction_base &); -} // namespace test - - -template<> inline std::string to_string(row const &value) -{ - return pqxx::test::list_row(value); -} - - -template<> inline std::string to_string(result const &value) -{ - return pqxx::test::list_result(value); -} - - -template<> inline std::string to_string(result::const_iterator const &value) -{ - return pqxx::test::list_result_iterator(value); -} -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/test/test_types.hxx b/ext/libpqxx-7.7.3/test/test_types.hxx deleted file mode 100644 index 38c045370..000000000 --- a/ext/libpqxx-7.7.3/test/test_types.hxx +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Custom types for testing & libpqxx support those types - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace pqxx -{ -template<> struct nullness : no_null -{}; - - -constexpr static auto hex_digit{"0123456789abcdef"}; - - -template<> struct string_traits -{ - static std::size_t size_buffer(std::byte const &) { return 3; } - - static zview to_buf(char *begin, char *end, std::byte const &value) - { - if (pqxx::internal::cmp_less(end - begin, size_buffer(value))) - throw pqxx::conversion_overrun{ - "Not enough buffer to convert std::byte."}; - auto uc{static_cast(value)}; - begin[0] = hex_digit[uc >> 4]; - begin[1] = hex_digit[uc & 0x0f]; - return zview{begin, 2u}; - } - - static char *into_buf(char *begin, char *end, std::byte const &value) - { - auto view{to_buf(begin, end, value)}; - return begin + std::size(view); - } -}; -} // namespace pqxx - - -class ipv4 -{ -public: - ipv4() : m_as_int{0u} {} - ipv4(ipv4 const &) = default; - ipv4(ipv4 &&) = default; - explicit ipv4(uint32_t i) : m_as_int{i} {} - ipv4( - unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4) : - ipv4() - { - set_byte(0, b1); - set_byte(1, b2); - set_byte(2, b3); - set_byte(3, b4); - } - - bool operator==(ipv4 const &o) const { return m_as_int == o.m_as_int; } - ipv4 &operator=(ipv4 const &) = default; - - /// Index bytes, from 0 to 3, in network (i.e. Big-Endian) byte order. - unsigned int operator[](int byte) const - { - if (byte < 0 or byte > 3) - throw pqxx::usage_error("Byte out of range."); - auto const shift = compute_shift(byte); - return static_cast((m_as_int >> shift) & 0xff); - } - - /// Set individual byte, in network byte order. - void set_byte(int byte, uint32_t value) - { - auto const shift = compute_shift(byte); - auto const blanked = (m_as_int & ~uint32_t(0xff << shift)); - m_as_int = (blanked | ((value & 0xff) << shift)); - } - -private: - static unsigned compute_shift(int byte) - { - if (byte < 0 or byte > 3) - throw pqxx::usage_error("Byte out of range."); - return static_cast((3 - byte) * 8); - } - - uint32_t m_as_int; -}; - - -using bytea = std::vector; - - -namespace pqxx -{ -template<> struct nullness : no_null -{}; - - -template<> struct string_traits -{ - static ipv4 from_string(std::string_view text) - { - ipv4 ts; - if (std::data(text) == nullptr) - internal::throw_null_conversion(type_name); - std::regex ipv4_regex{R"--((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))--"}; - std::smatch match; - // Need non-temporary for `std::regex_match()` - std::string sstr{text}; - if (not std::regex_match(sstr, match, ipv4_regex) or std::size(match) != 5) - throw std::runtime_error{"Invalid ipv4 format: " + std::string{text}}; - try - { - for (std::size_t i{0}; i < 4; ++i) - ts.set_byte(int(i), uint32_t(std::stoi(match[i + 1]))); - } - catch (std::invalid_argument const &) - { - throw std::runtime_error{"Invalid ipv4 format: " + std::string{text}}; - } - catch (std::out_of_range const &) - { - throw std::runtime_error{"Invalid ipv4 format: " + std::string{text}}; - } - return ts; - } - - static char *into_buf(char *begin, char *end, ipv4 const &value) - { - if (pqxx::internal::cmp_less(end - begin, size_buffer(value))) - throw conversion_error{"Buffer too small for ipv4."}; - char *here = begin; - for (int i = 0; i < 4; ++i) - { - here = string_traits::into_buf(here, end, value[i]); - *(here - 1) = '.'; - } - *(here - 1) = '\0'; - return here; - } - - static zview to_buf(char *begin, char *end, ipv4 const &value) - { - return zview{ - begin, - static_cast(into_buf(begin, end, value) - begin - 1)}; - } - - static constexpr std::size_t size_buffer(ipv4 const &) noexcept - { - return 20; - } -}; - - -namespace -{ -inline char nibble_to_hex(unsigned nibble) -{ - if (nibble < 10) - return char('0' + nibble); - else if (nibble < 16) - return char('a' + (nibble - 10)); - else - throw std::runtime_error{"Invalid digit going into bytea."}; -} - - -inline unsigned hex_to_digit(char hex) -{ - auto x = static_cast(hex); - if (x >= '0' and x <= '9') - return x - '0'; - else if (x >= 'a' and x <= 'f') - return 10 + x - 'a'; - else if (x >= 'A' and x <= 'F') - return 10 + x - 'A'; - else - throw std::runtime_error{"Invalid hex in bytea."}; -} -} // namespace - - -template<> struct nullness : no_null -{}; - - -template<> struct string_traits -{ - static bytea from_string(std::string_view text) - { - if ((std::size(text) & 1) != 0) - throw std::runtime_error{"Odd hex size."}; - bytea value; - value.reserve((std::size(text) - 2) / 2); - for (std::size_t i = 2; i < std::size(text); i += 2) - { - auto hi = hex_to_digit(text[i]), lo = hex_to_digit(text[i + 1]); - value.push_back(static_cast((hi << 4) | lo)); - } - return value; - } - - static zview to_buf(char *begin, char *end, bytea const &value) - { - auto const need = size_buffer(value); - auto const have = end - begin; - if (std::size_t(have) < need) - throw pqxx::conversion_overrun{"Not enough space in buffer for bytea."}; - char *pos = begin; - *pos++ = '\\'; - *pos++ = 'x'; - for (unsigned char const u : value) - { - *pos++ = nibble_to_hex(unsigned(u) >> 4); - *pos++ = nibble_to_hex(unsigned(u) & 0x0f); - } - *pos++ = '\0'; - return {begin, pos - begin - 1}; - } - - static char *into_buf(char *begin, char *end, bytea const &value) - { - return begin + std::size(to_buf(begin, end, value)) + 1; - } - - static std::size_t size_buffer(bytea const &value) - { - return 2 + 2 * std::size(value) + 1; - } -}; -} // namespace pqxx diff --git a/ext/libpqxx-7.7.3/test/unit/CMakeLists.txt b/ext/libpqxx-7.7.3/test/unit/CMakeLists.txt deleted file mode 100644 index f938a4181..000000000 --- a/ext/libpqxx-7.7.3/test/unit/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -if(NOT PostgreSQL_FOUND) - if(POLICY CMP0074) - cmake_policy(PUSH) - # CMP0074 is `OLD` by `cmake_minimum_required(VERSION 3.7)`, sets `NEW` - # to enable support CMake variable `PostgreSQL_ROOT`. - cmake_policy(SET CMP0074 NEW) - endif() - - find_package(PostgreSQL REQUIRED) - - if(POLICY CMP0074) - cmake_policy(POP) - endif() -endif() - -file(GLOB UNIT_TEST_SOURCES *.cxx) - -add_executable(unit_runner ${UNIT_TEST_SOURCES}) -target_link_libraries(unit_runner PUBLIC pqxx) -target_include_directories(unit_runner PRIVATE ${PostgreSQL_INCLUDE_DIRS}) -add_test( - NAME unit_runner - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMAND unit_runner -) diff --git a/ext/libpqxx-7.7.3/test/unit/test_array.cxx b/ext/libpqxx-7.7.3/test/unit/test_array.cxx deleted file mode 100644 index 229ac5145..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_array.cxx +++ /dev/null @@ -1,548 +0,0 @@ -#include - -#include "../test_helpers.hxx" - -// Test program for libpqxx array parsing. - -namespace pqxx -{ -template<> -struct nullness : no_null -{}; - - -inline std::string to_string(pqxx::array_parser::juncture const &j) -{ - using junc = pqxx::array_parser::juncture; - switch (j) - { - case junc::row_start: return "row_start"; - case junc::row_end: return "row_end"; - case junc::null_value: return "null_value"; - case junc::string_value: return "string_value"; - case junc::done: return "done"; - default: return "UNKNOWN JUNCTURE: " + to_string(static_cast(j)); - } -} -} // namespace pqxx - - -namespace -{ -void test_empty_arrays() -{ - std::pair output; - - // Parsing a null pointer just immediately returns "done". - output = pqxx::array_parser(std::string_view()).get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "get_next on null array did not return done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - // Parsing an empty array string immediately returns "done". - output = pqxx::array_parser("").get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "get_next on an empty array string did not return done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - // Parsing an empty array returns "row_start", "row_end", "done". - pqxx::array_parser empty_parser("{}"); - output = empty_parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Empty array did not start with row_start."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = empty_parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Empty array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = empty_parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Empty array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_null_value() -{ - std::pair output; - pqxx::array_parser containing_null("{NULL}"); - - output = containing_null.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array containing null did not start with row_start."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = containing_null.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::null_value, - "Array containing null did not return null_value."); - PQXX_CHECK_EQUAL(output.second, "", "Null value was not empty."); - - output = containing_null.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array containing null did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = containing_null.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array containing null did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_single_quoted_string() -{ - std::pair output; - pqxx::array_parser parser("{'item'}"); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "item", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_single_quoted_escaping() -{ - std::pair output; - pqxx::array_parser parser("{'don''t\\\\ care'}"); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "don't\\ care", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_double_quoted_string() -{ - std::pair output; - pqxx::array_parser parser("{\"item\"}"); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "item", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_double_quoted_escaping() -{ - std::pair output; - pqxx::array_parser parser(R"--({"don''t\\ care"})--"); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "don''t\\ care", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -// A pair of double quotes in a double-quoted string is an escaped quote. -void test_double_double_quoted_string() -{ - std::pair output; - pqxx::array_parser parser{R"--({"3"" steel"})--"}; - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - - PQXX_CHECK_EQUAL(output.second, "3\" steel", "Unexpected string value."); -} - - -void test_unquoted_string() -{ - std::pair output; - pqxx::array_parser parser("{item}"); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "item", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_multiple_values() -{ - std::pair output; - pqxx::array_parser parser("{1,2}"); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "1", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "2", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_nested_array() -{ - std::pair output; - pqxx::array_parser parser("{{item}}"); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Nested array did not start 2nd dimension with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "item", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Nested array did not end 2nd dimension with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_nested_array_with_multiple_entries() -{ - std::pair output; - pqxx::array_parser parser("{{1,2},{3,4}}"); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Nested array did not start 2nd dimension with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "1", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "2", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Nested array did not end 2nd dimension with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_start, - "Nested array did not descend to 2nd dimension with row_start."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "3", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::string_value, - "Array did not return string_value."); - PQXX_CHECK_EQUAL(output.second, "4", "Unexpected string value."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Nested array did not leave 2nd dimension with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::row_end, - "Array did not end with row_end."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); - - output = parser.get_next(); - PQXX_CHECK_EQUAL( - output.first, pqxx::array_parser::juncture::done, - "Array did not conclude with done."); - PQXX_CHECK_EQUAL(output.second, "", "Unexpected nonempty output."); -} - - -void test_array_parse() -{ - test_empty_arrays(); - test_null_value(); - test_single_quoted_string(); - test_single_quoted_escaping(); - test_double_quoted_string(); - test_double_quoted_escaping(); - test_double_double_quoted_string(); - test_unquoted_string(); - test_multiple_values(); - test_nested_array(); - test_nested_array_with_multiple_entries(); -} - - -void test_generate_empty_array() -{ - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{}), "{}", - "Basic array output is not as expected."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{}), "{}", - "String array comes out different."); -} - - -void test_generate_null_value() -{ - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{nullptr}), "{NULL}", - "Null array value did not come out as expected."); -} - - -void test_generate_single_item() -{ - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{42}), "{42}", - "Numeric conversion came out wrong."); - - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{"foo"}), "{\"foo\"}", - "String array conversion came out wrong."); -} - - -void test_generate_multiple_items() -{ - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{5, 4, 3, 2}), "{5,4,3,2}", - "Array with multiple values is not correct."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{"foo", "bar"}), - "{\"foo\",\"bar\"}", "Array with multiple strings came out wrong."); -} - - -void test_generate_nested_array() -{ - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector>{{1, 2}, {3, 4}}), - "{{1,2},{3,4}}", "Nested arrays don't work right."); -} - - -void test_generate_escaped_strings() -{ - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{"a\\b"}), "{\"a\\\\b\"}", - "Backslashes are not escaped properly."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::vector{"x\"y\""}), "{\"x\\\"y\\\"\"}", - "Double quotes are not escaped properly."); -} - - -void test_array_generate() -{ - test_generate_empty_array(); - test_generate_null_value(); - test_generate_single_item(); - test_generate_multiple_items(); - test_generate_nested_array(); - test_generate_escaped_strings(); -} - - -void test_array_roundtrip() -{ - pqxx::connection c; - pqxx::work w{c}; - - std::vector const in{0, 1, 2, 3, 5}; - auto const r1{w.exec1("SELECT " + c.quote(in) + "::integer[]")}; - pqxx::array_parser parser{r1[0].view()}; - auto item{parser.get_next()}; - PQXX_CHECK_EQUAL( - item.first, pqxx::array_parser::juncture::row_start, - "Array did not start with row_start."); - - std::vector out; - for (item = parser.get_next(); - item.first == pqxx::array_parser::juncture::string_value; - item = parser.get_next()) - { - out.push_back(pqxx::from_string(item.second)); - } - - PQXX_CHECK_EQUAL( - item.first, pqxx::array_parser::juncture::row_end, - "Array values did not end in row_end."); - PQXX_CHECK_EQUAL( - std::size(out), std::size(in), "Array came back with different length."); - - for (std::size_t i{0}; i < std::size(in); ++i) - PQXX_CHECK_EQUAL(out[i], in[i], "Array element has changed."); - - item = parser.get_next(); - PQXX_CHECK_EQUAL( - item.first, pqxx::array_parser::juncture::done, - "Array did not end in done."); -} - - -PQXX_REGISTER_TEST(test_array_parse); -PQXX_REGISTER_TEST(test_array_generate); -PQXX_REGISTER_TEST(test_array_roundtrip); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_binarystring.cxx b/ext/libpqxx-7.7.3/test/unit/test_binarystring.cxx deleted file mode 100644 index e6097d039..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_binarystring.cxx +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include -#include - -#include "../test_helpers.hxx" -#include "../test_types.hxx" - - -namespace -{ -pqxx::binarystring -make_binarystring(pqxx::transaction_base &T, std::string content) -{ -#include "pqxx/internal/ignore-deprecated-pre.hxx" - return pqxx::binarystring(T.exec1("SELECT " + T.quote_raw(content))[0]); -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -void test_binarystring() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - auto b{make_binarystring(tx, "")}; - PQXX_CHECK(std::empty(b), "Empty binarystring is not empty."); - PQXX_CHECK_EQUAL(b.str(), "", "Empty binarystring doesn't work."); - PQXX_CHECK_EQUAL(std::size(b), 0u, "Empty binarystring has nonzero size."); - PQXX_CHECK_EQUAL(b.length(), 0u, "Length/size mismatch."); - PQXX_CHECK(std::begin(b) == std::end(b), "Empty binarystring iterates."); - PQXX_CHECK( - std::cbegin(b) == std::begin(b), "Wrong cbegin for empty binarystring."); - PQXX_CHECK( - std::rbegin(b) == std::rend(b), "Empty binarystring reverse-iterates."); - PQXX_CHECK( - std::crbegin(b) == std::rbegin(b), - "Wrong crbegin for empty binarystring."); - PQXX_CHECK_THROWS( - b.at(0), std::out_of_range, "Empty binarystring accepts at()."); - - b = make_binarystring(tx, "z"); - PQXX_CHECK_EQUAL(b.str(), "z", "Basic nonempty binarystring is broken."); - PQXX_CHECK(not std::empty(b), "Nonempty binarystring is empty."); - PQXX_CHECK_EQUAL(std::size(b), 1u, "Bad binarystring size."); - PQXX_CHECK_EQUAL(b.length(), 1u, "Length/size mismatch."); - PQXX_CHECK( - std::begin(b) != std::end(b), "Nonempty binarystring does not iterate."); - PQXX_CHECK( - std::rbegin(b) != std::rend(b), - "Nonempty binarystring does not reverse-iterate."); - PQXX_CHECK(std::begin(b) + 1 == std::end(b), "Bad iteration."); - PQXX_CHECK(std::rbegin(b) + 1 == std::rend(b), "Bad reverse iteration."); - PQXX_CHECK(std::cbegin(b) == std::begin(b), "Wrong cbegin."); - PQXX_CHECK(std::cend(b) == std::end(b), "Wrong cend."); - PQXX_CHECK(std::crbegin(b) == std::rbegin(b), "Wrong crbegin."); - PQXX_CHECK(std::crend(b) == std::rend(b), "Wrong crend."); - PQXX_CHECK(b.front() == 'z', "Unexpected front()."); - PQXX_CHECK(b.back() == 'z', "Unexpected back()."); - PQXX_CHECK(b.at(0) == 'z', "Unexpected data at index 0."); - PQXX_CHECK_THROWS( - b.at(1), std::out_of_range, "Failed to catch range error."); - - std::string const simple{"ab"}; - b = make_binarystring(tx, simple); - PQXX_CHECK_EQUAL( - b.str(), simple, "Binary (un)escaping went wrong somewhere."); - PQXX_CHECK_EQUAL( - std::size(b), std::size(simple), "Escaping confuses length."); - - std::string const simple_escaped{ - tx.esc_raw(std::basic_string_view{ - reinterpret_cast(std::data(simple)), - std::size(simple)})}; - for (auto c : simple_escaped) - { - auto const uc{static_cast(c)}; - PQXX_CHECK(uc <= 127, "Non-ASCII byte in escaped string."); - } - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - PQXX_CHECK_EQUAL( - tx.quote_raw( - reinterpret_cast(simple.c_str()), - std::size(simple)), - tx.quote(b), "quote_raw is broken"); - PQXX_CHECK_EQUAL( - tx.quote(b), tx.quote_raw(simple), "Binary quoting is broken."); - PQXX_CHECK_EQUAL( - pqxx::binarystring(tx.exec1("SELECT " + tx.quote(b))[0]).str(), simple, - "Binary string is not idempotent."); -#include "pqxx/internal/ignore-deprecated-post.hxx" - - std::string const bytes("\x01\x23\x23\xa1\x2b\x0c\xff"); - b = make_binarystring(tx, bytes); - PQXX_CHECK_EQUAL(b.str(), bytes, "Binary data breaks (un)escaping."); - - std::string const nully("a\0b", 3); - b = make_binarystring(tx, nully); - PQXX_CHECK_EQUAL(b.str(), nully, "Nul byte broke binary (un)escaping."); - PQXX_CHECK_EQUAL(std::size(b), 3u, "Nul byte broke binarystring size."); - - b = make_binarystring(tx, "foo"); - PQXX_CHECK_EQUAL(std::string(b.get(), 3), "foo", "get() appears broken."); - - auto b1{make_binarystring(tx, "1")}, b2{make_binarystring(tx, "2")}; - PQXX_CHECK_NOT_EQUAL(b1.get(), b2.get(), "Madness rules."); - PQXX_CHECK_NOT_EQUAL(b1.str(), b2.str(), "Logic has no more meaning."); - b1.swap(b2); - PQXX_CHECK_NOT_EQUAL(b1.str(), b2.str(), "swap() equalized binarystrings."); - PQXX_CHECK_NOT_EQUAL(b1.str(), "1", "swap() did not happen."); - PQXX_CHECK_EQUAL(b1.str(), "2", "swap() is broken."); - PQXX_CHECK_EQUAL(b2.str(), "1", "swap() went insane."); - - b = make_binarystring(tx, "bar"); - b.swap(b); - PQXX_CHECK_EQUAL(b.str(), "bar", "Self-swap confuses binarystring."); - - b = make_binarystring(tx, "\\x"); - PQXX_CHECK_EQUAL(b.str(), "\\x", "Hex-escape header confused (un)escaping."); -} - - -void test_binarystring_conversion() -{ - constexpr char bytes[]{"f\to\0o\n\0"}; - std::string_view const data{bytes, std::size(bytes) - 1}; -#include "pqxx/internal/ignore-deprecated-pre.hxx" - pqxx::binarystring bin{data}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - auto const escaped{pqxx::to_string(bin)}; - PQXX_CHECK_EQUAL( - escaped, std::string_view{"\\x66096f006f0a00"}, "Unexpected hex escape."); - auto const restored{pqxx::from_string(escaped)}; - PQXX_CHECK_EQUAL( - std::size(restored), std::size(data), "Unescaping produced wrong length."); -} - - -void test_binarystring_stream() -{ - constexpr char bytes[]{"a\tb\0c"}; - std::string_view const data{bytes, std::size(bytes) - 1}; -#include "pqxx/internal/ignore-deprecated-pre.hxx" - pqxx::binarystring bin{data}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - - pqxx::connection conn; - pqxx::transaction tx{conn}; - tx.exec0("CREATE TEMP TABLE pqxxbinstream(id integer, bin bytea)"); - - auto to{pqxx::stream_to::table(tx, {"pqxxbinstream"})}; - to.write_values(0, bin); - to.complete(); - - auto ptr{reinterpret_cast(std::data(data))}; - auto expect{ - tx.quote(std::basic_string_view{ptr, std::size(data)})}; - PQXX_CHECK( - tx.query_value("SELECT bin = " + expect + " FROM pqxxbinstream"), - "binarystring did not stream_to properly."); - PQXX_CHECK_EQUAL( - tx.query_value("SELECT octet_length(bin) FROM pqxxbinstream"), - std::size(data), "Did the terminating zero break the bytea?"); -} - - -void test_binarystring_array_stream() -{ - pqxx::connection conn; - pqxx::transaction tx{conn}; - tx.exec0("CREATE TEMP TABLE pqxxbinstream(id integer, vec bytea[])"); - - constexpr char bytes1[]{"a\tb\0c"}, bytes2[]{"1\0.2"}; - std::string_view const data1{bytes1}, data2{bytes2}; -#include "pqxx/internal/ignore-deprecated-pre.hxx" - pqxx::binarystring bin1{data1}, bin2{data2}; - std::vector const vec{bin1, bin2}; -#include "pqxx/internal/ignore-deprecated-post.hxx" - - auto to{pqxx::stream_to::table(tx, {"pqxxbinstream"})}; - to.write_values(0, vec); - to.complete(); - - PQXX_CHECK_EQUAL( - tx.query_value( - "SELECT array_length(vec, 1) FROM pqxxbinstream"), - std::size(vec), "Array came out with wrong length."); - - auto ptr1{reinterpret_cast(std::data(data1))}, - ptr2{reinterpret_cast(std::data(data2))}; - auto expect1{ - tx.quote(std::basic_string_view{ptr1, std::size(data1)})}, - expect2{ - tx.quote(std::basic_string_view{ptr2, std::size(data2)})}; - PQXX_CHECK( - tx.query_value("SELECT vec[1] = " + expect1 + " FROM pqxxbinstream"), - "Bytea in array came out wrong."); - PQXX_CHECK( - tx.query_value("SELECT vec[2] = " + expect2 + " FROM pqxxbinstream"), - "First bytea in array worked, but second did not."); - PQXX_CHECK_EQUAL( - tx.query_value( - "SELECT octet_length(vec[1]) FROM pqxxbinstream"), - std::size(data1), "Bytea length broke inside array."); -} - - -PQXX_REGISTER_TEST(test_binarystring); -PQXX_REGISTER_TEST(test_binarystring_conversion); -PQXX_REGISTER_TEST(test_binarystring_stream); -PQXX_REGISTER_TEST(test_binarystring_array_stream); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_blob.cxx b/ext/libpqxx-7.7.3/test/unit/test_blob.cxx deleted file mode 100644 index 709c1f489..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_blob.cxx +++ /dev/null @@ -1,644 +0,0 @@ -#include - -#include -#include - -#include "../test_helpers.hxx" -#include "../test_types.hxx" - - -namespace -{ -void test_blob_is_useless_by_default() -{ - pqxx::blob b{}; - std::basic_string buf; - PQXX_CHECK_THROWS( - b.read(buf, 1), pqxx::usage_error, - "Read on default-constructed blob did not throw failure."); - PQXX_CHECK_THROWS( - b.write(buf), pqxx::usage_error, - "Write on default-constructed blob did not throw failure."); -} - - -void test_blob_create_makes_empty_blob() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::oid id{pqxx::blob::create(tx)}; - auto b{pqxx::blob::open_r(tx, id)}; - b.seek_end(0); - PQXX_CHECK_EQUAL(b.tell(), 0, "New blob is not empty."); -} - - -void test_blob_create_with_oid_requires_oid_be_free() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::create(tx)}; - - PQXX_CHECK_THROWS( - pqxx::ignore_unused(pqxx::blob::create(tx, id)), pqxx::failure, - "Not getting expected error when oid not free."); -} - - -void test_blob_create_with_oid_obeys_oid() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::create(tx)}; - pqxx::blob::remove(tx, id); - - auto actual_id{pqxx::blob::create(tx, id)}; - PQXX_CHECK_EQUAL(actual_id, id, "Create with oid returned different oid."); -} - - -void test_blobs_are_transactional() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::oid id{pqxx::blob::create(tx)}; - tx.abort(); - pqxx::work tx2{conn}; - PQXX_CHECK_THROWS( - pqxx::ignore_unused(pqxx::blob::open_r(tx2, id)), pqxx::failure, - "Blob from aborted transaction still exists."); -} - - -void test_blob_remove_removes_blob() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::oid id{pqxx::blob::create(tx)}; - pqxx::blob::remove(tx, id); - PQXX_CHECK_THROWS( - pqxx::ignore_unused(pqxx::blob::open_r(tx, id)), pqxx::failure, - "Attempt to open blob after removing should have failed."); -} - - -void test_blob_remove_is_not_idempotent() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::oid id{pqxx::blob::create(tx)}; - pqxx::blob::remove(tx, id); - PQXX_CHECK_THROWS( - pqxx::blob::remove(tx, id), pqxx::failure, - "Redundant remove() did not throw failure."); -} - - -void test_blob_checks_open_mode() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::oid id{pqxx::blob::create(tx)}; - pqxx::blob b_r{pqxx::blob::open_r(tx, id)}; - pqxx::blob b_w{pqxx::blob::open_w(tx, id)}; - pqxx::blob b_rw{pqxx::blob::open_rw(tx, id)}; - - std::basic_string buf{std::byte{3}, std::byte{2}, std::byte{1}}; - - // These are all allowed: - b_w.write(buf); - b_r.read(buf, 3); - b_rw.seek_end(0); - b_rw.write(buf); - b_rw.seek_abs(0); - b_rw.read(buf, 6); - - // These are not: - PQXX_CHECK_THROWS( - b_r.write(buf), pqxx::failure, "Read-only blob did not stop write."); - PQXX_CHECK_THROWS( - b_w.read(buf, 10), pqxx::failure, "Write-only blob did not stop read."); -} - - -void test_blob_supports_move() -{ - std::basic_string buf; - buf.push_back(std::byte{'x'}); - - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::oid id{pqxx::blob::create(tx)}; - pqxx::blob b1{pqxx::blob::open_rw(tx, id)}; - b1.write(buf); - - pqxx::blob b2{std::move(b1)}; - b2.seek_abs(0); - b2.read(buf, 1u); - - PQXX_CHECK_THROWS( - b1.read(buf, 1u), pqxx::usage_error, - "Blob still works after move construction."); - - b1 = std::move(b2); - b1.read(buf, 1u); - - PQXX_CHECK_THROWS( - b2.read(buf, 1u), pqxx::usage_error, - "Blob still works after move assignment."); -} - - -void test_blob_read_reads_data() -{ - std::basic_string const data{ - std::byte{'a'}, std::byte{'b'}, std::byte{'c'}}; - - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::oid id{pqxx::blob::from_buf(tx, data)}; - - std::basic_string buf; - auto b{pqxx::blob::open_rw(tx, id)}; - PQXX_CHECK_EQUAL( - b.read(buf, 2), 2u, "Full read() returned an unexpected value."); - PQXX_CHECK_EQUAL( - buf, (std::basic_string{std::byte{'a'}, std::byte{'b'}}), - "Read back the wrong data."); - PQXX_CHECK_EQUAL( - b.read(buf, 2), 1u, "Partial read() returned an unexpected value."); - PQXX_CHECK_EQUAL( - buf, (std::basic_string{std::byte{'c'}}), - "Continued read produced wrong data."); - PQXX_CHECK_EQUAL( - b.read(buf, 2), 0u, "read at end returned an unexpected value."); - PQXX_CHECK_EQUAL( - buf, (std::basic_string{}), "Read past end produced data."); -} - - -void test_blob_read_span() -{ -#if defined(PQXX_HAVE_SPAN) - std::basic_string const data{std::byte{'u'}, std::byte{'v'}, - std::byte{'w'}, std::byte{'x'}, - std::byte{'y'}, std::byte{'z'}}; - - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::oid id{pqxx::blob::from_buf(tx, data)}; - - auto b{pqxx::blob::open_r(tx, id)}; - std::basic_string string_buf; - string_buf.resize(2); - - std::span output; - - output = b.read(std::span{}); - PQXX_CHECK_EQUAL( - std::size(output), 0u, "Empty read produced nonempty buffer."); - output = b.read(string_buf); - PQXX_CHECK_EQUAL( - std::size(output), 2u, "Got unexpected buf size from blob::read()."); - PQXX_CHECK_EQUAL( - output[0], std::byte{'u'}, "Unexpected byte from blob::read()."); - PQXX_CHECK_EQUAL( - output[1], std::byte{'v'}, "Unexpected byte from blob::read()."); - - string_buf.resize(100); - output = b.read(std::span{string_buf.data(), 1}); - PQXX_CHECK_EQUAL( - std::size(output), 1u, - "Did blob::read() follow string size instead of span size?"); - PQXX_CHECK_EQUAL( - output[0], std::byte{'w'}, "Unexpected byte from blob::read()."); - - std::vector vec_buf; - vec_buf.resize(2); - auto output2{b.read(vec_buf)}; - PQXX_CHECK_EQUAL( - std::size(output2), 2u, "Got unexpected buf size from blob::read()."); - PQXX_CHECK_EQUAL( - output2[0], std::byte{'x'}, "Unexpected byte from blob::read()."); - PQXX_CHECK_EQUAL( - output2[1], std::byte{'y'}, "Unexpected byte from blob::read()."); - - vec_buf.resize(100); - output2 = b.read(vec_buf); - PQXX_CHECK_EQUAL(std::size(output2), 1u, "Weird things happened at EOF."); - PQXX_CHECK_EQUAL(output2[0], std::byte{'z'}, "Bad data at EOF."); -#endif // PQXX_HAVE_SPAN -} - - -void test_blob_reads_vector() -{ - char const content[]{"abcd"}; - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::from_buf( - tx, std::basic_string_view{ - reinterpret_cast(content), std::size(content)})}; - std::vector buf; - buf.resize(10); - auto out{pqxx::blob::open_r(tx, id).read(buf)}; - PQXX_CHECK_EQUAL( - std::size(out), std::size(content), - "Got wrong length back when reading as vector."); - PQXX_CHECK_EQUAL( - out[0], std::byte{'a'}, "Got bad data when reading as vector."); -} - - -void test_blob_write_appends_at_insertion_point() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::create(tx)}; - - auto b{pqxx::blob::open_rw(tx, id)}; - b.write(std::basic_string{std::byte{'z'}}); - b.write(std::basic_string{std::byte{'a'}}); - - std::basic_string buf; - b.read(buf, 5); - PQXX_CHECK_EQUAL( - buf, (std::basic_string{}), "Found data at the end."); - b.seek_abs(0); - b.read(buf, 5); - PQXX_CHECK_EQUAL( - buf, (std::basic_string{std::byte{'z'}, std::byte{'a'}}), - "Consecutive writes did not append correctly."); - - b.write(std::basic_string{std::byte{'x'}}); - // Blob now contains "zax". That's not we wanted... Rewind and rewrite. - b.seek_abs(1); - b.write(std::basic_string{std::byte{'y'}}); - b.seek_abs(0); - b.read(buf, 5); - PQXX_CHECK_EQUAL( - buf, - (std::basic_string{ - std::byte{'z'}, std::byte{'y'}, std::byte{'x'}}), - "Rewriting in the middle did not work right."); -} - - -void test_blob_writes_span() -{ -#if defined(PQXX_HAVE_SPAN) - pqxx::connection conn; - pqxx::work tx{conn}; - constexpr char content[]{"gfbltk"}; - std::basic_string data{ - reinterpret_cast(content), std::size(content)}; - - auto id{pqxx::blob::create(tx)}; - auto b{pqxx::blob::open_rw(tx, id)}; - b.write(std::span{data.data() + 1, 3u}); - b.seek_abs(0); - - std::vector buf; - buf.resize(4); - auto out{b.read(std::span{buf.data(), 4u})}; - PQXX_CHECK_EQUAL( - std::size(out), 3u, "Did not get expected number of bytes back."); - PQXX_CHECK_EQUAL(out[0], std::byte{'f'}, "Data did not come back right."); - PQXX_CHECK_EQUAL(out[2], std::byte{'l'}, "Data started right, ended wrong!"); -#endif // PQXX_HAVE_SPAN -} - - -void test_blob_resize_shortens_to_desired_length() -{ - std::basic_string const data{ - std::byte{'w'}, std::byte{'o'}, std::byte{'r'}, std::byte{'k'}}; - - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::from_buf(tx, data)}; - - pqxx::blob::open_w(tx, id).resize(2); - std::basic_string buf; - pqxx::blob::to_buf(tx, id, buf, 10); - PQXX_CHECK_EQUAL( - buf, (std::basic_string{std::byte{'w'}, std::byte{'o'}}), - "Truncate did not shorten correctly."); -} - - -void test_blob_resize_extends_to_desired_length() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{ - pqxx::blob::from_buf(tx, std::basic_string{std::byte{100}})}; - pqxx::blob::open_w(tx, id).resize(3); - std::basic_string buf; - pqxx::blob::to_buf(tx, id, buf, 10); - PQXX_CHECK_EQUAL( - buf, - (std::basic_string{std::byte{100}, std::byte{0}, std::byte{0}}), - "Resize did not zero-extend correctly."); -} - - -void test_blob_tell_tracks_position() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::create(tx)}; - auto b{pqxx::blob::open_rw(tx, id)}; - - PQXX_CHECK_EQUAL( - b.tell(), 0, "Empty blob started out in non-zero position."); - b.write(std::basic_string{std::byte{'e'}, std::byte{'f'}}); - PQXX_CHECK_EQUAL( - b.tell(), 2, "Empty blob started out in non-zero position."); - b.seek_abs(1); - PQXX_CHECK_EQUAL(b.tell(), 1, "tell() did not track seek."); -} - - -void test_blob_seek_sets_positions() -{ - std::basic_string data{ - std::byte{0}, std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}, - std::byte{5}, std::byte{6}, std::byte{7}, std::byte{8}, std::byte{9}}; - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::from_buf(tx, data)}; - auto b{pqxx::blob::open_r(tx, id)}; - - std::basic_string buf; - b.seek_rel(3); - b.read(buf, 1u); - PQXX_CHECK_EQUAL( - buf[0], std::byte{3}, - "seek_rel() from beginning did not take us to the right position."); - - b.seek_abs(2); - b.read(buf, 1u); - PQXX_CHECK_EQUAL( - buf[0], std::byte{2}, "seek_abs() did not take us to the right position."); - - b.seek_end(-2); - b.read(buf, 1u); - PQXX_CHECK_EQUAL( - buf[0], std::byte{8}, "seek_end() did not take us to the right position."); -} - - -void test_blob_from_buf_interoperates_with_to_buf() -{ - std::basic_string const data{std::byte{'h'}, std::byte{'i'}}; - std::basic_string buf; - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::blob::to_buf(tx, pqxx::blob::from_buf(tx, data), buf, 10); - PQXX_CHECK_EQUAL(buf, data, "from_buf()/to_buf() roundtrip did not work."); -} - - -void test_blob_append_from_buf_appends() -{ - std::basic_string const data{std::byte{'h'}, std::byte{'o'}}; - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::create(tx)}; - pqxx::blob::append_from_buf(tx, data, id); - pqxx::blob::append_from_buf(tx, data, id); - std::basic_string buf; - pqxx::blob::to_buf(tx, id, buf, 10); - PQXX_CHECK_EQUAL(buf, data + data, "append_from_buf() wrote wrong data?"); -} - - -namespace -{ -/// Wrap `std::fopen`. -/** This is just here to stop Visual Studio from advertising its own - * alternative. - */ -std::unique_ptr> -my_fopen(char const *path, char const *mode) -{ -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4996) -#endif - return {std::fopen(path, mode), std::fclose}; -#if defined(_MSC_VER) -# pragma warning(pop) -#endif -} - - -void read_file( - char const path[], std::size_t len, std::basic_string &buf) -{ - buf.resize(len); - auto f{my_fopen(path, "rb")}; - auto bytes{ - std::fread(reinterpret_cast(buf.data()), 1, len, f.get())}; - if (bytes == 0) - throw std::runtime_error{"Error reading test file."}; - buf.resize(bytes); -} - - -void write_file(char const path[], std::basic_string_view data) -{ - try - { - auto f{my_fopen(path, "wb")}; - if ( - std::fwrite( - reinterpret_cast(data.data()), 1, std::size(data), - f.get()) < std::size(data)) - std::runtime_error{"File write failed."}; - } - catch (const std::exception &) - { - std::remove(path); - throw; - } -} - - -/// Temporary file. -class TempFile -{ -public: - /// Create (and later clean up) a file at path containing data. - TempFile(char const path[], std::basic_string_view data) : - m_path(path) - { - write_file(path, data); - } - - ~TempFile() { std::remove(m_path.c_str()); } - -private: - std::string m_path; -}; -} // namespace - - -void test_blob_from_file_creates_blob_from_file_contents() -{ - char const temp_file[] = "blob-test-from_file.tmp"; - std::basic_string const data{std::byte{'4'}, std::byte{'2'}}; - - pqxx::connection conn; - pqxx::work tx{conn}; - std::basic_string buf; - - pqxx::oid id; - { - TempFile f{temp_file, data}; - id = pqxx::blob::from_file(tx, temp_file); - } - pqxx::blob::to_buf(tx, id, buf, 10); - PQXX_CHECK_EQUAL(buf, data, "Wrong data from blob::from_file()."); -} - - -void test_blob_from_file_with_oid_writes_blob() -{ - std::basic_string const data{std::byte{'6'}, std::byte{'9'}}; - char const temp_file[] = "blob-test-from_file-oid.tmp"; - std::basic_string buf; - - pqxx::connection conn; - pqxx::work tx{conn}; - - // Guarantee (more or less) that id is not in use. - auto id{pqxx::blob::create(tx)}; - pqxx::blob::remove(tx, id); - - { - TempFile f{temp_file, data}; - pqxx::blob::from_file(tx, temp_file, id); - } - pqxx::blob::to_buf(tx, id, buf, 10); - PQXX_CHECK_EQUAL(buf, data, "Wrong data from blob::from_file()."); -} - - -void test_blob_append_to_buf_appends() -{ - std::basic_string const data{ - std::byte{'b'}, std::byte{'l'}, std::byte{'u'}, std::byte{'b'}}; - - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::from_buf(tx, data)}; - - std::basic_string buf; - PQXX_CHECK_EQUAL( - pqxx::blob::append_to_buf(tx, id, 0u, buf, 1u), 1u, - "append_to_buf() returned unexpected value."); - PQXX_CHECK_EQUAL(std::size(buf), 1u, "Appended the wrong number of bytes."); - PQXX_CHECK_EQUAL( - pqxx::blob::append_to_buf(tx, id, 1u, buf, 5u), 3u, - "append_to_buf() returned unexpected value."); - PQXX_CHECK_EQUAL(std::size(buf), 4u, "Appended the wrong number of bytes."); - - PQXX_CHECK_EQUAL( - buf, data, "Reading using append_to_buf gave us wrong data."); -} - - -void test_blob_to_file_writes_file() -{ - std::basic_string const data{ - std::byte{'C'}, std::byte{'+'}, std::byte{'+'}}; - - char const temp_file[] = "blob-test-to_file.tmp"; - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{pqxx::blob::from_buf(tx, data)}; - std::basic_string buf; - - try - { - pqxx::blob::to_file(tx, id, temp_file); - read_file(temp_file, 10u, buf); - std::remove(temp_file); - } - catch (std::exception const &) - { - std::remove(temp_file); - throw; - } - PQXX_CHECK_EQUAL(buf, data, "Got wrong data from to_file()."); -} - - -void test_blob_close_leaves_blob_unusable() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - auto id{ - pqxx::blob::from_buf(tx, std::basic_string{std::byte{1}})}; - auto b{pqxx::blob::open_rw(tx, id)}; - b.close(); - std::basic_string buf; - PQXX_CHECK_THROWS( - b.read(buf, 1), pqxx::usage_error, - "Reading from closed blob did not fail right."); -} - - -void test_blob_accepts_std_filesystem_path() -{ -#if defined(PQXX_HAVE_PATH) && !defined(_WIN32) - // A bug in gcc 8's ~std::filesystem::path() causes a run-time crash. -# if !defined(__GNUC__) || (__GNUC__ > 8) - - char const temp_file[] = "blob-test-filesystem-path.tmp"; - std::basic_string const data{std::byte{'4'}, std::byte{'2'}}; - - pqxx::connection conn; - pqxx::work tx{conn}; - std::basic_string buf; - - TempFile f{temp_file, data}; - std::filesystem::path const path{temp_file}; - auto id{pqxx::blob::from_file(tx, path)}; - pqxx::blob::to_buf(tx, id, buf, 10); - PQXX_CHECK_EQUAL(buf, data, "Wrong data from blob::from_file()."); - -# endif -#endif -} - - -PQXX_REGISTER_TEST(test_blob_is_useless_by_default); -PQXX_REGISTER_TEST(test_blob_create_makes_empty_blob); -PQXX_REGISTER_TEST(test_blob_create_with_oid_requires_oid_be_free); -PQXX_REGISTER_TEST(test_blob_create_with_oid_obeys_oid); -PQXX_REGISTER_TEST(test_blobs_are_transactional); -PQXX_REGISTER_TEST(test_blob_remove_removes_blob); -PQXX_REGISTER_TEST(test_blob_remove_is_not_idempotent); -PQXX_REGISTER_TEST(test_blob_checks_open_mode); -PQXX_REGISTER_TEST(test_blob_supports_move); -PQXX_REGISTER_TEST(test_blob_read_reads_data); -PQXX_REGISTER_TEST(test_blob_reads_vector); -PQXX_REGISTER_TEST(test_blob_read_span); -PQXX_REGISTER_TEST(test_blob_write_appends_at_insertion_point); -PQXX_REGISTER_TEST(test_blob_writes_span); -PQXX_REGISTER_TEST(test_blob_resize_shortens_to_desired_length); -PQXX_REGISTER_TEST(test_blob_resize_extends_to_desired_length); -PQXX_REGISTER_TEST(test_blob_tell_tracks_position); -PQXX_REGISTER_TEST(test_blob_seek_sets_positions); -PQXX_REGISTER_TEST(test_blob_from_buf_interoperates_with_to_buf); -PQXX_REGISTER_TEST(test_blob_append_from_buf_appends); -PQXX_REGISTER_TEST(test_blob_from_file_creates_blob_from_file_contents); -PQXX_REGISTER_TEST(test_blob_from_file_with_oid_writes_blob); -PQXX_REGISTER_TEST(test_blob_append_to_buf_appends); -PQXX_REGISTER_TEST(test_blob_to_file_writes_file); -PQXX_REGISTER_TEST(test_blob_close_leaves_blob_unusable); -PQXX_REGISTER_TEST(test_blob_accepts_std_filesystem_path); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_cancel_query.cxx b/ext/libpqxx-7.7.3/test/unit/test_cancel_query.cxx deleted file mode 100644 index 5329d195f..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_cancel_query.cxx +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_cancel_query() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - // Calling cancel_query() while none is in progress has no effect. - conn.cancel_query(); - - // Nothing much is guaranteed about cancel_query, except that it doesn't make - // the process die in flames. - pqxx::pipeline p{tx, "test_cancel_query"}; - p.retain(0); - p.insert("SELECT pg_sleep(1)"); - conn.cancel_query(); -} - - -PQXX_REGISTER_TEST(test_cancel_query); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_column.cxx b/ext/libpqxx-7.7.3/test/unit/test_column.cxx deleted file mode 100644 index 9c50faff4..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_column.cxx +++ /dev/null @@ -1,61 +0,0 @@ -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_table_column() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - tx.exec0("CREATE TEMP TABLE pqxxfoo (x varchar, y integer, z integer)"); - tx.exec0("INSERT INTO pqxxfoo VALUES ('xx', 1, 2)"); - auto R{tx.exec("SELECT z,y,x FROM pqxxfoo")}; - auto X{tx.exec("SELECT x,y,z,99 FROM pqxxfoo")}; - - pqxx::row::size_type x{R.table_column(2)}, y{R.table_column(1)}, - z{R.table_column(static_cast(0))}; - - PQXX_CHECK_EQUAL(x, 0, "Wrong column number."); - PQXX_CHECK_EQUAL(y, 1, "Wrong column number."); - PQXX_CHECK_EQUAL(z, 2, "Wrong column number."); - - x = R.table_column("x"); - y = R.table_column("y"); - z = R.table_column("z"); - - PQXX_CHECK_EQUAL(x, 0, "Wrong number for named column."); - PQXX_CHECK_EQUAL(y, 1, "Wrong number for named column."); - PQXX_CHECK_EQUAL(z, 2, "Wrong number for named column."); - - pqxx::row::size_type xx{X[0].table_column(static_cast(0))}, - yx{X[0].table_column(pqxx::row::size_type(1))}, zx{X[0].table_column("z")}; - - PQXX_CHECK_EQUAL(xx, 0, "Bad result from table_column(int)."); - PQXX_CHECK_EQUAL(yx, 1, "Bad result from table_column(size_type)."); - PQXX_CHECK_EQUAL(zx, 2, "Bad result from table_column(string)."); - - for (pqxx::row::size_type i{0}; i < std::size(R[0]); ++i) - PQXX_CHECK_EQUAL( - R[0][i].table_column(), R.table_column(i), - "Bad result from column_table()."); - - int col; - PQXX_CHECK_THROWS_EXCEPTION( - col = R.table_column(3), "table_column() with invalid index didn't fail."); - pqxx::ignore_unused(col); - - PQXX_CHECK_THROWS_EXCEPTION( - col = R.table_column("nonexistent"), - "table_column() with invalid column name didn't fail."); - pqxx::ignore_unused(col); - - PQXX_CHECK_THROWS_EXCEPTION( - col = X.table_column(3), "table_column() on non-table didn't fail."); - pqxx::ignore_unused(col); -} -} // namespace - - -PQXX_REGISTER_TEST(test_table_column); diff --git a/ext/libpqxx-7.7.3/test/unit/test_composite.cxx b/ext/libpqxx-7.7.3/test/unit/test_composite.cxx deleted file mode 100644 index dcd65360c..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_composite.cxx +++ /dev/null @@ -1,98 +0,0 @@ -#include "../test_helpers.hxx" - -#include "pqxx/composite" -#include "pqxx/transaction" - -namespace -{ -void test_composite() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0("CREATE TYPE pqxxfoo AS (a integer, b text)"); - auto const r{tx.exec1("SELECT '(5,hello)'::pqxxfoo")}; - - int a; - std::string b; - pqxx::parse_composite(r[0].view(), a, b); - - PQXX_CHECK_EQUAL(a, 5, "Integer composite field came back wrong."); - PQXX_CHECK_EQUAL(b, "hello", "String composite field came back wrong."); -} - - -void test_composite_escapes() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::row r; - tx.exec0("CREATE TYPE pqxxsingle AS (x text)"); - std::string s; - - r = tx.exec1(R"--(SELECT '("a""b")'::pqxxsingle)--"); - pqxx::parse_composite(r[0].view(), s); - PQXX_CHECK_EQUAL( - s, "a\"b", "Double-double-quotes escaping did not parse correctly."); - - r = tx.exec1(R"--(SELECT '("a\"b")'::pqxxsingle)--"); - pqxx::parse_composite(r[0].view(), s); - PQXX_CHECK_EQUAL(s, "a\"b", "Backslash escaping did not parse correctly."); -} - - -void test_composite_handles_nulls() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::row r; - - tx.exec0("CREATE TYPE pqxxnull AS (a integer)"); - int nonnull; - r = tx.exec1("SELECT '()'::pqxxnull"); - PQXX_CHECK_THROWS( - pqxx::parse_composite(r[0].view(), nonnull), pqxx::conversion_error, - "No conversion error when reading a null into a nulless variable."); - std::optional nullable{5}; - pqxx::parse_composite(r[0].view(), nullable); - PQXX_CHECK( - not nullable.has_value(), "Null integer came out as having a value."); - - tx.exec0("CREATE TYPE pqxxnulls AS (a integer, b integer)"); - std::optional a{2}, b{4}; - r = tx.exec1("SELECT '(,)'::pqxxnulls"); - pqxx::parse_composite(r[0].view(), a, b); - PQXX_CHECK(not a.has_value(), "Null first integer stored as value."); - PQXX_CHECK(not b.has_value(), "Null second integer stored as value."); -} - - -void test_composite_renders_to_string() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - char buf[1000]; - - pqxx::composite_into_buf( - std::begin(buf), std::end(buf), 355, "foo", "b\na\\r"); - PQXX_CHECK_EQUAL( - std::string{buf}, "(355,\"foo\",\"b\na\\\\r\")", - "Composite was not rendered as expected."); - - tx.exec0("CREATE TYPE pqxxcomp AS (a integer, b text, c text)"); - auto const r{tx.exec1("SELECT '" + std::string{buf} + "'::pqxxcomp")}; - - int a; - std::string b, c; - bool const nonnull{r[0].composite_to(a, b, c)}; - PQXX_CHECK(nonnull, "Mistaken nullness."); - PQXX_CHECK_EQUAL(a, 355, "Int came back wrong."); - PQXX_CHECK_EQUAL(b, "foo", "Simple string came back wrong."); - PQXX_CHECK_EQUAL(c, "b\na\\r", "Escaping went wrong."); -} - - -PQXX_REGISTER_TEST(test_composite); -PQXX_REGISTER_TEST(test_composite_escapes); -PQXX_REGISTER_TEST(test_composite_handles_nulls); -PQXX_REGISTER_TEST(test_composite_renders_to_string); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_connection.cxx b/ext/libpqxx-7.7.3/test/unit/test_connection.cxx deleted file mode 100644 index bbb780854..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_connection.cxx +++ /dev/null @@ -1,212 +0,0 @@ -#include - -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_connection_string_constructor() -{ - pqxx::connection c1{""}; - pqxx::connection c2{std::string{}}; -} - - -void test_move_constructor() -{ - pqxx::connection c1; - PQXX_CHECK(c1.is_open(), "New connection is not open."); - - pqxx::connection c2{std::move(c1)}; - - PQXX_CHECK(not c1.is_open(), "Moving did not close original connection."); - PQXX_CHECK(c2.is_open(), "Moved constructor is not open."); - - pqxx::work tx{c2}; - PQXX_CHECK_EQUAL(tx.query_value("SELECT 5"), 5, "Weird result!"); - - PQXX_CHECK_THROWS( - pqxx::connection c3{std::move(c2)}, pqxx::usage_error, - "Moving a connection with a transaction open should be an error."); -} - - -void test_move_assign() -{ - pqxx::connection c1; - pqxx::connection c2; - - c2.close(); - - c2 = std::move(c1); - - PQXX_CHECK(not c1.is_open(), "Connection still open after being moved out."); - PQXX_CHECK(c2.is_open(), "Moved constructor is not open."); - - { - pqxx::work tx1{c2}; - PQXX_CHECK_EQUAL(tx1.query_value("SELECT 8"), 8, "What!?"); - - pqxx::connection c3; - PQXX_CHECK_THROWS( - c3 = std::move(c2), pqxx::usage_error, - "Moving a connection with a transaction open should be an error."); - - PQXX_CHECK_THROWS( - c2 = std::move(c3), pqxx::usage_error, - "Moving a connection onto one with a transaction open should be " - "an error."); - } - - // After failed move attempts, the connection is still usable. - pqxx::work tx2{c2}; - PQXX_CHECK_EQUAL(tx2.query_value("SELECT 6"), 6, "Huh!?"); -} - - -void test_encrypt_password() -{ - pqxx::connection c; - auto pw{c.encrypt_password("user", "password")}; - PQXX_CHECK(not std::empty(pw), "Encrypted password was empty."); - PQXX_CHECK_EQUAL( - std::strlen(pw.c_str()), std::size(pw), - "Encrypted password contains a null byte."); -} - - -void test_connection_string() -{ - pqxx::connection c; - std::string const connstr{c.connection_string()}; - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4996) -#endif - if (std::getenv("PGUSER") == nullptr) -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - { - PQXX_CHECK( - connstr.find("user=" + std::string{c.username()}) != std::string::npos, - "Connection string did not specify user name: " + connstr); - } - else - { - PQXX_CHECK( - connstr.find("user=" + std::string{c.username()}) == std::string::npos, - "Connection string specified user name, even when using default: " + - connstr); - } -} - - -#if defined(PQXX_HAVE_CONCEPTS) -template std::size_t length(STR const &str) -{ - return std::size(str); -} - - -std::size_t length(char const str[]) -{ - return std::strlen(str); -} -#endif // PQXX_HAVE_CONCEPTS - - -template void test_params_type() -{ -#if defined(PQXX_HAVE_CONCEPTS) - using item_t = std::remove_reference_t< - decltype(*std::declval>())>; - using key_t = decltype(std::get<0>(std::declval())); - using value_t = decltype(std::get<1>(std::declval())); - - // Set some parameters that are relatively safe to change arbitrarily. - MAP const params{{ - {key_t{"application_name"}, value_t{"pqxx-test"}}, - {key_t{"connect_timeout"}, value_t{"96"}}, - {key_t{"keepalives_idle"}, value_t{"771"}}, - }}; - - // Can we create a connection from these parameters? - pqxx::connection c{params}; - - // Check that the parameters came through in the connection string. - // We don't know the exact format, but the parameters have to be in there. - auto const min_size{std::accumulate( - std::cbegin(params), std::cend(params), std::size(params) - 1, - [](auto count, auto item) { - return count + length(std::get<0>(item)) + 1 + length(std::get<1>(item)); - })}; - - auto const connstr{c.connection_string()}; - PQXX_CHECK_GREATER_EQUAL( - std::size(connstr), min_size, - "Connection string can't possibly contain the options we gave."); - for (auto const &[key, value] : params) - { - PQXX_CHECK_NOT_EQUAL( - connstr.find(key), std::string::npos, - "Could not find param name '" + std::string{key} + - "' in connection string: " + connstr); - PQXX_CHECK_NOT_EQUAL( - connstr.find(value), std::string::npos, - "Could not find value for '" + std::string{value} + - "' in connection string: " + connstr); - } -#endif // PQXX_HAVE_CONCEPTS -} - - -void test_connection_params() -{ - // Connecting in this way supports a wide variety of formats for the - // parameters. - test_params_type>(); - test_params_type>(); - test_params_type>(); - test_params_type>(); - test_params_type>(); - test_params_type>>(); - test_params_type>>(); - test_params_type>>(); - test_params_type>>(); -} - - -void test_raw_connection() -{ - pqxx::connection conn1; - PQXX_CHECK(conn1.is_open(), "Fresh connection is not open!"); - pqxx::work tx1{conn1}; - PQXX_CHECK_EQUAL( - tx1.query_value("SELECT 8"), 8, "Something weird happened."); - pqxx::internal::pq::PGconn *raw{std::move(conn1).release_raw_connection()}; - PQXX_CHECK(raw != nullptr, "Raw connection is null."); - PQXX_CHECK( - not conn1.is_open(), - "Releasing raw connection did not close pqxx::connection."); - - pqxx::connection conn2{pqxx::connection::seize_raw_connection(raw)}; - PQXX_CHECK( - conn2.is_open(), "Can't produce open connection from raw connection."); - pqxx::work tx2{conn2}; - PQXX_CHECK_EQUAL( - tx2.query_value("SELECT 9"), 9, - "Raw connection did not produce a working new connection."); -} - - -PQXX_REGISTER_TEST(test_connection_string_constructor); -PQXX_REGISTER_TEST(test_move_constructor); -PQXX_REGISTER_TEST(test_move_assign); -PQXX_REGISTER_TEST(test_encrypt_password); -PQXX_REGISTER_TEST(test_connection_string); -PQXX_REGISTER_TEST(test_connection_params); -PQXX_REGISTER_TEST(test_raw_connection); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_cursor.cxx b/ext/libpqxx-7.7.3/test/unit/test_cursor.cxx deleted file mode 100644 index 8761f6946..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_cursor.cxx +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_stateless_cursor_provides_random_access(pqxx::connection &conn) -{ - pqxx::work tx{conn}; - pqxx::stateless_cursor< - pqxx::cursor_base::read_only, pqxx::cursor_base::owned> - c{tx, "SELECT * FROM generate_series(0, 3)", "count", false}; - - auto r{c.retrieve(1, 2)}; - PQXX_CHECK_EQUAL(std::size(r), 1, "Wrong number of rows from retrieve()."); - PQXX_CHECK_EQUAL(r[0][0].as(), 1, "Cursor retrieved wrong data."); - - r = c.retrieve(3, 10); - PQXX_CHECK_EQUAL(std::size(r), 1, "Expected 1 row retrieving past end."); - PQXX_CHECK_EQUAL(r[0][0].as(), 3, "Wrong data retrieved at end."); - - r = c.retrieve(0, 1); - PQXX_CHECK_EQUAL(std::size(r), 1, "Wrong number of rows back at beginning."); - PQXX_CHECK_EQUAL(r[0][0].as(), 0, "Wrong data back at beginning."); -} - - -void test_stateless_cursor_ignores_trailing_semicolon(pqxx::connection &conn) -{ - pqxx::work tx{conn}; - pqxx::stateless_cursor< - pqxx::cursor_base::read_only, pqxx::cursor_base::owned> - c{tx, "SELECT * FROM generate_series(0, 3) ;; ; \n \t ", "count", false}; - - auto r{c.retrieve(1, 2)}; - PQXX_CHECK_EQUAL(std::size(r), 1, "Trailing semicolon confused retrieve()."); -} - - -void test_cursor() -{ - pqxx::connection conn; - test_stateless_cursor_provides_random_access(conn); - test_stateless_cursor_ignores_trailing_semicolon(conn); -} - - -PQXX_REGISTER_TEST(test_cursor); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_encodings.cxx b/ext/libpqxx-7.7.3/test/unit/test_encodings.cxx deleted file mode 100644 index 4374671c6..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_encodings.cxx +++ /dev/null @@ -1,114 +0,0 @@ -#include "../test_helpers.hxx" - -#include "pqxx/internal/encodings.hxx" - - -namespace -{ -void test_scan_ascii() -{ - auto const scan{pqxx::internal::get_glyph_scanner( - pqxx::internal::encoding_group::MONOBYTE)}; - std::string const text{"hello"}; - - PQXX_CHECK_EQUAL( - scan(text.c_str(), std::size(text), 0), 1ul, - "Monobyte scanner acting up."); - PQXX_CHECK_EQUAL( - scan(text.c_str(), std::size(text), 1), 2ul, - "Monobyte scanner is inconsistent."); -} - - -void test_scan_utf8() -{ - auto const scan{ - pqxx::internal::get_glyph_scanner(pqxx::internal::encoding_group::UTF8)}; - - // Thai: "Khrab". - std::string const text{"\xe0\xb8\x95\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x9a"}; - PQXX_CHECK_EQUAL( - scan(text.c_str(), std::size(text), 0), 3ul, - "UTF-8 scanner mis-scanned Thai khor khwai."); - PQXX_CHECK_EQUAL( - scan(text.c_str(), std::size(text), 3), 6ul, - "UTF-8 scanner mis-scanned Thai ror reua."); -} - - -void test_for_glyphs_empty() -{ - bool iterated{false}; - pqxx::internal::for_glyphs( - pqxx::internal::encoding_group::MONOBYTE, - [&iterated](char const *, char const *) { iterated = true; }, "", 0); - PQXX_CHECK(!iterated, "Empty string went through an iteration."); -} - - -void test_for_glyphs_ascii() -{ - std::string const text{"hi"}; - std::vector points; - - pqxx::internal::for_glyphs( - pqxx::internal::encoding_group::UTF8, - [&points](char const *gbegin, char const *gend) { - points.push_back(gend - gbegin); - }, - text.c_str(), std::size(text)); - - PQXX_CHECK_EQUAL(std::size(points), 2u, "Wrong number of ASCII iterations."); - PQXX_CHECK_EQUAL(points[0], 1u, "ASCII iteration started off wrong."); - PQXX_CHECK_EQUAL(points[1], 1u, "ASCII iteration was inconsistent."); -} - - -void test_for_glyphs_utf8() -{ - // Greek: alpha omega. - std::string const text{"\xce\x91\xce\xa9"}; - std::vector points; - - pqxx::internal::for_glyphs( - pqxx::internal::encoding_group::UTF8, - [&points](char const *gbegin, char const *gend) { - points.push_back(gend - gbegin); - }, - text.c_str(), std::size(text)); - - PQXX_CHECK_EQUAL(std::size(points), 2u, "Wrong number of UTF-8 iterations."); - PQXX_CHECK_EQUAL(points[0], 2u, "UTF-8 iteration started off wrong."); - PQXX_CHECK_EQUAL(points[1], 2u, "ASCII iteration was inconsistent."); - - // Greek lambda, ASCII plus sign, Old Persian Gu. - std::string const mix{"\xce\xbb+\xf0\x90\x8e\xa6"}; - points.clear(); - - pqxx::internal::for_glyphs( - pqxx::internal::encoding_group::UTF8, - [&points](char const *gbegin, char const *gend) { - points.push_back(gend - gbegin); - }, - mix.c_str(), std::size(mix)); - - PQXX_CHECK_EQUAL(std::size(points), 3u, "Mixed UTF-8 iteration is broken."); - PQXX_CHECK_EQUAL(points[0], 2u, "Mixed UTF-8 iteration started off wrong."); - PQXX_CHECK_EQUAL(points[1], 1u, "Mixed UTF-8 iteration got ASCII wrong."); - PQXX_CHECK_EQUAL( - points[2], 4u, "Mixed UTF-8 iteration got long char wrong."); -} - - -void test_encodings() -{ - test_scan_ascii(); - test_scan_utf8(); - test_for_glyphs_empty(); - test_for_glyphs_ascii(); - test_for_glyphs_utf8(); -} - - -PQXX_REGISTER_TEST(test_encodings); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_error_verbosity.cxx b/ext/libpqxx-7.7.3/test/unit/test_error_verbosity.cxx deleted file mode 100644 index 67dc88763..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_error_verbosity.cxx +++ /dev/null @@ -1,37 +0,0 @@ -#include - -#include "../test_helpers.hxx" - -extern "C" -{ -#include -} - -namespace -{ -void test_error_verbosity() -{ - PQXX_CHECK_EQUAL( - static_cast(pqxx::error_verbosity::terse), - static_cast(PQERRORS_TERSE), - "error_verbosity enum should match PGVerbosity."); - PQXX_CHECK_EQUAL( - static_cast(pqxx::error_verbosity::normal), - static_cast(PQERRORS_DEFAULT), - "error_verbosity enum should match PGVerbosity."); - PQXX_CHECK_EQUAL( - static_cast(pqxx::error_verbosity::verbose), - static_cast(PQERRORS_VERBOSE), - "error_verbosity enum should match PGVerbosity."); - - pqxx::connection conn; - pqxx::work tx{conn}; - conn.set_verbosity(pqxx::error_verbosity::terse); - tx.exec1("SELECT 1"); - conn.set_verbosity(pqxx::error_verbosity::verbose); - tx.exec1("SELECT 2"); -} - - -PQXX_REGISTER_TEST(test_error_verbosity); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_errorhandler.cxx b/ext/libpqxx-7.7.3/test/unit/test_errorhandler.cxx deleted file mode 100644 index c2cd4a797..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_errorhandler.cxx +++ /dev/null @@ -1,223 +0,0 @@ -#include - -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -class TestErrorHandler final : public pqxx::errorhandler -{ -public: - TestErrorHandler( - pqxx::connection &c, std::vector &activated_handlers, - bool retval = true) : - pqxx::errorhandler(c), - return_value(retval), - message(), - handler_list(activated_handlers) - {} - - bool operator()(char const msg[]) noexcept override - { - message = std::string{msg}; - handler_list.push_back(this); - return return_value; - } - - bool return_value; - std::string message; - std::vector &handler_list; -}; -} // namespace - - -namespace pqxx -{ -template<> struct nullness -{ - // clang warns about these being unused. And clang 6 won't accept a - // [[maybe_unused]] attribute on them either! - - // static inline constexpr bool has_null{true}; - // static inline constexpr bool always_null{false}; - - static constexpr bool is_null(TestErrorHandler *e) noexcept - { - return e == nullptr; - } - static constexpr TestErrorHandler *null() noexcept { return nullptr; } -}; - - -template<> struct string_traits -{ - static constexpr std::size_t size_buffer(TestErrorHandler *const &) noexcept - { - return 100; - } - - static char *into_buf(char *begin, char *end, TestErrorHandler *const &value) - { - std::string text{"TestErrorHandler at " + pqxx::to_string(value)}; - if (pqxx::internal::cmp_greater_equal(std::size(text), end - begin)) - throw conversion_overrun{"Not enough buffer for TestErrorHandler."}; - std::memcpy(begin, text.c_str(), std::size(text) + 1); - return begin + std::size(text) + 1; - } -}; -} // namespace pqxx - - -namespace -{ -void test_process_notice_calls_errorhandler(pqxx::connection &c) -{ - std::vector dummy; - TestErrorHandler handler(c, dummy); - c.process_notice("Error!\n"); - PQXX_CHECK_EQUAL(handler.message, "Error!\n", "Error not handled."); -} - - -void test_error_handlers_get_called_newest_to_oldest(pqxx::connection &c) -{ - std::vector handlers; - TestErrorHandler h1(c, handlers); - TestErrorHandler h2(c, handlers); - TestErrorHandler h3(c, handlers); - c.process_notice("Warning.\n"); - PQXX_CHECK_EQUAL(h3.message, "Warning.\n", "Message not handled."); - PQXX_CHECK_EQUAL(h2.message, "Warning.\n", "Broken handling chain."); - PQXX_CHECK_EQUAL(h1.message, "Warning.\n", "Insane handling chain."); - PQXX_CHECK_EQUAL(std::size(handlers), 3u, "Wrong number of handler calls."); - PQXX_CHECK_EQUAL(&h3, handlers[0], "Unexpected handling order."); - PQXX_CHECK_EQUAL(&h2, handlers[1], "Insane handling order."); - PQXX_CHECK_EQUAL(&h1, handlers[2], "Impossible handling order."); -} - -void test_returning_false_stops_error_handling(pqxx::connection &c) -{ - std::vector handlers; - TestErrorHandler starved(c, handlers); - TestErrorHandler blocker(c, handlers, false); - c.process_notice("Error output.\n"); - PQXX_CHECK_EQUAL(std::size(handlers), 1u, "Handling chain was not stopped."); - PQXX_CHECK_EQUAL(handlers[0], &blocker, "Wrong handler got message."); - PQXX_CHECK_EQUAL(blocker.message, "Error output.\n", "Didn't get message."); - PQXX_CHECK_EQUAL(starved.message, "", "Message received; it shouldn't be."); -} - -void test_destroyed_error_handlers_are_not_called(pqxx::connection &c) -{ - std::vector handlers; - { - TestErrorHandler doomed(c, handlers); - } - c.process_notice("Unheard output."); - PQXX_CHECK( - std::empty(handlers), "Message was received on dead errorhandler."); -} - -void test_destroying_connection_unregisters_handlers() -{ - TestErrorHandler *survivor; - std::vector handlers; - { - pqxx::connection c; - survivor = new TestErrorHandler(c, handlers); - } - // Make some pointless use of survivor just to prove that this doesn't crash. - (*survivor)("Hi"); - PQXX_CHECK_EQUAL( - std::size(handlers), 1u, "Ghost of dead ex-connection haunts handler."); - delete survivor; -} - - -class MinimalErrorHandler final : public pqxx::errorhandler -{ -public: - explicit MinimalErrorHandler(pqxx::connection &c) : pqxx::errorhandler(c) {} - bool operator()(char const[]) noexcept override { return true; } -}; - - -void test_get_errorhandlers(pqxx::connection &c) -{ - std::unique_ptr eh3; - auto const handlers_before{c.get_errorhandlers()}; - std::size_t const base_handlers{std::size(handlers_before)}; - - { - MinimalErrorHandler eh1(c); - auto const handlers_with_eh1{c.get_errorhandlers()}; - PQXX_CHECK_EQUAL( - std::size(handlers_with_eh1), base_handlers + 1, - "Registering a handler didn't create exactly one handler."); - PQXX_CHECK_EQUAL( - std::size_t(*std::rbegin(handlers_with_eh1)), std::size_t(&eh1), - "Wrong handler or wrong order."); - - { - MinimalErrorHandler eh2(c); - auto const handlers_with_eh2{c.get_errorhandlers()}; - PQXX_CHECK_EQUAL( - std::size(handlers_with_eh2), base_handlers + 2, - "Adding second handler didn't work."); - PQXX_CHECK_EQUAL( - std::size_t(*(std::rbegin(handlers_with_eh2) + 1)), std::size_t(&eh1), - "Second handler upset order."); - PQXX_CHECK_EQUAL( - std::size_t(*std::rbegin(handlers_with_eh2)), std::size_t(&eh2), - "Second handler isn't right."); - } - auto const handlers_without_eh2{c.get_errorhandlers()}; - PQXX_CHECK_EQUAL( - std::size(handlers_without_eh2), base_handlers + 1, - "Handler destruction produced wrong-sized handlers list."); - PQXX_CHECK_EQUAL( - std::size_t(*std::rbegin(handlers_without_eh2)), std::size_t(&eh1), - "Destroyed wrong handler."); - - eh3 = std::make_unique(c); - auto const handlers_with_eh3{c.get_errorhandlers()}; - PQXX_CHECK_EQUAL( - std::size(handlers_with_eh3), base_handlers + 2, - "Remove-and-add breaks."); - PQXX_CHECK_EQUAL( - std::size_t(*std::rbegin(handlers_with_eh3)), std::size_t(eh3.get()), - "Added wrong third handler."); - } - auto const handlers_without_eh1{c.get_errorhandlers()}; - PQXX_CHECK_EQUAL( - std::size(handlers_without_eh1), base_handlers + 1, - "Destroying oldest handler didn't work as expected."); - PQXX_CHECK_EQUAL( - std::size_t(*std::rbegin(handlers_without_eh1)), std::size_t(eh3.get()), - "Destroyed wrong handler."); - - eh3.reset(); - - auto const handlers_without_all{c.get_errorhandlers()}; - PQXX_CHECK_EQUAL( - std::size(handlers_without_all), base_handlers, - "Destroying all custom handlers didn't work as expected."); -} - - -void test_errorhandler() -{ - pqxx::connection conn; - test_process_notice_calls_errorhandler(conn); - test_error_handlers_get_called_newest_to_oldest(conn); - test_returning_false_stops_error_handling(conn); - test_destroyed_error_handlers_are_not_called(conn); - test_destroying_connection_unregisters_handlers(); - test_get_errorhandlers(conn); -} - - -PQXX_REGISTER_TEST(test_errorhandler); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_escape.cxx b/ext/libpqxx-7.7.3/test/unit/test_escape.cxx deleted file mode 100644 index baff4d62c..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_escape.cxx +++ /dev/null @@ -1,228 +0,0 @@ -#include - -#include - -#include "../test_helpers.hxx" - -namespace -{ -using namespace std::literals; - - -void compare_esc( - pqxx::connection &c, pqxx::transaction_base &t, char const text[]) -{ - std::size_t const len{std::size(std::string{text})}; - PQXX_CHECK_EQUAL( - c.esc(std::string_view{text, len}), t.esc(std::string_view{text, len}), - "Connection & transaction escape differently."); - - PQXX_CHECK_EQUAL( - t.esc(std::string_view{text, len}), t.esc(text), - "Length argument to esc() changes result."); - - PQXX_CHECK_EQUAL( - t.esc(std::string{text}), t.esc(text), - "esc(std::string()) differs from esc(char const[])."); - - PQXX_CHECK_EQUAL( - text, - t.query_value( - "SELECT '" + t.esc(std::string_view{text, len}) + "'"), - "esc() is not idempotent."); - - PQXX_CHECK_EQUAL( - t.esc(std::string_view{text, len}), t.esc(text), - "Oversized buffer affects esc()."); -} - - -void test_esc(pqxx::connection &c, pqxx::transaction_base &t) -{ - PQXX_CHECK_EQUAL( - t.esc(std::string_view{"", 0}), "", - "Empty string doesn't escape properly."); - PQXX_CHECK_EQUAL( - t.esc(std::string_view{"'", 1}), "''", - "Single quote escaped incorrectly."); - PQXX_CHECK_EQUAL( - t.esc(std::string_view{"hello"}), "hello", "Trivial escape went wrong."); - char const *const escstrings[]{"x", " ", "", nullptr}; - for (std::size_t i{0}; escstrings[i] != nullptr; ++i) - compare_esc(c, t, escstrings[i]); -} - - -void test_quote(pqxx::connection &c, pqxx::transaction_base &t) -{ - PQXX_CHECK_EQUAL(t.quote("x"), "'x'", "Basic quote() fails."); - PQXX_CHECK_EQUAL( - t.quote(1), "'1'", "quote() not dealing with int properly."); - PQXX_CHECK_EQUAL(t.quote(0), "'0'", "Quoting zero is a problem."); - char const *const null_ptr{nullptr}; - PQXX_CHECK_EQUAL(t.quote(null_ptr), "NULL", "Not quoting NULL correctly."); - PQXX_CHECK_EQUAL( - t.quote(std::string{"'"}), "''''", "Escaping quotes goes wrong."); - - PQXX_CHECK_EQUAL( - t.quote("x"), c.quote("x"), - "Connection and transaction quote differently."); - - char const *test_strings[]{"", "x", "\\", "\\\\", "'", - "''", "\\'", "\t", "\n", nullptr}; - - for (std::size_t i{0}; test_strings[i] != nullptr; ++i) - { - auto r{t.query_value("SELECT " + t.quote(test_strings[i]))}; - PQXX_CHECK_EQUAL( - r, test_strings[i], "Selecting quoted string does not come back equal."); - } -} - - -void test_quote_name(pqxx::transaction_base &t) -{ - PQXX_CHECK_EQUAL( - "\"A b\"", t.quote_name("A b"), "Escaped identifier is not as expected."); - PQXX_CHECK_EQUAL( - std::string{"A b"}, - t.exec("SELECT 1 AS " + t.quote_name("A b")).column_name(0), - "Escaped identifier does not work in SQL."); -} - - -void test_esc_raw_unesc_raw(pqxx::transaction_base &t) -{ - constexpr char binary[]{"1\0023\\4x5"}; - std::basic_string const data( - reinterpret_cast(binary), std::size(binary)); - std::string const escaped{t.esc_raw( - std::basic_string_view{std::data(data), std::size(binary)})}; - - for (auto const i : escaped) - { - PQXX_CHECK_GREATER( - static_cast(static_cast(i)), 7u, - "Non-ASCII character in escaped data: " + escaped); - PQXX_CHECK_LESS( - static_cast(static_cast(i)), 127u, - "Non-ASCII character in escaped data: " + escaped); - } - - for (auto const i : escaped) - PQXX_CHECK( - isprint(i), "Unprintable character in escaped data: " + escaped); - - PQXX_CHECK_EQUAL( - escaped, "\\x3102335c34783500", "Binary data escaped wrong."); - PQXX_CHECK_EQUAL( - std::size(t.unesc_bin(escaped)), std::size(data), - "Wrong size after unescaping."); - auto unescaped{t.unesc_bin(escaped)}; - PQXX_CHECK_EQUAL( - std::size(unescaped), std::size(data), - "Unescaping did not restore original size."); - for (std::size_t i{0}; i < std::size(unescaped); ++i) - PQXX_CHECK_EQUAL( - int(unescaped[i]), int(data[i]), - "Unescaping binary data did not restore byte #" + pqxx::to_string(i) + - "."); -} - - -void test_esc_like(pqxx::transaction_base &tx) -{ - PQXX_CHECK_EQUAL(tx.esc_like(""), "", "esc_like breaks on empty string."); - PQXX_CHECK_EQUAL(tx.esc_like("abc"), "abc", "esc_like is broken."); - PQXX_CHECK_EQUAL(tx.esc_like("_"), "\\_", "esc_like fails on underscore."); - PQXX_CHECK_EQUAL(tx.esc_like("%"), "\\%", "esc_like fails on %."); - PQXX_CHECK_EQUAL( - tx.esc_like("a%b_c"), "a\\%b\\_c", "esc_like breaks on mix."); - PQXX_CHECK_EQUAL( - tx.esc_like("_", '+'), "+_", "esc_like ignores escape character."); -} - - -void test_escaping() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - test_esc(conn, tx); - test_quote(conn, tx); - test_quote_name(tx); - test_esc_raw_unesc_raw(tx); - test_esc_like(tx); -} - - -void test_esc_escapes_into_buffer() -{ -#if defined(PQXX_HAVE_CONCEPTS) - pqxx::connection conn; - pqxx::work tx{conn}; - - std::string buffer; - buffer.resize(20); - - auto const text{"Ain't"sv}; - auto escaped_text{tx.esc(text, buffer)}; - PQXX_CHECK_EQUAL(escaped_text, "Ain''t", "Escaping into buffer went wrong."); - - std::basic_string const data{std::byte{0x22}, std::byte{0x43}}; - auto escaped_data(tx.esc(data, buffer)); - PQXX_CHECK_EQUAL(escaped_data, "\\x2243", "Binary data escaped wrong."); -#endif -} - - -void test_esc_accepts_various_types() -{ -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - pqxx::connection conn; - pqxx::work tx{conn}; - - std::string buffer; - buffer.resize(20); - - std::string const text{"it's"}; - auto escaped_text{tx.esc(text, buffer)}; - PQXX_CHECK_EQUAL(escaped_text, "it''s", "Escaping into buffer went wrong."); - - std::vector const data{std::byte{0x23}, std::byte{0x44}}; - auto escaped_data(tx.esc(data, buffer)); - PQXX_CHECK_EQUAL(escaped_data, "\\x2344", "Binary data escaped wrong."); -#endif -} - - -void test_binary_esc_checks_buffer_length() -{ -#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN) - pqxx::connection conn; - pqxx::work tx{conn}; - - std::string buf; - std::basic_string bin{ - std::byte{'b'}, std::byte{'o'}, std::byte{'o'}}; - - buf.resize(2 * std::size(bin) + 3); - pqxx::ignore_unused(tx.esc(bin, buf)); - PQXX_CHECK_EQUAL(int{buf[0]}, int{'\\'}, "Unexpected binary escape format."); - PQXX_CHECK_NOT_EQUAL( - int(buf[std::size(buf) - 2]), int('\0'), "Escaped binary ends too soon."); - PQXX_CHECK_EQUAL( - int(buf[std::size(buf) - 1]), int('\0'), "Terminating zero is missing."); - - buf.resize(2 * std::size(bin) + 2); - PQXX_CHECK_THROWS( - pqxx::ignore_unused(tx.esc(bin, buf)), pqxx::range_error, - "Didn't get expected exception from escape overrun."); -#endif -} - - -PQXX_REGISTER_TEST(test_escaping); -PQXX_REGISTER_TEST(test_esc_escapes_into_buffer); -PQXX_REGISTER_TEST(test_esc_accepts_various_types); -PQXX_REGISTER_TEST(test_binary_esc_checks_buffer_length); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_exceptions.cxx b/ext/libpqxx-7.7.3/test/unit/test_exceptions.cxx deleted file mode 100644 index 4b84b7fba..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_exceptions.cxx +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - - -namespace -{ -void test_exceptions() -{ - std::string const broken_query{"SELECT HORRIBLE ERROR"}, - err{"Error message"}; - - try - { - throw pqxx::sql_error{err, broken_query}; - } - catch (std::exception const &e) - { - PQXX_CHECK_EQUAL(e.what(), err, "Exception contains wrong message."); - auto downcast{dynamic_cast(&e)}; - PQXX_CHECK( - downcast != nullptr, "exception-to-sql_error downcast is broken."); - PQXX_CHECK_EQUAL( - downcast->query(), broken_query, - "Getting query from pqxx exception is broken."); - } - - pqxx::connection conn; - pqxx::work tx{conn}; - try - { - tx.exec("INVALID QUERY HERE"); - } - catch (pqxx::syntax_error const &e) - { - // SQL syntax error has sqlstate error 42601. - PQXX_CHECK_EQUAL( - e.sqlstate(), "42601", "Unexpected sqlstate on syntax error."); - } -} - - -PQXX_REGISTER_TEST(test_exceptions); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_field.cxx b/ext/libpqxx-7.7.3/test/unit/test_field.cxx deleted file mode 100644 index 013ea1a82..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_field.cxx +++ /dev/null @@ -1,57 +0,0 @@ -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_field() -{ - pqxx::connection c; - pqxx::work tx{c}; - auto const r1{tx.exec1("SELECT 9")}; - auto const &f1{r1[0]}; - - PQXX_CHECK_EQUAL(f1.as(), "9", "as() is broken."); - PQXX_CHECK_EQUAL( - f1.as("z"), "9", "as(string) is broken."); - - PQXX_CHECK_EQUAL(f1.as(), 9, "as() is broken."); - PQXX_CHECK_EQUAL(f1.as(10), 9, "as(int) is broken."); - - std::string s; - PQXX_CHECK(f1.to(s), "to(string) failed."); - PQXX_CHECK_EQUAL(s, "9", "to(string) is broken."); - s = "x"; - PQXX_CHECK(f1.to(s, std::string{"7"}), "to(string, string) failed."); - PQXX_CHECK_EQUAL(s, "9", "to(string, string) is broken."); - - int i{}; - PQXX_CHECK(f1.to(i), "to(int) failed."); - PQXX_CHECK_EQUAL(i, 9, "to(int) is broken."); - i = 8; - PQXX_CHECK(f1.to(i, 12), "to(int, int) failed."); - PQXX_CHECK_EQUAL(i, 9, "to(int, int) is broken."); - - auto const r2{tx.exec1("SELECT NULL")}; - auto const f2{r2[0]}; - i = 100; - PQXX_CHECK_THROWS( - f2.as(), pqxx::conversion_error, "Null conversion failed to throw."); - PQXX_CHECK_EQUAL(i, 100, "Null conversion touched its output."); - - PQXX_CHECK_EQUAL(f2.as(66), 66, "as default is broken."); - - PQXX_CHECK(!(f2.to(i)), "to(int) failed to report a null."); - PQXX_CHECK(!(f2.to(i, 54)), "to(int, int) failed to report a null."); - PQXX_CHECK_EQUAL(i, 54, "to(int, int) failed to default."); - - auto const r3{tx.exec("SELECT generate_series(1, 5)")}; - PQXX_CHECK_EQUAL(r3.at(3, 0).as(), 4, "Two-argument at() went wrong."); -#if defined(PQXX_HAVE_MULTIDIMENSIONAL_SUBSCRIPT) - PQXX_CHECK_EQUAL((r3[3, 0].as()), 4, "Two-argument [] went wrong."); -#endif -} - - -PQXX_REGISTER_TEST(test_field); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_float.cxx b/ext/libpqxx-7.7.3/test/unit/test_float.cxx deleted file mode 100644 index a0463e4d0..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_float.cxx +++ /dev/null @@ -1,175 +0,0 @@ -#include - -#include - -#include "../test_helpers.hxx" - -namespace -{ -/// Test conversions for some floating-point type. -template void infinity_test() -{ - T inf{std::numeric_limits::infinity()}; - std::string inf_string; - T back_conversion; - - inf_string = pqxx::to_string(inf); - pqxx::from_string(inf_string, back_conversion); - PQXX_CHECK_LESS( - T(999999999), back_conversion, - "Infinity doesn't convert back to something huge."); - - inf_string = pqxx::to_string(-inf); - pqxx::from_string(inf_string, back_conversion); - PQXX_CHECK_LESS( - back_conversion, -T(999999999), "Negative infinity is broken"); -} - -void test_infinities() -{ - infinity_test(); - infinity_test(); - infinity_test(); -} - - -/// Reproduce bug #262: repeated float conversions break without charconv. -template void bug_262() -{ - pqxx::connection conn; - conn.prepare("stmt", "select cast($1 as float)"); - pqxx::work tr{conn}; - - // We must use the same float type both for passing the value to the - // statement and for retrieving result of the statement execution. This is - // due to an internal stringstream being instantiated as a a parameterized - // thread-local singleton. So, there are separate stream, - // stream, stream, but every such instance is a - // singleton. We should use only one of them for this test. - - pqxx::row row; - - // Nothing bad here, select a float value. - // The stream is clear, so just fill it with the value and extract str(). - row = tr.exec1("SELECT 1.0"); - - // This works properly, but as we parse the value from the stream, the - // seeking cursor moves towards the EOF. When the inevitable EOF happens - // 'eof' flag is set in the stream and 'good' flag is unset. - row[0].as(); - - // The second try. Select a float value again. The stream is not clean, so - // we need to put an empty string into its buffer {stream.str("");}. This - // resets the seeking cursor to 0. Then we will put the value using - // operator<<(). - // ... - // ... - // OOPS. stream.str("") does not reset 'eof' flag and 'good' flag! We are - // trying to read from EOF! This is no good. - // Throws on unpatched pqxx v6.4.5 - row = tr.exec1("SELECT 2.0"); - - // We won't get here without patch. The following statements are just for - // demonstration of how are intended to work. If we - // simply just reset the stream flags properly, this would work fine. - // The most obvious patch is just explicitly stream.seekg(0). - row[0].as(); - row = tr.exec1("SELECT 3.0"); - row[0].as(); -} - - -/// Test for bug #262. -void test_bug_262() -{ - bug_262(); - bug_262(); - bug_262(); -} - - -/// Test conversion of malformed floating-point values. -void test_bad_float() -{ - float x [[maybe_unused]]; - PQXX_CHECK_THROWS( - x = pqxx::from_string(""), pqxx::conversion_error, - "Conversion of empty string to float was not caught."); - - PQXX_CHECK_THROWS( - x = pqxx::from_string("Infancy"), pqxx::conversion_error, - "Misleading infinity was not caught."); - PQXX_CHECK_THROWS( - x = pqxx::from_string("-Infighting"), pqxx::conversion_error, - "Misleading negative infinity was not caught."); - - PQXX_CHECK_THROWS( - x = pqxx::from_string("Nanny"), pqxx::conversion_error, - "Conversion of misleading NaN was not caught."); -} - - -template void test_float_length(T value) -{ - auto const text{pqxx::to_string(value)}; - PQXX_CHECK_GREATER_EQUAL( - pqxx::size_buffer(value), std::size(text) + 1, - "Not enough buffer space for " + text + "."); -} - - -/// Test conversion of long float values to strings. -void test_long_float() -{ - test_float_length(0.1f); - test_float_length(0.1); - - test_float_length(std::numeric_limits::denorm_min()); - test_float_length(-std::numeric_limits::denorm_min()); - test_float_length(std::numeric_limits::min()); - test_float_length(-std::numeric_limits::min()); - test_float_length(std::numeric_limits::max()); - test_float_length(-std::numeric_limits::max()); - test_float_length(-std::nextafter(1.0f, 2.0f)); - - test_float_length(std::numeric_limits::denorm_min()); - test_float_length(-std::numeric_limits::denorm_min()); - test_float_length(std::numeric_limits::min()); - test_float_length(-std::numeric_limits::min()); - test_float_length(std::numeric_limits::max()); - test_float_length(-std::numeric_limits::max()); - test_float_length(-std::nextafter(1.0, 2.0)); - - test_float_length(std::numeric_limits::denorm_min()); - test_float_length(-std::numeric_limits::denorm_min()); - test_float_length(std::numeric_limits::min()); - test_float_length(-std::numeric_limits::min()); - test_float_length(std::numeric_limits::max()); - test_float_length(-std::numeric_limits::max()); - test_float_length(-std::nextafter(1.0L, 2.0L)); - - // Ahem. I'm not proud of this. We really can't assume much about the - // floating-point types, but I'd really like to try a few things to see that - // buffer sizes are in the right ballpark. So, if "double" is at least 64 - // bits, check for some examples of long conversions. - if constexpr (sizeof(double) >= 8) - { - auto constexpr awkward{-2.2250738585072014e-308}; - auto const text{pqxx::to_string(awkward)}; - PQXX_CHECK_LESS_EQUAL( - std::size(text), 25u, text + " converted to too long a string."); - } - if constexpr (sizeof(double) <= 8) - { - auto const text{pqxx::to_string(0.99)}; - PQXX_CHECK_LESS_EQUAL( - pqxx::size_buffer(0.99), 25u, text + " converted to too long a string."); - } -} - - -PQXX_REGISTER_TEST(test_infinities); -PQXX_REGISTER_TEST(test_bug_262); -PQXX_REGISTER_TEST(test_bad_float); -PQXX_REGISTER_TEST(test_long_float); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_largeobject.cxx b/ext/libpqxx-7.7.3/test/unit/test_largeobject.cxx deleted file mode 100644 index 8184fa2f8..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_largeobject.cxx +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include - -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_stream_large_object() -{ - pqxx::connection conn; - - // Construct a really nasty string. (Don't just construct a std::string from - // a char[] constant, because it'll terminate at the embedded zero.) - // - // The crucial thing is the "ff" byte at the beginning. It tests for - // possible conflation between "eof" (-1) and a char which just happens to - // have the same bit pattern as an 8-bit value of -1. This conflation can be - // a problem when it occurs at buffer boundaries. - constexpr char bytes[]{"\xff\0end"}; - std::string const contents{bytes, std::size(bytes)}; - - pqxx::work tx{conn}; -#include "pqxx/internal/ignore-deprecated-pre.hxx" - pqxx::largeobject new_obj{tx}; - - pqxx::olostream write{tx, new_obj}; - write << contents; - write.flush(); - - pqxx::largeobjectaccess check{tx, new_obj, std::ios::in | std::ios::binary}; - std::array buf; - std::size_t const len{ - static_cast(check.read(std::data(buf), std::size(buf)))}; - PQXX_CHECK_EQUAL(len, std::size(contents), "olostream truncated data."); - std::string const check_str{std::data(buf), len}; - PQXX_CHECK_EQUAL(check_str, contents, "olostream mangled data."); - - pqxx::ilostream read{tx, new_obj}; - std::string read_back; - std::string chunk; - while (read >> chunk) read_back += chunk; - - new_obj.remove(tx); - - PQXX_CHECK_EQUAL(read_back, contents, "Got wrong data from ilostream."); - PQXX_CHECK_EQUAL( - std::size(read_back), std::size(contents), "ilostream truncated data."); - PQXX_CHECK_EQUAL( - std::size(read_back), std::size(bytes), "ilostream truncated data."); -#include "pqxx/internal/ignore-deprecated-post.hxx" -} - - -PQXX_REGISTER_TEST(test_stream_large_object); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_nonblocking_connect.cxx b/ext/libpqxx-7.7.3/test/unit/test_nonblocking_connect.cxx deleted file mode 100644 index d1a32ac64..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_nonblocking_connect.cxx +++ /dev/null @@ -1,27 +0,0 @@ -#include - -#include - -#include "../test_helpers.hxx" - - -namespace -{ -void test_nonblocking_connect() -{ - pqxx::connecting nbc; - while (not nbc.done()) - { - pqxx::internal::wait_fd( - nbc.sock(), nbc.wait_to_read(), nbc.wait_to_write()); - nbc.process(); - } - - pqxx::connection conn{std::move(nbc).produce()}; - pqxx::work tx{conn}; - PQXX_CHECK_EQUAL(tx.query_value("SELECT 10"), 10, "Bad value!?"); -} - - -PQXX_REGISTER_TEST(test_nonblocking_connect); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_notification.cxx b/ext/libpqxx-7.7.3/test/unit/test_notification.cxx deleted file mode 100644 index 6487169b4..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_notification.cxx +++ /dev/null @@ -1,86 +0,0 @@ -#include - -#include - -#include - -#include - -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -class TestReceiver final : public pqxx::notification_receiver -{ -public: - std::string payload; - int backend_pid; - - TestReceiver(pqxx::connection &c, std::string const &channel_name) : - pqxx::notification_receiver(c, channel_name), - payload(), - backend_pid(0) - {} - - virtual void - operator()(std::string const &payload_string, int backend) override - { - this->payload = payload_string; - this->backend_pid = backend; - } -}; - - -void test_receive( - pqxx::transaction_base &t, std::string const &channel, - char const payload[] = nullptr) -{ - pqxx::connection &conn(t.conn()); - - std::string SQL{"NOTIFY \"" + channel + "\""}; - if (payload != nullptr) - SQL += ", " + t.quote(payload); - - TestReceiver receiver{t.conn(), channel}; - - // Clear out any previously pending notifications that might otherwise - // confuse the test. - conn.get_notifs(); - - // Notify, and receive. - t.exec(SQL); - t.commit(); - - int notifs{0}; - for (int i{0}; (i < 10) and (notifs == 0); - ++i, pqxx::internal::wait_for(1'000'000u)) - notifs = conn.get_notifs(); - - PQXX_CHECK_EQUAL(notifs, 1, "Got wrong number of notifications."); - PQXX_CHECK_EQUAL(receiver.backend_pid, conn.backendpid(), "Bad pid."); - if (payload == nullptr) - PQXX_CHECK(std::empty(receiver.payload), "Unexpected payload."); - else - PQXX_CHECK_EQUAL(receiver.payload, payload, "Bad payload."); -} - - -void test_notification() -{ - pqxx::connection conn; - TestReceiver receiver(conn, "mychannel"); - PQXX_CHECK_EQUAL(receiver.channel(), "mychannel", "Bad channel."); - - pqxx::work tx{conn}; - test_receive(tx, "channel1"); - - pqxx::nontransaction u(conn); - test_receive(u, "channel2", "payload"); -} - - -PQXX_REGISTER_TEST(test_notification); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_pipeline.cxx b/ext/libpqxx-7.7.3/test/unit/test_pipeline.cxx deleted file mode 100644 index 63b97662b..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_pipeline.cxx +++ /dev/null @@ -1,64 +0,0 @@ -#include - -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_pipeline() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - // A pipeline grabs transaction focus, blocking regular queries and such. - pqxx::pipeline pipe(tx, "test_pipeline_detach"); - PQXX_CHECK_THROWS( - tx.exec("SELECT 1"), std::logic_error, - "Pipeline does not block regular queries"); - - // Flushing a pipeline relinquishes transaction focus. - pipe.flush(); - auto r{tx.exec("SELECT 2")}; - PQXX_CHECK_EQUAL( - std::size(r), 1, "Wrong query result after flushing pipeline."); - PQXX_CHECK_EQUAL( - r[0][0].as(), 2, "Query returns wrong data after flushing pipeline."); - - // Inserting a query makes the pipeline grab transaction focus back. - auto q{pipe.insert("SELECT 2")}; - PQXX_CHECK_THROWS( - tx.exec("SELECT 3"), std::logic_error, - "Pipeline does not block regular queries"); - - // Invoking complete() also detaches the pipeline from the transaction. - pipe.complete(); - r = tx.exec("SELECT 4"); - PQXX_CHECK_EQUAL(std::size(r), 1, "Wrong query result after complete()."); - PQXX_CHECK_EQUAL( - r[0][0].as(), 4, "Query returns wrong data after complete()."); - - // The complete() also received any pending query results from the backend. - r = pipe.retrieve(q); - PQXX_CHECK_EQUAL(std::size(r), 1, "Wrong result from pipeline."); - PQXX_CHECK_EQUAL(r[0][0].as(), 2, "Pipeline returned wrong data."); - - // We can cancel while the pipe is empty, and things will still work. - pipe.cancel(); - - // Issue a query and cancel it. Measure time to see that we don't really - // wait. - using clock = std::chrono::steady_clock; - auto const start{clock::now()}; - pipe.retain(0); - pipe.insert("pg_sleep(10)"); - pipe.cancel(); - auto const finish{clock::now()}; - auto const seconds{ - std::chrono::duration_cast(finish - start).count()}; - PQXX_CHECK_LESS(seconds, 5, "Canceling a sleep took suspiciously long."); -} -} // namespace - -PQXX_REGISTER_TEST(test_pipeline); diff --git a/ext/libpqxx-7.7.3/test/unit/test_prepared_statement.cxx b/ext/libpqxx-7.7.3/test/unit/test_prepared_statement.cxx deleted file mode 100644 index c9eb4ee84..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_prepared_statement.cxx +++ /dev/null @@ -1,334 +0,0 @@ -#include -#include -#include -#include - -#include - -#include "../test_helpers.hxx" - -// Test program for libpqxx. Define and use prepared statements. - -#define COMPARE_RESULTS(name, lhs, rhs) \ - PQXX_CHECK_EQUAL( \ - rhs, lhs, \ - "Executing " name " as prepared statement yields different results."); - -namespace -{ -using namespace std::literals; - - -template std::string stringize(pqxx::transaction_base &t, T i) -{ - return stringize(t, pqxx::to_string(i)); -} - - -// Substitute variables in raw query. This is not likely to be very robust, -// but it should do for just this test. The main shortcomings are escaping, -// and not knowing when to quote the variables. -// Note we do the replacement backwards (meaning forward_only iterators won't -// do!) to avoid substituting e.g. "$12" as "$1" first. -template -std::string -subst(pqxx::transaction_base &t, std::string q, ITER patbegin, ITER patend) -{ - ptrdiff_t i{distance(patbegin, patend)}; - for (ITER arg{patend}; i > 0; --i) - { - --arg; - std::string const marker{"$" + pqxx::to_string(i)}, - var{stringize(t, *arg)}; - std::string::size_type const msz{std::size(marker)}; - while (q.find(marker) != std::string::npos) - q.replace(q.find(marker), msz, var); - } - return q; -} - - -template -std::string -subst(pqxx::transaction_base &t, std::string const &q, CNTNR const &patterns) -{ - return subst(t, q, std::begin(patterns), std::end(patterns)); -} - - -void test_registration_and_invocation() -{ - constexpr auto count_to_5{"SELECT * FROM generate_series(1, 5)"}; - - pqxx::connection c; - pqxx::work tx1{c}; - - // Prepare a simple statement. - tx1.conn().prepare("CountToFive", count_to_5); - - // The statement returns exactly what you'd expect. - COMPARE_RESULTS( - "CountToFive", tx1.exec_prepared("CountToFive"), tx1.exec(count_to_5)); - - // Re-preparing it is an error. - PQXX_CHECK_THROWS( - tx1.conn().prepare("CountToFive", count_to_5), pqxx::sql_error, - "Did not report re-definition of prepared statement."); - - tx1.abort(); - pqxx::work tx2{c}; - - // Executing a nonexistent prepared statement is also an error. - PQXX_CHECK_THROWS( - tx2.exec_prepared("NonexistentStatement"), pqxx::sql_error, - "Did not report invocation of nonexistent prepared statement."); -} - - -void test_basic_args() -{ - pqxx::connection c; - c.prepare("EchoNum", "SELECT $1::int"); - pqxx::work tx{c}; - auto r{tx.exec_prepared("EchoNum", 7)}; - PQXX_CHECK_EQUAL( - std::size(r), 1, "Did not get 1 row from prepared statement."); - PQXX_CHECK_EQUAL(std::size(r.front()), 1, "Did not get exactly one column."); - PQXX_CHECK_EQUAL(r[0][0].as(), 7, "Got wrong result."); - - auto rw{tx.exec_prepared1("EchoNum", 8)}; - PQXX_CHECK_EQUAL( - std::size(rw), 1, "Did not get 1 column from exec_prepared1."); - PQXX_CHECK_EQUAL(rw[0].as(), 8, "Got wrong result."); -} - - -void test_multiple_params() -{ - pqxx::connection c; - c.prepare("CountSeries", "SELECT * FROM generate_series($1::int, $2::int)"); - pqxx::work tx{c}; - auto r{tx.exec_prepared_n(4, "CountSeries", 7, 10)}; - PQXX_CHECK_EQUAL( - std::size(r), 4, "Wrong number of rows, but no error raised."); - PQXX_CHECK_EQUAL(r.front().front().as(), 7, "Wrong $1."); - PQXX_CHECK_EQUAL(r.back().front().as(), 10, "Wrong $2."); - - c.prepare("Reversed", "SELECT * FROM generate_series($2::int, $1::int)"); - r = tx.exec_prepared_n(3, "Reversed", 8, 6); - PQXX_CHECK_EQUAL( - r.front().front().as(), 6, "Did parameters get reordered?"); - PQXX_CHECK_EQUAL( - r.back().front().as(), 8, "$2 did not come through properly."); -} - - -void test_nulls() -{ - pqxx::connection c; - pqxx::work tx{c}; - c.prepare("EchoStr", "SELECT $1::varchar"); - auto rw{tx.exec_prepared1("EchoStr", nullptr)}; - PQXX_CHECK(rw.front().is_null(), "nullptr did not translate to null."); - - char const *n{nullptr}; - rw = tx.exec_prepared1("EchoStr", n); - PQXX_CHECK(rw.front().is_null(), "Null pointer did not translate to null."); -} - - -void test_strings() -{ - pqxx::connection c; - pqxx::work tx{c}; - c.prepare("EchoStr", "SELECT $1::varchar"); - auto rw{tx.exec_prepared1("EchoStr", "foo")}; - PQXX_CHECK_EQUAL( - rw.front().as(), "foo", "Wrong string result."); - - char const nasty_string[]{R"--('\"\)--"}; - rw = tx.exec_prepared1("EchoStr", nasty_string); - PQXX_CHECK_EQUAL( - rw.front().as(), std::string(nasty_string), - "Prepared statement did not quote/escape correctly."); - - rw = tx.exec_prepared1("EchoStr", std::string{nasty_string}); - PQXX_CHECK_EQUAL( - rw.front().as(), std::string(nasty_string), - "Quoting/escaping went wrong in std::string."); - - char nonconst[]{"non-const C string"}; - rw = tx.exec_prepared1("EchoStr", nonconst); - PQXX_CHECK_EQUAL( - rw.front().as(), std::string(nonconst), - "Non-const C string passed incorrectly."); -} - - -void test_binary() -{ - pqxx::connection c; - pqxx::work tx{c}; - c.prepare("EchoBin", "SELECT $1::bytea"); - constexpr char raw_bytes[]{"Binary\0bytes'\"with\tweird\xff bytes"}; - std::string const input{raw_bytes, std::size(raw_bytes)}; - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - { - pqxx::binarystring const bin{input}; - auto rw{tx.exec_prepared1("EchoBin", bin)}; - PQXX_CHECK_EQUAL( - pqxx::binarystring(rw[0]).str(), input, - "Binary string came out damaged."); - } -#include "pqxx/internal/ignore-deprecated-post.hxx" - - { - std::basic_string bytes{ - reinterpret_cast(raw_bytes), std::size(raw_bytes)}; - auto bp{tx.exec_prepared1("EchoBin", bytes)}; - auto bval{bp[0].as>()}; - PQXX_CHECK_EQUAL( - (std::string_view{ - reinterpret_cast(bval.c_str()), std::size(bval)}), - input, "Binary string parameter went wrong."); - } - - // Now try it with a complex type that ultimately uses the conversions of - // std::basic_string, but complex enough that the call may - // convert the data to a text string on the libpqxx side. Which would be - // okay, except of course it's likely to be slower. - - { - auto ptr{std::make_shared>( - reinterpret_cast(raw_bytes), std::size(raw_bytes))}; - auto rp{tx.exec_prepared1("EchoBin", ptr)}; - auto pval{rp[0].as>()}; - PQXX_CHECK_EQUAL( - (std::string_view{ - reinterpret_cast(pval.c_str()), std::size(pval)}), - input, "Binary string as shared_ptr-to-optional went wrong."); - } - - { - auto opt{std::optional>{ - std::in_place, reinterpret_cast(raw_bytes), - std::size(raw_bytes)}}; - auto op{tx.exec_prepared1("EchoBin", opt)}; - auto oval{op[0].as>()}; - PQXX_CHECK_EQUAL( - (std::string_view{ - reinterpret_cast(oval.c_str()), std::size(oval)}), - input, "Binary string as shared_ptr-to-optional went wrong."); - } - -#if defined(PQXX_HAVE_CONCEPTS) - // By the way, it doesn't have to be a std::basic_string. Any contiguous - // range will do. - { - std::vector data{std::byte{'x'}, std::byte{'v'}}; - auto op{tx.exec_prepared1("EchoBin", data)}; - auto oval{op[0].as>()}; - PQXX_CHECK_EQUAL( - std::size(oval), 2u, "Binary data came back as wrong length."); - PQXX_CHECK_EQUAL(static_cast(oval[0]), int('x'), "Wrong data."); - PQXX_CHECK_EQUAL(static_cast(oval[1]), int('v'), "Wrong data."); - } -#endif -} - - -void test_params() -{ - pqxx::connection c; - pqxx::work tx{c}; - c.prepare("Concat2Numbers", "SELECT 10 * $1 + $2"); - std::vector values{3, 9}; - pqxx::params params; - params.reserve(std::size(values)); - params.append_multi(values); - - auto const rw39{tx.exec_prepared1("Concat2Numbers", params)}; - PQXX_CHECK_EQUAL( - rw39.front().as(), 39, - "Dynamic prepared-statement parameters went wrong."); - - c.prepare("Concat4Numbers", "SELECT 1000*$1 + 100*$2 + 10*$3 + $4"); - auto const rw1396{tx.exec_prepared1("Concat4Numbers", 1, params, 6)}; - PQXX_CHECK_EQUAL( - rw1396.front().as(), 1396, - "Dynamic params did not interleave with static ones properly."); -} - - -void test_optional() -{ - pqxx::connection c; - pqxx::work tx{c}; - c.prepare("EchoNum", "SELECT $1::int"); - pqxx::row rw{ - tx.exec_prepared1("EchoNum", std::optional{std::in_place, 10})}; - PQXX_CHECK_EQUAL( - rw.front().as(), 10, - "optional (with value) did not return the right value."); - - rw = tx.exec_prepared1("EchoNum", std::optional{}); - PQXX_CHECK( - rw.front().is_null(), "optional without value did not come out as null."); -} - - -void test_prepared_statements() -{ - test_registration_and_invocation(); - test_basic_args(); - test_multiple_params(); - test_nulls(); - test_strings(); - test_binary(); - test_params(); - - test_optional(); -} - - -void test_placeholders_generates_names() -{ - using pqxx::operator""_zv; - pqxx::placeholders name; - PQXX_CHECK_EQUAL(name.view(), "$1"_zv, "Bad placeholders initial zview."); - PQXX_CHECK_EQUAL(name.view(), "$1"sv, "Bad placeholders string_view."); - PQXX_CHECK_EQUAL(name.get(), "$1", "Bad placeholders::get()."); - - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$2"_zv, "Incorrect placeholders::next()."); - - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$3"_zv, "Incorrect placeholders::next()."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$4"_zv, "Incorrect placeholders::next()."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$5"_zv, "Incorrect placeholders::next()."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$6"_zv, "Incorrect placeholders::next()."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$7"_zv, "Incorrect placeholders::next()."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$8"_zv, "Incorrect placeholders::next()."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$9"_zv, "Incorrect placeholders::next()."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$10"_zv, "Incorrect placeholders carry."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$11"_zv, "Incorrect placeholders 11."); - - while (name.count() < 999) name.next(); - PQXX_CHECK_EQUAL(name.view(), "$999"_zv, "Incorrect placeholders 999."); - name.next(); - PQXX_CHECK_EQUAL(name.view(), "$1000"_zv, "Incorrect large placeholder."); -} - - -PQXX_REGISTER_TEST(test_prepared_statements); -PQXX_REGISTER_TEST(test_placeholders_generates_names); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_range.cxx b/ext/libpqxx-7.7.3/test/unit/test_range.cxx deleted file mode 100644 index b40d9b043..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_range.cxx +++ /dev/null @@ -1,555 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - - -namespace -{ -void test_range_construct() -{ - using optint = std::optional; - using oibound = pqxx::inclusive_bound>; - using oxbound = pqxx::inclusive_bound>; - PQXX_CHECK_THROWS( - (pqxx::range{oibound{optint{}}, oibound{optint{}}}), - pqxx::argument_error, "Inclusive bound accepted a null."); - PQXX_CHECK_THROWS( - (pqxx::range{oxbound{optint{}}, oxbound{optint{}}}), - pqxx::argument_error, "Exclusive bound accepted a null."); - - using ibound = pqxx::inclusive_bound; - PQXX_CHECK_THROWS( - (pqxx::range{ibound{1}, ibound{0}}), pqxx::range_error, - "Range constructor accepted backwards range."); - - PQXX_CHECK_THROWS( - (pqxx::range{ - pqxx::inclusive_bound{-1000.0}, - pqxx::inclusive_bound{-std::numeric_limits::infinity()}}), - pqxx::range_error, - "Was able to construct range with infinity bound at the wrong end."); -} - - -void test_range_equality() -{ - using range = pqxx::range; - using ibound = pqxx::inclusive_bound; - using xbound = pqxx::exclusive_bound; - using ubound = pqxx::no_bound; - - PQXX_CHECK_EQUAL( - range{}, range{}, "Default-constructed range is not consistent."); - PQXX_CHECK_EQUAL( - (range{xbound{0}, xbound{0}}), (range{xbound{5}, xbound{5}}), - "Empty ranges at different values are not equal."); - - PQXX_CHECK_EQUAL( - (range{ubound{}, ubound{}}), (range{ubound{}, ubound{}}), - "Universal range is inconsistent."); - PQXX_CHECK_EQUAL( - (range{ibound{5}, ibound{8}}), (range{ibound{5}, ibound{8}}), - "Inclusive range is inconsistent."); - PQXX_CHECK_EQUAL( - (range{xbound{5}, xbound{8}}), (range{xbound{5}, xbound{8}}), - "Exclusive range is inconsistent."); - PQXX_CHECK_EQUAL( - (range{xbound{5}, ibound{8}}), (range{xbound{5}, ibound{8}}), - "Left-exclusive interval is not equal to itself."); - PQXX_CHECK_EQUAL( - (range{ibound{5}, xbound{8}}), (range{ibound{5}, xbound{8}}), - "Right-exclusive interval is not equal to itself."); - PQXX_CHECK_EQUAL( - (range{ubound{}, ibound{8}}), (range{ubound{}, ibound{8}}), - "Unlimited lower bound does not compare equal to same."); - PQXX_CHECK_EQUAL( - (range{ibound{8}, ubound{}}), (range{ibound{8}, ubound{}}), - "Unlimited upper bound does not compare equal to same."); - - PQXX_CHECK_NOT_EQUAL( - (range{ibound{5}, ibound{8}}), (range{xbound{5}, ibound{8}}), - "Equality does not detect inclusive vs. exclusive lower bound."); - PQXX_CHECK_NOT_EQUAL( - (range{ibound{5}, ibound{8}}), (range{ubound{}, ibound{8}}), - "Equality does not detect inclusive vs. unlimited lower bound."); - PQXX_CHECK_NOT_EQUAL( - (range{xbound{5}, ibound{8}}), (range{ubound{}, ibound{8}}), - "Equality does not detect exclusive vs. unlimited lower bound."); - PQXX_CHECK_NOT_EQUAL( - (range{ibound{5}, ibound{8}}), (range{ibound{5}, xbound{8}}), - "Equality does not detect inclusive vs. exclusive upper bound."); - PQXX_CHECK_NOT_EQUAL( - (range{ibound{5}, ibound{8}}), (range{ibound{5}, ubound{}}), - "Equality does not detect inclusive vs. unlimited upper bound."); - PQXX_CHECK_NOT_EQUAL( - (range{ibound{5}, xbound{8}}), (range{ibound{5}, ubound{}}), - "Equality does not detect exclusive vs. unlimited upper bound."); - - PQXX_CHECK_NOT_EQUAL( - (range{ibound{5}, ibound{8}}), (range{ibound{4}, ibound{8}}), - "Equality does not compare lower inclusive bound value."); - PQXX_CHECK_NOT_EQUAL( - (range{xbound{5}, ibound{8}}), (range{xbound{4}, ibound{8}}), - "Equality does not compare lower exclusive bound value."); - PQXX_CHECK_NOT_EQUAL( - (range{xbound{5}, ibound{8}}), (range{xbound{5}, ibound{7}}), - "Equality does not compare upper inclusive bound value."); - PQXX_CHECK_NOT_EQUAL( - (range{xbound{5}, xbound{8}}), (range{xbound{5}, xbound{7}}), - "Equality does not compare lower exclusive bound value."); -} - - -void test_range_empty() -{ - using range = pqxx::range; - using ibound = pqxx::inclusive_bound; - using xbound = pqxx::exclusive_bound; - using ubound = pqxx::no_bound; - PQXX_CHECK((range{}.empty()), "Default-constructed range is not empty."); - PQXX_CHECK( - (range{ibound{10}, xbound{10}}).empty(), - "Right-exclusive zero-length interval is not empty."); - PQXX_CHECK( - (range{xbound{10}, ibound{10}}).empty(), - "Left-exclusive zero-length interval is not empty."); - PQXX_CHECK( - (range{xbound{10}, xbound{10}}).empty(), - "Exclusive zero-length interval is not empty."); - - PQXX_CHECK( - not(range{ibound{10}, ibound{10}}).empty(), - "Inclusive zero-length interval is empty."); - PQXX_CHECK( - not(range{xbound{10}, ibound{11}}.empty()), - "Interval is incorrectly empty."); - PQXX_CHECK( - not(range{ubound{}, ubound{}}.empty()), - "Double-unlimited interval is empty."); - PQXX_CHECK( - not(range{ubound{}, xbound{0}}.empty()), - "Left-unlimited interval is empty."); - PQXX_CHECK( - not(range{xbound{0}, ubound{}}.empty()), - "Right-unlimited interval is empty."); -} - - -void test_range_contains() -{ - using range = pqxx::range; - using ibound = pqxx::inclusive_bound; - using xbound = pqxx::exclusive_bound; - using ubound = pqxx::no_bound; - - PQXX_CHECK(not(range{}.contains(-1)), "Empty range contains a value."); - PQXX_CHECK(not(range{}.contains(0)), "Empty range contains a value."); - PQXX_CHECK(not(range{}.contains(1)), "Empty range contains a value."); - - PQXX_CHECK( - not(range{ibound{5}, ibound{8}}.contains(4)), - "Inclusive range contains value outside its left bound."); - PQXX_CHECK( - (range{ibound{5}, ibound{8}}.contains(5)), - "Inclusive range does not contain value on its left bound."); - PQXX_CHECK( - (range{ibound{5}, ibound{8}}.contains(6)), - "Inclusive range does not contain value inside it."); - PQXX_CHECK( - (range{ibound{5}, ibound{8}}.contains(8)), - "Inclusive range does not contain value on its right bound."); - PQXX_CHECK( - not(range{ibound{5}, ibound{8}}.contains(9)), - "Inclusive range contains value outside its right bound."); - - PQXX_CHECK( - not(range{ibound{5}, xbound{8}}.contains(4)), - "Left-inclusive range contains value outside its left bound."); - PQXX_CHECK( - (range{ibound{5}, xbound{8}}.contains(5)), - "Left-inclusive range does not contain value on its left bound."); - PQXX_CHECK( - (range{ibound{5}, xbound{8}}.contains(6)), - "Left-inclusive range does not contain value inside it."); - PQXX_CHECK( - not(range{ibound{5}, xbound{8}}.contains(8)), - "Left-inclusive range contains value on its right bound."); - PQXX_CHECK( - not(range{ibound{5}, xbound{8}}.contains(9)), - "Left-inclusive range contains value outside its right bound."); - - PQXX_CHECK( - not(range{xbound{5}, ibound{8}}.contains(4)), - "Right-inclusive range contains value outside its left bound."); - PQXX_CHECK( - not(range{xbound{5}, ibound{8}}.contains(5)), - "Right-inclusive range does contains value on its left bound."); - PQXX_CHECK( - (range{xbound{5}, ibound{8}}.contains(6)), - "Right-inclusive range does not contain value inside it."); - PQXX_CHECK( - (range{xbound{5}, ibound{8}}.contains(8)), - "Right-inclusive range does not contain value on its right bound."); - PQXX_CHECK( - not(range{xbound{5}, ibound{8}}.contains(9)), - "Right-inclusive range contains value outside its right bound."); - - PQXX_CHECK( - not(range{xbound{5}, xbound{8}}.contains(4)), - "Exclusive range contains value outside its left bound."); - PQXX_CHECK( - not(range{xbound{5}, xbound{8}}.contains(5)), - "Exclusive range contains value on its left bound."); - PQXX_CHECK( - (range{xbound{5}, xbound{8}}.contains(6)), - "Exclusive range does not contain value inside it."); - PQXX_CHECK( - not(range{xbound{5}, xbound{8}}.contains(8)), - "Exclusive range does contains value on its right bound."); - PQXX_CHECK( - not(range{xbound{5}, xbound{8}}.contains(9)), - "Exclusive range contains value outside its right bound."); - - PQXX_CHECK( - (range{ubound{}, ibound{8}}.contains(7)), - "Right-inclusive range does not contain value inside it."); - PQXX_CHECK( - (range{ubound{}, ibound{8}}.contains(8)), - "Right-inclusive range does not contain value on its right bound."); - PQXX_CHECK( - not(range{ubound{}, ibound{8}}.contains(9)), - "Right-inclusive range contains value outside its right bound."); - - PQXX_CHECK( - (range{ubound{}, xbound{8}}.contains(7)), - "Right-exclusive range does not contain value inside it."); - PQXX_CHECK( - not(range{ubound{}, xbound{8}}.contains(8)), - "Right-exclusive range contains value on its right bound."); - PQXX_CHECK( - not(range{ubound{}, xbound{8}}.contains(9)), - "Right-exclusive range contains value outside its right bound."); - - PQXX_CHECK( - not(range{ibound{5}, ubound{}}.contains(4)), - "Left-inclusive range contains value outside its left bound."); - PQXX_CHECK( - (range{ibound{5}, ubound{}}.contains(5)), - "Left-inclusive range does not contain value on its left bound."); - PQXX_CHECK( - (range{ibound{5}, ubound{}}.contains(6)), - "Left-inclusive range does not contain value inside it."); - - PQXX_CHECK( - not(range{xbound{5}, ubound{}}.contains(4)), - "Left-exclusive range contains value outside its left bound."); - PQXX_CHECK( - not(range{xbound{5}, ubound{}}.contains(5)), - "Left-exclusive range contains value on its left bound."); - PQXX_CHECK( - (range{xbound{5}, ubound{}}.contains(6)), - "Left-exclusive range does not contain value inside it."); - - PQXX_CHECK( - (range{ubound{}, ubound{}}.contains(-1)), "Value not in universal range."); - PQXX_CHECK( - (range{ubound{}, ubound{}}.contains(0)), "Value not in universal range."); - PQXX_CHECK( - (range{ubound{}, ubound{}}.contains(1)), "Value not in universal range."); -} - - -void test_float_range_contains() -{ - using range = pqxx::range; - using ibound = pqxx::inclusive_bound; - using xbound = pqxx::exclusive_bound; - using ubound = pqxx::no_bound; - using limits = std::numeric_limits; - constexpr auto inf{limits::infinity()}; - - PQXX_CHECK( - not(range{ibound{4.0}, ibound{8.0}}.contains(3.9)), - "Float inclusive range contains value beyond its lower bound."); - PQXX_CHECK( - (range{ibound{4.0}, ibound{8.0}}.contains(4.0)), - "Float inclusive range does not contain its lower bound value."); - PQXX_CHECK( - (range{ibound{4.0}, ibound{8.0}}.contains(5.0)), - "Float inclusive range does not contain value inside it."); - - PQXX_CHECK( - (range{ibound{0}, ibound{inf}}).contains(9999.0), - "Range to infinity did not include large number."); - PQXX_CHECK( - not(range{ibound{0}, ibound{inf}}.contains(-0.1)), - "Range to infinity includes number outside it."); - PQXX_CHECK( - (range{ibound{0}, xbound{inf}}.contains(9999.0)), - "Range to exclusive infinity did not include large number."); - PQXX_CHECK( - (range{ibound{0}, ibound{inf}}).contains(inf), - "Range to inclusive infinity does not include infinity."); - PQXX_CHECK( - not(range{ibound{0}, xbound{inf}}.contains(inf)), - "Range to exclusive infinity includes infinity."); - PQXX_CHECK( - (range{ibound{0}, ubound{}}).contains(inf), - "Right-unlimited range does not include infinity."); - - PQXX_CHECK( - (range{ibound{-inf}, ibound{0}}).contains(-9999.0), - "Range from infinity did not include large negative number."); - PQXX_CHECK( - not(range{ibound{-inf}, ibound{0}}.contains(0.1)), - "Range from infinity includes number outside it."); - PQXX_CHECK( - (range{xbound{-inf}, ibound{0}}).contains(-9999.0), - "Range from exclusive infinity did not include large negative number."); - PQXX_CHECK( - (range{ibound{-inf}, ibound{0}}).contains(-inf), - "Range from inclusive infinity does not include negative infinity."); - PQXX_CHECK( - not(range{xbound{-inf}, ibound{0}}).contains(-inf), - "Range to infinity exclusive includes negative infinity."); - PQXX_CHECK( - (range{ubound{}, ibound{0}}).contains(-inf), - "Left-unlimited range does not include negative infinity."); -} - - -void test_range_subset() -{ - using range = pqxx::range; - using traits = pqxx::string_traits; - - std::string_view subsets[][2]{ - {"empty", "empty"}, {"(,)", "empty"}, {"(0,1)", "empty"}, - {"(,)", "[-10,10]"}, {"(,)", "(-10,10)"}, {"(,)", "(,)"}, - {"(,10)", "(,10)"}, {"(,10)", "(,9)"}, {"(,10]", "(,10)"}, - {"(,10]", "(,10]"}, {"(1,)", "(10,)"}, {"(1,)", "(9,)"}, - {"[1,)", "(10,)"}, {"[1,)", "[10,)"}, {"[0,5]", "[1,4]"}, - {"(0,5)", "[1,4]"}, - }; - for (auto const [super, sub] : subsets) - PQXX_CHECK( - traits::from_string(super).contains(traits::from_string(sub)), - pqxx::internal::concat( - "Range '", super, "' did not contain '", sub, "'.")); - - std::string_view non_subsets[][2]{ - {"empty", "[0,0]"}, {"empty", "(,)"}, {"[-10,10]", "(,)"}, - {"(-10,10)", "(,)"}, {"(,9)", "(,10)"}, {"(,10)", "(,10]"}, - {"[1,4]", "[0,4]"}, {"[1,4]", "[1,5]"}, {"(0,10)", "[0,10]"}, - {"(0,10)", "(0,10]"}, {"(0,10)", "[0,10)"}, - }; - for (auto const [super, sub] : non_subsets) - PQXX_CHECK( - not traits::from_string(super).contains(traits::from_string(sub)), - pqxx::internal::concat("Range '", super, "' contained '", sub, "'.")); -} - - -void test_range_to_string() -{ - using range = pqxx::range; - using ibound = pqxx::inclusive_bound; - using xbound = pqxx::exclusive_bound; - using ubound = pqxx::no_bound; - - PQXX_CHECK_EQUAL( - pqxx::to_string(range{}), "empty", "Empty range came out wrong."); - - PQXX_CHECK_EQUAL( - pqxx::to_string(range{ibound{5}, ibound{8}}), "[5,8]", - "Inclusive range came out wrong."); - PQXX_CHECK_EQUAL( - pqxx::to_string(range{xbound{5}, ibound{8}}), "(5,8]", - "Left-exclusive range came out wrong."); - PQXX_CHECK_EQUAL( - pqxx::to_string(range{ibound{5}, xbound{8}}), "[5,8)", - "Right-exclusive range came out wrong."); - PQXX_CHECK_EQUAL( - pqxx::to_string(range{xbound{5}, xbound{8}}), "(5,8)", - "Exclusive range came out wrong."); - - // Unlimited boundaries can use brackets or parentheses. Doesn't matter. - // We cheat and use some white-box knowledge of our implementation here. - PQXX_CHECK_EQUAL( - pqxx::to_string(range{ubound{}, ubound{}}), "(,)", - "Universal range came out unexpected."); - PQXX_CHECK_EQUAL( - pqxx::to_string(range{ubound{}, ibound{8}}), "(,8]", - "Left-unlimited range came out unexpected."); - PQXX_CHECK_EQUAL( - pqxx::to_string(range{ubound{}, xbound{8}}), "(,8)", - "Left-unlimited range came out unexpected."); - PQXX_CHECK_EQUAL( - pqxx::to_string(range{ibound{5}, ubound{}}), "[5,)", - "Right-unlimited range came out unexpected."); - PQXX_CHECK_EQUAL( - pqxx::to_string(range{xbound{5}, ubound{}}), "(5,)", - "Right-unlimited range came out unexpected."); -} - - -void test_parse_range() -{ - using range = pqxx::range; - using ubound = pqxx::no_bound; - using traits = pqxx::string_traits; - - constexpr std::string_view empties[]{"empty", "EMPTY", "eMpTy"}; - for (auto empty : empties) - PQXX_CHECK( - traits::from_string(empty).empty(), - pqxx::internal::concat( - "This was supposed to produce an empty range: '", empty, "'")); - - constexpr std::string_view universals[]{"(,)", "[,)", "(,]", "[,]"}; - for (auto univ : universals) - PQXX_CHECK_EQUAL( - traits::from_string(univ), (range{ubound{}, ubound{}}), - pqxx::internal::concat( - "This was supposed to produce a universal range: '", univ, "'")); - - PQXX_CHECK( - traits::from_string("(0,10]").lower_bound().is_exclusive(), - "Exclusive lower bound did not parse right."); - PQXX_CHECK( - traits::from_string("[0,10]").lower_bound().is_inclusive(), - "Inclusive lower bound did not parse right."); - PQXX_CHECK( - traits::from_string("(0,10)").upper_bound().is_exclusive(), - "Exclusive upper bound did not parse right."); - PQXX_CHECK( - traits::from_string("[0,10]").upper_bound().is_inclusive(), - "Inclusive upper bound did not parse right."); - - PQXX_CHECK_EQUAL( - *traits::from_string("(\"0\",\"10\")").lower_bound().value(), 0, - "Quoted range boundary did not parse right."); - PQXX_CHECK_EQUAL( - *traits::from_string("(\"0\",\"10\")").upper_bound().value(), 10, - "Quoted upper boundary did not parse right."); - - auto floats{ - pqxx::string_traits>::from_string("(0,1.0)")}; - PQXX_CHECK_GREATER( - *floats.lower_bound().value(), -0.001, - "Float lower bound is out of range."); - PQXX_CHECK_LESS( - *floats.lower_bound().value(), 0.001, - "Float lower bound is out of range."); - PQXX_CHECK_GREATER( - *floats.upper_bound().value(), 0.999, - "Float upper bound is out of range."); - PQXX_CHECK_LESS( - *floats.upper_bound().value(), 1.001, - "Float upper bound is out of range."); -} - - -void test_parse_bad_range() -{ - using range = pqxx::range; - using conv_err = pqxx::conversion_error; - using traits = pqxx::string_traits; - constexpr std::string_view bad_ranges[]{ - "", "x", "e", "empt", "emptyy", "()", - "[]", "(empty)", "(empty, 0)", "(0, empty)", ",", "(,", - ",)", "(1,2,3)", "(4,5x)", "(null, 0)", "[0, 1.0]", "[1.0, 0]", - }; - - for (auto bad : bad_ranges) - PQXX_CHECK_THROWS( - pqxx::ignore_unused(traits::from_string(bad)), conv_err, - pqxx::internal::concat( - "This range wasn't supposed to parse: '", bad, "'")); -} - - -/// Parse ranges lhs and rhs, return their intersection as a string. -template -std::string intersect(std::string_view lhs, std::string_view rhs) -{ - using traits = pqxx::string_traits>; - return pqxx::to_string(traits::from_string(lhs) & traits::from_string(rhs)); -} - - -void test_range_intersection() -{ - // Intersections and their expected results, in text form. - // Each row contains two ranges, and their intersection. - std::string_view intersections[][3]{ - {"empty", "empty", "empty"}, - {"(,)", "empty", "empty"}, - {"[,]", "empty", "empty"}, - {"empty", "[0,10]", "empty"}, - {"(,)", "(,)", "(,)"}, - {"(,)", "(5,8)", "(5,8)"}, - {"(,)", "[5,8)", "[5,8)"}, - {"(,)", "(5,8]", "(5,8]"}, - {"(,)", "[5,8]", "[5,8]"}, - {"(-1000,10)", "(0,1000)", "(0,10)"}, - {"[-1000,10)", "(0,1000)", "(0,10)"}, - {"(-1000,10]", "(0,1000)", "(0,10]"}, - {"[-1000,10]", "(0,1000)", "(0,10]"}, - {"[0,100]", "[0,100]", "[0,100]"}, - {"[0,100]", "[0,100)", "[0,100)"}, - {"[0,100]", "(0,100]", "(0,100]"}, - {"[0,100]", "(0,100)", "(0,100)"}, - {"[0,10]", "[11,20]", "empty"}, - {"[0,10]", "(11,20]", "empty"}, - {"[0,10]", "[11,20)", "empty"}, - {"[0,10]", "(11,20)", "empty"}, - {"[0,10]", "[10,11]", "[10,10]"}, - {"[0,10)", "[10,11]", "empty"}, - {"[0,10]", "(10,11]", "empty"}, - {"[0,10)", "(10,11]", "empty"}, - }; - for (auto [left, right, expected] : intersections) - { - PQXX_CHECK_EQUAL( - intersect(left, right), expected, - pqxx::internal::concat( - "Intersection of '", left, "' and '", right, - " produced unexpected result.")); - PQXX_CHECK_EQUAL( - intersect(right, left), expected, - pqxx::internal::concat( - "Intersection of '", left, "' and '", right, " was asymmetric.")); - } -} - - -void test_range_conversion() -{ - std::string_view const ranges[]{ - "empty", "(,)", "(,10)", "(0,)", "[0,10]", "[0,10)", "(0,10]", "(0,10)", - }; - - for (auto r : ranges) - { - auto const shortr{pqxx::from_string>(r)}; - pqxx::range intr{shortr}; - PQXX_CHECK_EQUAL( - pqxx::to_string(intr), r, "Converted range looks different."); - } -} - - -PQXX_REGISTER_TEST(test_range_construct); -PQXX_REGISTER_TEST(test_range_equality); -PQXX_REGISTER_TEST(test_range_empty); -PQXX_REGISTER_TEST(test_range_contains); -PQXX_REGISTER_TEST(test_float_range_contains); -PQXX_REGISTER_TEST(test_range_subset); -PQXX_REGISTER_TEST(test_range_to_string); -PQXX_REGISTER_TEST(test_parse_range); -PQXX_REGISTER_TEST(test_parse_bad_range); -PQXX_REGISTER_TEST(test_range_intersection); -PQXX_REGISTER_TEST(test_range_conversion); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_read_transaction.cxx b/ext/libpqxx-7.7.3/test/unit/test_read_transaction.cxx deleted file mode 100644 index 402f2a06f..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_read_transaction.cxx +++ /dev/null @@ -1,22 +0,0 @@ -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_read_transaction() -{ - pqxx::connection conn; - pqxx::read_transaction tx{conn}; - PQXX_CHECK_EQUAL( - tx.exec("SELECT 1")[0][0].as(), 1, - "Bad result from read transaction."); - - PQXX_CHECK_THROWS( - tx.exec("CREATE TABLE should_not_exist(x integer)"), pqxx::sql_error, - "Read-only transaction allows database to be modified."); -} - - -PQXX_REGISTER_TEST(test_read_transaction); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_result_iteration.cxx b/ext/libpqxx-7.7.3/test/unit/test_result_iteration.cxx deleted file mode 100644 index 3d26e3c3e..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_result_iteration.cxx +++ /dev/null @@ -1,137 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_result_iteration() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::result r{tx.exec("SELECT generate_series(1, 3)")}; - - PQXX_CHECK(std::end(r) != std::begin(r), "Broken begin/end."); - PQXX_CHECK(std::rend(r) != std::rbegin(r), "Broken rbegin/rend."); - - PQXX_CHECK(std::cbegin(r) == std::begin(r), "Wrong cbegin."); - PQXX_CHECK(std::cend(r) == std::end(r), "Wrong cend."); - PQXX_CHECK(std::crbegin(r) == std::rbegin(r), "Wrong crbegin."); - PQXX_CHECK(std::crend(r) == std::rend(r), "Wrong crend."); - - PQXX_CHECK_EQUAL(r.front().front().as(), 1, "Unexpected front()."); - PQXX_CHECK_EQUAL(r.back().front().as(), 3, "Unexpected back()."); -} - - -void test_result_iter() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::result r{tx.exec("SELECT generate_series(1, 3)")}; - - int total{0}; - for (auto const &[i] : r.iter()) total += i; - PQXX_CHECK_EQUAL(total, 6, "iter() loop did not get the right values."); -} - - -void test_result_iterator_swap() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::result r{tx.exec("SELECT generate_series(1, 3)")}; - - auto head{std::begin(r)}, next{head + 1}; - head.swap(next); - PQXX_CHECK_EQUAL(head[0].as(), 2, "Result iterator swap is wrong."); - PQXX_CHECK_EQUAL(next[0].as(), 1, "Result iterator swap is crazy."); - - auto tail{std::rbegin(r)}, prev{tail + 1}; - tail.swap(prev); - PQXX_CHECK_EQUAL(tail[0].as(), 2, "Reverse iterator swap is wrong."); - PQXX_CHECK_EQUAL(prev[0].as(), 3, "Reverse iterator swap is crazy."); -} - - -void test_result_iterator_assignment() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::result r{tx.exec("SELECT generate_series(1, 3)")}; - - pqxx::result::const_iterator fwd; - pqxx::result::const_reverse_iterator rev; - - fwd = std::begin(r); - PQXX_CHECK_EQUAL( - fwd[0].as(), std::begin(r)[0].as(), - "Result iterator assignment is wrong."); - - rev = std::rbegin(r); - PQXX_CHECK_EQUAL( - rev[0].as(), std::rbegin(r)[0].as(), - "Reverse iterator assignment is wrong."); -} - - -void check_employee(std::string name, int salary) -{ - PQXX_CHECK(name == "x" or name == "y" or name == "z", "Unknown name."); - PQXX_CHECK( - salary == 1000 or salary == 1200 or salary == 1500, "Unknown salary."); -} - - -void test_result_for_each() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0("CREATE TEMP TABLE employee(name varchar, salary int)"); - auto fill{pqxx::stream_to::table(tx, {"employee"}, {"name", "salary"})}; - fill.write_values("x", 1000); - fill.write_values("y", 1200); - fill.write_values("z", 1500); - fill.complete(); - - auto const res{tx.exec("SELECT name, salary FROM employee ORDER BY name")}; - - // Use for_each with a function. - res.for_each(check_employee); - - // Use for_each with a simple lambda. - res.for_each( - [](std::string name, int salary) { check_employee(name, salary); }); - - // Use for_each with a lambda closure. - std::string names{}; - int total{0}; - - res.for_each([&names, &total](std::string name, int salary) { - names.append(name); - total += salary; - }); - PQXX_CHECK_EQUAL( - names, "xyz", "result::for_each did not accumulate names correctly."); - PQXX_CHECK_EQUAL(total, 1000 + 1200 + 1500, "Salaries added up wrong."); - - // In addition to regular conversions, you can receive arguments as - // string_view, or as references. - names.clear(); - total = 0; - res.for_each([&names, &total](std::string_view &&name, int const &salary) { - names.append(name); - total += salary; - }); - PQXX_CHECK_EQUAL( - names, "xyz", "result::for_each did not accumulate names correctly."); - PQXX_CHECK_EQUAL(total, 1000 + 1200 + 1500, "Salaries added up wrong."); -} - - -PQXX_REGISTER_TEST(test_result_iteration); -PQXX_REGISTER_TEST(test_result_iter); -PQXX_REGISTER_TEST(test_result_iterator_swap); -PQXX_REGISTER_TEST(test_result_iterator_assignment); -PQXX_REGISTER_TEST(test_result_for_each); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_result_slicing.cxx b/ext/libpqxx-7.7.3/test/unit/test_result_slicing.cxx deleted file mode 100644 index be2055ee3..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_result_slicing.cxx +++ /dev/null @@ -1,157 +0,0 @@ -#include - -#include "../test_helpers.hxx" - -#include "pqxx/internal/ignore-deprecated-pre.hxx" - -namespace pqxx -{ -template<> struct nullness : no_null -{}; - -template<> -struct nullness - : no_null -{}; - - -template<> struct string_traits -{ - static constexpr zview text{"[row::const_iterator]"}; - static zview to_buf(char *, char *, row::const_iterator const &) - { - return text; - } - static char *into_buf(char *begin, char *end, row::const_iterator const &) - { - if ((end - begin) <= 30) - throw conversion_overrun{"Not enough buffer for const row iterator."}; - std::memcpy(begin, text.c_str(), std::size(text) + 1); - return begin + std::size(text); - } - static constexpr std::size_t - size_buffer(row::const_iterator const &) noexcept - { - return std::size(text) + 1; - } -}; - - -template<> struct string_traits -{ - static constexpr zview text{"[row::const_reverse_iterator]"}; - static pqxx::zview - to_buf(char *, char *, row::const_reverse_iterator const &) - { - return text; - } - static char * - into_buf(char *begin, char *end, row::const_reverse_iterator const &) - { - if ((end - begin) <= 30) - throw conversion_overrun{"Not enough buffer for const row iterator."}; - std::memcpy(begin, text.c_str(), std::size(text) + 1); - return begin + std::size(text); - } - static constexpr std::size_t - size_buffer(row::const_reverse_iterator const &) noexcept - { - return 100; - } -}; -} // namespace pqxx - -namespace -{ -void test_result_slicing() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - auto r{tx.exec("SELECT 1")}; - - PQXX_CHECK(not std::empty(r[0]), "A plain row shows up as empty."); - - // Empty slice at beginning of row. - pqxx::row s{r[0].slice(0, 0)}; - PQXX_CHECK(std::empty(s), "Empty slice does not show up as empty."); - PQXX_CHECK_EQUAL(std::size(s), 0, "Slicing produces wrong row size."); - PQXX_CHECK_EQUAL( - std::begin(s), std::end(s), "Slice begin()/end() are broken."); - PQXX_CHECK_EQUAL( - std::rbegin(s), std::rend(s), "Slice rbegin()/rend() are broken."); - - PQXX_CHECK_THROWS(s.at(0), pqxx::range_error, "at() does not throw."); - pqxx::row slice; - PQXX_CHECK_THROWS( - slice = r[0].slice(0, 2), pqxx::range_error, "No range check."); - pqxx::ignore_unused(slice); - PQXX_CHECK_THROWS( - slice = r[0].slice(1, 0), pqxx::range_error, "Can reverse-slice."); - pqxx::ignore_unused(slice); - - // Empty slice at end of row. - s = r[0].slice(1, 1); - PQXX_CHECK(std::empty(s), "empty() is broken."); - PQXX_CHECK_EQUAL(std::size(s), 0, "size() is broken."); - PQXX_CHECK_EQUAL(std::begin(s), std::end(s), "begin()/end() are broken."); - PQXX_CHECK_EQUAL( - std::rbegin(s), std::rend(s), "rbegin()/rend() are broken."); - - PQXX_CHECK_THROWS(s.at(0), pqxx::range_error, "at() is inconsistent."); - - // Slice that matches the entire row. - s = r[0].slice(0, 1); - PQXX_CHECK(not std::empty(s), "Nonempty slice shows up as empty."); - PQXX_CHECK_EQUAL(std::size(s), 1, "size() breaks for non-empty slice."); - PQXX_CHECK_EQUAL(std::begin(s) + 1, std::end(s), "Iteration is broken."); - PQXX_CHECK_EQUAL( - std::rbegin(s) + 1, std::rend(s), "Reverse iteration is broken."); - PQXX_CHECK_EQUAL(s.at(0).as(), 1, "Accessing a slice is broken."); - PQXX_CHECK_EQUAL(s[0].as(), 1, "operator[] is broken."); - PQXX_CHECK_THROWS(s.at(1).as(), pqxx::range_error, "at() is off."); - - // Meaningful slice at beginning of row. - r = tx.exec("SELECT 1, 2, 3"); - s = r[0].slice(0, 1); - PQXX_CHECK(not std::empty(s), "Slicing confuses empty()."); - PQXX_CHECK_THROWS( - s.at(1).as(), pqxx::range_error, "at() does not enforce slice."); - - // Meaningful slice that skips an initial column. - s = r[0].slice(1, 2); - PQXX_CHECK( - not std::empty(s), "Slicing away leading columns confuses empty()."); - PQXX_CHECK_EQUAL(s[0].as(), 2, "Slicing offset is broken."); - PQXX_CHECK_EQUAL( - std::begin(s)->as(), 2, "Iteration uses wrong offset."); - PQXX_CHECK_EQUAL( - std::begin(s) + 1, std::end(s), "Iteration has wrong range."); - PQXX_CHECK_EQUAL( - std::rbegin(s) + 1, std::rend(s), "Reverse iteration has wrong range."); - PQXX_CHECK_THROWS( - s.at(1).as(), pqxx::range_error, "Offset slicing is broken."); - - // Column names in a slice. - r = tx.exec("SELECT 1 AS one, 2 AS two, 3 AS three"); - s = r[0].slice(1, 2); - PQXX_CHECK_EQUAL(s["two"].as(), 2, "Column addressing breaks."); - PQXX_CHECK_THROWS( - pqxx::ignore_unused(s.column_number("one")), pqxx::argument_error, - "Can access column name before slice."); - PQXX_CHECK_THROWS( - pqxx::ignore_unused(s.column_number("three")), pqxx::argument_error, - "Can access column name after slice."); - PQXX_CHECK_EQUAL( - s.column_number("Two"), 0, "Column name is case sensitive."); - - // Identical column names. - r = tx.exec("SELECT 1 AS x, 2 AS x"); - s = r[0].slice(1, 2); - PQXX_CHECK_EQUAL(s["x"].as(), 2, "Identical column names break slice."); -} - - -PQXX_REGISTER_TEST(test_result_slicing); -} // namespace - -#include "pqxx/internal/ignore-deprecated-post.hxx" diff --git a/ext/libpqxx-7.7.3/test/unit/test_row.cxx b/ext/libpqxx-7.7.3/test/unit/test_row.cxx deleted file mode 100644 index 41770e3b1..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_row.cxx +++ /dev/null @@ -1,84 +0,0 @@ -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_row() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::result rows{tx.exec("SELECT 1, 2, 3")}; - pqxx::row r{rows[0]}; - PQXX_CHECK_EQUAL(std::size(r), 3, "Unexpected row size."); - PQXX_CHECK_EQUAL(r.at(0).as(), 1, "Wrong value at index 0."); - PQXX_CHECK(std::begin(r) != std::end(r), "Broken row iteration."); - PQXX_CHECK(std::begin(r) < std::end(r), "Row begin does not precede end."); - PQXX_CHECK(std::cbegin(r) == std::begin(r), "Wrong cbegin."); - PQXX_CHECK(std::cend(r) == std::end(r), "Wrong cend."); - PQXX_CHECK(std::rbegin(r) != std::rend(r), "Broken reverse row iteration."); - PQXX_CHECK(std::crbegin(r) == std::rbegin(r), "Wrong crbegin."); - PQXX_CHECK(std::crend(r) == std::rend(r), "Wrong crend."); - PQXX_CHECK_EQUAL(r.front().as(), 1, "Wrong row front()."); - PQXX_CHECK_EQUAL(r.back().as(), 3, "Wrong row back()."); -} - - -void test_row_iterator() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::result rows{tx.exec("SELECT 1, 2, 3")}; - - auto i{std::begin(rows[0])}; - PQXX_CHECK_EQUAL(i->as(), 1, "Row iterator is wrong."); - auto i2{i}; - PQXX_CHECK_EQUAL(i2->as(), 1, "Row iterator copy is wrong."); - i2++; - PQXX_CHECK_EQUAL(i2->as(), 2, "Row iterator increment is wrong."); - pqxx::row::const_iterator i3; - i3 = i2; - PQXX_CHECK_EQUAL(i3->as(), 2, "Row iterator assignment is wrong."); - - auto r{std::rbegin(rows[0])}; - PQXX_CHECK_EQUAL(r->as(), 3, "Row reverse iterator is wrong."); - auto r2{r}; - PQXX_CHECK_EQUAL(r2->as(), 3, "Row reverse iterator copy is wrong."); - r2++; - PQXX_CHECK_EQUAL( - r2->as(), 2, "Row reverse iterator increment is wrong."); - pqxx::row::const_reverse_iterator r3; - r3 = r2; - PQXX_CHECK_EQUAL( - i3->as(), 2, "Row reverse iterator assignment is wrong."); -} - - -void test_row_as() -{ - using pqxx::operator"" _zv; - - pqxx::connection conn; - pqxx::work tx{conn}; - - pqxx::row const r{tx.exec1("SELECT 1, 2, 3")}; - auto [one, two, three]{r.as()}; - static_assert(std::is_same_v); - static_assert(std::is_same_v); - static_assert(std::is_same_v); - PQXX_CHECK_EQUAL(one, 1, "row::as() did not produce the right int."); - PQXX_CHECK_GREATER(two, 1.9, "row::as() did not produce the right float."); - PQXX_CHECK_LESS(two, 2.1, "row::as() did not produce the right float."); - PQXX_CHECK_EQUAL( - three, "3"_zv, "row::as() did not produce the right zview."); - - PQXX_CHECK_EQUAL( - std::get<0>(tx.exec1("SELECT 999").as()), 999, - "Unary tuple did not extract right."); -} - - -PQXX_REGISTER_TEST(test_row); -PQXX_REGISTER_TEST(test_row_iterator); -PQXX_REGISTER_TEST(test_row_as); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_separated_list.cxx b/ext/libpqxx-7.7.3/test/unit/test_separated_list.cxx deleted file mode 100644 index 748379b47..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_separated_list.cxx +++ /dev/null @@ -1,33 +0,0 @@ -#include - -#include "../test_helpers.hxx" - -// Test program for separated_list. - -namespace -{ -void test_separated_list() -{ - PQXX_CHECK_EQUAL( - pqxx::separated_list(",", std::vector{}), "", - "Empty list came out wrong."); - - PQXX_CHECK_EQUAL( - pqxx::separated_list(",", std::vector{5}), "5", - "Single-element list came out wrong."); - - PQXX_CHECK_EQUAL( - pqxx::separated_list(",", std::vector{3, 6}), "3,6", - "Things go wrong once separators come in."); - - std::vector const nums{1, 2, 3}; - PQXX_CHECK_EQUAL( - pqxx::separated_list( - "+", std::begin(nums), std::end(nums), - [](auto elt) { return *elt * 2; }), - "2+4+6", "Accessors don't seem to work."); -} - - -PQXX_REGISTER_TEST(test_separated_list); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_simultaneous_transactions.cxx b/ext/libpqxx-7.7.3/test/unit/test_simultaneous_transactions.cxx deleted file mode 100644 index 9c1e2fe9c..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_simultaneous_transactions.cxx +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_simultaneous_transactions() -{ - pqxx::connection conn; - - pqxx::nontransaction n1{conn}; - PQXX_CHECK_THROWS( - pqxx::nontransaction n2{conn}, std::logic_error, - "Allowed to open simultaneous nontransactions."); -} - - -PQXX_REGISTER_TEST(test_simultaneous_transactions); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_sql_cursor.cxx b/ext/libpqxx-7.7.3/test/unit/test_sql_cursor.cxx deleted file mode 100644 index a0109a00b..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_sql_cursor.cxx +++ /dev/null @@ -1,270 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_forward_sql_cursor() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - // Plain owned, scoped, forward-only read-only cursor. - pqxx::internal::sql_cursor forward( - tx, "SELECT generate_series(1, 4)", "forward", - pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, - pqxx::cursor_base::owned, false); - - PQXX_CHECK_EQUAL(forward.pos(), 0, "Wrong initial position"); - PQXX_CHECK_EQUAL(forward.endpos(), -1, "Wrong initial endpos()"); - - auto empty_result{forward.empty_result()}; - PQXX_CHECK_EQUAL(std::size(empty_result), 0, "Empty result not empty"); - - auto displacement{0}; - auto one{forward.fetch(1, displacement)}; - PQXX_CHECK_EQUAL(std::size(one), 1, "Fetched wrong number of rows"); - PQXX_CHECK_EQUAL(one[0][0].as(), "1", "Unexpected result"); - PQXX_CHECK_EQUAL(displacement, 1, "Wrong displacement"); - PQXX_CHECK_EQUAL(forward.pos(), 1, "In wrong position"); - - auto offset{forward.move(1, displacement)}; - PQXX_CHECK_EQUAL(offset, 1, "Unexpected offset from move()"); - PQXX_CHECK_EQUAL(displacement, 1, "Unexpected displacement after move()"); - PQXX_CHECK_EQUAL(forward.pos(), 2, "Wrong position after move()"); - PQXX_CHECK_EQUAL(forward.endpos(), -1, "endpos() unexpectedly set"); - - auto row{forward.fetch(0, displacement)}; - PQXX_CHECK_EQUAL(std::size(row), 0, "fetch(0, displacement) returns rows"); - PQXX_CHECK_EQUAL(displacement, 0, "Unexpected displacement after fetch(0)"); - PQXX_CHECK_EQUAL(forward.pos(), 2, "fetch(0, displacement) affected pos()"); - - row = forward.fetch(0); - PQXX_CHECK_EQUAL(std::size(row), 0, "fetch(0) fetched wrong number of rows"); - PQXX_CHECK_EQUAL(forward.pos(), 2, "fetch(0) moved cursor"); - PQXX_CHECK_EQUAL(forward.pos(), 2, "fetch(0) affected pos()"); - - offset = forward.move(1); - PQXX_CHECK_EQUAL(offset, 1, "move(1) returned unexpected value"); - PQXX_CHECK_EQUAL(forward.pos(), 3, "move(1) after fetch(0) broke"); - - row = forward.fetch(1); - PQXX_CHECK_EQUAL( - std::size(row), 1, "fetch(1) returned wrong number of rows"); - PQXX_CHECK_EQUAL(forward.pos(), 4, "fetch(1) results in bad pos()"); - PQXX_CHECK_EQUAL(row[0][0].as(), "4", "pos() is lying"); - - empty_result = forward.fetch(1, displacement); - PQXX_CHECK_EQUAL(std::size(empty_result), 0, "Got rows at end of cursor"); - PQXX_CHECK_EQUAL(forward.pos(), 5, "Not at one-past-end position"); - PQXX_CHECK_EQUAL(forward.endpos(), 5, "Failed to notice end position"); - PQXX_CHECK_EQUAL(displacement, 1, "Wrong displacement at end position"); - - offset = forward.move(5, displacement); - PQXX_CHECK_EQUAL(offset, 0, "move() lied at end of result set"); - PQXX_CHECK_EQUAL(forward.pos(), 5, "pos() is beyond end"); - PQXX_CHECK_EQUAL(forward.endpos(), 5, "endpos() changed after end position"); - PQXX_CHECK_EQUAL(displacement, 0, "Wrong displacement after end position"); - - // Move through entire result set at once. - pqxx::internal::sql_cursor forward2( - tx, "SELECT generate_series(1, 4)", "forward", - pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, - pqxx::cursor_base::owned, false); - - // Move through entire result set at once. - offset = forward2.move(pqxx::cursor_base::all(), displacement); - PQXX_CHECK_EQUAL(offset, 4, "Unexpected number of rows in result set"); - PQXX_CHECK_EQUAL(displacement, 5, "displacement != rows+1"); - PQXX_CHECK_EQUAL(forward2.pos(), 5, "Bad pos() after skipping all rows"); - PQXX_CHECK_EQUAL(forward2.endpos(), 5, "Bad endpos() after skipping"); - - pqxx::internal::sql_cursor forward3( - tx, "SELECT generate_series(1, 4)", "forward", - pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, - pqxx::cursor_base::owned, false); - - // Fetch entire result set at once. - auto rows{forward3.fetch(pqxx::cursor_base::all(), displacement)}; - PQXX_CHECK_EQUAL( - std::size(rows), 4, "Unexpected number of rows in result set"); - PQXX_CHECK_EQUAL(displacement, 5, "displacement != rows+1"); - PQXX_CHECK_EQUAL(forward3.pos(), 5, "Bad pos() after fetching all rows"); - PQXX_CHECK_EQUAL(forward3.endpos(), 5, "Bad endpos() after fetching"); - - pqxx::internal::sql_cursor forward_empty( - tx, "SELECT generate_series(0, -1)", "forward_empty", - pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, - pqxx::cursor_base::owned, false); - - offset = forward_empty.move(3, displacement); - PQXX_CHECK_EQUAL(forward_empty.pos(), 1, "Bad pos() at end of result"); - PQXX_CHECK_EQUAL(forward_empty.endpos(), 1, "Bad endpos() in empty result"); - PQXX_CHECK_EQUAL(displacement, 1, "Bad displacement in empty result"); - PQXX_CHECK_EQUAL(offset, 0, "move() in empty result counted rows"); -} - -void test_scroll_sql_cursor() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - pqxx::internal::sql_cursor scroll( - tx, "SELECT generate_series(1, 10)", "scroll", - pqxx::cursor_base::random_access, pqxx::cursor_base::read_only, - pqxx::cursor_base::owned, false); - - PQXX_CHECK_EQUAL(scroll.pos(), 0, "Scroll cursor's initial pos() is wrong"); - PQXX_CHECK_EQUAL(scroll.endpos(), -1, "New scroll cursor has endpos() set"); - - auto rows{scroll.fetch(pqxx::cursor_base::next())}; - PQXX_CHECK_EQUAL(std::size(rows), 1, "Scroll cursor is broken"); - PQXX_CHECK_EQUAL(scroll.pos(), 1, "Scroll cursor's pos() is broken"); - PQXX_CHECK_EQUAL(scroll.endpos(), -1, "endpos() set prematurely"); - - // Turn cursor around. This is where we begin to feel SQL cursors' - // semantics: we pre-decrement, ending up on the position in front of the - // first row and returning no rows. - rows = scroll.fetch(pqxx::cursor_base::prior()); - PQXX_CHECK_EQUAL(std::empty(rows), true, "Turning around on fetch() broke"); - PQXX_CHECK_EQUAL(scroll.pos(), 0, "pos() is not back at zero"); - PQXX_CHECK_EQUAL( - scroll.endpos(), -1, "endpos() set on wrong side of result"); - - // Bounce off the left-hand side of the result set. Can't move before the - // starting position. - auto offset{0}, displacement{0}; - offset = scroll.move(-3, displacement); - PQXX_CHECK_EQUAL(offset, 0, "Rows found before beginning"); - PQXX_CHECK_EQUAL(displacement, 0, "Failed to bounce off beginning"); - PQXX_CHECK_EQUAL(scroll.pos(), 0, "pos() moved back from zero"); - PQXX_CHECK_EQUAL(scroll.endpos(), -1, "endpos() set on left-side bounce"); - - // Try bouncing off the left-hand side a little harder. Take 4 paces away - // from the boundary and run into it. - offset = scroll.move(4, displacement); - PQXX_CHECK_EQUAL(offset, 4, "Offset mismatch"); - PQXX_CHECK_EQUAL(displacement, 4, "Displacement mismatch"); - PQXX_CHECK_EQUAL(scroll.pos(), 4, "Position mismatch"); - PQXX_CHECK_EQUAL(scroll.endpos(), -1, "endpos() set at weird time"); - - offset = scroll.move(-10, displacement); - PQXX_CHECK_EQUAL(offset, 3, "Offset mismatch"); - PQXX_CHECK_EQUAL(displacement, -4, "Displacement mismatch"); - PQXX_CHECK_EQUAL(scroll.pos(), 0, "Hard bounce failed"); - PQXX_CHECK_EQUAL(scroll.endpos(), -1, "endpos() set during hard bounce"); - - rows = scroll.fetch(3); - PQXX_CHECK_EQUAL(scroll.pos(), 3, "Bad pos()"); - PQXX_CHECK_EQUAL(std::size(rows), 3, "Wrong number of rows"); - PQXX_CHECK_EQUAL(rows[2][0].as(), 3, "pos() does not match data"); - rows = scroll.fetch(-1); - PQXX_CHECK_EQUAL(scroll.pos(), 2, "Bad pos()"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 2, "pos() does not match data"); - - rows = scroll.fetch(1); - PQXX_CHECK_EQUAL(scroll.pos(), 3, "Bad pos() after inverse turnaround"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 3, "Data position mismatch"); -} - - -void test_adopted_sql_cursor() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - tx.exec0( - "DECLARE adopted SCROLL CURSOR FOR " - "SELECT generate_series(1, 3)"); - pqxx::internal::sql_cursor adopted(tx, "adopted", pqxx::cursor_base::owned); - PQXX_CHECK_EQUAL(adopted.pos(), -1, "Adopted cursor has known pos()"); - PQXX_CHECK_EQUAL(adopted.endpos(), -1, "Adopted cursor has known endpos()"); - - auto displacement{0}; - auto rows{adopted.fetch(pqxx::cursor_base::all(), displacement)}; - PQXX_CHECK_EQUAL(std::size(rows), 3, "Wrong number of rows in result"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 1, "Wrong result data"); - PQXX_CHECK_EQUAL(rows[2][0].as(), 3, "Wrong result data"); - PQXX_CHECK_EQUAL(displacement, 4, "Wrong displacement"); - PQXX_CHECK_EQUAL( - adopted.pos(), -1, "End-of-result set pos() on adopted cur"); - PQXX_CHECK_EQUAL(adopted.endpos(), -1, "endpos() set too early"); - - rows = adopted.fetch(pqxx::cursor_base::backward_all(), displacement); - PQXX_CHECK_EQUAL(std::size(rows), 3, "Wrong number of rows in result"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 3, "Wrong result data"); - PQXX_CHECK_EQUAL(rows[2][0].as(), 1, "Wrong result data"); - PQXX_CHECK_EQUAL(displacement, -4, "Wrong displacement"); - PQXX_CHECK_EQUAL(adopted.pos(), 0, "Failed to recognize starting position"); - PQXX_CHECK_EQUAL(adopted.endpos(), -1, "endpos() set too early"); - - auto offset{adopted.move(pqxx::cursor_base::all())}; - PQXX_CHECK_EQUAL(offset, 3, "Unexpected move() offset"); - PQXX_CHECK_EQUAL(adopted.pos(), 4, "Bad position on adopted cursor"); - PQXX_CHECK_EQUAL(adopted.endpos(), 4, "endpos() not set properly"); - - // Owned adopted cursors are cleaned up on destruction. - pqxx::connection conn2; - pqxx::work tx2(conn2, "tx2"); - tx2.exec0( - "DECLARE adopted2 CURSOR FOR " - "SELECT generate_series(1, 3)"); - { - pqxx::internal::sql_cursor(tx2, "adopted2", pqxx::cursor_base::owned); - } - // Modern backends: accessing the cursor now is an error, as you'd expect. - PQXX_CHECK_THROWS( - tx2.exec("FETCH 1 IN adopted2"), pqxx::sql_error, - "Owned adopted cursor not cleaned up"); - - tx2.abort(); - - pqxx::work tx3(conn2, "tx3"); - tx3.exec( - "DECLARE adopted3 CURSOR FOR " - "SELECT generate_series(1, 3)"); - { - pqxx::internal::sql_cursor(tx3, "adopted3", pqxx::cursor_base::loose); - } - tx3.exec("MOVE 1 IN adopted3"); -} - -void test_hold_cursor() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - // "With hold" cursor is kept after commit. - pqxx::internal::sql_cursor with_hold( - tx, "SELECT generate_series(1, 3)", "hold_cursor", - pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, - pqxx::cursor_base::owned, true); - tx.commit(); - pqxx::work tx2(conn, "tx2"); - auto rows{with_hold.fetch(1)}; - PQXX_CHECK_EQUAL( - std::size(rows), 1, "Did not get 1 row from with-hold cursor"); - - // Cursor without hold is closed on commit. - pqxx::internal::sql_cursor no_hold( - tx2, "SELECT generate_series(1, 3)", "no_hold_cursor", - pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, - pqxx::cursor_base::owned, false); - tx2.commit(); - pqxx::work tx3(conn, "tx3"); - PQXX_CHECK_THROWS( - no_hold.fetch(1), pqxx::sql_error, "Cursor not closed on commit"); -} - - -void cursor_tests() -{ - test_forward_sql_cursor(); - test_scroll_sql_cursor(); - test_adopted_sql_cursor(); - test_hold_cursor(); -} - - -PQXX_REGISTER_TEST(cursor_tests); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_stateless_cursor.cxx b/ext/libpqxx-7.7.3/test/unit/test_stateless_cursor.cxx deleted file mode 100644 index 79307c19e..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_stateless_cursor.cxx +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_stateless_cursor() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - pqxx::stateless_cursor< - pqxx::cursor_base::read_only, pqxx::cursor_base::owned> - empty(tx, "SELECT generate_series(0, -1)", "empty", false); - - auto rows{empty.retrieve(0, 0)}; - PQXX_CHECK_EQUAL(std::empty(rows), true, "Empty result not empty"); - rows = empty.retrieve(0, 1); - PQXX_CHECK_EQUAL(std::size(rows), 0, "Empty result returned rows"); - - PQXX_CHECK_EQUAL(empty.size(), 0, "Empty cursor not empty"); - - PQXX_CHECK_THROWS( - empty.retrieve(1, 0), std::out_of_range, "Empty cursor tries to retrieve"); - - pqxx::stateless_cursor< - pqxx::cursor_base::read_only, pqxx::cursor_base::owned> - stateless(tx, "SELECT generate_series(0, 9)", "stateless", false); - - PQXX_CHECK_EQUAL(stateless.size(), 10, "stateless_cursor::size() mismatch"); - - // Retrieve nothing. - rows = stateless.retrieve(1, 1); - PQXX_CHECK_EQUAL(std::size(rows), 0, "1-to-1 retrieval not empty"); - - // Retrieve two rows. - rows = stateless.retrieve(1, 3); - PQXX_CHECK_EQUAL(std::size(rows), 2, "Retrieved wrong number of rows"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 1, "Data/position mismatch"); - PQXX_CHECK_EQUAL(rows[1][0].as(), 2, "Data/position mismatch"); - - // Retrieve same rows in reverse. - rows = stateless.retrieve(2, 0); - PQXX_CHECK_EQUAL(std::size(rows), 2, "Retrieved wrong number of rows"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 2, "Data/position mismatch"); - PQXX_CHECK_EQUAL(rows[1][0].as(), 1, "Data/position mismatch"); - - // Retrieve beyond end. - rows = stateless.retrieve(9, 13); - PQXX_CHECK_EQUAL(std::size(rows), 1, "Row count wrong at end"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 9, "Data/pos mismatch at end"); - - // Retrieve beyond beginning. - rows = stateless.retrieve(0, -4); - PQXX_CHECK_EQUAL(std::size(rows), 1, "Row count wrong at beginning"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 0, "Data/pos mismatch at beginning"); - - // Retrieve entire result set backwards. - rows = stateless.retrieve(10, -15); - PQXX_CHECK_EQUAL( - std::size(rows), 10, "Reverse complete retrieval is broken"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 9, "Data mismatch"); - PQXX_CHECK_EQUAL(rows[9][0].as(), 0, "Data mismatch"); - - // Normal usage pattern: step through result set, 4 rows at a time. - rows = stateless.retrieve(0, 4); - PQXX_CHECK_EQUAL(std::size(rows), 4, "Wrong batch size"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 0, "Batch in wrong place"); - PQXX_CHECK_EQUAL(rows[3][0].as(), 3, "Batch in wrong place"); - - rows = stateless.retrieve(4, 8); - PQXX_CHECK_EQUAL(std::size(rows), 4, "Wrong batch size"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 4, "Batch in wrong place"); - PQXX_CHECK_EQUAL(rows[3][0].as(), 7, "Batch in wrong place"); - - rows = stateless.retrieve(8, 12); - PQXX_CHECK_EQUAL(std::size(rows), 2, "Wrong batch size"); - PQXX_CHECK_EQUAL(rows[0][0].as(), 8, "Batch in wrong place"); - PQXX_CHECK_EQUAL(rows[1][0].as(), 9, "Batch in wrong place"); -} - - -PQXX_REGISTER_TEST(test_stateless_cursor); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_strconv.cxx b/ext/libpqxx-7.7.3/test/unit/test_strconv.cxx deleted file mode 100644 index 602084e18..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_strconv.cxx +++ /dev/null @@ -1,143 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -enum colour -{ - red, - green, - blue -}; -enum class weather : short -{ - hot, - cold, - wet -}; -enum class many : unsigned long long -{ - bottom = 0, - top = std::numeric_limits::max(), -}; -} // namespace - -namespace pqxx -{ -PQXX_DECLARE_ENUM_CONVERSION(colour); -PQXX_DECLARE_ENUM_CONVERSION(weather); -PQXX_DECLARE_ENUM_CONVERSION(many); -} // namespace pqxx - - -namespace -{ -void test_strconv_bool() -{ - PQXX_CHECK_EQUAL(pqxx::to_string(false), "false", "Wrong to_string(false)."); - PQXX_CHECK_EQUAL(pqxx::to_string(true), "true", "Wrong to_string(true)."); - - bool result; - pqxx::from_string("false", result); - PQXX_CHECK_EQUAL(result, false, "Wrong from_string('false')."); - pqxx::from_string("FALSE", result); - PQXX_CHECK_EQUAL(result, false, "Wrong from_string('FALSE')."); - pqxx::from_string("f", result); - PQXX_CHECK_EQUAL(result, false, "Wrong from_string('f')."); - pqxx::from_string("F", result); - PQXX_CHECK_EQUAL(result, false, "Wrong from_string('F')."); - pqxx::from_string("0", result); - PQXX_CHECK_EQUAL(result, false, "Wrong from_string('0')."); - pqxx::from_string("true", result); - PQXX_CHECK_EQUAL(result, true, "Wrong from_string('true')."); - pqxx::from_string("TRUE", result); - PQXX_CHECK_EQUAL(result, true, "Wrong from_string('TRUE')."); - pqxx::from_string("t", result); - PQXX_CHECK_EQUAL(result, true, "Wrong from_string('t')."); - pqxx::from_string("T", result); - PQXX_CHECK_EQUAL(result, true, "Wrong from_string('T')."); - pqxx::from_string("1", result); - PQXX_CHECK_EQUAL(result, true, "Wrong from_string('1')."); -} - - -void test_strconv_enum() -{ - PQXX_CHECK_EQUAL(pqxx::to_string(red), "0", "Enum value did not convert."); - PQXX_CHECK_EQUAL(pqxx::to_string(green), "1", "Enum value did not convert."); - PQXX_CHECK_EQUAL(pqxx::to_string(blue), "2", "Enum value did not convert."); - - colour col; - pqxx::from_string("2", col); - PQXX_CHECK_EQUAL(col, blue, "Could not recover enum value from string."); -} - - -void test_strconv_class_enum() -{ - PQXX_CHECK_EQUAL( - pqxx::to_string(weather::hot), "0", "Class enum value did not convert."); - PQXX_CHECK_EQUAL( - pqxx::to_string(weather::wet), "2", "Enum value did not convert."); - - weather w; - pqxx::from_string("2", w); - PQXX_CHECK_EQUAL( - w, weather::wet, "Could not recover class enum value from string."); - - PQXX_CHECK_EQUAL( - pqxx::to_string(many::bottom), "0", - "Small wide enum did not convert right."); - PQXX_CHECK_EQUAL( - pqxx::to_string(many::top), - pqxx::to_string(std::numeric_limits::max()), - "Large wide enum did not convert right."); -} - - -void test_strconv_optional() -{ - PQXX_CHECK_THROWS( - pqxx::to_string(std::optional{}), pqxx::conversion_error, - "Converting an empty optional did not throw conversion error."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::optional{std::in_place, 10}), "10", - "std::optional does not convert right."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::optional{std::in_place, -10000}), "-10000", - "std::optional does not convert right."); -} - - -void test_strconv_smart_pointer() -{ - PQXX_CHECK_THROWS( - pqxx::to_string(std::unique_ptr{}), pqxx::conversion_error, - "Converting an empty unique_ptr did not throw conversion error."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::make_unique(10)), "10", - "std::unique_ptr does not convert right."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::make_unique(-10000)), "-10000", - "std::unique_ptr does not convert right."); - - PQXX_CHECK_THROWS( - pqxx::to_string(std::shared_ptr{}), pqxx::conversion_error, - "Converting an empty shared_ptr did not throw conversion error."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::make_shared(10)), "10", - "std::shared_ptr does not convert right."); - PQXX_CHECK_EQUAL( - pqxx::to_string(std::make_shared(-10000)), "-10000", - "std::shared_ptr does not convert right."); -} - - -PQXX_REGISTER_TEST(test_strconv_bool); -PQXX_REGISTER_TEST(test_strconv_enum); -PQXX_REGISTER_TEST(test_strconv_class_enum); -PQXX_REGISTER_TEST(test_strconv_optional); -PQXX_REGISTER_TEST(test_strconv_smart_pointer); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_stream_from.cxx b/ext/libpqxx-7.7.3/test/unit/test_stream_from.cxx deleted file mode 100644 index d8adb8bd1..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_stream_from.cxx +++ /dev/null @@ -1,344 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" -#include "../test_types.hxx" - -#include -#include -#include -#include -#include -#include - -#include - - -namespace -{ -void test_nonoptionals(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto extractor{pqxx::stream_from::query( - tx, "SELECT * FROM stream_from_test ORDER BY number0")}; - PQXX_CHECK(extractor, "stream_from failed to initialize."); - - std::tuple got_tuple; - - try - { - // We can't read the "910" row -- it contains nulls, which our tuple does - // not accept. - extractor >> got_tuple; - PQXX_CHECK_NOTREACHED( - "Failed to fail to stream null values into null-less fields."); - } - catch (pqxx::conversion_error const &e) - { - std::string const what{e.what()}; - if (what.find("null") == std::string::npos) - throw; - pqxx::test::expected_exception( - "Could not stream nulls into null-less fields: " + what); - } - - // The stream is still good though. - // The second tuple is fine. - extractor >> got_tuple; - PQXX_CHECK(extractor, "Stream ended prematurely."); - - PQXX_CHECK_EQUAL(std::get<0>(got_tuple), 1234, "Bad value."); - // Don't know much about the timestamp, but let's assume it starts with a - // year in the second millennium. - PQXX_CHECK( - std::get<1>(got_tuple).at(0) == '2', "Bad value. Expected timestamp."); - PQXX_CHECK_LESS( - std::size(std::get<1>(got_tuple)), 40u, "Unexpected length."); - PQXX_CHECK_GREATER( - std::size(std::get<1>(got_tuple)), 20u, "Unexpected length."); - PQXX_CHECK_EQUAL(std::get<2>(got_tuple), 4321, "Bad value."); - PQXX_CHECK_EQUAL(std::get<3>(got_tuple), (ipv4{8, 8, 8, 8}), "Bad value."); - PQXX_CHECK_EQUAL(std::get<4>(got_tuple), "hello\n \tworld", "Bad value."); - PQXX_CHECK_EQUAL( - std::get<5>(got_tuple), (bytea{'\x00', '\x01', '\x02'}), "Bad value."); - - // The third tuple contains some nulls. For what it's worth, when we *know* - // that we're getting nulls, we can stream them into nullptr_t fields. - std::tuple< - int, std::string, std::nullptr_t, std::nullptr_t, std::string, bytea> - tup_w_nulls; - - extractor >> tup_w_nulls; - PQXX_CHECK(extractor, "Stream ended prematurely."); - - PQXX_CHECK_EQUAL(std::get<0>(tup_w_nulls), 5678, "Bad value."); - PQXX_CHECK(std::get<2>(tup_w_nulls) == nullptr, "Bad null."); - PQXX_CHECK(std::get<3>(tup_w_nulls) == nullptr, "Bad null."); - - // We're at the end of the stream. - extractor >> tup_w_nulls; - PQXX_CHECK(not extractor, "Stream did not end."); - - // Of course we can't stream a non-null value into a nullptr field. - auto ex2{pqxx::stream_from::query(tx, "SELECT 1")}; - std::tuple null_tup; - try - { - ex2 >> null_tup; - PQXX_CHECK_NOTREACHED( - "stream_from should have refused to convert non-null value to " - "nullptr_t."); - } - catch (pqxx::conversion_error const &e) - { - std::string const what{e.what()}; - if (what.find("null") == std::string::npos) - throw; - pqxx::test::expected_exception( - std::string{"Could not extract row: "} + what); - } - ex2 >> null_tup; - PQXX_CHECK(not ex2, "Stream did not end."); - - PQXX_CHECK_SUCCEEDS( - tx.exec1("SELECT 1"), "Could not use transaction after stream_from."); -} - - -void test_bad_tuples(pqxx::connection &conn) -{ - pqxx::work tx{conn}; - auto extractor{pqxx::stream_from::table(tx, {"stream_from_test"})}; - PQXX_CHECK(extractor, "stream_from failed to initialize"); - - std::tuple got_tuple_too_short; - try - { - extractor >> got_tuple_too_short; - PQXX_CHECK_NOTREACHED("stream_from improperly read first row"); - } - catch (pqxx::usage_error const &e) - { - std::string what{e.what()}; - if ( - what.find("1") == std::string::npos or - what.find("6") == std::string::npos) - throw; - pqxx::test::expected_exception("Tuple is wrong size: " + what); - } - - std::tuple - got_tuple_too_long; - try - { - extractor >> got_tuple_too_long; - PQXX_CHECK_NOTREACHED("stream_from improperly read first row"); - } - catch (pqxx::usage_error const &e) - { - std::string what{e.what()}; - if ( - what.find("6") == std::string::npos or - what.find("7") == std::string::npos) - throw; - pqxx::test::expected_exception("Could not extract row: " + what); - } - - extractor.complete(); -} - - -#define ASSERT_FIELD_EQUAL(OPT, VAL) \ - PQXX_CHECK(static_cast(OPT), "unexpected null field"); \ - PQXX_CHECK_EQUAL(*OPT, VAL, "field value mismatch") -#define ASSERT_FIELD_NULL(OPT) \ - PQXX_CHECK(not static_cast(OPT), "expected null field") - - -template class O> -void test_optional(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto extractor{pqxx::stream_from::query( - tx, "SELECT * FROM stream_from_test ORDER BY number0")}; - PQXX_CHECK(extractor, "stream_from failed to initialize"); - - std::tuple, O, O, O, O> - got_tuple; - - extractor >> got_tuple; - PQXX_CHECK(extractor, "stream_from failed to read third row"); - PQXX_CHECK_EQUAL(std::get<0>(got_tuple), 910, "field value mismatch"); - ASSERT_FIELD_NULL(std::get<1>(got_tuple)); - ASSERT_FIELD_NULL(std::get<2>(got_tuple)); - ASSERT_FIELD_NULL(std::get<3>(got_tuple)); - ASSERT_FIELD_EQUAL(std::get<4>(got_tuple), "\\N"); - ASSERT_FIELD_EQUAL(std::get<5>(got_tuple), bytea{}); - - extractor >> got_tuple; - PQXX_CHECK(extractor, "stream_from failed to read first row."); - PQXX_CHECK_EQUAL(std::get<0>(got_tuple), 1234, "Field value mismatch."); - PQXX_CHECK( - static_cast(std::get<1>(got_tuple)), "Unexpected null field."); - // PQXX_CHECK_EQUAL(*std::get<1>(got_tuple), , "field value mismatch"); - ASSERT_FIELD_EQUAL(std::get<2>(got_tuple), 4321); - ASSERT_FIELD_EQUAL(std::get<3>(got_tuple), (ipv4{8, 8, 8, 8})); - ASSERT_FIELD_EQUAL(std::get<4>(got_tuple), "hello\n \tworld"); - ASSERT_FIELD_EQUAL(std::get<5>(got_tuple), (bytea{'\x00', '\x01', '\x02'})); - - extractor >> got_tuple; - PQXX_CHECK(extractor, "stream_from failed to read second row"); - PQXX_CHECK_EQUAL(std::get<0>(got_tuple), 5678, "field value mismatch"); - ASSERT_FIELD_EQUAL(std::get<1>(got_tuple), "2018-11-17 21:23:00"); - ASSERT_FIELD_NULL(std::get<2>(got_tuple)); - ASSERT_FIELD_NULL(std::get<3>(got_tuple)); - ASSERT_FIELD_EQUAL(std::get<4>(got_tuple), "\u3053\u3093\u306b\u3061\u308f"); - ASSERT_FIELD_EQUAL( - std::get<5>(got_tuple), (bytea{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'})); - - extractor >> got_tuple; - PQXX_CHECK(not extractor, "stream_from failed to detect end of stream"); - - extractor.complete(); -} - - -void test_stream_from() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0( - "CREATE TEMP TABLE stream_from_test (" - "number0 INT NOT NULL," - "ts1 TIMESTAMP NULL," - "number2 INT NULL," - "addr3 INET NULL," - "txt4 TEXT NULL," - "bin5 BYTEA NOT NULL" - ")"); - tx.exec_params( - "INSERT INTO stream_from_test VALUES ($1,$2,$3,$4,$5,$6)", 910, nullptr, - nullptr, nullptr, "\\N", bytea{}); - tx.exec_params( - "INSERT INTO stream_from_test VALUES ($1,$2,$3,$4,$5,$6)", 1234, "now", - 4321, ipv4{8, 8, 8, 8}, "hello\n \tworld", bytea{'\x00', '\x01', '\x02'}); - tx.exec_params( - "INSERT INTO stream_from_test VALUES ($1,$2,$3,$4,$5,$6)", 5678, - "2018-11-17 21:23:00", nullptr, nullptr, "\u3053\u3093\u306b\u3061\u308f", - bytea{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}); - tx.commit(); - - test_nonoptionals(conn); - test_bad_tuples(conn); - std::cout << "testing `std::unique_ptr` as optional...\n"; - test_optional(conn); - std::cout << "testing `std::optional` as optional...\n"; - test_optional(conn); -} - - -void test_stream_from_does_escaping() -{ - std::string const input{"a\t\n\n\n \\b\nc"}; - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0("CREATE TEMP TABLE badstr (str text)"); - tx.exec0("INSERT INTO badstr (str) VALUES (" + tx.quote(input) + ")"); - auto reader{pqxx::stream_from::table(tx, {"badstr"})}; - std::tuple out; - reader >> out; - PQXX_CHECK_EQUAL( - std::get<0>(out), input, "stream_from got weird characters wrong."); -} - - -void test_stream_from_does_iteration() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0("CREATE TEMP TABLE str (s text)"); - tx.exec0("INSERT INTO str (s) VALUES ('foo')"); - auto reader{pqxx::stream_from::table(tx, {"str"})}; - - int i{0}; - std::string out; - for (std::tuple t : reader.iter()) - { - i++; - out = std::get<0>(t); - } - PQXX_CHECK_EQUAL(i, 1, "Wrong number of iterations."); - PQXX_CHECK_EQUAL(out, "foo", "Got wrong string."); - - tx.exec0("INSERT INTO str (s) VALUES ('bar')"); - i = 0; - std::set strings; - auto reader2{pqxx::stream_from::table(tx, {"str"})}; - for (std::tuple t : reader2.iter()) - { - i++; - strings.insert(std::get<0>(t)); - } - PQXX_CHECK_EQUAL(i, 2, "Wrong number of iterations."); - PQXX_CHECK_EQUAL( - std::size(strings), 2u, "Wrong number of strings retrieved."); - PQXX_CHECK(strings.find("foo") != std::end(strings), "Missing key."); - PQXX_CHECK(strings.find("bar") != std::end(strings), "Missing key."); -} - - -void test_transaction_stream_from() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0("CREATE TEMP TABLE sample (id integer, name varchar)"); - tx.exec0("INSERT INTO sample (id, name) VALUES (321, 'something')"); - - int items{0}; - int id{0}; - std::string name; - - for (auto [iid, iname] : - tx.stream("SELECT id, name FROM sample")) - { - items++; - id = iid; - name = iname; - } - PQXX_CHECK_EQUAL(items, 1, "Wrong number of iterations."); - PQXX_CHECK_EQUAL(id, 321, "Got wrong int."); - PQXX_CHECK_EQUAL(name, std::string{"something"}, "Got wrong string."); - - PQXX_CHECK_EQUAL( - tx.query_value("SELECT 4"), 4, - "Loop did not relinquish transaction."); -} - - -void test_stream_from_read_row() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0("CREATE TEMP TABLE sample (id integer, name varchar, opt integer)"); - tx.exec0("INSERT INTO sample (id, name) VALUES (321, 'something')"); - - auto stream{pqxx::stream_from::table(tx, {"sample"})}; - auto fields{stream.read_row()}; - PQXX_CHECK_EQUAL(fields->size(), 3ul, "Wrong number of fields."); - PQXX_CHECK_EQUAL( - std::string((*fields)[0]), "321", "Integer field came out wrong."); - PQXX_CHECK_EQUAL( - std::string((*fields)[1]), "something", "Text field came out wrong."); - PQXX_CHECK(std::data((*fields)[2]) == nullptr, "Null field came out wrong."); - - auto last{stream.read_row()}; - PQXX_CHECK(last == nullptr, "No null pointer at end of stream."); -} - - -PQXX_REGISTER_TEST(test_stream_from); -PQXX_REGISTER_TEST(test_stream_from_does_escaping); -PQXX_REGISTER_TEST(test_stream_from_does_iteration); -PQXX_REGISTER_TEST(test_transaction_stream_from); -PQXX_REGISTER_TEST(test_stream_from_read_row); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_stream_to.cxx b/ext/libpqxx-7.7.3/test/unit/test_stream_to.cxx deleted file mode 100644 index ae4eb3c65..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_stream_to.cxx +++ /dev/null @@ -1,445 +0,0 @@ -#include -#include - -#include -#include - -#include "../test_helpers.hxx" -#include "../test_types.hxx" - -namespace -{ -std::string truncate_sql_error(std::string const &what) -{ - auto trunc{what.substr(0, what.find('\n'))}; - if (std::size(trunc) > 64) - trunc = trunc.substr(0, 61) + "..."; - return trunc; -} - - -void test_nonoptionals(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - auto const nonascii{"\u3053\u3093\u306b\u3061\u308f"}; - bytea const binary{'\x00', '\x01', '\x02'}, - text{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}; - - inserter << std::make_tuple( - 1234, "now", 4321, ipv4{8, 8, 4, 4}, "hello nonoptional world", binary); - inserter << std::make_tuple( - 5678, "2018-11-17 21:23:00", nullptr, nullptr, nonascii, text); - inserter << std::make_tuple(910, nullptr, nullptr, nullptr, "\\N", bytea{}); - - inserter.complete(); - - auto r1{tx.exec1("SELECT * FROM stream_to_test WHERE number0 = 1234")}; - PQXX_CHECK_EQUAL(r1[0].as(), 1234, "Read back wrong first int."); - PQXX_CHECK_EQUAL( - r1[4].as(), "hello nonoptional world", - "Read back wrong string."); - PQXX_CHECK_EQUAL(r1[3].as(), ipv4(8, 8, 4, 4), "Read back wrong ip."); - PQXX_CHECK_EQUAL(r1[5].as(), binary, "Read back wrong bytea."); - - auto r2{tx.exec1("SELECT * FROM stream_to_test WHERE number0 = 5678")}; - PQXX_CHECK_EQUAL(r2[0].as(), 5678, "Wrong int on second row."); - PQXX_CHECK(r2[2].is_null(), "Field 2 was meant to be null."); - PQXX_CHECK(r2[3].is_null(), "Field 3 was meant to be null."); - PQXX_CHECK_EQUAL(r2[4].as(), nonascii, "Wrong non-ascii text."); - tx.commit(); -} - -void test_nonoptionals_fold(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - auto const nonascii{"\u3053\u3093\u306b\u3061\u308f"}; - bytea const binary{'\x00', '\x01', '\x02'}, - text{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}; - - inserter.write_values( - 1234, "now", 4321, ipv4{8, 8, 4, 4}, "hello nonoptional world", binary); - inserter.write_values( - 5678, "2018-11-17 21:23:00", nullptr, nullptr, nonascii, text); - inserter.write_values(910, nullptr, nullptr, nullptr, "\\N", bytea{}); - - inserter.complete(); - - auto r1{tx.exec1("SELECT * FROM stream_to_test WHERE number0 = 1234")}; - PQXX_CHECK_EQUAL(r1[0].as(), 1234, "Read back wrong first int."); - PQXX_CHECK_EQUAL( - r1[4].as(), "hello nonoptional world", - "Read back wrong string."); - PQXX_CHECK_EQUAL(r1[3].as(), ipv4(8, 8, 4, 4), "Read back wrong ip."); - PQXX_CHECK_EQUAL(r1[5].as(), binary, "Read back wrong bytera."); - - auto r2{tx.exec1("SELECT * FROM stream_to_test WHERE number0 = 5678")}; - PQXX_CHECK_EQUAL(r2[0].as(), 5678, "Wrong int on second row."); - PQXX_CHECK(r2[2].is_null(), "Field 2 was meant to be null."); - PQXX_CHECK(r2[3].is_null(), "Field 3 was meant to be null."); - PQXX_CHECK_EQUAL(r2[4].as(), nonascii, "Wrong non-ascii text."); - tx.commit(); -} - - -/// Try to violate stream_to_test's not-null constraint using a stream_to. -void insert_bad_null_tuple(pqxx::stream_to &inserter) -{ - inserter << std::make_tuple( - nullptr, "now", 4321, ipv4{8, 8, 8, 8}, "hello world", - bytea{'\x00', '\x01', '\x02'}); - inserter.complete(); -} - - -void test_bad_null(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - PQXX_CHECK_THROWS( - insert_bad_null_tuple(inserter), pqxx::not_null_violation, - "Did not expected not_null_violation when stream_to inserts a bad null."); -} - - -/// Try to violate stream_to_test's not-null construct using a stream_to. -void insert_bad_null_write(pqxx::stream_to &inserter) -{ - inserter.write_values( - nullptr, "now", 4321, ipv4{8, 8, 8, 8}, "hello world", - bytea{'\x00', '\x01', '\x02'}); - inserter.complete(); -} - - -void test_bad_null_fold(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - PQXX_CHECK_THROWS( - insert_bad_null_write(inserter), pqxx::not_null_violation, - "Did not expected not_null_violation when stream_to inserts a bad null."); -} - - -void test_too_few_fields(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - try - { - inserter << std::make_tuple(1234, "now", 4321, ipv4{8, 8, 8, 8}); - inserter.complete(); - tx.commit(); - PQXX_CHECK_NOTREACHED("stream_from improperly inserted row"); - } - catch (pqxx::sql_error const &e) - { - std::string what{e.what()}; - if (what.find("missing data for column") == std::string::npos) - throw; - pqxx::test::expected_exception( - "Could not insert row: " + truncate_sql_error(what)); - } -} - -void test_too_few_fields_fold(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - try - { - inserter.write_values(1234, "now", 4321, ipv4{8, 8, 8, 8}); - inserter.complete(); - tx.commit(); - PQXX_CHECK_NOTREACHED("stream_from_fold improperly inserted row"); - } - catch (pqxx::sql_error const &e) - { - std::string what{e.what()}; - if (what.find("missing data for column") == std::string::npos) - throw; - pqxx::test::expected_exception( - "Fold - Could not insert row: " + truncate_sql_error(what)); - } -} - - -void test_too_many_fields(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - try - { - inserter << std::make_tuple( - 1234, "now", 4321, ipv4{8, 8, 8, 8}, "hello world", - bytea{'\x00', '\x01', '\x02'}, 5678); - inserter.complete(); - tx.commit(); - PQXX_CHECK_NOTREACHED("stream_from improperly inserted row"); - } - catch (pqxx::sql_error const &e) - { - std::string what{e.what()}; - if (what.find("extra data") == std::string::npos) - throw; - pqxx::test::expected_exception( - "Could not insert row: " + truncate_sql_error(what)); - } -} - -void test_too_many_fields_fold(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - try - { - inserter.write_values( - 1234, "now", 4321, ipv4{8, 8, 8, 8}, "hello world", - bytea{'\x00', '\x01', '\x02'}, 5678); - inserter.complete(); - tx.commit(); - PQXX_CHECK_NOTREACHED("stream_from_fold improperly inserted row"); - } - catch (pqxx::sql_error const &e) - { - std::string what{e.what()}; - if (what.find("extra data") == std::string::npos) - throw; - pqxx::test::expected_exception( - "Fold - Could not insert row: " + truncate_sql_error(what)); - } -} - - -void test_stream_to_does_nonnull_optional() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0("CREATE TEMP TABLE foo(x integer, y text)"); - auto inserter{pqxx::stream_to::table(tx, {"foo"})}; - inserter.write_values( - std::optional{368}, std::optional{"Text"}); - inserter.complete(); - auto const row{tx.exec1("SELECT x, y FROM foo")}; - PQXX_CHECK_EQUAL( - row[0].as(), "368", "Non-null int optional came out wrong."); - PQXX_CHECK_EQUAL( - row[1].as(), "Text", - "Non-null string optional came out wrong."); -} - - -template class O> -void test_optional(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - inserter << std::make_tuple( - 910, O{pqxx::nullness>::null()}, - O{pqxx::nullness>::null()}, - O{pqxx::nullness>::null()}, "\\N", bytea{}); - - inserter.complete(); - tx.commit(); -} - -template class O> -void test_optional_fold(pqxx::connection &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - inserter.write_values( - 910, O{pqxx::nullness>::null()}, - O{pqxx::nullness>::null()}, - O{pqxx::nullness>::null()}, "\\N", bytea{}); - - inserter.complete(); - tx.commit(); -} - - -// As an alternative to a tuple, you can also insert a container. -void test_container_stream_to() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - tx.exec0("CREATE TEMP TABLE test_container(a integer, b integer)"); - - auto inserter{pqxx::stream_to::table(tx, {"test_container"})}; - - inserter << std::vector{112, 244}; - inserter.complete(); - - auto read{tx.exec1("SELECT * FROM test_container")}; - PQXX_CHECK_EQUAL( - read[0].as(), 112, "stream_to on container went wrong."); - PQXX_CHECK_EQUAL( - read[1].as(), 244, "Second container field went wrong."); - tx.commit(); -} - -void test_variant_fold(pqxx::connection_base &connection) -{ - pqxx::work tx{connection}; - auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; - PQXX_CHECK(inserter, "stream_to failed to initialize"); - - inserter.write_values( - std::variant{1234}, - std::variant{"now"}, 4321, ipv4{8, 8, 8, 8}, - "hello world", bytea{'\x00', '\x01', '\x02'}); - inserter.write_values( - 5678, "2018-11-17 21:23:00", nullptr, nullptr, - "\u3053\u3093\u306b\u3061\u308f", - bytea{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}); - inserter.write_values(910, nullptr, nullptr, nullptr, "\\N", bytea{}); - - inserter.complete(); - tx.commit(); -} - -void clear_table(pqxx::connection &conn) -{ - pqxx::work tx{conn}; - tx.exec0("DELETE FROM stream_to_test"); - tx.commit(); -} - - -void test_stream_to() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - tx.exec0( - "CREATE TEMP TABLE stream_to_test (" - "number0 INT NOT NULL," - "ts1 TIMESTAMP NULL," - "number2 INT NULL," - "addr3 INET NULL," - "txt4 TEXT NULL," - "bin5 BYTEA NOT NULL" - ")"); - tx.commit(); - - test_nonoptionals(conn); - clear_table(conn); - test_nonoptionals_fold(conn); - clear_table(conn); - test_bad_null(conn); - clear_table(conn); - test_bad_null_fold(conn); - clear_table(conn); - test_too_few_fields(conn); - clear_table(conn); - test_too_few_fields_fold(conn); - clear_table(conn); - test_too_many_fields(conn); - clear_table(conn); - test_too_many_fields_fold(conn); - clear_table(conn); - test_optional(conn); - clear_table(conn); - test_optional_fold(conn); - clear_table(conn); - test_optional(conn); - clear_table(conn); - test_optional_fold(conn); - clear_table(conn); - test_variant_fold(conn); -} - - -void test_stream_to_factory_with_static_columns() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - tx.exec0("CREATE TEMP TABLE pqxx_stream_to(a integer, b varchar)"); - - auto stream{pqxx::stream_to::table(tx, {"pqxx_stream_to"}, {"a", "b"})}; - stream.write_values(3, "three"); - stream.complete(); - - auto r{tx.exec1("SELECT a, b FROM pqxx_stream_to")}; - PQXX_CHECK_EQUAL(r[0].as(), 3, "Failed to stream_to a table."); - PQXX_CHECK_EQUAL( - r[1].as(), "three", - "Failed to stream_to a string to a table."); -} - - -void test_stream_to_factory_with_dynamic_columns() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - tx.exec0("CREATE TEMP TABLE pqxx_stream_to(a integer, b varchar)"); - - std::vector columns{"a", "b"}; -#if defined(PQXX_HAVE_CONCEPTS) - auto stream{pqxx::stream_to::table(tx, {"pqxx_stream_to"}, columns)}; -#else - auto stream{pqxx::stream_to::raw_table( - tx, conn.quote_table({"pqxx_stream_to"}), conn.quote_columns(columns))}; -#endif - stream.write_values(4, "four"); - stream.complete(); - - auto r{tx.exec1("SELECT a, b FROM pqxx_stream_to")}; - PQXX_CHECK_EQUAL( - r[0].as(), 4, "Failed to stream_to a table with dynamic columns."); - PQXX_CHECK_EQUAL( - r[1].as(), "four", - "Failed to stream_to a string to a table with dynamic columns."); -} - - -void test_stream_to_quotes_arguments() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - - std::string const table{R"--(pqxx_Stream"'x)--"}, column{R"--(a'"b)--"}; - - tx.exec0( - "CREATE TEMP TABLE " + tx.quote_name(table) + "(" + tx.quote_name(column) + - " integer)"); - auto write{pqxx::stream_to::table(tx, {table}, {column})}; - write.write_values(12); - write.complete(); - - PQXX_CHECK_EQUAL( - tx.query_value( - "SELECT " + tx.quote_name(column) + " FROM " + tx.quote_name(table)), - 12, "Stream wrote wrong value."); -} - - -PQXX_REGISTER_TEST(test_stream_to); -PQXX_REGISTER_TEST(test_container_stream_to); -PQXX_REGISTER_TEST(test_stream_to_does_nonnull_optional); -PQXX_REGISTER_TEST(test_stream_to_factory_with_static_columns); -PQXX_REGISTER_TEST(test_stream_to_factory_with_dynamic_columns); -PQXX_REGISTER_TEST(test_stream_to_quotes_arguments); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_string_conversion.cxx b/ext/libpqxx-7.7.3/test/unit/test_string_conversion.cxx deleted file mode 100644 index 30bc084f5..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_string_conversion.cxx +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include - -#include -#include - -#include "../test_helpers.hxx" - -// Some enums with string conversions. -enum EnumA -{ - ea0, - ea1, - ea2 -}; -enum EnumB -{ - eb0, - eb1, - eb2 -}; -namespace pqxx -{ -PQXX_DECLARE_ENUM_CONVERSION(EnumA); -PQXX_DECLARE_ENUM_CONVERSION(EnumB); -} // namespace pqxx - - -namespace -{ -// "A minimal difference." -constexpr double thres{0.00001}; - - -void test_string_conversion() -{ - PQXX_CHECK_EQUAL( - "C string array", pqxx::to_string("C string array"), - "C-style string constant does not convert to string properly."); - - char text_array[]{"C char array"}; - PQXX_CHECK_EQUAL( - "C char array", pqxx::to_string(text_array), - "C-style non-const char array does not convert to string properly."); - - char const *text_ptr{"C string pointer"}; - PQXX_CHECK_EQUAL( - "C string pointer", pqxx::to_string(text_ptr), - "C-style string pointer does not convert to string properly."); - - std::string const cxx_string{"C++ string"}; - PQXX_CHECK_EQUAL( - "C++ string", pqxx::to_string(cxx_string), - "C++-style string object does not convert to string properly."); - - PQXX_CHECK_EQUAL("0", pqxx::to_string(0), "Zero does not convert right."); - PQXX_CHECK_EQUAL( - "1", pqxx::to_string(1), "Basic integer does not convert right."); - PQXX_CHECK_EQUAL("-1", pqxx::to_string(-1), "Negative numbers don't work."); - PQXX_CHECK_EQUAL( - "9999", pqxx::to_string(9999), "Larger numbers don't work."); - PQXX_CHECK_EQUAL( - "-9999", pqxx::to_string(-9999), "Larger negative numbers don't work."); - - int x; - pqxx::from_string("0", x); - PQXX_CHECK_EQUAL(0, x, "Zero does not parse right."); - pqxx::from_string("1", x); - PQXX_CHECK_EQUAL(1, x, "Basic integer does not parse right."); - pqxx::from_string("-1", x); - PQXX_CHECK_EQUAL(-1, x, "Negative numbers don't work."); - pqxx::from_string("9999", x); - PQXX_CHECK_EQUAL(9999, x, "Larger numbers don't work."); - pqxx::from_string("-9999", x); - PQXX_CHECK_EQUAL(-9999, x, "Larger negative numbers don't work."); - - // Bug #263 describes a case where this kind of overflow went undetected. - if (sizeof(unsigned int) == 4) - { - std::uint32_t u; - PQXX_CHECK_THROWS( - pqxx::from_string("4772185884", u), pqxx::conversion_error, - "Overflow not detected."); - } - - // We can convert to and from long double. The implementation may fall - // back on a thread-local std::stringstream. Each call does its own - // cleanup, so the conversion works multiple times. - constexpr long double ld1{123456789.25}, ld2{9876543210.5}; - constexpr char lds1[]{"123456789.25"}, lds2[]{"9876543210.5"}; - PQXX_CHECK_EQUAL( - pqxx::to_string(ld1).substr(0, 12), lds1, - "Wrong conversion from long double."); - PQXX_CHECK_EQUAL( - pqxx::to_string(ld2).substr(0, 12), lds2, - "Wrong value on repeated conversion from long double."); - long double ldi1, ldi2; - pqxx::from_string(lds1, ldi1); - PQXX_CHECK_BOUNDS( - ldi1, ld1 - thres, ld1 + thres, "Wrong conversion to long double."); - pqxx::from_string(lds2, ldi2); - PQXX_CHECK_BOUNDS( - ldi2, ld2 - thres, ld2 + thres, - "Wrong repeated conversion to long double."); - - // We can define string conversions for enums. - PQXX_CHECK_EQUAL( - pqxx::to_string(ea0), "0", "Enum-to-string conversion is broken."); - PQXX_CHECK_EQUAL( - pqxx::to_string(eb0), "0", - "Enum-to-string conversion is inconsistent between enum types."); - PQXX_CHECK_EQUAL( - pqxx::to_string(ea1), "1", - "Enum-to-string conversion breaks for nonzero value."); - - EnumA ea; - pqxx::from_string("2", ea); - PQXX_CHECK_EQUAL(ea, ea2, "String-to-enum conversion is broken."); -} - - -void test_convert_variant_to_string() -{ - PQXX_CHECK_EQUAL( - pqxx::to_string(std::variant{99}), "99", - "First variant field did not convert right."); - - PQXX_CHECK_EQUAL( - pqxx::to_string(std::variant{"Text"}), "Text", - "Second variant field did not convert right."); -} - - -void test_integer_conversion() -{ - PQXX_CHECK_EQUAL( - pqxx::from_string("12"), 12, "Basic integer conversion failed."); - PQXX_CHECK_EQUAL( - pqxx::from_string(" 12"), 12, - "Leading whitespace confused integer conversion."); - PQXX_CHECK_THROWS( - pqxx::ignore_unused(pqxx::from_string("")), pqxx::conversion_error, - "Converting empty string to integer did not throw conversion error."); - PQXX_CHECK_THROWS( - pqxx::ignore_unused(pqxx::from_string(" ")), pqxx::conversion_error, - "Converting whitespace to integer did not throw conversion error."); - PQXX_CHECK_EQUAL( - pqxx::from_string("-6"), -6, - "Leading whitespace did not work with negative number."); - PQXX_CHECK_THROWS( - pqxx::ignore_unused(pqxx::from_string("- 3")), pqxx::conversion_error, - "A space between negation and number was not properly flagged."); - PQXX_CHECK_THROWS( - pqxx::ignore_unused(pqxx::from_string("-")), pqxx::conversion_error, - "Just a minus sign should not parse as an integer."); -} - - -void test_convert_null() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - PQXX_CHECK_EQUAL( - tx.quote(nullptr), "NULL", "Null pointer did not come out as SQL 'null'."); - PQXX_CHECK_EQUAL( - tx.quote(std::nullopt), "NULL", - "std::nullopt did not come out as SQL 'null'."); - PQXX_CHECK_EQUAL( - tx.quote(std::monostate{}), "NULL", - "std::monostate did not come out as SQL 'null'."); -} - - -PQXX_REGISTER_TEST(test_string_conversion); -PQXX_REGISTER_TEST(test_convert_variant_to_string); -PQXX_REGISTER_TEST(test_integer_conversion); -PQXX_REGISTER_TEST(test_convert_null); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_subtransaction.cxx b/ext/libpqxx-7.7.3/test/unit/test_subtransaction.cxx deleted file mode 100644 index 4ba909bec..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_subtransaction.cxx +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void make_table(pqxx::transaction_base &trans) -{ - trans.exec0("CREATE TEMP TABLE foo (x INTEGER)"); -} - - -void insert_row(pqxx::transaction_base &trans) -{ - trans.exec0("INSERT INTO foo(x) VALUES (1)"); -} - - -int count_rows(pqxx::transaction_base &trans) -{ - return trans.query_value("SELECT count(*) FROM foo"); -} - - -void test_subtransaction_commits_if_commit_called(pqxx::connection &conn) -{ - pqxx::work trans(conn); - make_table(trans); - { - pqxx::subtransaction sub(trans); - insert_row(sub); - sub.commit(); - } - PQXX_CHECK_EQUAL( - count_rows(trans), 1, "Work done in committed subtransaction was lost."); -} - - -void test_subtransaction_aborts_if_abort_called(pqxx::connection &conn) -{ - pqxx::work trans(conn); - make_table(trans); - { - pqxx::subtransaction sub(trans); - insert_row(sub); - sub.abort(); - } - PQXX_CHECK_EQUAL( - count_rows(trans), 0, "Aborted subtransaction was not rolled back."); -} - - -void test_subtransaction_aborts_implicitly(pqxx::connection &conn) -{ - pqxx::work trans(conn); - make_table(trans); - { - pqxx::subtransaction sub(trans); - insert_row(sub); - } - PQXX_CHECK_EQUAL( - count_rows(trans), 0, - "Uncommitted subtransaction was not rolled back uring destruction."); -} - - -void test_subtransaction() -{ - pqxx::connection conn; - test_subtransaction_commits_if_commit_called(conn); - test_subtransaction_aborts_if_abort_called(conn); - test_subtransaction_aborts_implicitly(conn); -} - - -PQXX_REGISTER_TEST(test_subtransaction); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_test_helpers.cxx b/ext/libpqxx-7.7.3/test/unit/test_test_helpers.cxx deleted file mode 100644 index 89cde627e..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_test_helpers.cxx +++ /dev/null @@ -1,214 +0,0 @@ -#include "../test_helpers.hxx" - -namespace -{ -void empty() {} - - -void test_check_notreached() -{ - // At a minimum, PQXX_CHECK_NOTREACHED must work. - bool failed{true}; - try - { - PQXX_CHECK_NOTREACHED("(expected)"); - failed = false; - } - catch (pqxx::test::test_failure const &) - { - // This is what we expect. - } - if (not failed) - throw pqxx::test::test_failure( - __FILE__, __LINE__, "PQXX_CHECK_NOTREACHED is broken."); -} - - -// Test PQXX_CHECK. -void test_check() -{ - PQXX_CHECK(true, "PQXX_CHECK is broken."); - - bool failed{true}; - try - { - PQXX_CHECK(false, "(expected)"); - failed = false; - } - catch (pqxx::test::test_failure const &) - {} - if (not failed) - PQXX_CHECK_NOTREACHED("PQXX_CHECK failed to notice failure."); -} - - -// Test PQXX_CHECK_THROWS_EXCEPTION. -void test_check_throws_exception() -{ - // PQXX_CHECK_THROWS_EXCEPTION expects std::exception... - PQXX_CHECK_THROWS_EXCEPTION( - throw std::exception(), - "PQXX_CHECK_THROWS_EXCEPTION did not catch std::exception."); - - // ...or any exception type derived from it. - PQXX_CHECK_THROWS_EXCEPTION( - throw pqxx::test::test_failure(__FILE__, __LINE__, "(expected)"), - "PQXX_CHECK_THROWS_EXCEPTION() failed to catch expected exception."); - - // Any other type is an error. - bool failed{true}; - try - { - PQXX_CHECK_THROWS_EXCEPTION(throw 1, "(expected)"); - failed = false; - } - catch (pqxx::test::test_failure const &) - {} - PQXX_CHECK( - failed, - "PQXX_CHECK_THROWS_EXCEPTION did not complain about non-exception."); - - // But there _must_ be an exception. - failed = true; - try - { - // If the test fails to throw, this throws a failure. - PQXX_CHECK_THROWS_EXCEPTION(empty(), "(expected)"); - // So we shouldn't get to this point. - failed = false; - } - catch (pqxx::test::test_failure const &) - { - // Instead, we go straight here. - } - PQXX_CHECK( - failed, "PQXX_CHECK_THROWS_EXCEPTION did not notice missing exception."); - - // PQXX_CHECK_THROWS_EXCEPTION can test itself... - PQXX_CHECK_THROWS_EXCEPTION( - PQXX_CHECK_THROWS_EXCEPTION(empty(), "(expected)"), - "PQXX_CHECK_THROWS_EXCEPTION failed to throw for missing exception."); - - PQXX_CHECK_THROWS_EXCEPTION( - PQXX_CHECK_THROWS_EXCEPTION(throw 1, "(expected)"), - "PQXX_CHECK_THROWS_EXCEPTION ignored wrong exception type."); -} - - -// Test PQXX_CHECK_THROWS. -void test_check_throws() -{ - PQXX_CHECK_THROWS( - throw pqxx::test::test_failure(__FILE__, __LINE__, "(expected)"), - pqxx::test::test_failure, - "PQXX_CHECK_THROWS() failed to catch expected exception."); - - // Even if it's not std::exception-derived. - PQXX_CHECK_THROWS(throw 1, int, "(expected)"); - - // PQXX_CHECK_THROWS means there _must_ be an exception. - bool failed{true}; - try - { - // If the test fails to throw, PQXX_CHECK_THROWS throws a failure. - PQXX_CHECK_THROWS(empty(), std::runtime_error, "(expected)"); - // So we shouldn't get to this point. - failed = false; - } - catch (pqxx::test::test_failure const &) - { - // Instead, we go straight here. - } - PQXX_CHECK(failed, "PQXX_CHECK_THROWS did not notice missing exception."); - - // The exception must be of the right type (or a subclass of the right type). - failed = true; - try - { - // If the test throws the wrong type, PQXX_CHECK_THROWS throws a failure. - PQXX_CHECK_THROWS( - throw std::exception(), pqxx::test::test_failure, "(expected)"); - failed = false; - } - catch (pqxx::test::test_failure const &) - { - // Instead, we go straight here. - } - PQXX_CHECK(failed, "PQXX_CHECK_THROWS did not notice wrong exception type."); - - // PQXX_CHECK_THROWS can test itself... - PQXX_CHECK_THROWS( - PQXX_CHECK_THROWS(empty(), pqxx::test::test_failure, "(expected)"), - pqxx::test::test_failure, - "PQXX_CHECK_THROWS failed to throw for missing exception."); - - PQXX_CHECK_THROWS( - PQXX_CHECK_THROWS(throw 1, std::runtime_error, "(expected)"), - pqxx::test::test_failure, - "PQXX_CHECK_THROWS failed to throw for wrong exception type."); -} - - -void test_test_helpers() -{ - test_check_notreached(); - test_check(); - test_check_throws_exception(); - test_check_throws(); - - // Test other helpers against PQXX_CHECK_THROWS. - PQXX_CHECK_THROWS( - PQXX_CHECK_NOTREACHED("(expected)"), pqxx::test::test_failure, - "PQXX_CHECK_THROWS did not catch PQXX_CHECK_NOTREACHED."); - - PQXX_CHECK_THROWS( - PQXX_CHECK(false, "(expected)"), pqxx::test::test_failure, - "PQXX_CHECK_THROWS did not catch failing PQXX_CHECK."); - - PQXX_CHECK_THROWS( - PQXX_CHECK_THROWS( - PQXX_CHECK(true, "(shouldn't happen)"), pqxx::test::test_failure, - "(expected)"), - pqxx::test::test_failure, - "PQXX_CHECK_THROWS on successful PQXX_CHECK failed to throw."); - - // PQXX_CHECK_EQUAL tests for equality. Its arguments need not be of the - // same type, as long as equality between them is defined. - PQXX_CHECK_EQUAL(1, 1, "PQXX_CHECK_EQUAL is broken."); - PQXX_CHECK_EQUAL(1, 1L, "PQXX_CHECK_EQUAL breaks on type mismatch."); - - PQXX_CHECK_THROWS( - PQXX_CHECK_EQUAL(1, 2, "(expected)"), pqxx::test::test_failure, - "PQXX_CHECK_EQUAL fails to spot inequality."); - - // PQXX_CHECK_NOT_EQUAL is like PQXX_CHECK_EQUAL, but tests for inequality. - PQXX_CHECK_NOT_EQUAL(1, 2, "PQXX_CHECK_NOT_EQUAL is broken."); - PQXX_CHECK_THROWS( - PQXX_CHECK_NOT_EQUAL(1, 1, "(expected)"), pqxx::test::test_failure, - "PQXX_CHECK_NOT_EQUAL fails to fail when arguments are equal."); - PQXX_CHECK_THROWS( - PQXX_CHECK_NOT_EQUAL(1, 1L, "(expected)"), pqxx::test::test_failure, - "PQXX_CHECK_NOT_EQUAL breaks on type mismatch."); - - // PQXX_CHECK_BOUNDS checks a value against a range. - PQXX_CHECK_BOUNDS(2, 1, 3, "PQXX_CHECK_BOUNDS wrongly finds fault."); - - PQXX_CHECK_THROWS( - PQXX_CHECK_BOUNDS(1, 2, 3, "(Expected)"), pqxx::test::test_failure, - "PQXX_CHECK_BOUNDS did not detect value below permitted range."); - - // PQXX_CHECK_BOUNDS tests against a half-open interval. - PQXX_CHECK_BOUNDS(1, 1, 3, "PQXX_CHECK_BOUNDS goes wrong on lower bound."); - PQXX_CHECK_THROWS( - PQXX_CHECK_BOUNDS(3, 1, 3, "(Expected)"), pqxx::test::test_failure, - "PQXX_CHECK_BOUNDS interval is not half-open."); - - // PQXX_CHECK_BOUNDS deals well with empty intervals. - PQXX_CHECK_THROWS( - PQXX_CHECK_BOUNDS(1, 2, 1, "(Expected)"), pqxx::test::test_failure, - "PQXX_CHECK_BOUNDS did not detect empty interval."); -} - - -PQXX_REGISTER_TEST(test_test_helpers); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_thread_safety_model.cxx b/ext/libpqxx-7.7.3/test/unit/test_thread_safety_model.cxx deleted file mode 100644 index cf7627cb3..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_thread_safety_model.cxx +++ /dev/null @@ -1,23 +0,0 @@ -#include "../test_helpers.hxx" - -#include - -namespace -{ -void test_thread_safety_model() -{ - auto const model{pqxx::describe_thread_safety()}; - - if (model.safe_libpq and model.safe_kerberos) - PQXX_CHECK_EQUAL( - model.description, "", - "Thread-safety looks okay but model description is nonempty."); - else - PQXX_CHECK_NOT_EQUAL( - model.description, "", - "Thread-safety model is imperfect but lacks description."); -} - - -PQXX_REGISTER_TEST(test_thread_safety_model); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_time.cxx b/ext/libpqxx-7.7.3/test/unit/test_time.cxx deleted file mode 100644 index 2fb79d472..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_time.cxx +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -#if defined(PQXX_HAVE_YEAR_MONTH_DAY) -using namespace std::literals; - - -void test_date_string_conversion() -{ - pqxx::connection conn; - pqxx::work tx{conn}; - std::tuple const conversions[]{ - {-542, 1, 1, "0543-01-01 BC"sv}, - {-1, 2, 3, "0002-02-03 BC"sv}, - {0, 9, 14, "0001-09-14 BC"sv}, - {1, 12, 8, "0001-12-08"sv}, - {2021, 10, 24, "2021-10-24"sv}, - {10191, 8, 30, "10191-08-30"sv}, - {-4712, 1, 1, "4713-01-01 BC"sv}, - {32767, 12, 31, "32767-12-31"sv}, - {2000, 2, 29, "2000-02-29"sv}, - {2004, 2, 29, "2004-02-29"sv}, - // This one won't work in postgres, but we can test the conversions. - {-32767, 11, 3, "32768-11-03 BC"sv}, - }; - for (auto const &[y, m, d, text] : conversions) - { - std::chrono::year_month_day const date{ - std::chrono::year{y}, std::chrono::month{m}, std::chrono::day{d}}; - PQXX_CHECK_EQUAL( - pqxx::to_string(date), text, "Date did not convert right."); - PQXX_CHECK_EQUAL( - pqxx::from_string(text), date, - "Date did not parse right."); - if (int{date.year()} > -4712) - { - // We can't test this for years before 4713 BC (4712 BCE), because - // postgres doesn't handle earlier years. - PQXX_CHECK_EQUAL( - tx.query_value( - "SELECT '" + pqxx::to_string(date) + "'::date"), - text, "Backend interpreted date differently."); - } - } - - std::string_view const invalid[]{ - ""sv, - "yesterday"sv, - "1981-01"sv, - "2010"sv, - "2010-8-9"sv, - "1900-02-29"sv, - "2021-02-29"sv, - "2000-11-29-3"sv, - "1900-02-29"sv, - "2003-02-29"sv, - "12-12-12"sv, - "0000-09-16"sv, - "-01-01"sv, - "-1000-01-01"sv, - "1000-00-01"sv, - "1000-01-00"sv, - "2001y-01-01"sv, - "10-09-08"sv, - "0-01-01"sv, - "0000-01-01"sv, - "2021-13-01"sv, - "2021-+02-01"sv, - "2021-12-32"sv, - }; - for (auto const text : invalid) - PQXX_CHECK_THROWS( - pqxx::ignore_unused( - pqxx::from_string(text)), - pqxx::conversion_error, - pqxx::internal::concat("Invalid date '", text, "' parsed as if valid.")); -} - - -PQXX_REGISTER_TEST(test_date_string_conversion); -#endif // PQXX_HAVE_YEAR_MONTH_DAY -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_transaction.cxx b/ext/libpqxx-7.7.3/test/unit/test_transaction.cxx deleted file mode 100644 index 2ae016a26..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_transaction.cxx +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - - -namespace -{ -void test_nontransaction_continues_after_error() -{ - pqxx::connection c; - pqxx::nontransaction tx{c}; - - PQXX_CHECK_EQUAL( - tx.query_value("SELECT 9"), 9, "Simple query went wrong."); - PQXX_CHECK_THROWS( - tx.exec("SELECT 1/0"), pqxx::sql_error, "Expected error did not happen."); - - PQXX_CHECK_EQUAL( - tx.query_value("SELECT 5"), 5, "Wrong result after error."); -} - - -std::string const table{"pqxx_test_transaction"}; - - -void delete_temp_table(pqxx::transaction_base &tx) -{ - tx.exec0(std::string{"DROP TABLE IF EXISTS "} + table); -} - - -void create_temp_table(pqxx::transaction_base &tx) -{ - tx.exec0("CREATE TEMP TABLE " + table + " (x integer)"); -} - - -void insert_temp_table(pqxx::transaction_base &tx, int value) -{ - tx.exec0( - "INSERT INTO " + table + " (x) VALUES (" + pqxx::to_string(value) + ")"); -} - -int count_temp_table(pqxx::transaction_base &tx) -{ - return tx.query_value("SELECT count(*) FROM " + table); -} - - -void test_nontransaction_autocommits() -{ - pqxx::connection c; - - pqxx::nontransaction tx1{c}; - delete_temp_table(tx1); - create_temp_table(tx1); - tx1.commit(); - - pqxx::nontransaction tx2{c}; - insert_temp_table(tx2, 4); - tx2.abort(); - - pqxx::nontransaction tx3{c}; - PQXX_CHECK_EQUAL( - count_temp_table(tx3), 1, - "Did not keep effect of aborted nontransaction."); - delete_temp_table(tx3); -} - - -template void test_double_close() -{ - pqxx::connection c; - - TX tx1{c}; - tx1.exec1("SELECT 1"); - tx1.commit(); - tx1.commit(); - - TX tx2{c}; - tx2.exec1("SELECT 2"); - tx2.abort(); - tx2.abort(); - - TX tx3{c}; - tx3.exec1("SELECT 3"); - tx3.commit(); - PQXX_CHECK_THROWS( - tx3.abort(), pqxx::usage_error, "Abort after commit not caught."); - ; - - TX tx4{c}; - tx4.exec1("SELECT 4"); - tx4.abort(); - PQXX_CHECK_THROWS( - tx4.commit(), pqxx::usage_error, "Commit after abort not caught."); -} - - -void test_transaction() -{ - test_nontransaction_continues_after_error(); - test_nontransaction_autocommits(); - test_double_close>(); - test_double_close(); - test_double_close(); - test_double_close>(); -} - - -PQXX_REGISTER_TEST(test_transaction); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_transaction_base.cxx b/ext/libpqxx-7.7.3/test/unit/test_transaction_base.cxx deleted file mode 100644 index bea15b190..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_transaction_base.cxx +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_exec0(pqxx::transaction_base &trans) -{ - pqxx::result E{trans.exec0("SELECT * FROM pg_tables WHERE 0 = 1")}; - PQXX_CHECK(std::empty(E), "Nonempty result from exec0."); - - PQXX_CHECK_THROWS( - trans.exec0("SELECT 99"), pqxx::unexpected_rows, - "Nonempty exec0 result did not throw unexpected_rows."); -} - - -void test_exec1(pqxx::transaction_base &trans) -{ - pqxx::row R{trans.exec1("SELECT 99")}; - PQXX_CHECK_EQUAL(std::size(R), 1, "Wrong size result from exec1."); - PQXX_CHECK_EQUAL(R.front().as(), 99, "Wrong result from exec1."); - - PQXX_CHECK_THROWS( - trans.exec1("SELECT * FROM pg_tables WHERE 0 = 1"), pqxx::unexpected_rows, - "Empty exec1 result did not throw unexpected_rows."); - PQXX_CHECK_THROWS( - trans.exec1("SELECT * FROM generate_series(1, 2)"), pqxx::unexpected_rows, - "Two-row exec1 result did not throw unexpected_rows."); -} - - -void test_exec_n(pqxx::transaction_base &trans) -{ - pqxx::result R{trans.exec_n(3, "SELECT * FROM generate_series(1, 3)")}; - PQXX_CHECK_EQUAL(std::size(R), 3, "Wrong result size from exec_n."); - - PQXX_CHECK_THROWS( - trans.exec_n(2, "SELECT * FROM generate_series(1, 3)"), - pqxx::unexpected_rows, - "exec_n did not throw unexpected_rows for an undersized result."); - PQXX_CHECK_THROWS( - trans.exec_n(4, "SELECT * FROM generate_series(1, 3)"), - pqxx::unexpected_rows, - "exec_n did not throw unexpected_rows for an oversized result."); -} - - -void test_query_value(pqxx::connection &conn) -{ - pqxx::work tx{conn}; - - PQXX_CHECK_EQUAL( - tx.query_value("SELECT 84 / 2"), 42, - "Got wrong value from query_value."); - PQXX_CHECK_THROWS( - tx.query_value("SAVEPOINT dummy"), pqxx::unexpected_rows, - "Got field when none expected."); - PQXX_CHECK_THROWS( - tx.query_value("SELECT generate_series(1, 2)"), pqxx::unexpected_rows, - "Failed to fail for multiple rows."); - PQXX_CHECK_THROWS( - tx.query_value("SELECT 1, 2"), pqxx::usage_error, - "No error for too many fields."); - PQXX_CHECK_THROWS( - tx.query_value("SELECT 3.141"), pqxx::conversion_error, - "Got int field from float string."); -} - - -void test_transaction_base() -{ - pqxx::connection conn; - { - pqxx::work tx{conn}; - test_exec_n(tx); - test_exec0(tx); - test_exec1(tx); - } - test_query_value(conn); -} - - -void test_transaction_for_each() -{ - constexpr auto query{ - "SELECT i, concat('x', (2*i)::text) " - "FROM generate_series(1, 3) AS i " - "ORDER BY i"}; - pqxx::connection conn; - pqxx::work tx{conn}; - std::string ints; - std::string strings; - tx.for_each(query, [&ints, &strings](int i, std::string const &s) { - ints += pqxx::to_string(i) + " "; - strings += s + " "; - }); - PQXX_CHECK_EQUAL(ints, "1 2 3 ", "Unexpected int sequence."); - PQXX_CHECK_EQUAL(strings, "x2 x4 x6 ", "Unexpected string sequence."); -} - - -PQXX_REGISTER_TEST(test_transaction_base); -PQXX_REGISTER_TEST(test_transaction_for_each); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_transaction_focus.cxx b/ext/libpqxx-7.7.3/test/unit/test_transaction_focus.cxx deleted file mode 100644 index 48fdfdd3f..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_transaction_focus.cxx +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -auto make_focus(pqxx::dbtransaction &tx) -{ - return pqxx::stream_from::query(tx, "SELECT * from generate_series(1, 10)"); -} - - -void test_cannot_run_statement_during_focus() -{ - pqxx::connection conn; - pqxx::transaction tx{conn}; - tx.exec("SELECT 1"); - auto focus{make_focus(tx)}; - PQXX_CHECK_THROWS( - tx.exec("SELECT 1"), pqxx::usage_error, - "Command during focus did not throw expected error."); -} - - -void test_cannot_run_prepared_statement_during_focus() -{ - pqxx::connection conn; - conn.prepare("foo", "SELECT 1"); - pqxx::transaction tx{conn}; - tx.exec_prepared("foo"); - auto focus{make_focus(tx)}; - PQXX_CHECK_THROWS( - tx.exec_prepared("foo"), pqxx::usage_error, - "Prepared statement during focus did not throw expected error."); -} - -void test_cannot_run_params_statement_during_focus() -{ - pqxx::connection conn; - pqxx::transaction tx{conn}; - tx.exec_params("select $1", 10); - auto focus{make_focus(tx)}; - PQXX_CHECK_THROWS( - tx.exec_params("select $1", 10), pqxx::usage_error, - "Parameterized statement during focus did not throw expected error."); -} - - -PQXX_REGISTER_TEST(test_cannot_run_statement_during_focus); -PQXX_REGISTER_TEST(test_cannot_run_prepared_statement_during_focus); -PQXX_REGISTER_TEST(test_cannot_run_params_statement_during_focus); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_transactor.cxx b/ext/libpqxx-7.7.3/test/unit/test_transactor.cxx deleted file mode 100644 index 43034807e..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_transactor.cxx +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include - -#include "../test_helpers.hxx" - -namespace -{ -void test_transactor_newstyle_executes_simple_query() -{ - pqxx::connection conn; - auto const r{pqxx::perform([&conn] { - return pqxx::work{conn}.exec("SELECT generate_series(1, 4)"); - })}; - - PQXX_CHECK_EQUAL(std::size(r), 4, "Unexpected result size."); - PQXX_CHECK_EQUAL(r.columns(), 1, "Unexpected number of columns."); - PQXX_CHECK_EQUAL(r[0][0].as(), 1, "Unexpected first row."); - PQXX_CHECK_EQUAL(r[3][0].as(), 4, "Unexpected last row."); -} - - -void test_transactor_newstyle_can_return_void() -{ - bool done{false}; - pqxx::perform([&done]() noexcept { done = true; }); - PQXX_CHECK(done, "Callback was not executed."); -} - - -void test_transactor_newstyle_completes_upon_success() -{ - int attempts{0}; - pqxx::perform([&attempts]() noexcept { attempts++; }); - PQXX_CHECK_EQUAL(attempts, 1, "Successful transactor didn't run 1 time."); -} - - -void test_transactor_newstyle_retries_broken_connection() -{ - int counter{0}; - auto const &callback{[&counter] { - ++counter; - if (counter == 1) - throw pqxx::broken_connection(); - return counter; - }}; - - int const result{pqxx::perform(callback)}; - PQXX_CHECK_EQUAL(result, 2, "Transactor run returned wrong result."); - PQXX_CHECK_EQUAL(counter, result, "Number of retries does not match."); -} - - -void test_transactor_newstyle_retries_rollback() -{ - int counter{0}; - auto const &callback{[&counter] { - ++counter; - if (counter == 1) - throw pqxx::transaction_rollback("Simulated error"); - return counter; - }}; - - int const result{pqxx::perform(callback)}; - PQXX_CHECK_EQUAL(result, 2, "Transactor run returned wrong result."); - PQXX_CHECK_EQUAL(counter, result, "Number of retries does not match."); -} - - -void test_transactor_newstyle_does_not_retry_in_doubt_error() -{ - int counter{0}; - auto const &callback{[&counter] { - ++counter; - throw pqxx::in_doubt_error("Simulated error"); - }}; - - PQXX_CHECK_THROWS( - pqxx::perform(callback), pqxx::in_doubt_error, - "Transactor did not propagate in_doubt_error."); - PQXX_CHECK_EQUAL(counter, 1, "Transactor retried after in_doubt_error."); -} - - -void test_transactor_newstyle_does_not_retry_other_error() -{ - int counter{0}; - auto const &callback{[&counter] { - ++counter; - throw std::runtime_error("Simulated error"); - }}; - - PQXX_CHECK_THROWS( - pqxx::perform(callback), std::runtime_error, - "Transactor did not propagate std exception."); - PQXX_CHECK_EQUAL(counter, 1, "Transactor retried after std exception."); -} - - -void test_transactor_newstyle_repeats_up_to_given_number_of_attempts() -{ - int const attempts{5}; - int counter{0}; - auto const &callback{[&counter] { - ++counter; - throw pqxx::transaction_rollback("Simulated error"); - }}; - - PQXX_CHECK_THROWS( - pqxx::perform(callback, attempts), pqxx::transaction_rollback, - "Not propagating original exception."); - PQXX_CHECK_EQUAL(counter, attempts, "Number of retries does not match."); -} - - -void test_transactor() -{ - test_transactor_newstyle_executes_simple_query(); - test_transactor_newstyle_can_return_void(); - test_transactor_newstyle_completes_upon_success(); - test_transactor_newstyle_retries_broken_connection(); - test_transactor_newstyle_retries_rollback(); - test_transactor_newstyle_does_not_retry_in_doubt_error(); - test_transactor_newstyle_does_not_retry_other_error(); - test_transactor_newstyle_repeats_up_to_given_number_of_attempts(); -} - - -PQXX_REGISTER_TEST(test_transactor); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_type_name.cxx b/ext/libpqxx-7.7.3/test/unit/test_type_name.cxx deleted file mode 100644 index af1c93eb5..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_type_name.cxx +++ /dev/null @@ -1,19 +0,0 @@ -#include "../test_helpers.hxx" - -namespace -{ -void test_type_name() -{ - // It's hard to test in more detail, because spellings may differ. - // For instance, one compiler might call "const unsigned int*" what another - // might call "unsigned const *". And Visual Studio prefixes "class" to - // class types. - std::string const i{pqxx::type_name}; - PQXX_CHECK_LESS(std::size(i), 5u, "type_name is suspiciously long."); - PQXX_CHECK_EQUAL( - i.substr(0, 1), "i", "type_name does not start with 'i'."); -} - - -PQXX_REGISTER_TEST(test_type_name); -} // namespace diff --git a/ext/libpqxx-7.7.3/test/unit/test_zview.cxx b/ext/libpqxx-7.7.3/test/unit/test_zview.cxx deleted file mode 100644 index f8ce5b9e1..000000000 --- a/ext/libpqxx-7.7.3/test/unit/test_zview.cxx +++ /dev/null @@ -1,16 +0,0 @@ -#include - -#include "../test_helpers.hxx" - - -namespace -{ -void test_zview_literal() -{ - using pqxx::operator"" _zv; - - PQXX_CHECK_EQUAL(("foo"_zv), pqxx::zview{"foo"}, "zview literal is broken."); -} - -PQXX_REGISTER_TEST(test_zview_literal); -} // namespace diff --git a/ext/libpqxx-7.7.3/tools/Makefile.am b/ext/libpqxx-7.7.3/tools/Makefile.am deleted file mode 100644 index 9f918cd5a..000000000 --- a/ext/libpqxx-7.7.3/tools/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -EXTRA_DIST = \ - extract_version \ - lint \ - rmlo.cxx \ - splitconfig \ - template2mak.py \ - pqxxthreadsafety.cxx - -AM_CPPFLAGS=-I$(top_builddir)/include -I$(top_srcdir)/include ${POSTGRES_INCLUDE} -# Override automatically generated list of default includes. It contains only -# unnecessary entries, and incorrectly mentions include/pqxx directly. -DEFAULT_INCLUDES= - -noinst_PROGRAMS = rmlo pqxxthreadsafety - -rmlo_SOURCES = rmlo.cxx -rmlo_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} - -pqxxthreadsafety_SOURCES = pqxxthreadsafety.cxx -pqxxthreadsafety_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} diff --git a/ext/libpqxx-7.7.3/tools/Makefile.in b/ext/libpqxx-7.7.3/tools/Makefile.in deleted file mode 100644 index 4e21cb265..000000000 --- a/ext/libpqxx-7.7.3/tools/Makefile.in +++ /dev/null @@ -1,638 +0,0 @@ -# Makefile.in generated by automake 1.16.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2021 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -noinst_PROGRAMS = rmlo$(EXEEXT) pqxxthreadsafety$(EXEEXT) -subdir = tools -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ - $(top_srcdir)/config/m4/ltoptions.m4 \ - $(top_srcdir)/config/m4/ltsugar.m4 \ - $(top_srcdir)/config/m4/ltversion.m4 \ - $(top_srcdir)/config/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -PROGRAMS = $(noinst_PROGRAMS) -am_pqxxthreadsafety_OBJECTS = pqxxthreadsafety.$(OBJEXT) -pqxxthreadsafety_OBJECTS = $(am_pqxxthreadsafety_OBJECTS) -pqxxthreadsafety_DEPENDENCIES = $(top_builddir)/src/libpqxx.la -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -am_rmlo_OBJECTS = rmlo.$(OBJEXT) -rmlo_OBJECTS = $(am_rmlo_OBJECTS) -rmlo_DEPENDENCIES = $(top_builddir)/src/libpqxx.la -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -depcomp = $(SHELL) $(top_srcdir)/config/depcomp -am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/pqxxthreadsafety.Po \ - ./$(DEPDIR)/rmlo.Po -am__mv = mv -f -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_@AM_V@) -am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) -am__v_CXX_0 = @echo " CXX " $@; -am__v_CXX_1 = -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) -am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) -am__v_CXXLD_0 = @echo " CXXLD " $@; -am__v_CXXLD_1 = -SOURCES = $(pqxxthreadsafety_SOURCES) $(rmlo_SOURCES) -DIST_SOURCES = $(pqxxthreadsafety_SOURCES) $(rmlo_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp \ - $(top_srcdir)/config/mkinstalldirs -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSCOPE = @CSCOPE@ -CTAGS = @CTAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ETAGS = @ETAGS@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_DOT = @HAVE_DOT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR = @MKDIR@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PG_CONFIG = @PG_CONFIG@ -PKG_CONFIG = @PKG_CONFIG@ -POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ -PQXXVERSION = @PQXXVERSION@ -PQXX_ABI = @PQXX_ABI@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_postgres_lib = @with_postgres_lib@ -EXTRA_DIST = \ - extract_version \ - lint \ - rmlo.cxx \ - splitconfig \ - template2mak.py \ - pqxxthreadsafety.cxx - -AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include ${POSTGRES_INCLUDE} -# Override automatically generated list of default includes. It contains only -# unnecessary entries, and incorrectly mentions include/pqxx directly. -DEFAULT_INCLUDES = -rmlo_SOURCES = rmlo.cxx -rmlo_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} -pqxxthreadsafety_SOURCES = pqxxthreadsafety.cxx -pqxxthreadsafety_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} -all: all-am - -.SUFFIXES: -.SUFFIXES: .cxx .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu tools/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstPROGRAMS: - @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list - -pqxxthreadsafety$(EXEEXT): $(pqxxthreadsafety_OBJECTS) $(pqxxthreadsafety_DEPENDENCIES) $(EXTRA_pqxxthreadsafety_DEPENDENCIES) - @rm -f pqxxthreadsafety$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(pqxxthreadsafety_OBJECTS) $(pqxxthreadsafety_LDADD) $(LIBS) - -rmlo$(EXEEXT): $(rmlo_OBJECTS) $(rmlo_DEPENDENCIES) $(EXTRA_rmlo_DEPENDENCIES) - @rm -f rmlo$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(rmlo_OBJECTS) $(rmlo_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pqxxthreadsafety.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rmlo.Po@am__quote@ # am--include-marker - -$(am__depfiles_remade): - @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) - -.cxx.o: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< - -.cxx.obj: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cxx.lo: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(PROGRAMS) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ - mostlyclean-am - -distclean: distclean-am - -rm -f ./$(DEPDIR)/pqxxthreadsafety.Po - -rm -f ./$(DEPDIR)/rmlo.Po - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/pqxxthreadsafety.Po - -rm -f ./$(DEPDIR)/rmlo.Po - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ - clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ - ctags ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - -.PRECIOUS: Makefile - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ext/libpqxx-7.7.3/tools/deprecations b/ext/libpqxx-7.7.3/tools/deprecations deleted file mode 100755 index f3970838b..000000000 --- a/ext/libpqxx-7.7.3/tools/deprecations +++ /dev/null @@ -1,6 +0,0 @@ -#! /bin/sh -set -eu - -MARKER='include.*ignore-deprecated-pre' -FILES="src include tools/*.cxx test config-tests" -grep -Ircl $MARKER $FILES | sort diff --git a/ext/libpqxx-7.7.3/tools/extract_version b/ext/libpqxx-7.7.3/tools/extract_version deleted file mode 100755 index 920ed9aad..000000000 --- a/ext/libpqxx-7.7.3/tools/extract_version +++ /dev/null @@ -1,73 +0,0 @@ -#! /bin/sh -set -eu - -ARG="${1:-}" - -# Source directory. In out-of-tree builds, Automake sets this for us. -srcdir=${srcdir:-.} - - -# Print usage information. -usage() { - cat <... - -Acceptable option values are: - -h, --help Print this message, and exit. - -a, --abi Show libpqxx ABI version; leave out revision number. - -f, --full Show full libpqxx version string (the default). - -M, --major Show major libpqxx version. - -m, --minor Show minor libpqxx version (between major and revision). -EOF -} - - -# Print "unknown argument" error. -unknown_arg() { - cat <&2 -Unknown argument: $1. -Try - - $0 --help - -for usage information. -EOF -} - - -case "$ARG" in -''|-f|--full) - # Default: Print full version. - cat $srcdir/VERSION - ;; - --h|--help) - # Print usage information, and exit. - usage - exit - ;; - --a|--abi) - # Print just the ABI version (major & minor). - sed -e 's/^\([^.]*\.[^.]*\)\..*/\1/' $srcdir/VERSION - ;; - --M|--major) - # Print the major version number. - sed -e 's/^\([^.]*\)\..*/\1/' $srcdir/VERSION - ;; - --m|--minor) - # Print the minor version number. - sed -e 's/^[^.]*\.\([^.]*\)\..*/\1/' $srcdir/VERSION - ;; - -*) - unknown_arg $ARG - exit 1 - ;; -esac diff --git a/ext/libpqxx-7.7.3/tools/format b/ext/libpqxx-7.7.3/tools/format deleted file mode 100755 index 2645ccdf6..000000000 --- a/ext/libpqxx-7.7.3/tools/format +++ /dev/null @@ -1,20 +0,0 @@ -#! /bin/bash -# -# Reformat source code using clang-format. -# -# This script is not portable: as of Ubuntu 21.04, virtualenv's "activate" -# seems to rely on a non-POSIX variable, $OSTYPE. - -set -C -u -e - -# Reformat C++ files. -find -name \*.cxx -o -name \*.hxx | xargs clang-format -i - - -# Reformat CMake files. -WORKDIR=$(mktemp -d) -virtualenv -q --python=$(which python3) "$WORKDIR/venv" -. "$WORKDIR/venv/bin/activate" -pip install -q six pyaml cmake-format -(find -name CMakeLists.txt | xargs cmake-format -i) || /bin/true -rm -rf "$WORKDIR" diff --git a/ext/libpqxx-7.7.3/tools/lint b/ext/libpqxx-7.7.3/tools/lint deleted file mode 100755 index 7beadbb27..000000000 --- a/ext/libpqxx-7.7.3/tools/lint +++ /dev/null @@ -1,197 +0,0 @@ -#! /bin/bash -# -# Routine sanity checks for libpqxx source tree. -# -# Optionally, set environment variable "srcdir" to the source directory. It -# defaults to the parent directory of the one where this script is. This trick -# requires bash (or a close equivalent) as the shell. - -set -eu -o pipefail - -SRCDIR="${srcdir:-$(dirname "${BASH_SOURCE[0]}")/..}" -PQXXVERSION="$(cd "$SRCDIR" && "$SRCDIR/tools/extract_version")" - -ARGS="${1:-}" - - -# Check that all source code is ASCII. -# -# I'd love to have rich Unicode, but I can live without it. But we don't want -# any surprises in contributions. -check_ascii() { - local exotics=$( - find -name \*.cxx -o -name \*.hxx | - xargs cat | - tr -d '\011-\176' | - wc -c - ) - if [ $exotics != 0 ] - then - echo >&2 "There's a non-ASCII character somewhere." - exit 1 - fi -} - - -# This version must be at the top of the NEWS file. -check_news_version() { - if ! head -n1 $SRCDIR/NEWS | grep -q "^$PQXXVERSION\$" - then - cat <&2 -Version $PQXXVERSION is not at the top of NEWS. -EOF - exit 1 - fi -} - - -# Count number of times header $1 is included from each of given input files. -# Output is lines of :, one line per file, sorted. -count_includes() { - local HEADER_NAME WS PAT - HEADER_NAME="$1" - shift - WS="[[:space:]]*" - PAT="^${WS}#${WS}include${WS}[<\"]$HEADER_NAME[>\"]" - # It's OK for the grep to fail. - (grep -c "$PAT" $* || /bin/true) | sort -} - - -# Check that any includes of $1-pre.hxx are matched by $1-post.hxx ones. -match_pre_post_headers() { - local NAME TEMPDIR PRE POST HEADERS - NAME="$1" - TEMPDIR="$(mktemp -d)" - if test -z "$TEMPDIR" - then - echo >&2 "Could not create temporary directory." - exit 1 - fi - PRE="$TEMPDIR/pre" - POST="$TEMPDIR/post" - HEADERS=$(find include/pqxx/* -type f | grep -v '\.swp$') - count_includes \ - $SRCDIR/NAME-pre.hxx $HEADERS >"$PRE" - count_includes \ - $SRCDIR/NAME-post.hxx $HEADERS >"$POST" - DIFF="$(diff "$PRE" "$POST")" || /bin/true - rm -r -- "$TEMPDIR" - if test -n "$DIFF" - then - cat <&2 -Mismatched pre/post header pairs: - -$DIFF -EOF - exit 1 - fi -} - - -# Any file that includes header-pre.hxx must also include header-post.hxx, and -# vice versa. Similar for ignore-deprecated-{pre|post}.hxx. -check_compiler_internal_headers() { - match_pre_post_headers "pqxx/internal/header" - match_pre_post_headers "pqxx/internal/ignore-deprecated" -} - - -cpplint() { - local cxxflags dialect includes - - if which clang-tidy >/dev/null - then - if [ -e compile_flags ] - then - # Pick out relevant flags, but leave out the rest. - # If we're not compiling with clang, compile_flags may contain - # options that clang-tidy doesn't recognise. - dialect="$(grep -o -- '-std=[^[:space:]]*' compile_flags || true)" - includes="$( - grep -o -- '-I[[:space:]]*[^[:space:]]*' compile_flags || - true)" - else - dialect="" - includes="" - fi - - cxxflags="$dialect $includes" - -# TODO: Please, is there any way we can parallelise this? -# TODO: I'd like cppcoreguidelines-*, but it's a tsunami of false positives. -# TODO: Some useful checks in abseil-*, but it recommends "use our library." -# TODO: Check test/, but tolerate some of the dubious stuff tests do. - clang-tidy \ - $(find $SRCDIR/src $SRCDIR/tools -name \*.cxx) \ - --checks=boost-*, \ - -- \ - -I$SRCDIR/include -Iinclude $cxxflags - fi - - # Run Facebook's "infer" static analyser, if available. - # Instructions here: https://fbinfer.com/docs/getting-started/ - if which infer >/dev/null - then - # This will work in an out-of-tree build, but either way it does - # require a successful "configure", or a cmake with the "make" - # generator. - infer capture -- make -j$(nproc) - infer run - fi -} - - -pylint() { - local PYFILES="$SRCDIR/tools/*.py $SRCDIR/tools/splitconfig" - echo "Skipping pocketlint; it's not up to date with Python3." - # if which pocketlint >/dev/null - # then - # pocketlint $PYFILES - # fi - - if which pyflakes3 >/dev/null - then - pyflakes3 $PYFILES - fi -} - - -main() { - local full="no" - for arg in $ARGS - do - case $arg in - -h|--help) - cat <&2 "Unknown argument: '$arg'" - exit 1 - ;; - esac - done - - check_ascii - pylint - check_news_version - check_compiler_internal_headers - if [ $full == "yes" ] - then - cpplint - fi -} - - -main diff --git a/ext/libpqxx-7.7.3/tools/m4esc.py b/ext/libpqxx-7.7.3/tools/m4esc.py deleted file mode 100755 index 355169db2..000000000 --- a/ext/libpqxx-7.7.3/tools/m4esc.py +++ /dev/null @@ -1,70 +0,0 @@ -#! /usr/bin/env python3 - -"""M4-quote text, for use as a literal in configure.ac. - -Produces M4 "code" which evaluates to the input text. - -It's not easy to read plain text from an input file in M4, without having it -expanded as M4. Sometimes all we want is literal text! -""" -from __future__ import ( - absolute_import, - print_function, - unicode_literals, - ) - -from argparse import ArgumentParser -from sys import ( - stdin, - stdout, - ) - - -def parse_args(): - parser = ArgumentParser(description=__doc__) - parser.add_argument( - '--open', '-a', default='[[', help="Current open-quote symbol.") - parser.add_argument( - '--close', '-b', default=']]', help="Current close-quote symbol.") - parser.add_argument( - '--input', '-i', default='-', help="Input file, or '-' for stdin.") - parser.add_argument( - '--output', '-o', default='-', help="Output file, or '-' for stdout.") - return parser.parse_args() - - -def open_input(in_file): - if in_file == '-': - return stdin - else: - return open(in_file) - - -def open_output(out_file): - if out_file == '-': - return stdout - else: - return open(out_file, 'w') - - -def escape(line): - return ( - line - .replace('[', '@<:@') - .replace(']', '@:>@') - .replace('#', '@%:@') - .replace('$', '@S|@') - ) - - -def main(args): - with open_input(args.input) as istr, open_output(args.output) as ostr: - ostr.write(args.open) - for line in istr: - ostr.write(escape(line)) - ostr.write('\n') - ostr.write(args.close) - - -if __name__ == '__main__': - main(parse_args()) diff --git a/ext/libpqxx-7.7.3/tools/pqxxthreadsafety.cxx b/ext/libpqxx-7.7.3/tools/pqxxthreadsafety.cxx deleted file mode 100644 index afa8fb01f..000000000 --- a/ext/libpqxx-7.7.3/tools/pqxxthreadsafety.cxx +++ /dev/null @@ -1,10 +0,0 @@ -// Print thread-safety information for present libpqxx build. -#include - -#include "pqxx/util" - - -int main() -{ - std::cout << pqxx::describe_thread_safety().description << std::endl; -} diff --git a/ext/libpqxx-7.7.3/tools/rmlo.cxx b/ext/libpqxx-7.7.3/tools/rmlo.cxx deleted file mode 100644 index 5db9605f1..000000000 --- a/ext/libpqxx-7.7.3/tools/rmlo.cxx +++ /dev/null @@ -1,39 +0,0 @@ -// Remove large objects given on the command line from the default database. -#include - -#include "pqxx/pqxx" - - -int main(int, char *argv[]) -{ - pqxx::connection conn; - bool failures = false; - - try - { - for (int i{1}; argv[i]; ++i) - { - auto o{pqxx::from_string(argv[i])}; - try - { - pqxx::perform([o, &conn] { - pqxx::work tx{conn}; - pqxx::blob::remove(tx, o); - tx.commit(); - }); - } - catch (std::exception const &e) - { - std::cerr << e.what() << std::endl; - failures = true; - } - } - } - catch (std::exception const &e) - { - std::cerr << e.what() << std::endl; - return 2; - } - - return failures; -} diff --git a/ext/libpqxx-7.7.3/tools/splitconfig b/ext/libpqxx-7.7.3/tools/splitconfig deleted file mode 100755 index 2f4be957f..000000000 --- a/ext/libpqxx-7.7.3/tools/splitconfig +++ /dev/null @@ -1,244 +0,0 @@ -#! /usr/bin/env python3 - -"""Extract configuration items into various configuration headers. - -This uses the configitems file, a database consisting of text lines with the -following single-tab-separated fields: - - Name of the configuration item, e.g. PQXX_HAVE_PTRDIFF_T. - - Publication marker: public or internal. - - A single environmental factor determining the item, e.g. libpq or compiler. -""" - -from __future__ import ( - absolute_import, - print_function, - unicode_literals, - ) - -from argparse import ArgumentParser -import codecs -from errno import ENOENT -import os.path -from os import getcwd -import re -from sys import ( - getdefaultencoding, - getfilesystemencoding, - stdout, - ) - -__metaclass__ = type - - -def guess_fs_encoding(): - """Try to establish the filesystem encoding. - - It's a sad thing: some guesswork is involved. The encoding often seems to - be conservatively, and incorrectly, set to ascii. - """ - candidates = [ - getfilesystemencoding(), - getdefaultencoding(), - 'utf-8', - ] - for encoding in candidates: - lower = encoding.lower() - if lower != 'ascii' and lower != 'ansi_x3.4-1968': - return encoding - raise AssertionError("unreachable code reached.") - - -def guess_output_encoding(): - """Return the encoding of standard output.""" - # Apparently builds in Docker containers may have None as an encoding. - # Fall back to ASCII. If this ever happens in a non-ASCII path, well, - # there may be a more difficult decision to be made. We'll burn that - # bridge when we get to it, as they almost say. - return stdout.encoding or 'ascii' - - -def decode_path(path): - """Decode a path element from bytes to unicode string.""" - return path.decode(guess_fs_encoding()) - - -def encode_path(path): - """Encode a path element from unicode string to bytes.""" - # Nasty detail: unicode strings are stored as UTF-16. Which can contain - # surrogate pairs. And those break in encoding, unless you use this - # special error handler. - return path.encode(guess_fs_encoding(), 'surrogateescape') - - -def read_text_file(path, encoding='utf-8'): - """Read text file, return as string, or `None` if file is not there.""" - assert isinstance(path, type('')) - try: - with codecs.open(encode_path(path), encoding=encoding) as stream: - return stream.read() - except IOError as error: - if error.errno == ENOENT: - return None - else: - raise - - -def read_lines(path, encoding='utf-8'): - """Read text file, return as list of lines.""" - assert isinstance(path, type('')) - with codecs.open(encode_path(path), encoding=encoding) as stream: - return list(stream) - - -def read_configitems(filename): - """Read the configuration-items database. - - :param filename: Path to the configitems file. - :return: Sequence of text lines from configitems file. - """ - return [line.split() for line in read_lines(filename)] - - -def map_configitems(items): - """Map each config item to publication/factor. - - :param items: Sequence of config items: (name, publication, factor). - :return: Dict mapping each item name to a tuple (publication, factor). - """ - return { - item: (publication, factor) - for item, publication, factor in items - } - - -def read_header(source_tree, filename): - """Read the original config.h generated by autoconf. - - :param source_tree: Path to libpqxx source tree. - :param filename: Path to the config.h file. - :return: Sequence of text lines from config.h. - """ - assert isinstance(source_tree, type('')) - assert isinstance(filename, type('')) - return read_lines(os.path.join(source_tree, filename)) - - -def extract_macro_name(config_line): - """Extract a cpp macro name from a configuration line. - - :param config_line: Text line from config.h which may define a macro. - :return: Name of macro defined in `config_line` if it is a `#define` - statement, or None. - """ - config_line = config_line.strip() - match = re.match('\s*#\s*define\s+([^\s]+)', config_line) - if match is None: - return None - else: - return match.group(1) - - -def extract_section(header_lines, items, publication, factor): - """Extract config items for given publication/factor from header lines. - - :param header_lines: Sequence of header lines from config.h. - :param items: Dict mapping macro names to (publication, factor). - :param publication: Extract only macros for this publication tag. - :param factor: Extract only macros for this environmental factor. - :return: Sequence of `#define` lines from `header_lines` insofar they - fall within the requested section. - """ - return sorted( - line.strip() - for line in header_lines - if items.get(extract_macro_name(line)) == (publication, factor) - ) - - -def compose_header(lines, publication, factor): - """Generate header text containing given lines.""" - intro = ( - "/* Automatically generated from config.h: %s/%s config. */" - % (publication, factor) - ) - return '\n'.join([intro, ''] + lines + ['']) - - -def generate_config(source_tree, header_lines, items, publication, factor): - """Generate config file for a given section, if appropriate. - - Writes nothing if the configuration file ends up identical to one that's - already there. - - :param source_tree: Location of the libpqxx source tree. - :param header_lines: Sequence of header lines from config.h. - :param items: Dict mapping macro names to (publication, factor). - :param publication: Extract only macros for this publication tag. - :param factor: Extract only macros for this environmental factor. - """ - assert isinstance(source_tree, type('')) - config_file = os.path.join( - source_tree, 'include', 'pqxx', - 'config-%s-%s.h' % (publication, factor)) - unicode_path = config_file.encode(guess_output_encoding(), 'replace') - section = extract_section(header_lines, items, publication, factor) - contents = compose_header(section, publication, factor) - if read_text_file(config_file) == contents: - print("Generating %s: no changes--skipping." % unicode_path) - return - - print("Generating %s: %d item(s)." % (unicode_path, len(section))) - path = encode_path(config_file) - with codecs.open(path, 'wb', encoding='ascii') as header: - header.write(contents) - - -def parse_args(): - """Parse command-line arguments.""" - default_source_tree = os.path.dirname( - os.path.dirname(os.path.normpath(os.path.abspath(__file__)))) - parser = ArgumentParser(description=__doc__) - parser.add_argument( - 'sourcetree', metavar='PATH', default=default_source_tree, - help="Location of libpqxx source tree. Defaults to '%(default)s'.") - return parser.parse_args() - - -def check_args(args): - """Validate command-line arguments.""" - if not os.path.isdir(args.sourcetree): - raise Exception("Not a directory: '%s'." % args.sourcetree) - - -def get_current_dir(): - cwd = getcwd() - if isinstance(cwd, bytes): - return decode_path(cwd) - else: - return cwd - - -def main(): - """Main program entry point.""" - args = parse_args() - check_args(args) - # The configitems file is under revision control; it's in sourcetree. - items = read_configitems(os.path.join(args.sourcetree, 'configitems')) - publications = sorted(set(item[1] for item in items)) - factors = sorted(set(item[2] for item in items)) - # The config.h header is generated; it's in the build tree, which should - # be where we are. - directory = get_current_dir() - original_header = read_header( - directory, - os.path.join('include', 'pqxx', 'config.h')) - items_map = map_configitems(items) - - for publication in publications: - for factor in factors: - generate_config( - directory, original_header, items_map, publication, factor) - - -if __name__ == '__main__': - main() diff --git a/ext/libpqxx-7.7.3/tools/template2mak.py b/ext/libpqxx-7.7.3/tools/template2mak.py deleted file mode 100755 index 9a5286d95..000000000 --- a/ext/libpqxx-7.7.3/tools/template2mak.py +++ /dev/null @@ -1,194 +0,0 @@ -#! /usr/bin/env python3 -"""Minimal macro processor. Used for generating VC++ makefiles. - -The available template commands are: - - Expand a template section for each file in a list of file patterns:: - ###MAKTEMPLATE:FOREACH my/path*/*.cxx,other*.cxx - ... - ###MAKTEMPLATE:ENDFOREACH - - In the template section, you can use `###BASENAME###` to get the base name - of the file being processed (e.g. "base" for "../base.cxx"), and you can - use `###FILENAME###` to get the full filename. - - -Copyright (c) 2000-2022, Bart Samwel and Jeroen T. Vermeulen. -""" - -from __future__ import ( - absolute_import, - print_function, - unicode_literals, - ) - -from argparse import ( - ArgumentError, - ArgumentParser, - RawDescriptionHelpFormatter, - ) -from contextlib import contextmanager -from glob import glob -import os -from sys import ( - argv, - stdin, - stderr, - stdout, - ) -import sys -from textwrap import dedent - - -def expand_foreach_file(path, block, outfile): - """Expand a "foreach" block for a single file path. - - Write the results to outfile. - """ - basepath, _ = os.path.splitext(os.path.basename(path)) - for line in block: - line = line.replace("###FILENAME###", path) - line = line.replace("###BASENAME###", basepath) - outfile.write(line) - - -def match_globs(globs): - """List all files matching any item in globs. - - Eliminates duplicates. - """ - return sorted({ - path - for pattern in globs - for path in glob(pattern) - }) - - -def expand_foreach(globs, block, outfile): - """Expand a foreach block for each file matching one of globs. - - Write the results to outfile. - """ - # We'll be iterating over block a variable number of times. Turn it - # from a generic iterable into an immutable array. - block = tuple(block) - for path in match_globs(globs): - expand_foreach_file(path, block, outfile) - - -# Header to be prefixed to the generated file. -OUTPUT_HEADER = dedent("""\ - # AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. - # - # This file is generated automatically by libpqxx's {script} script, and - # will be rewritten from time to time. - # - # If you modify this file, chances are your modifications will be lost. - # - # The {script} script should be available in the tools directory of the - # libpqxx source archive. - """) - - -foreach_marker = r"###MAKTEMPLATE:FOREACH " -end_foreach_marker = r"###MAKTEMPLATE:ENDFOREACH" - - -def parse_foreach(line): - """Parse FOREACH directive, if line contains one. - - :param line: One line of template input. - :return: A list of FOREACH globs, or None if this was not a FOREACH line. - """ - line = line.strip() - if line.startswith(foreach_marker): - return line[len(foreach_marker):].split(',') - else: - return None - - -def read_foreach_block(infile): - """Read a FOREACH block from infile (not including the FOREACH directive). - - Assumes that the FOREACH directive was in the preceding line. Consumes - the line with the ENDFOREACH directive, but does not yield it. - - :return: Iterable of lines. - """ - for line in infile: - if line.strip().startswith(end_foreach_marker): - return - yield line - - -def expand_template(infile, outfile): - """Expand the template in infile, and write the results to outfile.""" - for line in infile: - globs = parse_foreach(line) - if globs is None: - # Not a FOREACH line. Copy to output. - outfile.write(line) - else: - block = read_foreach_block(infile) - expand_foreach(globs, block, outfile) - - -@contextmanager -def open_stream(path=None, default=None, mode='r'): - """Open file at given path, or yield default. Close as appropriate. - - The default should be a stream, not a path; closing the context will not - close it. - """ - if path is None: - yield default - else: - with open(path, mode) as stream: - yield stream - - -def parse_args(): - """Parse command-line arguments. - - :return: Tuple of: input path (or None for stdin), output path (or None - for stdout). - """ - parser = ArgumentParser( - description=__doc__, formatter_class=RawDescriptionHelpFormatter) - - parser.add_argument( - 'template', nargs='?', - help="Input template. Defaults to standard input.") - parser.add_argument( - 'output', nargs='?', - help="Output file. Defaults to standard output.") - - args = parser.parse_args() - return args.template, args.output - - -def write_header(stream, template_path=None): - """Write header to stream.""" - hr = ('# ' + '#' * 78) + "\n" - script = os.path.basename(argv[0]) - - outstream.write(hr) - outstream.write(OUTPUT_HEADER.format(script=script)) - if template_path is not None: - outstream.write("#\n") - outstream.write("# Generated from template '%s'.\n" % template_path) - outstream.write(hr) - - -if __name__ == '__main__': - try: - template_path, output_path = parse_args() - except ArgumentError as error: - stderr.write('%s\n' % error) - sys.exit(2) - - input_stream = open_stream(template_path, stdin, 'r') - output_stream = open_stream(output_path, stdout, 'w') - with input_stream as instream, output_stream as outstream: - write_header(outstream, template_path) - expand_template(instream, outstream) diff --git a/ext/libpqxx-7.7.3/tools/test_all.py b/ext/libpqxx-7.7.3/tools/test_all.py deleted file mode 100755 index 29f33050c..000000000 --- a/ext/libpqxx-7.7.3/tools/test_all.py +++ /dev/null @@ -1,630 +0,0 @@ -#! /usr/bin/env python3 -"""Brute-force test script: test libpqxx against many compilers etc. - -This script makes no changes in the source tree; all builds happen in -temporary directories. - -To make this possible, you may need to run "make distclean" in the -source tree. The configure script will refuse to configure otherwise. -""" - -# Without this, pocketlint does not yet understand the print function. -from __future__ import print_function - -from abc import ( - ABCMeta, - abstractmethod, - ) -from argparse import ArgumentParser -from contextlib import contextmanager -from datetime import datetime -from functools import partial -import json -from multiprocessing import ( - JoinableQueue, - Process, - Queue, - ) -from multiprocessing.pool import ( - Pool, - ) -from os import ( - cpu_count, - getcwd, - ) -import os.path -from queue import Empty -from shutil import rmtree -from subprocess import ( - CalledProcessError, - check_call, - check_output, - DEVNULL, - ) -from sys import ( - stderr, - stdout, - ) -from tempfile import mkdtemp -from textwrap import dedent - - -CPUS = cpu_count() - -GCC_VERSIONS = list(range(8, 14)) -GCC = ['g++-%d' % ver for ver in GCC_VERSIONS] -CLANG_VERSIONS = list(range(7, 15)) -CLANG = ['clang++-6.0'] + ['clang++-%d' % ver for ver in CLANG_VERSIONS] -CXX = GCC + CLANG - -STDLIB = ( - '', - '-stdlib=libc++', - ) - -OPT = ('-O0', '-O3') - -LINK = { - 'static': ['--enable-static', '--disable-shared'], - 'dynamic': ['--disable-static', '--enable-shared'], -} - -DEBUG = { - 'plain': [], - 'audit': ['--enable-audit'], - 'maintainer': ['--enable-maintainer-mode'], - 'full': ['--enable-audit', '--enable-maintainer-mode'], -} - - -# CMake "generators." Maps a value for cmake's -G option to a command line to -# run. -# -# I prefer Ninja if available, because it's fast. But hey, the default will -# work. -# -# Maps the name of the generator (as used with cmake's -G option) to the -# actual command line needed to do the build. -CMAKE_GENERATORS = { - 'Ninja': ['ninja'], - 'Unix Makefiles': ['make', '-j%d' % CPUS], -} - - -class Fail(Exception): - """A known, well-handled exception. Doesn't need a traceback.""" - - -class Skip(Exception): - """"We're not doing this build. It's not an error though.""" - - -def run(cmd, output, cwd=None): - """Run a command, write output to file-like object.""" - command_line = ' '.join(cmd) - output.write("%s\n\n" % command_line) - check_call(cmd, stdout=output, stderr=output, cwd=cwd) - - -def report(output, message): - """Report a message to output, and standard output.""" - print(message, flush=True) - output.write('\n\n') - output.write(message) - output.write('\n') - - -def file_contains(path, text): - """Does the file at path contain text?""" - with open(path) as stream: - for line in stream: - if text in line: - return True - return False - - -@contextmanager -def tmp_dir(): - """Create a temporary directory, and clean it up again.""" - tmp = mkdtemp() - try: - yield tmp - finally: - rmtree(tmp) - - -def write_check_code(work_dir): - """Write a simple C++ program so we can tesst whether we can compile it. - - Returns the file's full path. - """ - path = os.path.join(work_dir, "check.cxx") - with open(path, 'w') as source: - source.write(dedent("""\ - #include - int main() - { - std::cout << "Hello world." << std::endl; - } - """)) - - return path - - -def check_compiler(work_dir, cxx, stdlib, check, verbose=False): - """Is the given compiler combo available?""" - err_file = os.path.join(work_dir, 'stderr.log') - if verbose: - err_output = open(err_file, 'w') - else: - err_output = DEVNULL - try: - command = [cxx, check] - if stdlib != '': - command.append(stdlib) - check_call(command, cwd=work_dir, stderr=err_output) - except (OSError, CalledProcessError): - if verbose: - with open(err_file) as errors: - stdout.write(errors.read()) - print("Can't build with '%s %s'. Skipping." % (cxx, stdlib)) - return False - else: - return True - - -# TODO: Use Pool. -def check_compilers(compilers, stdlibs, verbose=False): - """Check which compiler configurations are viable.""" - with tmp_dir() as work_dir: - check = write_check_code(work_dir) - return [ - (cxx, stdlib) - for stdlib in stdlibs - for cxx in compilers - if check_compiler( - work_dir, cxx, stdlib, check=check, verbose=verbose) - ] - - -def find_cmake_command(): - """Figure out a CMake generator we can use, or None.""" - try: - caps = check_output(['cmake', '-E', 'capabilities']) - except FileNotFoundError: - return None - - names = {generator['name'] for generator in json.loads(caps)['generators']} - for gen in CMAKE_GENERATORS.keys(): - if gen in names: - return gen - return None - - -class Config: - """Configuration for a build. - - These classes must be suitable for pickling, so we can send its objects to - worker processes. - """ - __metaclass__ = ABCMeta - - @abstractmethod - def name(self): - """Return an identifier for this build configuration.""" - - def make_log_name(self): - """Compose log file name for this build.""" - return "build-%s.out" % self.name() - - -class Build: - """A pending or ondoing build, in its own directory. - - Each step returns True for Success, or False for failure. - - These classes must be suitable for pickling, so we can send its objects to - worker processes. - """ - def __init__(self, logs_dir, config=None): - self.config = config - self.log = os.path.join(logs_dir, config.make_log_name()) - # Start a fresh log file. - with open(self.log, 'w') as log: - log.write("Starting %s.\n" % datetime.utcnow()) - self.work_dir = mkdtemp() - - def clean_up(self): - """Delete the build tree.""" - rmtree(self.work_dir) - - @abstractmethod - def configure(self, log): - """Prepare for a build.""" - - @abstractmethod - def build(self, log): - """Build the code, including the tests. Don't run tests though.""" - - def test(self, log): - """Run tests.""" - run( - [os.path.join(os.path.curdir, 'test', 'runner')], log, - cwd=self.work_dir) - - def logging(self, function): - """Call function, pass open write handle for `self.log`.""" -# TODO: Should probably be a decorator. - with open(self.log, 'a') as log: - try: - function(log) - except Exception as error: - log.write("%s\n" % error) - raise - - def do_configure(self): - """Call `configure`, writing output to `self.log`.""" - self.logging(self.configure) - - def do_build(self): - """Call `build`, writing output to `self.log`.""" - self.logging(self.build) - - def do_test(self): - """Call `test`, writing output to `self.log`.""" - self.logging(self.test) - - -class AutotoolsConfig(Config): - """A combination of build options for the "configure" script.""" - def __init__(self, cxx, opt, stdlib, link, link_opts, debug, debug_opts): - self.cxx = cxx - self.opt = opt - self.stdlib = stdlib - self.link = link - self.link_opts = link_opts - self.debug = debug - self.debug_opts = debug_opts - - def name(self): - return '_'.join([ - self.cxx, self.opt, self.stdlib, self.link, self.debug]) - - -class AutotoolsBuild(Build): - """Build using the "configure" script.""" - __metaclass__ = ABCMeta - - def configure(self, log): - configure = [ - os.path.join(getcwd(), "configure"), - "CXX=%s" % self.config.cxx, - ] - - if self.config.stdlib == '': - configure += [ - "CXXFLAGS=%s" % self.config.opt, - ] - else: - configure += [ - "CXXFLAGS=%s %s" % (self.config.opt, self.config.stdlib), - "LDFLAGS=%s" % self.config.stdlib, - ] - - configure += [ - "--disable-documentation", - ] + self.config.link_opts + self.config.debug_opts - - run(configure, log, cwd=self.work_dir) - - def build(self, log): - run(['make', '-j%d' % CPUS], log, cwd=self.work_dir) - # Passing "TESTS=" like this will suppress the actual running of - # the tests. We run them in the "test" stage. - run(['make', '-j%d' % CPUS, 'check', 'TESTS='], log, cwd=self.work_dir) - - -class CMakeConfig(Config): - """Configuration for a CMake build.""" - def __init__(self, generator): - self.generator = generator - self.builder = CMAKE_GENERATORS[generator] - - def name(self): - return "cmake" - - -class CMakeBuild(Build): - """Build using CMake. - - Ignores the config for now. - """ - __metaclass__ = ABCMeta - - def configure(self, log): - source_dir = getcwd() - generator = self.config.generator - run( - ['cmake', '-G', generator, source_dir], output=log, - cwd=self.work_dir) - - def build(self, log): - run(self.config.builder, log, cwd=self.work_dir) - - -def parse_args(): - """Parse command-line arguments.""" - parser = ArgumentParser(description=__doc__) - parser.add_argument('--verbose', '-v', action='store_true') - parser.add_argument( - '--compilers', '-c', default=','.join(CXX), - help="Compilers, separated by commas. Default is %(default)s.") - parser.add_argument( - '--optimize', '-O', default=','.join(OPT), - help=( - "Alternative optimisation options, separated by commas. " - "Default is %(default)s.")) - parser.add_argument( - '--stdlibs', '-L', default=','.join(STDLIB), - help=( - "Comma-separated options for choosing standard library. " - "Defaults to %(default)s.")) - parser.add_argument( - '--logs', '-l', default='.', metavar='DIRECTORY', - help="Write build logs to DIRECTORY.") - parser.add_argument( - '--jobs', '-j', default=CPUS, metavar='CPUS', - help=( - "When running 'make', run up to CPUS concurrent processes. " - "Defaults to %(default)s.")) - parser.add_argument( - '--minimal', '-m', action='store_true', - help="Make it as short a run as possible. For testing this script.") - return parser.parse_args() - - -def soft_get(queue, block=True): - """Get an item off `queue`, or `None` if the queue is empty.""" - try: - return queue.get(block) - except Empty: - return None - - -def read_queue(queue, block=True): - """Read entries off `queue`, terminating when it gets a `None`. - - Also terminates when the queue is empty. - """ - entry = soft_get(queue, block) - while entry is not None: - yield entry - entry = soft_get(queue, block) - - -def service_builds(in_queue, fail_queue, out_queue): - """Worker process for "build" stage: process one job at a time. - - Sends successful builds to `out_queue`, and failed builds to `fail_queue`. - - Terminates when it receives a `None`, at which point it will send a `None` - into `out_queue` in turn. - """ - for build in read_queue(in_queue): - try: - build.do_build() - except Exception as error: - fail_queue.put((build, "%s" % error)) - else: - out_queue.put(build) - in_queue.task_done() - - # Mark the end of the queue. - out_queue.put(None) - - -def service_tests(in_queue, fail_queue, out_queue): - """Worker process for "test" stage: test one build at a time. - - Sends successful builds to `out_queue`, and failed builds to `fail_queue`. - - Terminates when it receives a final `None`. Does not send out a final - `None` of its own. - """ - for build in read_queue(in_queue): - try: - build.do_test() - except Exception as error: - fail_queue.put((build, "%s" % error)) - else: - out_queue.put(build) - in_queue.task_done() - - -def report_failures(queue, message): - """Report failures from a failure queue. Return total number.""" - failures = 0 - for build, error in read_queue(queue, block=False): - print("%s: %s - %s" % (message, build.config.name(), error)) - failures += 1 - return failures - - -def count_entries(queue): - """Get and discard all entries from `queue`, return the total count.""" - total = 0 - for _ in read_queue(queue, block=False): - total += 1 - return total - - -def gather_builds(args): - """Produce the list of builds we want to perform.""" - if args.verbose: - print("\nChecking available compilers.") - - compiler_candidates = args.compilers.split(',') - compilers = check_compilers( - compiler_candidates, args.stdlibs.split(','), - verbose=args.verbose) - if list(compilers) == []: - raise Fail( - "Did not find any viable compilers. Tried: %s." - % ', '.join(compiler_candidates)) - - opt_levels = args.optimize.split(',') - link_types = LINK.items() - debug_mixes = DEBUG.items() - - if args.minimal: - compilers = compilers[:1] - opt_levels = opt_levels[:1] - link_types = list(link_types)[:1] - debug_mixes = list(debug_mixes)[:1] - - builds = [ - AutotoolsBuild( - args.logs, - AutotoolsConfig( - opt=opt, link=link, link_opts=link_opts, debug=debug, - debug_opts=debug_opts, cxx=cxx, stdlib=stdlib)) - for opt in sorted(opt_levels) - for link, link_opts in sorted(link_types) - for debug, debug_opts in sorted(debug_mixes) - for cxx, stdlib in compilers - ] - - cmake = find_cmake_command() - if cmake is not None: - builds.append(CMakeBuild(args.logs, CMakeConfig(cmake))) - return builds - - -def enqueue(queue, build, *args): - """Put `build` on `queue`. - - Ignores additional arguments, so that it can be used as a clalback for - `Pool`. - - We do this instead of a lambda in order to get the closure right. We want - the build for the current iteration, not the last one that was executed - before the lambda runs. - """ - queue.put(build) - - -def enqueue_error(queue, build, error): - """Put the pair of `build` and `error` on `queue`.""" - queue.put((build, error)) - - -def main(args): - """Do it all.""" - if not os.path.isdir(args.logs): - raise Fail("Logs location '%s' is not a directory." % args.logs) - - builds = gather_builds(args) - if args.verbose: - print("Lined up %d builds." % len(builds)) - - # The "configure" step is single-threaded. We can run many at the same - # time, even when we're also running a "build" step at the same time. - # This means we may run a lot more processes than we have CPUs, but there's - # no law against that. There's also I/O time to be covered. - configure_pool = Pool() - - # Builds which have failed the "configure" stage, with their errors. This - # queue must never stall, so that we can let results pile up here while the - # work continues. - configure_fails = Queue(len(builds)) - - # Waiting list for the "build" stage. It contains Build objects, - # terminated by a final None to signify that there are no more builds to be - # done. - build_queue = JoinableQueue(10) - - # Builds that have failed the "build" stage. - build_fails = Queue(len(builds)) - - # Waiting list for the "test" stage. It contains Build objects, terminated - # by a final None. - test_queue = JoinableQueue(10) - - # The "build" step tries to utilise all CPUs, and it may use a fair bit of - # memory. Run only one of these at a time, in a single worker process. - build_worker = Process( - target=service_builds, args=(build_queue, build_fails, test_queue)) - build_worker.start() - - # Builds that have failed the "test" stage. - test_fails = Queue(len(builds)) - - # Completed builds. This must never stall. - done_queue = JoinableQueue(len(builds)) - - # The "test" step can not run concurrently (yet). So, run tests serially - # in a single worker process. It takes its jobs directly from the "build" - # worker. - test_worker = Process( - target=service_tests, args=(test_queue, test_fails, done_queue)) - test_worker.start() - - # Feed all builds into the "configure" pool. Each build which passes this - # stage goes into the "build" queue. - for build in builds: - configure_pool.apply_async( - build.do_configure, callback=partial(enqueue, build_queue, build), - error_callback=partial(enqueue_error, configure_fails, build)) - if args.verbose: - print("All jobs are underway.") - configure_pool.close() - configure_pool.join() - -# TODO: Async reporting for faster feedback. - configure_fail_count = report_failures(configure_fails, "CONFIGURE FAIL") - if args.verbose: - print("Configure stage done.") - - # Mark the end of the build queue for the build worker. - build_queue.put(None) - - build_worker.join() -# TODO: Async reporting for faster feedback. - build_fail_count = report_failures(build_fails, "BUILD FAIL") - if args.verbose: - print("Build step done.") - - # Mark the end of the test queue for the test worker. - test_queue.put(None) - - test_worker.join() -# TODO: Async reporting for faster feedback. -# TODO: Collate failures into meaningful output, e.g. "shared library fails." - test_fail_count = report_failures(test_fails, "TEST FAIL") - if args.verbose: - print("Test step done.") - - # All done. Clean up. - for build in builds: - build.clean_up() - - ok_count = count_entries(done_queue) - if ok_count == len(builds): - print("All tests OK.") - else: - print( - "Failures during configure: %d - build: %d - test: %d. OK: %d." - % ( - configure_fail_count, - build_fail_count, - test_fail_count, - ok_count, - )) - - -if __name__ == '__main__': - try: - exit(main(parse_args())) - except Fail as failure: - stderr.write("%s\n" % failure) - exit(2) diff --git a/ext/libpqxx-7.7.3/tools/todo b/ext/libpqxx-7.7.3/tools/todo deleted file mode 100755 index 87429f4b2..000000000 --- a/ext/libpqxx-7.7.3/tools/todo +++ /dev/null @@ -1,31 +0,0 @@ -#! /bin/bash -# -# List "TODO" and "XXX" items in the given files, or throughout the source -# code. - -set -e -u -o pipefail - -# TODO: Make location-independent? -find_source() { - echo configure.ac - find . -name \*.cxx -o -name \*.hxx | sed -e 's|^\./||' | sort - for f in $(ls tools) - do - echo tools/$f - done -} - - -FILES=${*:-$(find_source)} - - -# Search for "$1:" in files $2. -# (This function adds the colon. That way, the search statement itself won't -# show up in the search.) -search_for() { - grep $1: $2 -} - - -search_for XXX "$FILES" || true -search_for TODO "$FILES" || true diff --git a/ext/libpqxx-7.7.3/tools/update-copyright b/ext/libpqxx-7.7.3/tools/update-copyright deleted file mode 100755 index 9d1eb5a97..000000000 --- a/ext/libpqxx-7.7.3/tools/update-copyright +++ /dev/null @@ -1,29 +0,0 @@ -#! /bin/bash -# -# Update the libpqxx copyright strings in the current directory. -# -# Usage: update-copyright [year] -# -# Where "year" is the new copyright year. Defaults to the current year. -# -# Assumes GNU grep and GNU sed. -set -eu -o pipefail - -# The regexes are a bit awkward because they must work in both grep and sed. -# -# F'rinstance, PREFIX can't include the dash because our replacement string in -# sed would have a backreference (e.g. "\3") immediately followed by a year -# (e.g. 2022), and there's no clear boundary between the backreference number -# and the year: "\32022". -PREFIX='Copyright (c),* 2000' -YEAR='20[0-9][0-9]' -NEW_YEAR="${1:-$(date '+%Y')}" -SUFFIX=',* \(.* and \)*Jeroen T\. Vermeulen' -grep -rIl "$PREFIX-$YEAR$SUFFIX" | - xargs -r sed -i -e "s/\\($PREFIX\\)-$YEAR\\($SUFFIX\\)/\\1-$NEW_YEAR\\2/" - -# This one is so different that I'd rather keep it a special case. -sed \ - -i \ - -e "s/\\(2000\\)-$YEAR\\(,* Jeroen T\\. Vermeulen\\)/\1-$NEW_YEAR\\2/" \ - doc/conf.py diff --git a/ext/lwip/CHANGELOG b/ext/lwip/CHANGELOG new file mode 100644 index 000000000..af68299ed --- /dev/null +++ b/ext/lwip/CHANGELOG @@ -0,0 +1,3349 @@ +HISTORY + +(CVS HEAD) + + * [Enter new changes just after this line - do not remove this line] + + ++ New features: + + + ++ Bugfixes: + + + + +(STABLE-1.4.1) + + ++ New features: + + 2012-03-25: Simon Goldschmidt (idea by Mason) + * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h + which are a simple wrapper to the correct lwIP include files. + + 2012-01-16: Simon Goldschmidt + * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP + + 2011-12-17: Simon Goldschmidt + * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) + (fixes bug #35061) + + 2011-09-27: Simon Goldschmidt + * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) + (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) + + 2011-09-21: Simon Goldschmidt + * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on + send (TCP only, bug #33820) + + 2011-09-21: Simon Goldschmidt + * init.c: Converted runtime-sanity-checks into compile-time checks that can + be disabled (since runtime checks can often not be seen on embedded targets) + + 2011-09-11: Simon Goldschmidt + * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file + to get a clear separation of which functions an application or port may use + (task #11281) + + 2011-09-11: Simon Goldschmidt + * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize + initial local TCP/UDP ports (so that different port ranges are used after + a reboot; bug #33818; this one added tcp_init/udp_init functions again) + + 2011-09-03: Simon Goldschmidt + * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) + + 2011-08-24: Simon Goldschmidt + * opt.h, netif.h/.c: added netif remove callback (bug #32397) + + 2011-07-26: Simon Goldschmidt + * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter + function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) + + 2011-07-21: Simon Goldschmidt (patch by hanhui) + * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: + Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. + Also added code to allow ip_forward() to forward non-broadcast packets to + the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). + + 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) + * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that + pcb->state != LISTEN + + 2011-05-14: Simon Goldschmidt (patch by Stphane Lesage) + * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static + memory message + + + ++ Bugfixes: + + 2012-09-26: Simon Goldschmidt + * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7843 Fix corner case with dhcp timeouts + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-05-08: Simon Goldschmidt + * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was + a debug-check issue only) + + 2012-03-27: Simon Goldschmidt + * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c + + 2012-03-27: Simon Goldschmidt (patch by Mason) + * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the + send MSS + + 2012-03-22: Simon Goldschmidt + * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward + + 2012-03-20: Simon Goldschmidt (patch by Mason) + * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list + + 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) + * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, + possible bug on little endian system + + 2012-02-23: Simon Goldschmidt + * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt + * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() + (bug #35541: PPP Memory Leak) + + 2012-02-16: Simon Goldschmidt + * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt (patch by Stphane Lesage) + * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed + + 2012-02-15: Simon Goldschmidt + * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with + MEMP_MEM_MALLOC==1 + + 2012-02-12: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on + MSS > pcb->snd_wnd (by not creating segments bigger than half the window) + + 2012-02-11: Simon Goldschmidt + * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait + queue while closing + + 2012-01-22: Simon Goldschmidt + * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) + + 2012-01-21: Simon Goldschmidt + * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb + + 2012-01-20: Simon Goldschmidt + * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths + + 2012-01-20: Simon Goldschmidt + * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy + + 2011-11-25: Simon Goldschmidt + * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt + tcp_active_pcbs in some cases + + 2011-11-23: Simon Goldschmidt + * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with + '#ifndef sys_msleep' + + 2011-11-22: Simon Goldschmidt + * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when + netif is brought down + + 2011-10-28: Simon Goldschmidt + * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks + + 2011-10-23: Simon Goldschmidt + * mem.c: fixed bug #34429: possible memory corruption with + LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 + + 2011-10-18: Simon Goldschmidt + * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard + error value + + 2011-10-18: Simon Goldschmidt + * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small + windows (bug #34176 select after non-blocking send times out) + + 2011-10-18: Simon Goldschmidt + * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't + consider netif->mtu, causes slow network + + 2011-10-18: Simon Goldschmidt + * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code + + 2011-10-18: Simon Goldschmidt + * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS + + 2011-10-17: Simon Goldschmidt + * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api + + 2011-10-13: Simon Goldschmidt + * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no + zero window is received) by starting the persist timer when a zero window is + received, not when we have more data queued for sending than fits into the + window + + 2011-10-13: Simon Goldschmidt + * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex + + 2011-10-13: Simon Goldschmidt + * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is + used and not all protocols are enabled + + 2011-10-12: Simon Goldschmidt + * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 + + 2011-10-09: Simon Goldschmidt + * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect + byte value when pcb->unacked != NULL + + 2011-10-09: Simon Goldschmidt + * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong + + 2011-09-27: Simon Goldschmidt + * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... + + 2011-09-27: Simon Goldschmidt + * tcp_in.c: fixed bug #28288: Data after FIN in oos queue + + 2011-09-27: Simon Goldschmidt + * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf + + 2011-09-24: Simon Goldschmidt + * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 + + 2011-09-23: Simon Goldschmidt + * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for + the last packet including FIN can lose data + + 2011-09-22: Simon Goldschmidt + * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into + account + + 2011-09-21: Simon Goldschmidt + * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks + in init.c + + 2011-09-20: Simon Goldschmidt + * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) + + 2011-09-11: Simon Goldschmidt + * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs + (bug #34019) + + 2011-09-09: Simon Goldschmidt + * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if + udp port matches + + 2011-09-03: Simon Goldschmidt + * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet + is aggregated and sent to application + + 2011-09-01: Simon Goldschmidt + * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared + to other options + + 2011-09-01: Simon Goldschmidt + * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno + + 2011-08-24: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling + accept() on UDP connections + + 2011-08-24: Simon Goldschmidt + * sockets.h: fixed bug #34057 socklen_t should be a typedef + + 2011-08-24: Simon Goldschmidt + * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) + + 2011-08-24: Simon Goldschmidt + * dhcp.c: fixed bug #34122 dhcp: hostname can overflow + + 2011-08-24: Simon Goldschmidt + * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr + + 2011-08-22: Simon Goldschmidt + * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This + merely prevents nagle from not transmitting fast after closing.) + + 2011-07-22: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns + always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now + lwip_send() sends as much as possible for non-blocking sockets + + 2011-07-22: Simon Goldschmidt + * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented + for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level. + + 2011-07-21: Simon Goldschmidt + * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by + sending an ARP request when an ARP entry is used in the last minute before + it would time out. + + 2011-07-04: Simon Goldschmidt + * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. + + 2011-06-26: Simon Goldschmidt + * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by + updating its documentation only. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an + unaligned pointer. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" + + 2011-05-25: Simon Goldschmidt + * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range) + + + +(STABLE-1.4.0) + + ++ New features: + + 2011-03-27: Simon Goldschmidt + * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and + calculate it in tcp_zero_window_probe (the only place where it was used). + + 2010-11-21: Simon Goldschmidt + * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif + (fixes bug #31525). + + 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) + * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for + IP_MULTICAST_LOOP at socket- and raw-API level. + + 2010-06-16: Simon Goldschmidt + * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow + link-layer-addressed UDP traffic to be received while a netif is down (just + like DHCP during configuration) + + 2010-05-22: Simon Goldschmidt + * many many files: bug #27352: removed packing from ip_addr_t, the packed + version is now only used in protocol headers. Added global storage for + current src/dest IP address while in input functions. + + 2010-05-16: Simon Goldschmidt + * def.h: task #10391: Add preprocessor-macros for compile-time htonl + calculation (and use them throughout the stack where applicable) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool + instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own + MEMP pool instead of the heap + + 2010-05-13: Simon Goldschmidt + * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added + new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast + packets to more than one pcb. + + 2010-05-02: Simon Goldschmidt + * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending + UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-04-30: Simon Goldschmidt + * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that + take a precalculated checksum, added pbuf_fill_chksum() to copy data + into a pbuf and at the same time calculating the checksum for that data + + 2010-04-29: Simon Goldschmidt + * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying + 2-byte-aligned IP addresses and MAC addresses + + 2010-04-28: Patch by Bill Auerbach + * ip.c: Inline generating IP checksum to save a function call + + 2010-04-14: Simon Goldschmidt + * tcpip.h/.c, timers.c: Added an overridable define to get informed when the + tcpip_thread processes messages or timeouts to implement a watchdog. + + 2010-03-28: Simon Goldschmidt + * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing + fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-03-27: Simon Goldschmidt + * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ + etharp_query to prevent unnecessary function calls (inspired by + patch #7135). + + 2010-03-20: Simon Goldschmidt + * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code + since the linker cannot do this automatically to save space. + + 2010-03-20: Simon Goldschmidt + * opt.h, etharp.c/.h: Added support for static ARP table entries + + 2010-03-14: Simon Goldschmidt + * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum + when creating TCP segments, not when (re-)transmitting them. + + 2010-03-07: Simon Goldschmidt + * sockets.c: bug #28775 (select/event_callback: only check select_cb_list + on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. + This should speed up receiving data on sockets as the select code in + event_callback is only executed when select is waiting. + + 2010-03-06: Simon Goldschmidt + * tcp_out.c: task #7013 (Create option to have all packets delivered to + netif->output in one piece): Always copy to try to create single pbufs + in tcp_write. + + 2010-03-06: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv + by not allocating a netbuf): added function netconn_recv_tcp_pbuf() + for tcp netconns to receive pbufs, not netbufs; use that function + for tcp sockets. + + 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt + * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: + Work on tcp_enqueue: Don't waste memory when chaining segments, + added option TCP_OVERSIZE to prevent creating many small pbufs when + calling tcp_write with many small blocks of data. Instead, pbufs are + allocated larger than needed and the space is used for later calls to + tcp_write. + + 2010-02-21: Simon Goldschmidt + * stats.c/.h: Added const char* name to mem- and memp-stats for easier + debugging. + + 2010-02-21: Simon Goldschmidt + * tcp.h (and usages), added tcp_impl.h: Splitted API and internal + implementation of tcp to make API usage cleare to application programmers + + 2010-02-14: Simon Goldschmidt/Stephane Lesage + * ip_addr.h: Improved some defines working on ip addresses, added faster + macro to copy addresses that cannot be NULL + + 2010-02-13: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- + blocking send operation) + + 2010-02-12: Simon Goldschmidt + * sockets.c/.h: Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + 2010-02-12: Simon Goldschmidt + * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated + memory): added autoip_set_struct() and dhcp_set_struct() to let autoip + and dhcp work with user-allocated structs instead of callin mem_malloc + + 2010-02-12: Simon Goldschmidt/Jeff Barber + * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has + SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT + + 2010-02-12: Simon Goldschmidt + * sys layer: task #10139 (Prefer statically allocated memory): converted + mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; + converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX + to let sys.h use binary semaphores instead of mutexes - as before) + + 2010-02-09: Simon Goldschmidt (Simon Kallweit) + * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 + (Restart system timeout handling) + + 2010-02-09: Simon Goldschmidt + * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into + netif.c) - loopif does not have to be created by the port any more, + just define LWIP_HAVE_LOOPIF to 1. + + 2010-02-08: Simon Goldschmidt + * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa + inet_ntoa_r/ipaddr_ntoa_r + + 2010-02-08: Simon Goldschmidt + * netif.h: Added netif_s/get_igmp_mac_filter() macros + + 2010-02-05: Simon Goldschmidt + * netif.h: Added function-like macros to get/set the hostname on a netif + + 2010-02-04: Simon Goldschmidt + * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to + make changing the actual implementation behind the typedef easier. + + 2010-02-01: Simon Goldschmidt + * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool + for allocating memory when getaddrinfo() is called. + + 2010-01-31: Simon Goldschmidt + * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse + them once instead of parsing for every option. This also removes + the need for mem_malloc from dhcp_recv and makes it possible to + correctly retrieve the BOOTP file. + + 2010-01-30: simon Goldschmidt + * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect + the sockets array. + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, api_msg.c, sockets.c: Added except set support in select + (patch #6860) + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: + Add non-blocking support for connect (partly from patch #6860), + plus many cleanups in socket & netconn API. + + 2010-01-27: Simon Goldschmidt + * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding + to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 + + 2010-01-26: Simon Goldschmidt + * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. + + 2010-01-14: Simon Goldschmidt + * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback + by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() + + 2010-01-13: Simon Goldschmidt + * mem.c: The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + (patch #6966 and bug #26133) + + 2010-01-10: Simon Goldschmidt (Bill Auerbach) + * opt.h, memp.c: patch #6822 (Add option to place memory pools in + separate arrays) + + 2010-01-10: Simon Goldschmidt + * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define + LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) + + 2009-12-31: Simon Goldschmidt + * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h + added timers.c/.h: Separated timer implementation from semaphore/mbox + implementation, moved timer implementation to timers.c/.h, timers are + now only called from tcpip_thread or by explicitly checking them. + (TASK#7235) + + 2009-12-27: Simon Goldschmidt + * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option + LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) + + + ++ Bugfixes: + + 2011-04-20: Simon Goldschmidt + * sys_arch.txt: sys_arch_timeouts() is not needed any more. + + 2011-04-13: Simon Goldschmidt + * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by + using ports in the IANA private/dynamic range (49152 through 65535). + + 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: + * etharp.h/.c: Fixed broken VLAN support. + + 2011-03-27: Simon Goldschmidt + * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp + pcbs) by checking if the pcb was bound (local_port != 0). + + 2011-03-27: Simon Goldschmidt + * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) + + 2011-03-27: Simon Goldschmidt + * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and + raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. + + 2011-03-27: Simon Goldschmidt + * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route + is present never times out) by starting retransmission timer before checking + route. + + 2011-03-22: Simon Goldschmidt + * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only + calling sio_read_abort() if the file descriptor is valid. + + 2011-03-14: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect + more than once can render a socket useless) since it mainly involves changing + "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. + + 2011-03-13: Simon Goldschmidt + * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing + err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: + use EALRADY instead of -1 + + 2011-03-13: Simon Goldschmidt + * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the + connection has been aborted by err_tcp (since this is not a normal closing + procedure). + + 2011-03-13: Simon Goldschmidt + * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind + with pcb->state != CLOSED + + 2011-02-17: Simon Goldschmidt + * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in + documentation + + 2011-02-17: Simon Goldschmidt + * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. + + 2011-01-24: Simon Goldschmidt + * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems + + 2010-12-02: Simon Goldschmidt + * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. + + 2010-11-23: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for + LWIP_SO_RCVBUF and ioctl/FIONREAD. + + 2010-11-23: Simon Goldschmidt + * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at + least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. + + 2010-11-23: Simon Goldschmidt + * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after + refusing 'refused_data' again. + + 2010-11-22: Simon Goldschmidt + * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS + after a successful nonblocking connection. + + 2010-11-22: Simon Goldschmidt + * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr + must be sent link-local + + 2010-11-22: Simon Goldschmidt + * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for + LWIP_TIMERS==0 + + 2010-11-20: Simon Goldschmidt + * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number + + 2010-11-20: Simon Goldschmidt + * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to + resemble other stacks. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else + no-copy TCP writes will never succeed. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does + not match documentation: return ERR_ARG instead of ERR_VAL if not + initialized or wrong argument. + + 2010-10-20: Simon Goldschmidt + * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 + + 2010-10-05: Simon Goldschmidt + * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when + replugging the network cable after an AutoIP address was assigned. + + 2010-08-10: Simon Goldschmidt + * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs + + 2010-08-03: Simon Goldschmidt + * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) + + 2010-08-01: Simon Goldschmidt (patch by Greg Renda) + * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big + endian architectures) + + 2010-07-28: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP + disabled. + + 2010-07-27: Simon Goldschmidt + * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no + harm but never did anything + + 2010-07-21: Simon Goldschmidt + * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not + add IP options) + + 2010-07-16: Kieran Mansley + * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator + + 2010-07-10: Simon Goldschmidt + * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options + + 2010-06-30: Simon Goldschmidt + * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in + netconn_delete) + + 2010-06-28: Kieran Mansley + * timers.c remove unportable printing of C function pointers + + 2010-06-24: Simon Goldschmidt + * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag + NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading + + 2010-06-24: Simon Goldschmidt + * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly + implemented shutdown at socket level. + + 2010-06-21: Simon Goldschmidt + * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has + problems with zero-copy DMA MACs) by adding custom pbufs and implementing + custom pbufs that reference other (original) pbufs. Additionally set + IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. + + 2010-06-15: Simon Goldschmidt + * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses + + 2010-06-14: Simon Goldschmidt + * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses + + 2010-06-12: Simon Goldschmidt + * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop + state + + 2010-05-17: Simon Goldschmidt + * netdb.c: Correctly NULL-terminate h_addr_list + + 2010-05-16: Simon Goldschmidt + * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent + "symbol already defined" i.e. when linking to winsock + + 2010-05-05: Simon Goldschmidt + * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may + overflow) + + 2010-04-21: Simon Goldschmidt + * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening + connection) + + 2010-03-28: Luca Ceresoli + * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers + + 2010-03-27: Luca Ceresoli + * mib2.c: patch #7130: remove meaningless const qualifiers + + 2010-03-26: Simon Goldschmidt + * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too + + 2010-03-26: Simon Goldschmidt + * various files: Fixed compiling with different options disabled (TCP/UDP), + triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled + + 2010-03-25: Simon Goldschmidt + * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly + + 2010-03-25: Simon Goldschmidt + * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side + overrunning our rcv_wnd in ooseq case. + + 2010-03-22: Simon Goldschmidt + * tcp.c: tcp_listen() did not copy the pcb's prio. + + 2010-03-19: Simon Goldschmidt + * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set + + 2010-03-14: Simon Goldschmidt + * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports + where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h + and basing PBUF_LINK_HLEN on it. + + 2010-03-08: Simon Goldschmidt + * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections + when assiging routable address): when checking incoming packets and + aborting existing connection on address change, filter out link-local + addresses. + + 2010-03-06: Simon Goldschmidt + * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING + + 2010-03-06: Simon Goldschmidt + * ipv4/ip.c: Don't try to forward link-local addresses + + 2010-03-06: Simon Goldschmidt + * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- + addresses to gw + + 2010-03-05: Simon Goldschmidt + * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type + and state. + + 2010-03-05: Simon Goldschmidt + * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split + into multiple calls to tcp_write. + + 2010-02-21: Simon Goldschmidt + * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep + the implementation of DNS_USES_STATIC_BUF==1) + + 2010-02-20: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement + close() vs. shutdown(). Now the application does not get any more + recv callbacks after calling tcp_close(). Added tcp_shutdown(). + + 2010-02-19: Simon Goldschmidt + * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent + confusion with realloc() + + 2010-02-15: Simon Goldschmidt/Stephane Lesage + * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK + (fixes bug #28899) + + 2010-02-14: Simon Goldschmidt + * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with + LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and + admin-status of a netif are up + + 2010-02-14: Simon Goldschmidt + * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet + reception and is not really necessary + + 2010-02-14: Simon Goldschmidt + * etharp.c/.h: Fixed ARP input processing: only add a new entry if a + request was directed as us (RFC 826, Packet Reception), otherwise + only update existing entries; internalized some functions + + 2010-02-14: Simon Goldschmidt + * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be + disabled on netif used for PPPoE) by adding a new netif flag + (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet + device but prevents usage of ARP (so that ethernet_input can be used + for PPPoE). + + 2010-02-12: Simon Goldschmidt + * netif.c: netif_set_link_up/down: only do something if the link state + actually changes + + 2010-02-12: Simon Goldschmidt/Stephane Lesage + * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking + connect) + + 2010-02-12: Simon Goldschmidt + * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) + + 2010-02-09: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 + (recv() makes receive window update for data that wasn't received by + application) + + 2010-02-09: Simon Goldschmidt/Stephane Lesage + * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out + or any netconn_recv() error) + + 2010-02-09: Simon Goldschmidt + * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) + + 2010-02-09: Simon Goldschmidt + * netif.c: For loopback packets, adjust the stats- and snmp-counters + for the loopback netif. + + 2010-02-08: Simon Goldschmidt + * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity + since they are not used anywhere else. + + 2010-02-08: Simon Goldschmidt (Stphane Lesage) + * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats + (patch from bug #28798) + + 2010-02-08: Simon Goldschmidt (Stphane Lesage) + * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and + another bug when LWIP_RAND() returns zero. + + 2010-02-04: Simon Goldschmidt + * nearly every file: Use macros defined in ip_addr.h (some of them new) + to work with IP addresses (preparation for bug #27352 - Change ip_addr + from struct to typedef (u32_t) - and better code). + + 2010-01-31: Simon Goldschmidt + * netif.c: Don't call the link-callback from netif_set_up/down() since + this invalidly retriggers DHCP. + + 2010-01-29: Simon Goldschmidt + * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the + portability file inet.h and its contents from the stack: moved htonX- + functions to def.h (and the new def.c - they are not ipv4 dependent), + let inet.h depend on ip_addr.h and not the other way round. + This fixes bug #28732. + + 2010-01-28: Kieran Mansley + * tcp.c: Ensure ssthresh >= 2*MSS + + 2010-01-27: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv + callback can lead to accessing unallocated memory. As a consequence, + ERR_ABRT means the application has called tcp_abort()! + + 2010-01-25: Simon Goldschmidt + * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY + not implemented in SNMP): write-only or not-accessible are still + returned by getnext (though not by get) + + 2010-01-24: Simon Goldschmidt + * snmp: Renamed the private mib node from 'private' to 'mib_private' to + not use reserved C/C++ keywords + + 2010-01-23: Simon Goldschmidt + * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less + than 1 ms + + 2010-01-21: Simon Goldschmidt + * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called + if tcp_enqueue fails) both in raw- and netconn-API + + 2010-01-19: Simon Goldschmidt + * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp + + 2010-01-18: Iordan Neshev/Simon Goldschmidt + * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some + bugfix backports from 2.4.x. + + 2010-01-18: Simon Goldschmidt + * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong + + 2010-01-17: Simon Goldschmidt + * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): + task #10102: "netconn: clean up conn->err threading issues" by adding + error return value to struct api_msg_msg + + 2010-01-17: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() + to return err_t (bugs #27709 and #28087) + + 2010-01-14: Simon Goldschmidt + * ...: Use typedef for function prototypes throughout the stack. + + 2010-01-13: Simon Goldschmidt + * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive + window = 0) by correctly draining recvmbox/acceptmbox + + 2010-01-11: Simon Goldschmidt + * pap.c: Fixed bug #13315 (PPP PAP authentication can result in + erroneous callbacks) by copying the code from recent pppd + + 2010-01-10: Simon Goldschmidt + * raw.c: Fixed bug #28506 (raw_bind should filter received packets) + + 2010-01-10: Simon Goldschmidt + * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) + + 2010-01-08: Simon Goldschmidt + * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) + + 2010-01-08: Simon Goldschmidt + * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string + passed to dns_local_addhost() might be volatile + + 2010-01-07: Simon Goldschmidt + * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too + + 2010-01-06: Simon Goldschmidt + * netdb.h: Fixed bug #28496: missing include guards in netdb.h + + 2009-12-31: Simon Goldschmidt + * many ppp files: Reorganised PPP source code from ucip structure to pppd + structure to easily compare our code against the pppd code (around v2.3.1) + + 2009-12-27: Simon Goldschmidt + * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted + unit test + + +(STABLE-1.3.2) + + ++ New features: + + 2009-10-27 Simon Goldschmidt/Stephan Lesage + * netifapi.c/.h: Added netifapi_netif_set_addr() + + 2009-10-07 Simon Goldschmidt/Fabian Koch + * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to + support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) + + 2009-08-26 Simon Goldschmidt/Simon Kallweit + * slipif.c/.h: bug #26397: SLIP polling support + + 2009-08-25 Simon Goldschmidt + * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), + New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. + + 2009-08-25 Simon Goldschmidt + * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) + + 2009-08-24 Jakob Stoklund Olesen + * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond + to netif_set_link_up(). + + 2009-08-23 Simon Goldschmidt + * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state + to a human-readable string. + + ++ Bugfixes: + + 2009-12-24: Kieran Mansley + * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing + (BUG#28241) + + 2009-12-06: Simon Goldschmidt + * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can + be statically allocated (like in ucip) + + 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) + * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT + + 2009-12-03: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit + could have non-zero length + + 2009-12-02: Simon Goldschmidt + * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting + tcp_input_pcb until after calling the pcb's callbacks + + 2009-11-29: Simon Goldschmidt + * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- + sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code + + 2009-11-29: Simon Goldschmidt + * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by + queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty + + 2009-11-26: Simon Goldschmidt + * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending + segment + + 2009-11-26: Simon Goldschmidt + * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle + algorithm at PCB level + + 2009-11-22: Simon Goldschmidt + * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent + + 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) + * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when + reusing time-wait pcb + + 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) + * sockets.c: Fixed bug #28062: Data received directly after accepting + does not wake up select + + 2009-11-11: Simon Goldschmidt + * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) + + 2009-10-30: Simon Goldschmidt + * opt.h: Increased default value for TCP_MSS to 536, updated default + value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. + + 2009-10-28: Kieran Mansley + * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code + to follow algorithm from TCP/IP Illustrated + + 2009-10-27: Kieran Mansley + * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK + + 2009-10-25: Simon Goldschmidt + * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if + pcb->recv is NULL to keep rcv_wnd correct) + + 2009-10-25: Simon Goldschmidt + * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state + + 2009-10-23: Simon Goldschmidt (David Empson) + * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes + + 2009-10-21: Simon Goldschmidt + * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and + trailing 1 byte len (SYN/FIN) + + 2009-10-21: Simon Goldschmidt + * tcp_out.c: Fixed bug #27315: zero window probe and FIN + + 2009-10-19: Simon Goldschmidt + * dhcp.c/.h: Minor code simplification (don't store received pbuf, change + conditional code to assert where applicable), check pbuf length before + testing for valid reply + + 2009-10-19: Simon Goldschmidt + * dhcp.c: Removed most calls to udp_connect since they aren't necessary + when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. + + 2009-10-16: Simon Goldschmidt + * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop + valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is + enabled + + 2009-10-15: Simon Goldschmidt (Oleg Tyshev) + * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit + + 2009-10-15: Simon Goldschmidt + * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() + timeout + + 2009-10-15: Simon Goldschmidt + * autoip.c: Fixed bug #27704: autoip starts with wrong address + LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead + of network byte order + + 2009-10-11 Simon Goldschmidt (Jrg Kesten) + * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments + which are not consecutive when retransmitting unacked segments + + 2009-10-09 Simon Goldschmidt + * opt.h: Fixed default values of some stats to only be enabled if used + Fixes bug #27338: sys_stats is defined when NO_SYS = 1 + + 2009-08-30 Simon Goldschmidt + * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK + function" by checking for loopback before calling ip_frag + + 2009-08-25 Simon Goldschmidt + * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27078: Possible memory leak in pppInit() + + 2009-08-23 Simon Goldschmidt + * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result + is error. + + 2009-08-23 Simon Goldschmidt + * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF + Fixed wrong parenthesis, added check in init.c + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms + + 2009-08-23 Simon Goldschmidt + * many ppp files: bug #27267: Added include to string.h where needed + + 2009-08-23 Simon Goldschmidt + * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) + + +(STABLE-1.3.1) + + ++ New features: + + 2009-05-10 Simon Goldschmidt + * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option + LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only + one pbuf to help MACs that don't support scatter-gather DMA. + + 2009-05-09 Simon Goldschmidt + * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming + ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + + 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen + * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive + extended info about the currently received packet. + + 2009-04-27 Simon Goldschmidt + * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 + + 2009-04-25 Simon Goldschmidt + * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next + bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). + + 2009-04-21 Simon Goldschmidt + * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static + hosts table. New configuration options DNS_LOCAL_HOSTLIST and + DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined + as an external function for lookup. + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for + TCP timestamp options, off by default. Rework tcp_enqueue() to + take option flags rather than specified option data + + 2009-02-18 Simon Goldschmidt + * cc.h: Added printf formatter for size_t: SZT_F + + 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) + * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast + pings + + 2009-02-12 Simon Goldschmidt + * init.h: Added LWIP_VERSION to get the current version of the stack + + 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) + * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead + of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc + is otherwise used) + + 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) + * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() + is only used by UDPLITE at present, so conditionalise it. + + 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) + * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP + "seed" address. This should reduce AUTOIP conflicts if + LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. + + 2008-10-02 Jonathan Larmour and Rishi Khan + * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking + socket. + + 2008-06-30 Simon Goldschmidt + * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from + interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows + mem_free to run between mem_malloc iterations. Added illegal counter for + mem stats. + + 2008-06-27 Simon Goldschmidt + * stats.h/.c, some other files: patch #6483: stats module improvement: + Added defines to display each module's statistic individually, added stats + defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. + + 2008-06-17 Simon Goldschmidt + * err.h: patch #6459: Made err_t overridable to use a more efficient type + (define LWIP_ERR_T in cc.h) + + 2008-06-17 Simon Goldschmidt + * slipif.c: patch #6480: Added a configuration option for slipif for symmetry + to loopif + + 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) + * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly + modified version of patch # 6370: Moved loopif code to netif.c so that + loopback traffic is supported on all netifs (all local IPs). + Added option to limit loopback packets for each netifs. + + + ++ Bugfixes: + 2009-08-12 Kieran Mansley + * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when + out of window or out of order properly + + 2009-08-12 Kieran Mansley + * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 + + 2009-07-28 Simon Goldschmidt + * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s + + 2009-07-27 Kieran Mansley + * api.h api_msg.h netdb.h sockets.h: add missing #include directives + + 2009-07-09 Kieran Mansley + * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for + recv_avail and don't increment counters until message successfully + sent to mbox + + 2009-06-25 Kieran Mansley + * api_msg.c api.h: BUG26722: initialise netconn write variables + in netconn_alloc + + 2009-06-25 Kieran Mansley + * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set + + 2009-06-25 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct + simultaneous close behaviour, and make snd_nxt have the same meaning + as in the RFCs. + + 2009-05-12 Simon Goldschmidt + * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on + arp_table / uses etharp_query" by adding etharp_gratuitous() + + 2009-05-12 Simon Goldschmidt + * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options + to the IP header (used by igmp_ip_output_if) + + 2009-05-06 Simon Goldschmidt + * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if + defined) for SWAP_BYTES_IN_WORD to speed up checksumming. + + 2009-05-05 Simon Goldschmidt + * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() + to crash + + 2009-05-04 Simon Goldschmidt + * init.c: snmp was not initialized in lwip_init() + + 2009-05-04 Frdric Bernon + * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. + + 2009-05-03 Simon Goldschmidt + * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full + (and unsent->next == NULL) + + 2009-05-02 Simon Goldschmidt + * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after + 1.3.0 in CVS only) - fixes compilation of ppp_oe.c + + 2009-05-02 Simon Goldschmidt + * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields + + 2009-05-01 Simon Goldschmidt + * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets + + 2009-05-01 Simon Goldschmidt + * ppp.c: bug #24228: Memory corruption with PPP and DHCP + + 2009-04-29 Frdric Bernon + * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the + SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception + of broadcast packets even when this option wasn't set. Port maintainers + which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. + If you want this option also filter broadcast on recv operations, you also + have to set IP_SOF_BROADCAST_RECV=1 in opt.h. + + 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen + * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and + DHCP/AUTOIP cooperation + + 2009-04-25 Simon Goldschmidt, Oleg Tyshev + * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd + Fixed by sorting the unsent and unacked queues (segments are inserted at the + right place in tcp_output and tcp_rexmit). + + 2009-04-25 Simon Goldschmidt + * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation + when debugging": memp_sizes contained the wrong sizes (including sanity + regions); memp pools for MEM_USE_POOLS were too small + + 2009-04-24 Simon Goldschmidt, Frdric Bernon + * inet.c: patch #6765: Fix a small problem with the last changes (incorrect + behavior, with with ip address string not ended by a '\0', a space or a + end of line) + + 2009-04-19 Simon Goldschmidt + * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, + pcb->err is called, not pcb->connected (with an error code). + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with + no-copy-tcpwrite": deallocate option data, only concat segments with same flags + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated + in the header pbuf, not the data pbuf) + + 2009-04-18 Simon Goldschmidt + * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() + + 2009-04-15 Simon Goldschmidt + * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp + + 2009-04-15 Simon Goldschmidt + * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in + + 2009-04-15 Simon Goldschmidt + * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function + ip_hinted_output() (for smaller code mainly) + + 2009-04-15 Simon Goldschmidt + * inet.c: patch #6765: Supporting new line characters in inet_aton() + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; + Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu + is big enough in dhcp_start + + 2009-04-15 Simon Goldschmidt + * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak + + 2009-04-15 Simon Goldschmidt + * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY + + 2009-04-15 Simon Goldschmidt + * sockets.c: bug #26121: set_errno can be overridden + + 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) + * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when + LWIP_TCP==0 + + 2009-04-09 Kieran Mansley (patch from Roy Lee ) + * tcp.h: Patch#6802 Add do-while-clauses to those function like + macros in tcp.h + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window + updates are calculated and sent (BUG20515) + + * tcp_in.c: cope with SYN packets received during established states, + and retransmission of initial SYN. + + * tcp_out.c: set push bit correctly when tcp segments are merged + + 2009-03-27 Kieran Mansley + * tcp_out.c set window correctly on probes (correcting change made + yesterday) + + 2009-03-26 Kieran Mansley + * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping + connections where no reset required (bug #25622) + + * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + (bug #20779) + + 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) + * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be + too small depending on MEM_ALIGNMENT + + 2009-02-16 Simon Goldschmidt + * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; + converted size argument of netconn_write to 'size_t' + + 2009-02-16 Simon Goldschmidt + * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host + by moving accept callback function pointer to TCP_PCB_COMMON + + 2009-02-12 Simon Goldschmidt + * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" + option) + + 2009-02-11 Simon Goldschmidt + * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) + + 2009-02-11 Simon Goldschmidt + * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: + RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) + + 2009-02-10 Simon Goldschmidt + * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: + Accepts_pending is decrease on a corresponding listen pcb when a connection + in state SYN_RCVD is close. + + 2009-01-28 Jonathan Larmour + * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run + out of pool pbufs. + + 2008-12-19 Simon Goldschmidt + * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 + + 2008-12-10 Tamas Somogyi, Frdric Bernon + * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and + port uses deleted netbuf. + + 2008-10-18 Simon Goldschmidt + * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length + in tcp_parseopt + + 2008-10-15 Simon Goldschmidt + * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers + by packing the struct ip_reass_helper. + + 2008-10-03 David Woodhouse, Jonathan Larmour + * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. + + 2008-10-02 Jonathan Larmour + * dns.c: Hard-code structure sizes, to avoid issues on some compilers where + padding is included. + + 2008-09-30 Jonathan Larmour + * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an + assertion check that addrlen isn't NULL. + + 2008-09-30 Jonathan Larmour + * tcp.c: Fix bug #24227, wrong error message in tcp_bind. + + 2008-08-26 Simon Goldschmidt + * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and + inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h + + 2008-08-14 Simon Goldschmidt + * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when + tcp_close returns != ERR_OK) + + 2008-07-08 Frdric Bernon + * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters + in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). + + 2008-06-24 Jonathan Larmour + * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused + if tcp_seg_copy fails. + + 2008-06-17 Simon Goldschmidt + * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) + and created defines for swapping bytes and folding u32 to u16. + + 2008-05-30 Kieran Mansley + * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd + rather than rcv_ann_wnd when deciding if packets are in-window. + Contributed by + + 2008-05-30 Kieran Mansley + * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow + passing as function pointers when MEM_LIBC_MALLOC is defined. + + 2008-05-09 Jonathan Larmour + * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to + stop it being treated as a fatal error. + + 2008-04-15 Simon Goldschmidt + * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP + (flag now cleared) + + 2008-03-27 Simon Goldschmidt + * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free + from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 + in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs + or heap memory from interrupt context + + 2008-03-26 Simon Goldschmidt + * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote + host sent a zero mss as TCP option. + + +(STABLE-1.3.0) + + ++ New features: + + 2008-03-10 Jonathan Larmour + * inet_chksum.c: Allow choice of one of the sample algorithms to be + made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. + + 2008-01-22 Frdric Bernon + * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in + TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. + + 2008-01-14 Frdric Bernon + * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable + to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the + tcp_recv callback (see rawapi.txt). + + 2008-01-14 Frdric Bernon, Marc Chaland + * ip.c: Integrate patch #6369" ip_input : checking before realloc". + + 2008-01-12 Frdric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::sem per netconn::op_completed like suggested for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-12 Frdric Bernon + * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, + DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues + sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". + + 2008-01-10 Frdric Bernon + * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 + "Add return value to sys_mbox_post". tcpip_callback is always defined as + "blocking" ("block" parameter = 1). + + 2008-01-10 Frdric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-05 Frdric Bernon + * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: + Introduce changes for task #7490 "Add return value to sys_mbox_post" with some + modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which + indicate the number of pointers query by the mailbox. There is three defines + in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the + netconn::acceptmbox. Port maintainers, you can decide to just add this new + parameter in your implementation, but to ignore it to keep the previous behavior. + The new sys_mbox_trypost function return a value to know if the mailbox is + full or if the message is posted. Take a look to sys_arch.txt for more details. + This new function is used in tcpip_input (so, can be called in an interrupt + context since the function is not blocking), and in recv_udp and recv_raw. + + 2008-01-04 Frdric Bernon, Simon Goldschmidt, Jonathan Larmour + * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, + tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the + "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add + documentation in the rawapi.txt file. + + 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer + + 2007-12-31 Frdric Bernon, Luca Ceresoli + * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets + in autoip". The change in etharp_raw could be removed, since all calls to + etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be + wrong in the future. + + 2007-12-30 Frdric Bernon, Tom Evans + * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address + Filtering" reported by Tom Evans. + + 2007-12-21 Frdric Bernon, Simon Goldschmidt, Jonathan Larmour + * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, + sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API + applications have to call 'tcp_accepted(pcb)' in their accept callback to + keep accepting new connections. + + 2007-12-13 Frdric Bernon + * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" + by err_t type. Add a new err_t code "ERR_INPROGRESS". + + 2007-12-12 Frdric Bernon + * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles + are the one which have ram usage. + + 2007-12-05 Frdric Bernon + * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static + set of variables (=0) or a local one (=1). In this last case, your port should + provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" + which have to do a copy of "h" and return a pointer ont the "per-thread" copy. + + 2007-12-03 Simon Goldschmidt + * ip.c: ip_input: check if a packet is for inp first before checking all other + netifs on netif_list (speeds up packet receiving in most cases) + + 2007-11-30 Simon Goldschmidt + * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access + UDP: move a (connected) pcb selected for input to the front of the list of + pcbs so that it is found faster next time. Same for RAW pcbs that have eaten + a packet. + + 2007-11-28 Simon Goldschmidt + * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS + + 2007-11-25 Simon Goldschmidt + * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy + algorithm. + + 2007-11-24 Simon Goldschmidt + * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c + to the new file netdb.c; included lwip_getaddrinfo. + + 2007-11-21 Simon Goldschmidt + * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss + based on the MTU of the netif used to send. Enabled by default. Disable by + setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. + + 2007-11-19 Frdric Bernon + * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name + received match the name query), implement DNS_USES_STATIC_BUF (the place where + copy dns payload to parse the response), return an error if there is no place + for a new query, and fix some minor problems. + + 2007-11-16 Simon Goldschmidt + * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c + removed files: core/inet.c, core/inet6.c + Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into + inet and chksum part; changed includes in all lwIP files as appropriate + + 2007-11-16 Simon Goldschmidt + * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential + dns resolver function for netconn api (netconn_gethostbyname) and socket api + (gethostbyname/gethostbyname_r). + + 2007-11-15 Jim Pettinato, Frdric Bernon + * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name + requests with RAW api interface. Initialization is done in lwip_init() with + build time options. DNS timer is added in tcpip_thread context. DHCP can set + DNS server ip addresses when options are received. You need to set LWIP_DNS=1 + in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get + some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" + list with points to improve. + + 2007-11-06 Simon Goldschmidt + * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly + enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status + for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. + + 2007-11-06 Simon Goldschmidt + * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include + core header files in api.h (ip/tcp/udp/raw.h) to hide the internal + implementation from netconn api applications. + + 2007-11-03 Frdric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & + RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled + by default). Netconn API users can use the netconn_recv_bufsize macro to access + it. This is a first release which have to be improve for TCP. Note it used the + netconn::recv_avail which need to be more "thread-safe" (note there is already + the problem for FIONREAD with lwip_ioctl/ioctlsocket). + + 2007-11-01 Frdric Bernon, Marc Chaland + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: + Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api + layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api + layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. + Note that previous "copy" parameter for "write" APIs is now called "apiflags". + + 2007-10-24 Frdric Bernon + * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than + TCP_EVENT_xxx macros to get a code more readable. It could also help to remove + some code (like we have talk in "patch #5919 : Create compile switch to remove + select code"), but it could be done later. + + 2007-10-08 Simon Goldschmidt + * many files: Changed initialization: many init functions are not needed any + more since we now rely on the compiler initializing global and static + variables to zero! + + 2007-10-06 Simon Goldschmidt + * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY + to enqueue the received pbufs so that multiple packets can be reassembled + simultaneously and no static reassembly buffer is needed. + + 2007-10-05 Simon Goldschmidt + * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so + all netifs (or ports) can use it. + + 2007-10-05 Frdric Bernon + * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the + common function to reduce a little bit the footprint (for all functions using + only the "netif" parameter). + + 2007-10-03 Frdric Bernon + * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, + netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce + a little bit the footprint (for all functions using only the "netif" parameter). + + 2007-09-15 Frdric Bernon + * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF + option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for + netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for + IP_MULTICAST_TTL and IP_MULTICAST_IF. + + 2007-09-10 Frdric Bernon + * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles + even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() + each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can + decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but + call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() + or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. + This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside + snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only + when it's queried (any direct call to "sysuptime" is changed by a call to + snmp_get_sysuptime). + + 2007-09-09 Frdric Bernon, Bill Florac + * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, + and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags + if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). + igmp_report_groups() is now called inside netif_set_link_up() (need to have + LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait + the next query message to receive the matching multicast streams). + + 2007-09-08 Frdric Bernon + * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains + IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). + Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). + Enable to access to these fields with LWIP_TCP=0. + + 2007-09-05 Frdric Bernon + * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, + ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option + LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). + Be careful, disabling ICMP make your product non-compliant to RFC1122, but + help to reduce footprint, and to reduce "visibility" on the Internet. + + 2007-09-05 Frdric Bernon, Bill Florac + * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list + for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new + parameters have to be provided: a task name, and a task stack size. For this + one, since it's platform dependant, you could define the best one for you in + your lwipopts.h. For port maintainers, you can just add these new parameters + in your sys_arch.c file, and but it's not mandatory, use them in your OS + specific functions. + + 2007-09-05 Frdric Bernon + * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings + inside init.c for task #7142 "Sanity check user-configurable values". + + 2007-09-04 Frdric Bernon, Bill Florac + * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by + memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the + value). It will avoid potential fragmentation problems, use a counter to know + how many times a group is used on an netif, and free it when all applications + leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity + check if LWIP_IGMP!=0). + + 2007-09-03 Frdric Bernon + * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". + Initialize igmp_mac_filter to NULL in netif_add (this field should be set in + the netif's "init" function). Use the "imr_interface" field (for socket layer) + and/or the "interface" field (for netconn layer), for join/leave operations. + The igmp_join/leavegroup first parameter change from a netif to an ipaddr. + This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). + + 2007-08-30 Frdric Bernon + * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions + from api/api_lib". Now netbuf API is independant of netconn, and can be used + with other API (application based on raw API, or future "socket2" API). Ports + maintainers just have to add src/api/netbuf.c in their makefile/projects. + + 2007-08-30 Frdric Bernon, Jonathan Larmour + * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check + user-configurable values". + + 2007-08-29 Frdric Bernon + * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. + igmp_start is call inside netif_add. Now, igmp initialization is in the same + spirit than the others modules. Modify some IGMP debug traces. + + 2007-08-29 Frdric Bernon + * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" + Add lwip_init function to regroup all modules initializations, and to provide + a place to add code for task #7142 "Sanity check user-configurable values". + Ports maintainers should remove direct initializations calls from their code, + and add init.c in their makefiles. Note that lwip_init() function is called + inside tcpip_init, but can also be used by raw api users since all calls are + disabled when matching options are disabled. Also note that their is new options + in opt.h, you should configure in your lwipopts.h (they are enabled per default). + + 2007-08-26 Marc Boucher + * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL + since they can under certain circumstances be called with an invalid conn + pointer after the connection has been closed (and conn has been freed). + + 2007-08-25 Frdric Bernon (Artem Migaev's Patch) + * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". + Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. + + 2007-08-22 Frdric Bernon + * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK + to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. + + 2007-08-22 Frdric Bernon + * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & + ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the + name is tcpip_input (we keep the name of 1.2.0 function). + + 2007-08-17 Jared Grubb + * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool + settings into new memp_std.h and optional user file lwippools.h. This adds + more dynamic mempools, and allows the user to create an arbitrary number of + mempools for mem_malloc. + + 2007-08-16 Marc Boucher + * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; + otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely + close the connection. + + 2007-08-16 Marc Boucher + * sockets.c: lwip_accept(): check netconn_peer() error return. + + 2007-08-16 Marc Boucher + * mem.c, mem.h: Added mem_calloc(). + + 2007-08-16 Marc Boucher + * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) + for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG + and starving other message types. + Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API + + 2007-08-16 Marc Boucher + * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf + type and flgs (later renamed to flags). + Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. + Improved lwip_recvfrom(). TCP push now propagated. + + 2007-08-16 Marc Boucher + * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global + provided by etharp. + + 2007-08-16 Marc Boucher + * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, + etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: + Added PPPoE support and various PPP improvements. + + 2007-07-25 Simon Goldschmidt + * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, + making netbuf_copy_partial use this function. + + 2007-07-25 Simon Goldschmidt + * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with + 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and + other stacks. + + 2007-07-13 Jared Grubb (integrated by Frdric Bernon) + * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add + a link callback in the netif struct, and functions to handle it. Be carefull + for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) + if you want to be sure to be compatible with future changes... + + 2007-06-30 Frdric Bernon + * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. + + 2007-06-21 Simon Goldschmidt + * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both + LWIP_AUTOIP =0 and =1 to remove redundant code. + + 2007-06-21 Simon Goldschmidt + * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option + MEM_USE_POOLS to use 4 pools with different sized elements instead of a + heap. This both prevents memory fragmentation and gives a higher speed + at the cost of more memory consumption. Turned off by default. + + 2007-06-21 Simon Goldschmidt + * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of + netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into + int to be able to send a bigger buffer than 64K with one time (mainly + used from lwip_send). + + 2007-06-21 Simon Goldschmidt + * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write + into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. + + 2007-06-21 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in + netconn_write from api_lib.c to api_msg.c to also prevent multiple context- + changes on low memory or empty send-buffer. + + 2007-06-18 Simon Goldschmidt + * etharp.c, etharp.h: Changed etharp to use a defined hardware address length + of 6 to avoid loading netif->hwaddr_len every time (since this file is only + used for ethernet and struct eth_addr already had a defined length of 6). + + 2007-06-17 Simon Goldschmidt + * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets + to disable UDP checksum generation on transmit. + + 2007-06-13 Frdric Bernon, Simon Goldschmidt + * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid + pointers or parameters, and let the possibility to redefined it in cc.h. Use + this macro to check "conn" parameter in api_msg.c functions. + + 2007-06-11 Simon Goldschmidt + * sockets.c, sockets.h: Added UDP lite support for sockets + + 2007-06-10 Simon Goldschmidt + * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled + by default) to switch off UDP-Lite support if not needed (reduces udp.c code + size) + + 2007-06-09 Dominik Spies (integrated by Frdric Bernon) + * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: + AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and + LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt + (see TODO mark in the source code). + + 2007-06-09 Simon Goldschmidt + * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for + etharp_output() to match netif->output so etharp_output() can be used + directly as netif->output to save one function call. + + 2007-06-08 Simon Goldschmidt + * netif.h, ethernetif.c, slipif.c, loopif.c: Added define + NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, + added initialization of those to ethernetif, slipif and loopif. + + 2007-05-18 Simon Goldschmidt + * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF + (defaulting to off for now) that can be set to 0 to send fragmented + packets by passing PBUF_REFs down the stack. + + 2007-05-23 Frdric Bernon + * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP + connections, such present in patch #5959. + + 2007-05-23 Frdric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx + code in only one part... + + 2007-05-18 Simon Goldschmidt + * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp + elements to overflow. This is achieved by adding some bytes before and after + each pool element (increasing their size, of course), filling them with a + prominent value and checking them on freeing the element. + Set it to 2 to also check every element in every pool each time memp_malloc() + or memp_free() is called (slower but more helpful). + + 2007-05-10 Simon Goldschmidt + * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for + PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce + code size. + + 2007-05-11 Frdric Bernon + * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: + Include a function pointer instead of a table index in the message to reduce + footprint. Disable some part of lwip_send and lwip_sendto if some options are + not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). + + 2007-05-10 Simon Goldschmidt + * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus + \ extern "C" {' in all header files. Now you can write your application using + the lwIP stack in C++ and simply #include the core files. Note I have left + out the netif/ppp/*h header files for now, since I don't know which files are + included by applications and which are for internal use only. + + 2007-05-09 Simon Goldschmidt + * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library + memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for + situations where some compilers might inline the copy and save a function + call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). + + 2007-05-08 Simon Goldschmidt + * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) + to be overriden in case the C-library malloc implementation is not protected + against concurrent access. + + 2007-05-04 Simon Goldschmidt (Atte Kojo) + * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending + multiple packets to the same host. + + 2007-05-04 Frdric Bernon, Jonathan Larmour + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible + to corrupt remote addr/port connection state". Reduce problems "not enought memory" with + netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between + sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. + Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, + these fields are now renamed "addr" & "port". + + 2007-04-11 Jonathan Larmour + * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new + sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return + with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro + by the port in sys_arch.h if desired. + + 2007-04-06 Frdric Bernon, Simon Goldschmidt + * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API + allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp + clients, using new functions from netifapi.h. Disable as default (no port change to do). + + 2007-04-05 Frdric Bernon + * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. + + 2007-04-04 Simon Goldschmidt + * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) + use this for and architecture-independent form to tell the compiler you intentionally + are not using this variable. Can be overriden in cc.h. + + 2007-03-28 Frdric Bernon + * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to + define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded + string, point on one of your's ethernetif field, or alloc a string you will free yourself). + It will be used by DHCP to register a client hostname, but can also be use when you call + snmp_set_sysname. + + 2007-03-28 Frdric Bernon + * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to + initialize a network interface's flag with. It tell this interface is an ethernet + device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility + Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). + + 2007-03-26 Frdric Bernon, Jonathan Larmour + * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build + time if you only use PPP or SLIP. The default is enable. Note we don't have to call + etharp_init in your port's initilization sequence if you use tcpip.c, because this call + is done in tcpip_init function. + + 2007-03-22 Frdric Bernon + * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the + new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in + your lwipopts.h. More, unused counters are not defined in the stats structs, and not + display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined + but never used. Fix msg_in.c with the correct #if test for a stat display. + + 2007-03-21 Kieran Mansley + * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). + Provides callback on netif up/down state change. + + 2007-03-11 Frdric Bernon, Mace Gael, Steve Reynolds + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, + ip.c, netif.h, tcpip.c, opt.h: + New configuration option LWIP_IGMP to enable IGMP processing. Based on only one + filter per all network interfaces. Declare a new function in netif to enable to + control the MAC filter (to reduce lwIP traffic processing). + + 2007-03-11 Frdric Bernon + * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can + be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this + unless you know what you're doing (default are RFC1122 compliant). Note + that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. + + 2007-03-08 Frdric Bernon + * tcp.h: Keepalive values can be configured at compile time, but don't change + this unless you know what you're doing (default are RFC1122 compliant). + + 2007-03-08 Frdric Bernon + * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: + Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO + on UDP sockets/netconn. + + 2007-03-08 Simon Goldschmidt + * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. + + 2007-03-06 Frdric Bernon + * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: + Implement SO_RCVTIMEO on UDP sockets/netconn. + + 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) + * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated + on the stack and remove the API msg type from memp + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * sockets.h, sockets.c: Move socket initialization to new + lwip_socket_init() function. + NOTE: this changes the API with ports. Ports will have to be + updated to call lwip_socket_init() now. + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * api_lib.c: Use memcpy in netbuf_copy_partial. + + + ++ Bug fixes: + + 2008-03-17 Frdric Bernon, Ed Kerekes + * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have + some problems to fill the IP header on some targets, use now the + ip.h macros to do it). + + 2008-03-13 Frdric Bernon + * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using + (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a + TCP connection caused a crash. Note that using (lwip_)recvfrom + like this is a bit slow and that using (lwip)getpeername is the + good lwip way to do it (so, using recv is faster on tcp sockets). + + 2008-03-12 Frdric Bernon, Jonathan Larmour + * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's + recv_raw() does not consume data", and the ping sample (with + LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom + returned the IP payload, without the IP header). + + 2008-03-04 Jonathan Larmour + * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors + and/or warnings on some systems where mem_size_t and size_t differ. + * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. + + 2008-03-04 Kieran Mansley (contributions by others) + * Numerous small compiler error/warning fixes from contributions to + mailing list after 1.3.0 release candidate made. + + 2008-01-25 Cui hengbin (integrated by Frdric Bernon) + * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. + + 2008-01-15 Kieran Mansley + * tcp_out.c: BUG20511. Modify persist timer to start when we are + prevented from sending by a small send window, not just a zero + send window. + + 2008-01-09 Jonathan Larmour + * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid + conflict with Linux system headers. + + 2008-01-06 Jonathan Larmour + * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP + address entirely on receiving a DHCPNAK, and restarting discovery. + + 2007-12-21 Simon Goldschmidt + * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail + is not protected" by using new macros for interlocked access to modify/test + netconn->recv_avail. + + 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) + * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) + + 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling + of silly window avoidance and prevent lwIP from shrinking the window) + + 2007-12-04 Simon Goldschmidt + * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last + data packet was lost): add assert that all segment lists are empty in + tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED + state from LAST_ACK in tcp_process + + 2007-12-02 Simon Goldschmidt + * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET + If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now + has to be set to 0 in lwipopts.h + + 2007-12-02 Simon Goldschmidt + * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always + allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen + netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. + This is a fix for thread-safety and allocates all items needed for a netconn + when the netconn is created. + + 2007-11-30 Simon Goldschmidt + * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple + netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed + to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same + port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) + + 2007-11-27 Simon Goldschmidt + * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by + letting ip_route only use netifs that are up. + + 2007-11-27 Simon Goldschmidt + * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF + and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and + sockets block most operations once they have seen a fatal error. + + 2007-11-27 Simon Goldschmidt + * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the + netif to send as an argument (to be able to send on netifs that are down). + + 2007-11-26 Simon Goldschmidt + * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs + arrive out-of-order + + 2007-11-21 Simon Goldschmidt + * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early + Fixed the nagle algorithm; nagle now also works for all raw API applications + and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' + + 2007-11-12 Frdric Bernon + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most + of the netconn_peer and netconn_addr processing is done inside tcpip_thread + context in do_getaddr. + + 2007-11-10 Simon Goldschmidt + * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can + happen any time). Now the packet simply isn't enqueued when out of memory. + + 2007-11-01 Simon Goldschmidt + * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or + TCP_MSS if that is smaller) as long as no MSS option is received from the + remote host. + + 2007-11-01 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) + is now based on TCP_MSS instead of pcb->mss (on passive open now effectively + sending our configured TCP_MSS instead of the one received). + + 2007-11-01 Simon Goldschmidt + * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was + calculated based on the configured TCP_MSS, not on the MSS option received + with SYN+ACK. + + 2007-10-09 Simon Goldschmidt + * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too + short and also was generated wrong if checksum coverage != tot_len; + receive: checksum was calculated wrong if checksum coverage != tot_len + + 2007-10-08 Simon Goldschmidt + * mem.c: lfree was not updated in mem_realloc! + + 2007-10-07 Frdric Bernon + * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential + crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: + this change cause an API breakage for netconn_addr, since a parameter + type change. Any compiler should cause an error without any changes in + yours netconn_peer calls (so, it can't be a "silent change"). It also + reduce a little bit the footprint for socket layer (lwip_getpeername & + lwip_getsockname use now a common lwip_getaddrname function since + netconn_peer & netconn_addr have the same parameters). + + 2007-09-20 Simon Goldschmidt + * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) + by checking tcp_tw_pcbs also + + 2007-09-19 Simon Goldschmidt + * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) + + 2007-09-15 Mike Kleshov + * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) + + 2007-09-06 Frdric Bernon + * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove + it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which + already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" + if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. + + 2007-08-30 Frdric Bernon + * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, + and fix some coding style. + + 2007-08-28 Frdric Bernon + * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any + kind of packets. These packets are considered like Ethernet packets (payload + pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets + are considered like IP packets (payload pointing to iphdr). + + 2007-08-27 Frdric Bernon + * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error + problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state + and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). + + 2007-08-24 Kieran Mansley + * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy + compiler (Paradigm C++) + + 2007-08-09 Frdric Bernon, Bill Florac + * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. + Introduce IGMP_STATS to centralize statistics management. + + 2007-08-09 Frdric Bernon, Bill Florac + * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast + packet on a udp pcb binded on an netif's IP address, and not on "any". + + 2007-08-09 Frdric Bernon, Bill Florac + * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. + This is mainly on using lookup/lookfor, and some coding styles... + + 2007-07-26 Frdric Bernon (and "thedoctor") + * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. + + 2007-07-25 Simon Goldschmidt + * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if + tcp_output fails in tcp_close, the code in do_close_internal gets simpler + (tcp_output is called again later from tcp timers). + + 2007-07-25 Simon Goldschmidt + * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old + copy_from_pbuf, which illegally modified the given pbuf. + + 2007-07-25 Simon Goldschmidt + * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: + changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). + + 2007-07-24 Simon Goldschmidt + * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the + correct state (must be CLOSED). + + 2007-07-13 Thomas Taranowski (commited by Jared Grubb) + * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed + allocation. It now returns NULL. + + 2007-07-13 Frdric Bernon + * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in + all error cases. + + 2007-07-13 Frdric Bernon + * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, + because current code doesn't follow rawapi.txt documentation. + + 2007-07-13 Kieran Mansley + * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in + out of sequence processing of received packets + + 2007-07-03 Simon Goldschmidt + * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an + assumption is made that this pbuf is in one piece (i.e. not chained). These + assumptions clash with the possibility of converting to fully pool-based + pbuf implementations, where PBUF_RAM pbufs might be chained. + + 2007-07-03 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems + when closing tcp netconns: removed conn->sem, less context switches when + closing, both netconn_close and netconn_delete should safely close tcp + connections. + + 2007-07-02 Simon Goldschmidt + * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, + tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) + to cache ARP table indices with each pcb instead of single-entry cache for + the complete stack. + + 2007-07-02 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent + warnings when assigning to smaller types. + + 2007-06-28 Simon Goldschmidt + * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. + + 2007-06-28 Simon Goldschmidt + * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if + a segment contained chained pbufs) + + 2007-06-28 Frdric Bernon + * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute + a "pseudo-random" value based on netif's MAC and some autoip fields. It's always + possible to define this macro in your own lwipopts.h to always use C library's + rand(). Note that autoip_create_rand_addr doesn't use this macro. + + 2007-06-28 Frdric Bernon + * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option + LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications + in api_lib/api_msg (use pointers and not type with table, etc...) + + 2007-06-26 Simon Goldschmidt + * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload + for udp packets with no matching pcb. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match + could get udp input packets if the remote side matched. + + 2007-06-13 Simon Goldschmidt + * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get + changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. + + 2007-06-13 Simon Goldschmidt + * api_msg.c: pcb_new sets conn->err if protocol is not implemented + -> netconn_new_..() does not allocate a new connection for unsupported + protocols. + + 2007-06-13 Frdric Bernon, Simon Goldschmidt + * api_lib.c: change return expression in netconn_addr and netconn_peer, because + conn->err was reset to ERR_OK without any reasons (and error was lost)... + + 2007-06-13 Frdric Bernon, Matthias Weisser + * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename + MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid + some macro names collision with some OS macros. + + 2007-06-11 Simon Goldschmidt + * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, + create checksum over the complete packet. On RX, if it's < 8 (and not 0), + discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both + UDP & UDP Lite. + + 2007-06-11 Srinivas Gollakota & Oleg Tyshev + * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" + where TCP flags wasn't initialized in tcp_keepalive. + + 2007-06-03 Simon Goldschmidt + * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function + registered, p->payload was modified without modifying p->len if sending + icmp_dest_unreach() (had no negative effect but was definitively wrong). + + 2007-06-03 Simon Goldschmidt + * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp + re-used the input pbuf even if that didn't have enough space to include the + link headers. Now the space is tested and a new pbuf is allocated for the + echo response packet if the echo request pbuf isn't big enough. + + 2007-06-01 Simon Goldschmidt + * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. + + 2007-05-23 Frdric Bernon + * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only + allocated by do_listen if success) and netconn_accept errors handling. In + most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" + by ASSERT, except for netconn_delete. + + 2007-05-23 Frdric Bernon + * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return + an error code if it's impossible to fetch a pbuf on a TCP connection (and not + directly close the recvmbox). + + 2007-05-22 Simon Goldschmidt + * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of + bound but unconnected (and non-listening) tcp_pcbs. + + 2007-05-22 Frdric Bernon + * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only + used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of + sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features + like "sys_timeout" in their application threads. + + 2007-05-22 Frdric Bernon + * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see + which parameters are used by which do_xxx function, and to avoid "misusing" + parameters (patch #5938). + + 2007-05-22 Simon Goldschmidt + * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: + changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto + is only 8 bits wide. This affects the api, as there, the protocol was + u16_t, too. + + 2007-05-18 Simon Goldschmidt + * memp.c: addition to patch #5913: smaller pointer was returned but + memp_memory was the same size -> did not save memory. + + 2007-05-16 Simon Goldschmidt + * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns + != ERR_OK. + + 2007-05-16 Simon Goldschmidt + * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same + as the one of the netif used for sending to prevent sending from old + addresses after a netif address gets changed (partly fixes bug #3168). + + 2007-05-16 Frdric Bernon + * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work + with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in + tcpip_init) because we have to be sure that network interfaces are already + added (mac filter is updated only in igmp_init for the moment). + + 2007-05-16 Simon Goldschmidt + * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls + into sys_arch_sem_wait calls to prevent timers from running while waiting + for the heap. This fixes bug #19167. + + 2007-05-13 Simon Goldschmidt + * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines + for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from + tcp.h to sockets.h. + + 2007-05-07 Simon Goldschmidt + * mem.c: Another attempt to fix bug #17922. + + 2007-05-04 Simon Goldschmidt + * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() + implementation so that it can be reused (don't allocate the target + pbuf inside pbuf_copy()). + + 2007-05-04 Simon Goldschmidt + * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem + to save a little RAM (next pointer of memp is not used while not in pool). + + 2007-05-03 "maq" + * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. + (patch #3574). + + 2007-04-23 Simon Goldschmidt + * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results + in NULL reference for incoming TCP packets". Loopif has to be configured + (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() + (multithreading environments, e.g. netif->input() = tcpip_input()) or + putting packets on a list that is fed to the stack by calling loopif_poll() + (single-thread / NO_SYS / polling environment where e.g. + netif->input() = ip_input). + + 2007-04-17 Jonathan Larmour + * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold + the difference between two u16_t's. + * sockets.h: FD_SETSIZE needs to match number of sockets, which is + MEMP_NUM_NETCONN in sockets.c right now. + + 2007-04-12 Jonathan Larmour + * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). + + 2007-04-12 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission + timer is reset to fix bug#19434, with help from Oleg Tyshev. + + 2007-04-11 Simon Goldschmidt + * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than + previously thought need to be copied (everything but PBUF_ROM!). Cleaned up + pbuf.c: removed functions no needed any more (by etharp). + + 2007-04-11 Kieran Mansley + * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix + "Constant is long" warnings with 16bit compilers. Contributed by + avatar@mmlab.cse.yzu.edu.tw + + 2007-04-05 Frdric Bernon, Jonathan Larmour + * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on + the mailbox is active". Now, the post is only done during a connect, and do_send, + do_write and do_join_leave_group don't do anything if a previous error was signaled. + + 2007-04-03 Frdric Bernon + * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output + packets. See patch #5834. + + 2007-03-30 Frdric Bernon + * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add + missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. + + 2007-03-30 Frdric Bernon + * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with + others environment defines (these were too "generic"). + + 2007-03-28 Frdric Bernon + * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call + result and can cause a crash. lwip_send now check netbuf_ref result. + + 2007-03-28 Simon Goldschmidt + * sockets.c Remove "#include " from sockets.c to avoid multiple + definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is + defined. This is the way it should have been already (looking at + doc/sys_arch.txt) + + 2007-03-28 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + + IP and TCP headers *and* physical link headers + + 2007-03-26 Frdric Bernon (based on patch from Dmitry Potapov) + * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause + to send some garbage. It is not a definitive solution, but the patch does solve + the problem for most cases. + + 2007-03-22 Frdric Bernon + * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). + + 2007-03-22 Frdric Bernon + * api_lib.c: somes resources couldn't be freed if there was errors during + netconn_new_with_proto_and_callback. + + 2007-03-22 Frdric Bernon + * ethernetif.c: update netif->input calls to check return value. In older ports, + it's a good idea to upgrade them, even if before, there could be another problem + (access to an uninitialized mailbox). + + 2007-03-21 Simon Goldschmidt + * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed + by casting to unsigned). + + 2007-03-21 Frdric Bernon + * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from + api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a + dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. + Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a + faster and more reliable communication between api_lib and tcpip. + + 2007-03-21 Frdric Bernon + * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. + + 2007-03-21 Frdric Bernon + * api_msg.c, igmp.c, igmp.h: Fix C++ style comments + + 2007-03-21 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + + IP and TCP headers + + 2007-03-21 Kieran Mansley + * Fix all uses of pbuf_header to check the return value. In some + cases just assert if it fails as I'm not sure how to fix them, but + this is no worse than before when they would carry on regardless + of the failure. + + 2007-03-21 Kieran Mansley + * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and + comment out missing header include in icmp.c + + 2007-03-20 Frdric Bernon + * memp.h, stats.c: Fix stats_display function where memp_names table wasn't + synchronized with memp.h. + + 2007-03-20 Frdric Bernon + * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, + tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with + network interfaces. Also fix a compiler warning. + + 2007-03-20 Kieran Mansley + * udp.c: Only try and use pbuf_header() to make space for headers if + not a ROM or REF pbuf. + + 2007-03-19 Frdric Bernon + * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() + and api_msg_post(). + + 2007-03-19 Frdric Bernon + * Remove unimplemented "memp_realloc" function from memp.h. + + 2007-03-11 Simon Goldschmidt + * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused + memory corruption. + + 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) + * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 + (missing `const' qualifier in socket functions), to get more compatible to + standard POSIX sockets. + + 2007-03-11 Frdric Bernon (based on patch from Dmitry Potapov) + * sockets.c: Add asserts inside bind, connect and sendto to check input + parameters. Remove excessive set_errno() calls after get_socket(), because + errno is set inside of get_socket(). Move last sock_set_errno() inside + lwip_close. + + 2007-03-09 Simon Goldschmidt + * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory + was allocated too small. + + 2007-03-06 Simon Goldschmidt + * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect + the stack from concurrent access. + + 2007-03-06 Frdric Bernon, Dmitry Potapov + * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy + call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). + + 2007-03-06 Simon Goldschmidt + * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files + if IP_FRAG == 0 and IP_REASSEMBLY == 0 + + 2007-03-06 Frdric Bernon, Simon Goldschmidt + * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration + option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. + Allow to do ARP processing for incoming packets inside tcpip_thread + (protecting ARP layer against concurrent access). You can also disable + old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. + Older ports have to use tcpip_ethinput. + + 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) + * err.h, err.c: fixed compiler warning "initialization dircards qualifiers + from pointer target type" + + 2007-03-05 Frdric Bernon + * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, + ETHARP_TRUST_IP_MAC, review SO_REUSE) + + 2007-03-04 Frdric Bernon + * api_msg.c: Remove some compiler warnings : parameter "pcb" was never + referenced. + + 2007-03-04 Frdric Bernon + * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from + Dmitry Potapov). + The api_msg struct stay on the stack (not moved to netconn struct). + + 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) + * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if + SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) + Also fixed cast warning in pbuf_alloc() + + 2007-03-04 Simon Goldschmidt + * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt + existing pbuf chain when enqueuing multiple pbufs to a pending ARP request + + 2007-03-03 Frdric Bernon + * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" + It is static, and never used in udp.c except udp_init(). + + 2007-03-02 Simon Goldschmidt + * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from + tcpip_thread() to tcpip_init(). This way, raw API connections can be + initialized before tcpip_thread is running (e.g. before OS is started) + + 2007-03-02 Frdric Bernon + * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call + interval. + + 2007-02-28 Kieran Mansley + * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved + outside the region of the pbuf by pbuf_header() + + 2007-02-28 Kieran Mansley + * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero + when supplied timeout is also non-zero + +(STABLE-1.2.0) + + 2006-12-05 Leon Woestenberg + * CHANGELOG: Mention STABLE-1.2.0 release. + + ++ New features: + + 2006-12-01 Christiaan Simons + * mem.h, opt.h: Added MEM_LIBC_MALLOC option. + Note this is a workaround. Currently I have no other options left. + + 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) + * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define + to include/lwip/opt.h. + * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. + Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. + * opt.h: Add above new options. + + 2006-08-18 Christiaan Simons + * tcp_{in,out}.c: added SNMP counters. + * ipv4/ip.c: added SNMP counters. + * ipv4/ip_frag.c: added SNMP counters. + + 2006-08-08 Christiaan Simons + * etharp.{c,h}: added etharp_find_addr() to read + (stable) ethernet/IP address pair from ARP table + + 2006-07-14 Christiaan Simons + * mib_structs.c: added + * include/lwip/snmp_structs.h: added + * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct + + 2006-07-06 Christiaan Simons + * snmp/asn1_{enc,dec}.c added + * snmp/mib2.c added + * snmp/msg_{in,out}.c added + * include/lwip/snmp_asn1.h added + * include/lwip/snmp_msg.h added + * doc/snmp_agent.txt added + + 2006-03-29 Christiaan Simons + * inet.c, inet.h: Added platform byteswap support. + Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and + optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. + + ++ Bug fixes: + + 2006-11-30 Christiaan Simons + * dhcp.c: Fixed false triggers of request_timeout. + + 2006-11-28 Christiaan Simons + * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. + + 2006-10-11 Christiaan Simons + * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: + Partially accepted patch #5449 for ANSI C compatibility / build fixes. + * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol + identifier from 170 to 136 (bug #17574). + + 2006-10-10 Christiaan Simons + * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. + + 2006-08-17 Christiaan Simons + * udp.c: Fixed bug #17200, added check for broadcast + destinations for PCBs bound to a unicast address. + + 2006-08-07 Christiaan Simons + * api_msg.c: Flushing TCP output in do_close() (bug #15926). + + 2006-06-27 Christiaan Simons + * api_msg.c: Applied patch for cold case (bug #11135). + In accept_function() ensure newconn->callback is always initialized. + + 2006-06-15 Christiaan Simons + * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), + facilitate printing of mem_size_t and u16_t statistics. + + 2006-06-14 Christiaan Simons + * api_msg.c: Applied patch #5146 to handle allocation failures + in accept() by Kevin Lawson. + + 2006-05-26 Christiaan Simons + * api_lib.c: Removed conn->sem creation and destruction + from netconn_write() and added sys_sem_new to netconn_new_*. + +(STABLE-1_1_1) + + 2006-03-03 Christiaan Simons + * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap + access and added pbuf_alloc() return value checks. + + 2006-01-01 Leon Woestenberg + * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is + now handled by the checksum routine properly. + + 2006-02-27 Leon Woestenberg + * pbuf.c: Fix alignment; pbuf_init() would not work unless + pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) + + 2005-12-20 Leon Woestenberg + * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch + submitted by Mitrani Hiroshi. + + 2005-12-15 Christiaan Simons + * inet.c: Disabled the added summing routine to preserve code space. + + 2005-12-14 Leon Woestenberg + * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. + Added Curt McDowell's optimized checksumming routine for future + inclusion. Need to create test case for unaliged, aligned, odd, + even length combination of cases on various endianess machines. + + 2005-12-09 Christiaan Simons + * inet.c: Rewrote standard checksum routine in proper portable C. + + 2005-11-25 Christiaan Simons + * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. + * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, + u32_t, s32_t typedefs. This solves most debug word-length assumes. + + 2005-07-17 Leon Woestenberg + * inet.c: Fixed unaligned 16-bit access in the standard checksum + routine by Peter Jolasson. + * slipif.c: Fixed implementation assumption of single-pbuf datagrams. + + 2005-02-04 Leon Woestenberg + * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. + * tcp_{out|in}.c: Applied patch fixing unaligned access. + + 2005-01-04 Leon Woestenberg + * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. + + 2005-01-03 Leon Woestenberg + * udp.c: UDP pcb->recv() was called even when it was NULL. + +(STABLE-1_1_0) + + 2004-12-28 Leon Woestenberg + * etharp.*: Disabled multiple packets on the ARP queue. + This clashes with TCP queueing. + + 2004-11-28 Leon Woestenberg + * etharp.*: Fixed race condition from ARP request to ARP timeout. + Halved the ARP period, doubled the period counts. + ETHARP_MAX_PENDING now should be at least 2. This prevents + the counter from reaching 0 right away (which would allow + too little time for ARP responses to be received). + + 2004-11-25 Leon Woestenberg + * dhcp.c: Decline messages were not multicast but unicast. + * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. + Do not try hard to insert arbitrary packet's source address, + etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. + etharp_query() now always DOES call ETHARP_TRY_HARD so that users + querying an address will see it appear in the cache (DHCP could + suffer from this when a server invalidly gave an in-use address.) + * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are + comparing network addresses (identifiers), not the network masks + themselves. + * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given + IP address actually belongs to the network of the given interface. + + 2004-11-24 Kieran Mansley + * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. + +(STABLE-1_1_0-RC1) + + 2004-10-16 Kieran Mansley + * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, + even if one is already pending, if the rcv_wnd is above a threshold + (currently TCP_WND/2). This avoids waiting for a timer to expire to send a + delayed ACK in order to open the window if the stack is only receiving data. + + 2004-09-12 Kieran Mansley + * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. + + 2004-08-20 Tony Mountifield + * etharp.c: Make sure the first pbuf queued on an ARP entry + is properly ref counted. + + 2004-07-27 Tony Mountifield + * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler + warnings about comparison. + * pbuf.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. Closed an unclosed comment. + * tcp.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. + * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). + * inet.c: Added a couple of casts to quiet the compiler. + No need to test isascii(c) before isdigit(c) or isxdigit(c). + + 2004-07-22 Tony Mountifield + * inet.c: Made data types consistent in inet_ntoa(). + Added casts for return values of checksum routines, to pacify compiler. + * ip_frag.c, tcp_out.c, sockets.c, pbuf.c + Small corrections to some debugging statements, to pacify compiler. + + 2004-07-21 Tony Mountifield + * etharp.c: Removed spurious semicolon and added missing end-of-comment. + * ethernetif.c Updated low_level_output() to match prototype for + netif->linkoutput and changed low_level_input() similarly for consistency. + * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype + of raw_recv() in raw.h and so avoid compiler error. + * sockets.c: Added trivial (int) cast to keep compiler happier. + * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. + +(STABLE-1_0_0) + + ++ Changes: + + 2004-07-05 Leon Woestenberg + * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure + your cc.h file defines this either 1 or 0. If non-defined, + defaults to 1. + * .c: Added and includes where used. + * etharp.c: Made some array indices unsigned. + + 2004-06-27 Leon Woestenberg + * netif.*: Added netif_set_up()/down(). + * dhcp.c: Changes to restart program flow. + + 2004-05-07 Leon Woestenberg + * etharp.c: In find_entry(), instead of a list traversal per candidate, do a + single-pass lookup for different candidates. Should exploit locality. + + 2004-04-29 Leon Woestenberg + * tcp*.c: Cleaned up source comment documentation for Doxygen processing. + * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. + * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by + the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. + + ++ Bug fixes: + + 2004-04-27 Leon Woestenberg + * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution + suggested by Timmy Brolin. Fix for 32-bit processors that cannot access + non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix + is to prefix the 14-bit Ethernet headers with two padding bytes. + + 2004-04-23 Leon Woestenberg + * ip_addr.c: Fix in the ip_addr_isbroadcast() check. + * etharp.c: Fixed the case where the packet that initiates the ARP request + is not queued, and gets lost. Fixed the case where the packets destination + address is already known; we now always queue the packet and perform an ARP + request. + +(STABLE-0_7_0) + + ++ Bug fixes: + + * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. + * Fixed TCP bug in dequeueing of FIN from out of order segment queue. + * Fixed two possible NULL references in rare cases. + +(STABLE-0_6_6) + + ++ Bug fixes: + + * Fixed DHCP which did not include the IP address in DECLINE messages. + + ++ Changes: + + * etharp.c has been hauled over a bit. + +(STABLE-0_6_5) + + ++ Bug fixes: + + * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. + * Packets sent from ARP queue had invalid source hardware address. + + ++ Changes: + + * Pass-by ARP requests do now update the cache. + + ++ New features: + + * No longer dependent on ctype.h. + * New socket options. + * Raw IP pcb support. + +(STABLE-0_6_4) + + ++ Bug fixes: + + * Some debug formatters and casts fixed. + * Numereous fixes in PPP. + + ++ Changes: + + * DEBUGF now is LWIP_DEBUGF + * pbuf_dechain() has been re-enabled. + * Mentioned the changed use of CVS branches in README. + +(STABLE-0_6_3) + + ++ Bug fixes: + + * Fixed pool pbuf memory leak in pbuf_alloc(). + Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. + Reported by Savin Zlobec. + + * PBUF_POOL chains had their tot_len field not set for non-first + pbufs. Fixed in pbuf_alloc(). + + ++ New features: + + * Added PPP stack contributed by Marc Boucher + + ++ Changes: + + * Now drops short packets for ICMP/UDP/TCP protocols. More robust. + + * ARP queueuing now queues the latest packet instead of the first. + This is the RFC recommended behaviour, but can be overridden in + lwipopts.h. + +(0.6.2) + + ++ Bugfixes: + + * TCP has been fixed to deal with the new use of the pbuf->ref + counter. + + * DHCP dhcp_inform() crash bug fixed. + + ++ Changes: + + * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed + pbuf_refresh(). This has sped up pbuf pool operations considerably. + Implemented by David Haas. + +(0.6.1) + + ++ New features: + + * The packet buffer implementation has been enhanced to support + zero-copy and copy-on-demand for packet buffers which have their + payloads in application-managed memory. + Implemented by David Haas. + + Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy + if an outgoing packet can be directly sent on the link, or perform + a copy-on-demand when necessary. + + The application can safely assume the packet is sent, and the RAM + is available to the application directly after calling udp_send() + or similar function. + + ++ Bugfixes: + + * ARP_QUEUEING should now correctly work for all cases, including + PBUF_REF. + Implemented by Leon Woestenberg. + + ++ Changes: + + * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer + to a '0.0.0.0' IP address. + + * The packet buffer implementation is changed. The pbuf->ref counter + meaning has changed, and several pbuf functions have been + adapted accordingly. + + * netif drivers have to be changed to set the hardware address length field + that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). + See the contrib/ports/c16x cs8900 driver as a driver example. + + * netif's have a dhcp field that must be initialized to NULL by the driver. + See the contrib/ports/c16x cs8900 driver as a driver example. + +(0.5.x) This file has been unmaintained up to 0.6.1. All changes are + logged in CVS but have not been explained here. + +(0.5.3) Changes since version 0.5.2 + + ++ Bugfixes: + + * memp_malloc(MEMP_API_MSG) could fail with multiple application + threads because it wasn't protected by semaphores. + + ++ Other changes: + + * struct ip_addr now packed. + + * The name of the time variable in arp.c has been changed to ctime + to avoid conflicts with the time() function. + +(0.5.2) Changes since version 0.5.1 + + ++ New features: + + * A new TCP function, tcp_tmr(), now handles both TCP timers. + + ++ Bugfixes: + + * A bug in tcp_parseopt() could cause the stack to hang because of a + malformed TCP option. + + * The address of new connections in the accept() function in the BSD + socket library was not handled correctly. + + * pbuf_dechain() did not update the ->tot_len field of the tail. + + * Aborted TCP connections were not handled correctly in all + situations. + + ++ Other changes: + + * All protocol header structs are now packed. + + * The ->len field in the tcp_seg structure now counts the actual + amount of data, and does not add one for SYN and FIN segments. + +(0.5.1) Changes since version 0.5.0 + + ++ New features: + + * Possible to run as a user process under Linux. + + * Preliminary support for cross platform packed structs. + + * ARP timer now implemented. + + ++ Bugfixes: + + * TCP output queue length was badly initialized when opening + connections. + + * TCP delayed ACKs were not sent correctly. + + * Explicit initialization of BSS segment variables. + + * read() in BSD socket library could drop data. + + * Problems with memory alignment. + + * Situations when all TCP buffers were used could lead to + starvation. + + * TCP MSS option wasn't parsed correctly. + + * Problems with UDP checksum calculation. + + * IP multicast address tests had endianess problems. + + * ARP requests had wrong destination hardware address. + + ++ Other changes: + + * struct eth_addr changed from u16_t[3] array to u8_t[6]. + + * A ->linkoutput() member was added to struct netif. + + * TCP and UDP ->dest_* struct members where changed to ->remote_*. + + * ntoh* macros are now null definitions for big endian CPUs. + +(0.5.0) Changes since version 0.4.2 + + ++ New features: + + * Redesigned operating system emulation layer to make porting easier. + + * Better control over TCP output buffers. + + * Documenation added. + + ++ Bugfixes: + + * Locking issues in buffer management. + + * Bugfixes in the sequential API. + + * IP forwarding could cause memory leakage. This has been fixed. + + ++ Other changes: + + * Directory structure somewhat changed; the core/ tree has been + collapsed. + +(0.4.2) Changes since version 0.4.1 + + ++ New features: + + * Experimental ARP implementation added. + + * Skeleton Ethernet driver added. + + * Experimental BSD socket API library added. + + ++ Bugfixes: + + * In very intense situations, memory leakage could occur. This has + been fixed. + + ++ Other changes: + + * Variables named "data" and "code" have been renamed in order to + avoid name conflicts in certain compilers. + + * Variable++ have in appliciable cases been translated to ++variable + since some compilers generate better code in the latter case. + +(0.4.1) Changes since version 0.4 + + ++ New features: + + * TCP: Connection attempts time out earlier than data + transmissions. Nagle algorithm implemented. Push flag set on the + last segment in a burst. + + * UDP: experimental support for UDP-Lite extensions. + + ++ Bugfixes: + + * TCP: out of order segments were in some cases handled incorrectly, + and this has now been fixed. Delayed acknowledgements was broken + in 0.4, has now been fixed. Binding to an address that is in use + now results in an error. Reset connections sometimes hung an + application; this has been fixed. + + * Checksum calculation sometimes failed for chained pbufs with odd + lengths. This has been fixed. + + * API: a lot of bug fixes in the API. The UDP API has been improved + and tested. Error reporting and handling has been + improved. Logical flaws and race conditions for incoming TCP + connections has been found and removed. + + * Memory manager: alignment issues. Reallocating memory sometimes + failed, this has been fixed. + + * Generic library: bcopy was flawed and has been fixed. + + ++ Other changes: + + * API: all datatypes has been changed from generic ones such as + ints, to specified ones such as u16_t. Functions that return + errors now have the correct type (err_t). + + * General: A lot of code cleaned up and debugging code removed. Many + portability issues have been fixed. + + * The license was changed; the advertising clause was removed. + + * C64 port added. + + * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri + Kosunen, Mikael Caleres, and Frits Wilmink for reporting and + fixing bugs! + +(0.4) Changes since version 0.3.1 + + * Memory management has been radically changed; instead of + allocating memory from a shared heap, memory for objects that are + rapidly allocated and deallocated is now kept in pools. Allocation + and deallocation from those memory pools is very fast. The shared + heap is still present but is used less frequently. + + * The memory, memory pool, and packet buffer subsystems now support + 4-, 2-, or 1-byte alignment. + + * "Out of memory" situations are handled in a more robust way. + + * Stack usage has been reduced. + + * Easier configuration of lwIP parameters such as memory usage, + TTLs, statistics gathering, etc. All configuration parameters are + now kept in a single header file "lwipopts.h". + + * The directory structure has been changed slightly so that all + architecture specific files are kept under the src/arch + hierarchy. + + * Error propagation has been improved, both in the protocol modules + and in the API. + + * The code for the RTXC architecture has been implemented, tested + and put to use. + + * Bugs have been found and corrected in the TCP, UDP, IP, API, and + the Internet checksum modules. + + * Bugs related to porting between a 32-bit and a 16-bit architecture + have been found and corrected. + + * The license has been changed slightly to conform more with the + original BSD license, including the advertisement clause. + +(0.3.1) Changes since version 0.3 + + * Fix of a fatal bug in the buffer management. Pbufs with allocated + RAM never returned the RAM when the pbuf was deallocated. + + * TCP congestion control, window updates and retransmissions did not + work correctly. This has now been fixed. + + * Bugfixes in the API. + +(0.3) Changes since version 0.2 + + * New and improved directory structure. All include files are now + kept in a dedicated include/ directory. + + * The API now has proper error handling. A new function, + netconn_err(), now returns an error code for the connection in + case of errors. + + * Improvements in the memory management subsystem. The system now + keeps a pointer to the lowest free memory block. A new function, + mem_malloc2() tries to allocate memory once, and if it fails tries + to free some memory and retry the allocation. + + * Much testing has been done with limited memory + configurations. lwIP now does a better job when overloaded. + + * Some bugfixes and improvements to the buffer (pbuf) subsystem. + + * Many bugfixes in the TCP code: + + - Fixed a bug in tcp_close(). + + - The TCP receive window was incorrectly closed when out of + sequence segments was received. This has been fixed. + + - Connections are now timed-out of the FIN-WAIT-2 state. + + - The initial congestion window could in some cases be too + large. This has been fixed. + + - The retransmission queue could in some cases be screwed up. This + has been fixed. + + - TCP RST flag now handled correctly. + + - Out of sequence data was in some cases never delivered to the + application. This has been fixed. + + - Retransmitted segments now contain the correct acknowledgment + number and advertised window. + + - TCP retransmission timeout backoffs are not correctly computed + (ala BSD). After a number of retransmissions, TCP now gives up + the connection. + + * TCP connections now are kept on three lists, one for active + connections, one for listening connections, and one for + connections that are in TIME-WAIT. This greatly speeds up the fast + timeout processing for sending delayed ACKs. + + * TCP now provides proper feedback to the application when a + connection has been successfully set up. + + * More comments have been added to the code. The code has also been + somewhat cleaned up. + +(0.2) Initial public release. diff --git a/ext/lwip/COPYING b/ext/lwip/COPYING new file mode 100644 index 000000000..e23898b5e --- /dev/null +++ b/ext/lwip/COPYING @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + diff --git a/ext/lwip/FILES b/ext/lwip/FILES new file mode 100644 index 000000000..66253196f --- /dev/null +++ b/ext/lwip/FILES @@ -0,0 +1,4 @@ +src/ - The source code for the lwIP TCP/IP stack. +doc/ - The documentation for lwIP. + +See also the FILES file in each subdirectory. diff --git a/ext/lwip/README b/ext/lwip/README new file mode 100644 index 000000000..a62cc4f38 --- /dev/null +++ b/ext/lwip/README @@ -0,0 +1,89 @@ +INTRODUCTION + +lwIP is a small independent implementation of the TCP/IP protocol +suite that has been developed by Adam Dunkels at the Computer and +Networks Architectures (CNA) lab at the Swedish Institute of Computer +Science (SICS). + +The focus of the lwIP TCP/IP implementation is to reduce the RAM usage +while still having a full scale TCP. This making lwIP suitable for use +in embedded systems with tens of kilobytes of free RAM and room for +around 40 kilobytes of code ROM. + +FEATURES + + * IP (Internet Protocol) including packet forwarding over multiple network + interfaces + * ICMP (Internet Control Message Protocol) for network maintenance and debugging + * IGMP (Internet Group Management Protocol) for multicast traffic management + * UDP (User Datagram Protocol) including experimental UDP-lite extensions + * TCP (Transmission Control Protocol) with congestion control, RTT estimation + and fast recovery/fast retransmit + * Specialized raw/native API for enhanced performance + * Optional Berkeley-like socket API + * DNS (Domain names resolver) + * SNMP (Simple Network Management Protocol) + * DHCP (Dynamic Host Configuration Protocol) + * AUTOIP (for IPv4, conform with RFC 3927) + * PPP (Point-to-Point Protocol) + * ARP (Address Resolution Protocol) for Ethernet + +LICENSE + +lwIP is freely available under a BSD license. + +DEVELOPMENT + +lwIP has grown into an excellent TCP/IP stack for embedded devices, +and developers using the stack often submit bug fixes, improvements, +and additions to the stack to further increase its usefulness. + +Development of lwIP is hosted on Savannah, a central point for +software development, maintenance and distribution. Everyone can +help improve lwIP by use of Savannah's interface, CVS and the +mailing list. A core team of developers will commit changes to the +CVS source tree. + +The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and +contributions (such as platform ports) are in the 'contrib' module. + +See doc/savannah.txt for details on CVS server access for users and +developers. + +Last night's CVS tar ball can be downloaded from: + http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING] + +The current CVS trees are web-browsable: + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/ + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/contrib/ + +Submit patches and bugs via the lwIP project page: + http://savannah.nongnu.org/projects/lwip/ + + +DOCUMENTATION + +The original out-dated homepage of lwIP and Adam Dunkels' papers on +lwIP are at the official lwIP home page: + http://www.sics.se/~adam/lwip/ + +Self documentation of the source code is regularly extracted from the +current CVS sources and is available from this web page: + http://www.nongnu.org/lwip/ + +There is now a constantly growin wiki about lwIP at + http://lwip.wikia.com/wiki/LwIP_Wiki + +Also, there are mailing lists you can subscribe at + http://savannah.nongnu.org/mail/?group=lwip +plus searchable archives: + http://lists.nongnu.org/archive/html/lwip-users/ + http://lists.nongnu.org/archive/html/lwip-devel/ + +Reading Adam's papers, the files in docs/, browsing the source code +documentation and browsing the mailing list archives is a good way to +become familiar with the design of lwIP. + +Adam Dunkels +Leon Woestenberg + diff --git a/ext/lwip/UPGRADING b/ext/lwip/UPGRADING new file mode 100644 index 000000000..6501107a7 --- /dev/null +++ b/ext/lwip/UPGRADING @@ -0,0 +1,144 @@ +This file lists major changes between release versions that require +ports or applications to be changed. Use it to update a port or an +application written for an older version of lwIP to correctly work +with newer versions. + + +(CVS HEAD) + + * [Enter new changes just after this line - do not remove this line] + + ++ Application changes: + + * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for + compatibility to old applications, but will be removed in the future). + + * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() + + +++ Raw API: + * Changed the semantics of tcp_close() (since it was rather a + shutdown before): Now the application does *NOT* get any calls to the recv + callback (aside from NULL/closed) after calling tcp_close() + + * When calling tcp_abort() from a raw API TCP callback function, + make sure you return ERR_ABRT to prevent accessing unallocated memory. + (ERR_ABRT now means the applicaiton has called tcp_abort!) + + +++ Netconn API: + * Changed netconn_receive() and netconn_accept() to return + err_t, not a pointer to new data/netconn. + + +++ Socket API: + * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they + now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. + + * Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + +++ all APIs: + * correctly implemented SO(F)_REUSEADDR + + ++ Port changes + + +++ new files: + + * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: + + * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains + the actual application programmer's API + + * Separated timer implementation from sys.h/.c, moved to timers.h/.c; + Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you + still want to use your own timer implementation for NO_SYS==0 (as before). + + +++ sys layer: + + * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ + sys_sem_t; + + * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + + * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use + binary semaphores instead of mutexes - as before) + + +++ new options: + + * Don't waste memory when chaining segments, added option TCP_OVERSIZE to + prevent creating many small pbufs when calling tcp_write with many small + blocks of data. Instead, pbufs are allocated larger than needed and the + space is used for later calls to tcp_write. + + * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs + in tcp_write/udp_send. + + * Added an additional option LWIP_ETHERNET to support ethernet without ARP + (necessary for pure PPPoE) + + * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may + be used to place these pools into user-defined memory by using external + declaration. + + * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT + + +++ new pools: + + * Netdb uses a memp pool for allocating memory when getaddrinfo() is called, + so MEMP_NUM_NETDB has to be set accordingly. + + * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so + MEMP_NUM_LOCALHOSTLIST has to be set accordingly. + + * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have + to be set accordingly. + + * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES + has to be set accordingly + + * Integrated loopif into netif.c - loopif does not have to be created by the + port any more, just define LWIP_HAVE_LOOPIF to 1. + + * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined + in cc.h, e.g. used by igmp) + + * Added printf-formatter X8_F to printf u8_t as hex + + * The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + + * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work + with user-allocated structs instead of calling mem_malloc + + * Added const char* name to mem- and memp-stats for easier debugging. + + * Calculate the TCP/UDP checksum while copying to only fetch data once: + Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum + + * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to + more than one pcb. + + * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned + off any more, if this is set to 0, only one packet (the most recent one) is + queued (like demanded by RFC 1122). + + + ++ Major bugfixes/improvements + + * Implemented tcp_shutdown() to only shut down one end of a connection + * Implemented shutdown() at socket- and netconn-level + * Added errorset support to select() + improved select speed overhead + * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) + * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 + * Use macros defined in ip_addr.h to work with IP addresses + * Implemented many nonblocking socket/netconn functions + * Fixed ARP input processing: only add a new entry if a request was directed as us + * mem_realloc() to mem_trim() to prevent confusion with realloc() + * Some improvements for AutoIP (don't route/forward link-local addresses, don't break + existing connections when assigning a routable address) + * Correctly handle remote side overrunning our rcv_wnd in ooseq case + * Removed packing from ip_addr_t, the packed version is now only used in protocol headers + * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 + * Added support for static ARP table entries + +(STABLE-1.3.2) + + * initial version of this file diff --git a/ext/lwip/src/FILES b/ext/lwip/src/FILES new file mode 100644 index 000000000..952aeabb4 --- /dev/null +++ b/ext/lwip/src/FILES @@ -0,0 +1,13 @@ +api/ - The code for the high-level wrapper API. Not needed if + you use the lowel-level call-back/raw API. + +core/ - The core of the TPC/IP stack; protocol implementations, + memory and buffer management, and the low-level raw API. + +include/ - lwIP include files. + +netif/ - Generic network interface device drivers are kept here, + as well as the ARP module. + +For more information on the various subdirectories, check the FILES +file in each directory. diff --git a/ext/lwip/src/api/api_lib.c b/ext/lwip/src/api/api_lib.c new file mode 100644 index 000000000..4bdf08edf --- /dev/null +++ b/ext/lwip/src/api/api_lib.c @@ -0,0 +1,780 @@ +/** + * @file + * Sequential API External module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* This is the part of the API that is linked with + the application */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" + +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" + +#include + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is also created. + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) +{ + struct netconn *conn; + struct api_msg msg; + + conn = netconn_alloc(t, callback); + if (conn != NULL) { + msg.function = do_newconn; + msg.msg.msg.n.proto = proto; + msg.msg.conn = conn; + if (TCPIP_APIMSG(&msg) != ERR_OK) { + LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); + LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); + LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + sys_sem_free(&conn->op_completed); + sys_mbox_free(&conn->recvmbox); + memp_free(MEMP_NETCONN, conn); + return NULL; + } + } + return conn; +} + +/** + * Close a netconn 'connection' and free its resources. + * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate + * after this returns. + * + * @param conn the netconn to delete + * @return ERR_OK if the connection was deleted + */ +err_t +netconn_delete(struct netconn *conn) +{ + struct api_msg msg; + + /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ + if (conn == NULL) { + return ERR_OK; + } + + msg.function = do_delconn; + msg.msg.conn = conn; + tcpip_apimsg(&msg); + + netconn_free(conn); + + /* don't care for return value of do_delconn since it only calls void functions */ + + return ERR_OK; +} + +/** + * Get the local or remote IP address and port of a netconn. + * For RAW netconns, this returns the protocol instead of a port! + * + * @param conn the netconn to query + * @param addr a pointer to which to save the IP address + * @param port a pointer to which to save the port (or protocol for RAW) + * @param local 1 to get the local IP address, 0 to get the remote one + * @return ERR_CONN for invalid connections + * ERR_OK if the information was retrieved + */ +err_t +netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); + + msg.function = do_getaddr; + msg.msg.conn = conn; + msg.msg.msg.ad.ipaddr = addr; + msg.msg.msg.ad.port = port; + msg.msg.msg.ad.local = local; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Bind a netconn to a specific local IP address and port. + * Binding one netconn twice might not always be checked correctly! + * + * @param conn the netconn to bind + * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY + * to bind to all addresses) + * @param port the local port to bind the netconn to (not used for RAW) + * @return ERR_OK if bound, any other err_t on failure + */ +err_t +netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_bind; + msg.msg.conn = conn; + msg.msg.msg.bc.ipaddr = addr; + msg.msg.msg.bc.port = port; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Connect a netconn to a specific remote IP address and port. + * + * @param conn the netconn to connect + * @param addr the remote IP address to connect to + * @param port the remote port to connect to (no used for RAW) + * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise + */ +err_t +netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_connect; + msg.msg.conn = conn; + msg.msg.msg.bc.ipaddr = addr; + msg.msg.msg.bc.port = port; + /* This is the only function which need to not block tcpip_thread */ + err = tcpip_apimsg(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Disconnect a netconn from its current peer (only valid for UDP netconns). + * + * @param conn the netconn to disconnect + * @return TODO: return value is not set here... + */ +err_t +netconn_disconnect(struct netconn *conn) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_disconnect; + msg.msg.conn = conn; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Set a TCP netconn into listen mode + * + * @param conn the tcp netconn to set to listen mode + * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 + * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns + * don't return any error (yet?)) + */ +err_t +netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) +{ +#if LWIP_TCP + struct api_msg msg; + err_t err; + + /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ + LWIP_UNUSED_ARG(backlog); + + LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_listen; + msg.msg.conn = conn; +#if TCP_LISTEN_BACKLOG + msg.msg.msg.lb.backlog = backlog; +#endif /* TCP_LISTEN_BACKLOG */ + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(backlog); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * Accept a new connection on a TCP listening netconn. + * + * @param conn the TCP listen netconn + * @param new_conn pointer where the new connection is stored + * @return ERR_OK if a new connection has been received or an error + * code otherwise + */ +err_t +netconn_accept(struct netconn *conn, struct netconn **new_conn) +{ +#if LWIP_TCP + struct netconn *newconn; + err_t err; +#if TCP_LISTEN_BACKLOG + struct api_msg msg; +#endif /* TCP_LISTEN_BACKLOG */ + + LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); + *new_conn = NULL; + LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;); + + err = conn->last_err; + if (ERR_IS_FATAL(err)) { + /* don't recv on fatal errors: this might block the application task + waiting on acceptmbox forever! */ + return err; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + + if (newconn == NULL) { + /* connection has been aborted */ + NETCONN_SET_SAFE_ERR(conn, ERR_ABRT); + return ERR_ABRT; + } +#if TCP_LISTEN_BACKLOG + /* Let the stack know that we have accepted the connection. */ + msg.function = do_recv; + msg.msg.conn = conn; + /* don't care for the return value of do_recv */ + TCPIP_APIMSG(&msg); +#endif /* TCP_LISTEN_BACKLOG */ + + *new_conn = newconn; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(new_conn); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * Receive data: actual implementation that doesn't care whether pbuf or netbuf + * is received + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf/netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +static err_t +netconn_recv_data(struct netconn *conn, void **new_buf) +{ + void *buf = NULL; + u16_t len; + err_t err; +#if LWIP_TCP + struct api_msg msg; +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + + err = conn->last_err; + if (ERR_IS_FATAL(err)) { + /* don't recv on fatal errors: this might block the application task + waiting on recvmbox forever! */ + /* @todo: this does not allow us to fetch data that has been put into recvmbox + before the fatal error occurred - is that a problem? */ + return err; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (conn->type == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + if (!netconn_get_noautorecved(conn) || (buf == NULL)) { + /* Let the stack know that we have taken the data. */ + /* TODO: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + msg.function = do_recv; + msg.msg.conn = conn; + if (buf != NULL) { + msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len; + } else { + msg.msg.msg.r.len = 1; + } + /* don't care for the return value of do_recv */ + TCPIP_APIMSG(&msg); + } + + /* If we are closed, we indicate that we no longer wish to use the socket */ + if (buf == NULL) { + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + /* Avoid to lose any previous error code */ + NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); + return ERR_CLSD; + } + len = ((struct pbuf *)buf)->tot_len; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ +#if (LWIP_UDP || LWIP_RAW) + { + LWIP_ASSERT("buf != NULL", buf != NULL); + len = netbuf_len((struct netbuf *)buf); + } +#endif /* (LWIP_UDP || LWIP_RAW) */ + +#if LWIP_SO_RCVBUF + SYS_ARCH_DEC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); + + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +} + +/** + * Receive data (in form of a pbuf) from a TCP netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + * ERR_ARG if conn is not a TCP netconn + */ +err_t +netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) +{ + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && + netconn_type(conn) == NETCONN_TCP, return ERR_ARG;); + + return netconn_recv_data(conn, (void **)new_buf); +} + +/** + * Receive data (in form of a netbuf containing a packet buffer) from a netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +err_t +netconn_recv(struct netconn *conn, struct netbuf **new_buf) +{ +#if LWIP_TCP + struct netbuf *buf = NULL; + err_t err; +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (conn->type == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + struct pbuf *p = NULL; + /* This is not a listening netconn, since recvmbox is set */ + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + NETCONN_SET_SAFE_ERR(conn, ERR_MEM); + return ERR_MEM; + } + + err = netconn_recv_data(conn, (void **)&p); + if (err != ERR_OK) { + memp_free(MEMP_NETBUF, buf); + return err; + } + LWIP_ASSERT("p != NULL", p != NULL); + + buf->p = p; + buf->ptr = p; + buf->port = 0; + ip_addr_set_any(&buf->addr); + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ + { +#if (LWIP_UDP || LWIP_RAW) + return netconn_recv_data(conn, (void **)new_buf); +#endif /* (LWIP_UDP || LWIP_RAW) */ + } +} + +/** + * TCP: update the receive window: by calling this, the application + * tells the stack that it has processed data and is able to accept + * new data. + * ATTENTION: use with care, this is mainly used for sockets! + * Can only be used when calling netconn_set_noautorecved(conn, 1) before. + * + * @param conn the netconn for which to update the receive window + * @param length amount of data processed (ATTENTION: this must be accurate!) + */ +void +netconn_recved(struct netconn *conn, u32_t length) +{ +#if LWIP_TCP + if ((conn != NULL) && (conn->type == NETCONN_TCP) && + (netconn_get_noautorecved(conn))) { + struct api_msg msg; + /* Let the stack know that we have taken the data. */ + /* TODO: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + msg.function = do_recv; + msg.msg.conn = conn; + msg.msg.msg.r.len = length; + /* don't care for the return value of do_recv */ + TCPIP_APIMSG(&msg); + } +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(length); +#endif /* LWIP_TCP */ +} + +/** + * Send data (in form of a netbuf) to a specific remote IP address and port. + * Only to be used for UDP and RAW netconns (not TCP). + * + * @param conn the netconn over which to send data + * @param buf a netbuf containing the data to send + * @param addr the remote IP address to which to send the data + * @param port the remote port to which to send the data + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port) +{ + if (buf != NULL) { + ip_addr_set(&buf->addr, addr); + buf->port = port; + return netconn_send(conn, buf); + } + return ERR_VAL; +} + +/** + * Send data over a UDP or RAW netconn (that is already connected). + * + * @param conn the UDP or RAW netconn over which to send data + * @param buf a netbuf containing the data to send + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_send(struct netconn *conn, struct netbuf *buf) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); + msg.function = do_send; + msg.msg.conn = conn; + msg.msg.msg.b = buf; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Send data over a TCP netconn. + * + * @param conn the TCP netconn over which to send data + * @param dataptr pointer to the application buffer that contains the data to send + * @param size size of the application data to send + * @param apiflags combination of following flags : + * - NETCONN_COPY: data will be copied into memory belonging to the stack + * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent + * - NETCONN_DONTBLOCK: only write the data if all dat can be written at once + * @param bytes_written pointer to a location that receives the number of written bytes + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written) +{ + struct api_msg msg; + err_t err; + u8_t dontblock; + + LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;); + if (size == 0) { + return ERR_OK; + } + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); + if (dontblock && !bytes_written) { + /* This implies netconn_write() cannot be used for non-blocking send, since + it has no way to return the number of bytes written. */ + return ERR_VAL; + } + + /* non-blocking write sends as much */ + msg.function = do_write; + msg.msg.conn = conn; + msg.msg.msg.w.dataptr = dataptr; + msg.msg.msg.w.apiflags = apiflags; + msg.msg.msg.w.len = size; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout != 0) { + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + msg.msg.msg.w.time_started = sys_now(); + } else { + msg.msg.msg.w.time_started = 0; + } +#endif /* LWIP_SO_SNDTIMEO */ + + /* For locking the core: this _can_ be delayed on low memory/low send buffer, + but if it is, this is done inside api_msg.c:do_write(), so we can use the + non-blocking version here. */ + err = TCPIP_APIMSG(&msg); + if ((err == ERR_OK) && (bytes_written != NULL)) { + if (dontblock +#if LWIP_SO_SNDTIMEO + || (conn->send_timeout != 0) +#endif /* LWIP_SO_SNDTIMEO */ + ) { + /* nonblocking write: maybe the data has been sent partly */ + *bytes_written = msg.msg.msg.w.len; + } else { + /* blocking call succeeded: all data has been sent if it */ + *bytes_written = size; + } + } + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Close ot shutdown a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close or shutdown + * @param how fully close or only shutdown one side? + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +static err_t +netconn_close_shutdown(struct netconn *conn, u8_t how) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_close; + msg.msg.conn = conn; + /* shutting down both ends is the same as closing */ + msg.msg.msg.sd.shut = how; + /* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close, + don't use TCPIP_APIMSG here */ + err = tcpip_apimsg(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Close a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_close(struct netconn *conn) +{ + /* shutting down both ends is the same as closing */ + return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); +} + +/** + * Shut down one or both sides of a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to shut down + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) +{ + return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); +} + +#if LWIP_IGMP +/** + * Join multicast groups for UDP netconns. + * + * @param conn the UDP netconn for which to change multicast addresses + * @param multiaddr IP address of the multicast group to join or leave + * @param netif_addr the IP address of the network interface on which to send + * the igmp message + * @param join_or_leave flag whether to send a join- or leave-message + * @return ERR_OK if the action was taken, any err_t on error + */ +err_t +netconn_join_leave_group(struct netconn *conn, + ip_addr_t *multiaddr, + ip_addr_t *netif_addr, + enum netconn_igmp join_or_leave) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_join_leave_group; + msg.msg.conn = conn; + msg.msg.msg.jl.multiaddr = multiaddr; + msg.msg.msg.jl.netif_addr = netif_addr; + msg.msg.msg.jl.join_or_leave = join_or_leave; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Execute a DNS query, only one IP address is returned + * + * @param name a string representation of the DNS host name to query + * @param addr a preallocated ip_addr_t where to store the resolved IP address + * @return ERR_OK: resolving succeeded + * ERR_MEM: memory error, try again later + * ERR_ARG: dns client not initialized or invalid hostname + * ERR_VAL: dns server response was invalid + */ +err_t +netconn_gethostbyname(const char *name, ip_addr_t *addr) +{ + struct dns_api_msg msg; + err_t err; + sys_sem_t sem; + + LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); + + err = sys_sem_new(&sem, 0); + if (err != ERR_OK) { + return err; + } + + msg.name = name; + msg.addr = addr; + msg.err = &err; + msg.sem = &sem; + + tcpip_callback(do_gethostbyname, &msg); + sys_sem_wait(&sem); + sys_sem_free(&sem); + + return err; +} +#endif /* LWIP_DNS*/ + +#endif /* LWIP_NETCONN */ diff --git a/ext/lwip/src/api/api_msg.c b/ext/lwip/src/api/api_msg.c new file mode 100644 index 000000000..d4e44b9ad --- /dev/null +++ b/ext/lwip/src/api/api_msg.c @@ -0,0 +1,1565 @@ +/** + * @file + * Sequential API Internal module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" + +#include "lwip/ip.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/tcpip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" + +#include + +#define SET_NONBLOCKING_CONNECT(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) +#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +/* forward declarations */ +#if LWIP_TCP +static err_t do_writemore(struct netconn *conn); +static void do_close_internal(struct netconn *conn); +#endif + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only references it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip_addr_t *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; + + LWIP_UNUSED_ARG(addr); + conn = (struct netconn *)arg; + + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { +#if LWIP_SO_RCVBUF + int recv_avail; + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { + return 0; + } +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if (q != NULL) { + u16_t len; + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return 0; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; + u16_t len; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + ip_addr_set(&buf->addr, addr); + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + const struct ip_hdr* iphdr = ip_current_header(); + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr)); +#if LWIP_CHECKSUM_ON_COPY + buf->flags = NETBUF_FLAG_DESTADDR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + ip_addr_set(&buf->toaddr, ip_current_dest_addr()); + buf->toport_chksum = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + len = p->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (conn == NULL) { + return ERR_VAL; + } + if (!sys_mbox_valid(&conn->recvmbox)) { + /* recvmbox already deleted */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + + /* don't overwrite fatal errors! */ + NETCONN_SET_SAFE_ERR(conn, err); + + if (p != NULL) { + len = p->tot_len; + } else { + len = 0; + } + + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { + /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ + return ERR_MEM; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + do_writemore(conn); + } else if (conn->state == NETCONN_CLOSE) { + do_close_internal(conn); + } + /* @todo: implement connect timeout here? */ + + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + do_writemore(conn); + } else if (conn->state == NETCONN_CLOSE) { + do_close_internal(conn); + } + + if (conn) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + enum netconn_state old_state; + SYS_ARCH_DECL_PROTECT(lev); + + conn = (struct netconn *)arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + /* no check since this is always fatal! */ + SYS_ARCH_PROTECT(lev); + conn->last_err = err; + SYS_ARCH_UNPROTECT(lev); + + /* reset conn->state now before waking up other threads */ + old_state = conn->state; + conn->state = NETCONN_NONE; + + /* Notify the user layer about a connection error. Used to signal + select. */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + /* Try to release selects pending on 'read' or 'write', too. + They will get an error if they actually try to read or write. */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + /* pass NULL-message to recvmbox to wake up pending recv */ + if (sys_mbox_valid(&conn->recvmbox)) { + /* use trypost to prevent deadlock */ + sys_mbox_trypost(&conn->recvmbox, NULL); + } + /* pass NULL-message to acceptmbox to wake up pending accept */ + if (sys_mbox_valid(&conn->acceptmbox)) { + /* use trypost to preven deadlock */ + sys_mbox_trypost(&conn->acceptmbox, NULL); + } + + if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || + (old_state == NETCONN_CONNECT)) { + /* calling do_writemore/do_close_internal is not necessary + since the pcb has already been deleted! */ + int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) { + /* set error return code */ + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + conn->current_msg->err = err; + conn->current_msg = NULL; + /* wake up the waiting task */ + sys_sem_signal(&conn->op_completed); + } + } else { + LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, 4); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn = (struct netconn *)arg; + + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); + + if (!sys_mbox_valid(&conn->acceptmbox)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); + return ERR_VAL; + } + + /* We have to set the callback here even though + * the new socket is unknown. conn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { + /* When returning != ERR_OK, the pcb is aborted in tcp_process(), + so do nothing here! */ + /* remove all references to this netconn from the pcb */ + struct tcp_pcb* pcb = newconn->pcb.tcp; + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_poll(pcb, NULL, 4); + tcp_err(pcb, NULL); + /* remove reference from to the pcb from this netconn */ + newconn->pcb.tcp = NULL; + /* no need to drain since we know the recvmbox is empty. */ + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + * @return msg->conn->err, but the return value is currently ignored + */ +static void +pcb_new(struct api_msg_msg *msg) +{ + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new(msg->msg.n.proto); + if(msg->conn->pcb.raw == NULL) { + msg->err = ERR_MEM; + break; + } + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new(); + if(msg->conn->pcb.udp == NULL) { + msg->err = ERR_MEM; + break; + } +#if LWIP_UDPLITE + if (msg->conn->type==NETCONN_UDPLITE) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (msg->conn->type==NETCONN_UDPNOCHKSUM) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new(); + if(msg->conn->pcb.tcp == NULL) { + msg->err = ERR_MEM; + break; + } + setup_tcp(msg->conn); + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->err = ERR_VAL; + break; + } +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param msg the api_msg_msg describing the connection type + */ +void +do_newconn(struct api_msg_msg *msg) +{ + msg->err = ERR_OK; + if(msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size; + + conn = (struct netconn *)memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + +#if (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_UDP_RECVMBOX_SIZE) && \ + (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_TCP_RECVMBOX_SIZE) + size = DEFAULT_RAW_RECVMBOX_SIZE; +#else + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + goto free_and_return; + } +#endif + + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { + goto free_and_return; + } + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + sys_sem_free(&conn->op_completed); + goto free_and_return; + } + +#if LWIP_TCP + sys_mbox_set_invalid(&conn->acceptmbox); +#endif + conn->state = NETCONN_NONE; +#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; +#endif /* LWIP_SOCKET */ + conn->callback = callback; +#if LWIP_TCP + conn->current_msg = NULL; + conn->write_offset = 0; +#endif /* LWIP_TCP */ +#if LWIP_SO_SNDTIMEO + conn->send_timeout = 0; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; +#endif /* LWIP_SO_RCVBUF */ + conn->flags = 0; + return conn; +free_and_return: + memp_free(MEMP_NETCONN, conn); + return NULL; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); + LWIP_ASSERT("recvmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("acceptmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); + + memp_free(MEMP_NETCONN, conn); +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +static void +netconn_drain(struct netconn *conn) +{ + void *mem; +#if LWIP_TCP + struct pbuf *p; +#endif /* LWIP_TCP */ + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + + /* Delete and drain the recvmbox. */ + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { +#if LWIP_TCP + if (conn->type == NETCONN_TCP) { + if(mem != NULL) { + p = (struct pbuf*)mem; + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_recved(conn->pcb.tcp, p->tot_len); + } + pbuf_free(p); + } + } else +#endif /* LWIP_TCP */ + { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); + } + + /* Delete and drain the acceptmbox. */ +#if LWIP_TCP + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_accepted(conn->pcb.tcp); + } + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); + } + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); + } +#endif /* LWIP_TCP */ +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +static void +do_close_internal(struct netconn *conn) +{ + err_t err; + u8_t shut, shut_rx, shut_tx, close; + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + + shut = conn->current_msg->msg.sd.shut; + shut_rx = shut & NETCONN_SHUT_RD; + shut_tx = shut & NETCONN_SHUT_WR; + /* shutting down both ends is the same as closing */ + close = shut == NETCONN_SHUT_RDWR; + + /* Set back some callback pointers */ + if (close) { + tcp_arg(conn->pcb.tcp, NULL); + } + if (conn->pcb.tcp->state == LISTEN) { + tcp_accept(conn->pcb.tcp, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut_rx) { + tcp_recv(conn->pcb.tcp, NULL); + tcp_accept(conn->pcb.tcp, NULL); + } + if (shut_tx) { + tcp_sent(conn->pcb.tcp, NULL); + } + if (close) { + tcp_poll(conn->pcb.tcp, NULL, 4); + tcp_err(conn->pcb.tcp, NULL); + } + } + /* Try to close the connection */ + if (close) { + err = tcp_close(conn->pcb.tcp); + } else { + err = tcp_shutdown(conn->pcb.tcp, shut_rx, shut_tx); + } + if (err == ERR_OK) { + /* Closing succeeded */ + conn->current_msg->err = ERR_OK; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (close) { + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + } + if (shut_rx) { + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + if (shut_tx) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + /* wake up the application task */ + sys_sem_signal(&conn->op_completed); + } else { + /* Closing failed, restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); + tcp_sent(conn->pcb.tcp, sent_tcp); + tcp_poll(conn->pcb.tcp, poll_tcp, 4); + tcp_err(conn->pcb.tcp, err_tcp); + tcp_arg(conn->pcb.tcp, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_delconn(struct api_msg_msg *msg) +{ + /* @todo TCP: abort running write/connect? */ + if ((msg->conn->state != NETCONN_NONE) && + (msg->conn->state != NETCONN_LISTEN) && + (msg->conn->state != NETCONN_CONNECT)) { + /* this only happens for TCP netconns */ + LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP); + msg->err = ERR_INPROGRESS; + } else { + LWIP_ASSERT("blocking connect in progress", + (msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + + if (msg->conn->pcb.tcp != NULL) { + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->msg.sd.shut = NETCONN_SHUT_RDWR; + msg->conn->current_msg = msg; + do_close_internal(msg->conn); + /* API_EVENT is called inside do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + msg->conn->pcb.tcp = NULL; + } + /* tcp netconns don't come here! */ + + /* @todo: this lets select make the socket readable and writable, + which is wrong! errfd instead? */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + } + if (sys_sem_valid(&msg->conn->op_completed)) { + sys_sem_signal(&msg->conn->op_completed); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +do_bind(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + int was_blocking; + + LWIP_UNUSED_ARG(pcb); + + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + + LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); + LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", + (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); + + if (conn->current_msg != NULL) { + conn->current_msg->err = err; + } + if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + was_blocking = !IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (!was_blocking) { + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + } + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + if (was_blocking) { + sys_sem_signal(&conn->op_completed); + } + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +do_connect(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ + msg->err = ERR_CLSD; + } else { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + /* Prevent connect while doing any other action. */ + if (msg->conn->state != NETCONN_NONE) { + msg->err = ERR_ISCONN; + } else { + setup_tcp(msg->conn); + msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, + msg->msg.bc.port, do_connected); + if (msg->err == ERR_OK) { + u8_t non_blocking = netconn_is_nonblocking(msg->conn); + msg->conn->state = NETCONN_CONNECT; + SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); + if (non_blocking) { + msg->err = ERR_INPROGRESS; + } else { + msg->conn->current_msg = msg; + /* sys_sem_signal() is called from do_connected (or err_tcp()), + * when the connection is established! */ + return; + } + } + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); + break; + } + } + sys_sem_signal(&msg->conn->op_completed); +} + +/** + * Connect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param msg the api_msg_msg pointing to the connection to disconnect + */ +void +do_disconnect(struct api_msg_msg *msg) +{ +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + msg->err = ERR_OK; + } else +#endif /* LWIP_UDP */ + { + msg->err = ERR_VAL; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_listen(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (msg->conn->type == NETCONN_TCP) { + if (msg->conn->state == NETCONN_NONE) { +#if TCP_LISTEN_BACKLOG + struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog); +#else /* TCP_LISTEN_BACKLOG */ + struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp); +#endif /* TCP_LISTEN_BACKLOG */ + if (lpcb == NULL) { + /* in this case, the old pcb is still allocated */ + msg->err = ERR_MEM; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (sys_mbox_valid(&msg->conn->recvmbox)) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); + } + msg->err = ERR_OK; + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); + } + if (msg->err == ERR_OK) { + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } else { + /* since the old pcb is already deallocated, free lpcb now */ + tcp_close(lpcb); + msg->conn->pcb.tcp = NULL; + } + } + } + } else { + msg->err = ERR_ARG; + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_send(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (ip_addr_isany(&msg->msg.b->addr)) { + msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: +#if LWIP_CHECKSUM_ON_COPY + if (ip_addr_isany(&msg->msg.b->addr)) { + msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } else { + msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, + &msg->msg.b->addr, msg->msg.b->port, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ip_addr_isany(&msg->msg.b->addr)) { + msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_recv(struct api_msg_msg *msg) +{ + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (msg->conn->type == NETCONN_TCP) { +#if TCP_LISTEN_BACKLOG + if (msg->conn->pcb.tcp->state == LISTEN) { + tcp_accepted(msg->conn->pcb.tcp); + } else +#endif /* TCP_LISTEN_BACKLOG */ + { + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + }while(remaining != 0); + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +do_writemore(struct netconn *conn) +{ + err_t err; + void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + u8_t dontblock = netconn_is_nonblocking(conn) || + (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); + u8_t apiflags = conn->current_msg->msg.w.apiflags; + + LWIP_ASSERT("conn != NULL", conn != NULL); + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", + conn->write_offset < conn->current_msg->msg.w.len); + +#if LWIP_SO_SNDTIMEO + if ((conn->send_timeout != 0) && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + if (conn->write_offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + conn->current_msg->msg.w.len = 0; + } else { + /* partial write */ + err = ERR_OK; + conn->current_msg->msg.w.len = conn->write_offset; + } + } else +#endif /* LWIP_SO_SNDTIMEO */ + { + dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; + diff = conn->current_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock){ + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + /* if OK or memory error, check available space */ + if ((err == ERR_OK) || (err == ERR_MEM)) { +err_mem: + if (dontblock && (len < conn->current_msg->msg.w.len)) { + /* non-blocking write did not write everything: mark the pcb non-writable + and let poll_tcp check writable space to mark the pcb writable again */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; + } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { + /* The queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } + + if (err == ERR_OK) { + conn->write_offset += len; + if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { + /* return sent length */ + conn->current_msg->msg.w.len = conn->write_offset; + /* everything was written */ + write_finished = 1; + conn->write_offset = 0; + } + tcp_output(conn->pcb.tcp); + } else if ((err == ERR_MEM) && !dontblock) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called + we do NOT return to the application thread, since ERR_MEM is + only a temporary error! */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + tcp_output(conn->pcb.tcp); + +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; +#if LWIP_TCPIP_CORE_LOCKING + if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0) +#endif + { + sys_sem_signal(&conn->op_completed); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else + return ERR_MEM; +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_write(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->type == NETCONN_TCP) { +#if LWIP_TCP + if (msg->conn->state != NETCONN_NONE) { + /* netconn is connecting, closing or in blocking write */ + msg->err = ERR_INPROGRESS; + } else if (msg->conn->pcb.tcp != NULL) { + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by do_writemore */ + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); + msg->conn->current_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED; + if (do_writemore(msg->conn) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(&msg->conn->op_completed, 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + do_writemore(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for both cases: if do_writemore was called, don't ACK the APIMSG + since do_writemore ACKs it! */ + return; + } else { + msg->err = ERR_CONN; + } +#else /* LWIP_TCP */ + msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_getaddr(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.ip != NULL) { + *(msg->msg.ad.ipaddr) = (msg->msg.ad.local ? msg->conn->pcb.ip->local_ip : + msg->conn->pcb.ip->remote_ip); + + msg->err = ERR_OK; + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->err = ERR_CONN; + } else { + *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port); + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("invalid netconn_type", 0); + break; + } + } else { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close a TCP pcb contained in a netconn + * Called from netconn_close + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_close(struct api_msg_msg *msg) +{ +#if LWIP_TCP + /* @todo: abort running write/connect? */ + if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) { + /* this only happens for TCP netconns */ + LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP); + msg->err = ERR_INPROGRESS; + } else if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) { + if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) { + /* LISTEN doesn't support half shutdown */ + msg->err = ERR_CONN; + } else { + if (msg->msg.sd.shut & NETCONN_SHUT_RD) { + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + } + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->conn->current_msg = msg; + do_close_internal(msg->conn); + /* for tcp netconns, do_close_internal ACKs the message */ + return; + } + } else +#endif /* LWIP_TCP */ + { + msg->err = ERR_VAL; + } + sys_sem_signal(&msg->conn->op_completed); +} + +#if LWIP_IGMP +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_join_leave_group(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr); + } else { + msg->err = igmp_leavegroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr); + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } else { + msg->err = ERR_CONN; + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +do_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0); + LWIP_UNUSED_ARG(name); + + if (ipaddr == NULL) { + /* timeout or memory error */ + *msg->err = ERR_VAL; + } else { + /* address was resolved */ + *msg->err = ERR_OK; + *msg->addr = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(msg->sem); +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + *msg->err = dns_gethostbyname(msg->name, msg->addr, do_dns_found, msg); + if (*msg->err != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(msg->sem); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ diff --git a/ext/lwip/src/api/err.c b/ext/lwip/src/api/err.c new file mode 100644 index 000000000..92fa8b7db --- /dev/null +++ b/ext/lwip/src/api/err.c @@ -0,0 +1,75 @@ +/** + * @file + * Error Management module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/err.h" + +#ifdef LWIP_DEBUG + +static const char *err_strerr[] = { + "Ok.", /* ERR_OK 0 */ + "Out of memory error.", /* ERR_MEM -1 */ + "Buffer error.", /* ERR_BUF -2 */ + "Timeout.", /* ERR_TIMEOUT -3 */ + "Routing problem.", /* ERR_RTE -4 */ + "Operation in progress.", /* ERR_INPROGRESS -5 */ + "Illegal value.", /* ERR_VAL -6 */ + "Operation would block.", /* ERR_WOULDBLOCK -7 */ + "Address in use.", /* ERR_USE -8 */ + "Already connected.", /* ERR_ISCONN -9 */ + "Connection aborted.", /* ERR_ABRT -10 */ + "Connection reset.", /* ERR_RST -11 */ + "Connection closed.", /* ERR_CLSD -12 */ + "Not connected.", /* ERR_CONN -13 */ + "Illegal argument.", /* ERR_ARG -14 */ + "Low-level netif error.", /* ERR_IF -15 */ +}; + +/** + * Convert an lwip internal error to a string representation. + * + * @param err an lwip internal err_t + * @return a string representation for err + */ +const char * +lwip_strerr(err_t err) +{ + return err_strerr[-err]; + +} + +#endif /* LWIP_DEBUG */ diff --git a/ext/lwip/src/api/netbuf.c b/ext/lwip/src/api/netbuf.c new file mode 100644 index 000000000..9390c9ee9 --- /dev/null +++ b/ext/lwip/src/api/netbuf.c @@ -0,0 +1,245 @@ +/** + * @file + * Network buffer management + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netbuf.h" +#include "lwip/memp.h" + +#include + +/** + * Create (allocate) and initialize a new netbuf. + * The netbuf doesn't yet contain a packet buffer! + * + * @return a pointer to a new netbuf + * NULL on lack of memory + */ +struct +netbuf *netbuf_new(void) +{ + struct netbuf *buf; + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf != NULL) { + buf->p = NULL; + buf->ptr = NULL; + ip_addr_set_any(&buf->addr); + buf->port = 0; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + buf->flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + buf->toport_chksum = 0; +#if LWIP_NETBUF_RECVINFO + ip_addr_set_any(&buf->toaddr); +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ + return buf; + } else { + return NULL; + } +} + +/** + * Deallocate a netbuf allocated by netbuf_new(). + * + * @param buf pointer to a netbuf allocated by netbuf_new() + */ +void +netbuf_delete(struct netbuf *buf) +{ + if (buf != NULL) { + if (buf->p != NULL) { + pbuf_free(buf->p); + buf->p = buf->ptr = NULL; + } + memp_free(MEMP_NETBUF, buf); + } +} + +/** + * Allocate memory for a packet buffer for a given netbuf. + * + * @param buf the netbuf for which to allocate a packet buffer + * @param size the size of the packet buffer to allocate + * @return pointer to the allocated memory + * NULL if no memory could be allocated + */ +void * +netbuf_alloc(struct netbuf *buf, u16_t size) +{ + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + + /* Deallocate any previously allocated memory. */ + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (buf->p == NULL) { + return NULL; + } + LWIP_ASSERT("check that first pbuf can hold size", + (buf->p->len >= size)); + buf->ptr = buf->p; + return buf->p->payload; +} + +/** + * Free the packet buffer included in a netbuf + * + * @param buf pointer to the netbuf which contains the packet buffer to free + */ +void +netbuf_free(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = buf->ptr = NULL; +} + +/** + * Let a netbuf reference existing (non-volatile) data. + * + * @param buf netbuf which should reference the data + * @param dataptr pointer to the data to reference + * @param size size of the data + * @return ERR_OK if data is referenced + * ERR_MEM if data couldn't be referenced due to lack of memory + */ +err_t +netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) +{ + LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (buf->p == NULL) { + buf->ptr = NULL; + return ERR_MEM; + } + buf->p->payload = (void*)dataptr; + buf->p->len = buf->p->tot_len = size; + buf->ptr = buf->p; + return ERR_OK; +} + +/** + * Chain one netbuf to another (@see pbuf_chain) + * + * @param head the first netbuf + * @param tail netbuf to chain after head, freed by this function, may not be reference after returning + */ +void +netbuf_chain(struct netbuf *head, struct netbuf *tail) +{ + LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;); + LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); + pbuf_cat(head->p, tail->p); + head->ptr = head->p; + memp_free(MEMP_NETBUF, tail); +} + +/** + * Get the data pointer and length of the data inside a netbuf. + * + * @param buf netbuf to get the data from + * @param dataptr pointer to a void pointer where to store the data pointer + * @param len pointer to an u16_t where the length of the data is stored + * @return ERR_OK if the information was retreived, + * ERR_BUF on error. + */ +err_t +netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) +{ + LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); + + if (buf->ptr == NULL) { + return ERR_BUF; + } + *dataptr = buf->ptr->payload; + *len = buf->ptr->len; + return ERR_OK; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the next part. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + * @return -1 if there is no next part + * 1 if moved to the next part but now there is no next part + * 0 if moved to the next part and there are still more parts + */ +s8_t +netbuf_next(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;); + if (buf->ptr->next == NULL) { + return -1; + } + buf->ptr = buf->ptr->next; + if (buf->ptr->next == NULL) { + return 1; + } + return 0; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the beginning of the packet. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + */ +void +netbuf_first(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + buf->ptr = buf->p; +} + +#endif /* LWIP_NETCONN */ diff --git a/ext/lwip/src/api/netdb.c b/ext/lwip/src/api/netdb.c new file mode 100644 index 000000000..6a4bac561 --- /dev/null +++ b/ext/lwip/src/api/netdb.c @@ -0,0 +1,353 @@ +/** + * @file + * API functions for name resolving + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/netdb.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/err.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/api.h" +#include "lwip/dns.h" + +#include +#include + +/** helper struct for gethostbyname_r to access the char* buffer */ +struct gethostbyname_r_helper { + ip_addr_t *addr_list[2]; + ip_addr_t addr; + char *aliases; +}; + +/** h_errno is exported in netdb.h for access by applications. */ +#if LWIP_DNS_API_DECLARE_H_ERRNO +int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + +/** define "hostent" variables storage: 0 if we use a static (but unprotected) + * set of variables for lwip_gethostbyname, 1 if we use a local storage */ +#ifndef LWIP_DNS_API_HOSTENT_STORAGE +#define LWIP_DNS_API_HOSTENT_STORAGE 0 +#endif + +/** define "hostent" variables storage */ +#if LWIP_DNS_API_HOSTENT_STORAGE +#define HOSTENT_STORAGE +#else +#define HOSTENT_STORAGE static +#endif /* LWIP_DNS_API_STATIC_HOSTENT */ + +/** + * Returns an entry containing addresses of address family AF_INET + * for the host with name name. + * Due to dns_gethostbyname limitations, only one address is returned. + * + * @param name the hostname to resolve + * @return an entry containing addresses of address family AF_INET + * for the host with name name + */ +struct hostent* +lwip_gethostbyname(const char *name) +{ + err_t err; + ip_addr_t addr; + + /* buffer variables for lwip_gethostbyname() */ + HOSTENT_STORAGE struct hostent s_hostent; + HOSTENT_STORAGE char *s_aliases; + HOSTENT_STORAGE ip_addr_t s_hostent_addr; + HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; + + /* query host IP address */ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + h_errno = HOST_NOT_FOUND; + return NULL; + } + + /* fill hostent */ + s_hostent_addr = addr; + s_phostent_addr[0] = &s_hostent_addr; + s_phostent_addr[1] = NULL; + s_hostent.h_name = (char*)name; + s_hostent.h_aliases = &s_aliases; + s_hostent.h_addrtype = AF_INET; + s_hostent.h_length = sizeof(ip_addr_t); + s_hostent.h_addr_list = (char**)&s_phostent_addr; + +#if DNS_DEBUG + /* dump hostent */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", s_hostent.h_aliases)); + if (s_hostent.h_aliases != NULL) { + u8_t idx; + for ( idx=0; s_hostent.h_aliases[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx])); + } + } + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", s_hostent.h_addr_list)); + if (s_hostent.h_addr_list != NULL) { + u8_t idx; + for ( idx=0; s_hostent.h_addr_list[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); + } + } +#endif /* DNS_DEBUG */ + +#if LWIP_DNS_API_HOSTENT_STORAGE + /* this function should return the "per-thread" hostent after copy from s_hostent */ + return sys_thread_hostent(&s_hostent); +#else + return &s_hostent; +#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ +} + +/** + * Thread-safe variant of lwip_gethostbyname: instead of using a static + * buffer, this function takes buffer and errno pointers as arguments + * and uses these for the result. + * + * @param name the hostname to resolve + * @param ret pre-allocated struct where to store the result + * @param buf pre-allocated buffer where to store additional data + * @param buflen the size of buf + * @param result pointer to a hostent pointer that is set to ret on success + * and set to zero on error + * @param h_errnop pointer to an int where to store errors (instead of modifying + * the global h_errno) + * @return 0 on success, non-zero on error, additional error information + * is stored in *h_errnop instead of h_errno to be thread-safe + */ +int +lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + err_t err; + struct gethostbyname_r_helper *h; + char *hostname; + size_t namelen; + int lh_errno; + + if (h_errnop == NULL) { + /* ensure h_errnop is never NULL */ + h_errnop = &lh_errno; + } + + if (result == NULL) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + /* first thing to do: set *result to nothing */ + *result = NULL; + if ((name == NULL) || (ret == NULL) || (buf == NULL)) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + + namelen = strlen(name); + if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { + /* buf can't hold the data needed + a copy of name */ + *h_errnop = ERANGE; + return -1; + } + + h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); + hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); + + /* query host IP address */ + err = netconn_gethostbyname(name, &h->addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + *h_errnop = HOST_NOT_FOUND; + return -1; + } + + /* copy the hostname into buf */ + MEMCPY(hostname, name, namelen); + hostname[namelen] = 0; + + /* fill hostent */ + h->addr_list[0] = &h->addr; + h->addr_list[1] = NULL; + h->aliases = NULL; + ret->h_name = hostname; + ret->h_aliases = &h->aliases; + ret->h_addrtype = AF_INET; + ret->h_length = sizeof(ip_addr_t); + ret->h_addr_list = (char**)&h->addr_list; + + /* set result != NULL */ + *result = ret; + + /* return success */ + return 0; +} + +/** + * Frees one or more addrinfo structures returned by getaddrinfo(), along with + * any additional storage associated with those structures. If the ai_next field + * of the structure is not null, the entire list of structures is freed. + * + * @param ai struct addrinfo to free + */ +void +lwip_freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + memp_free(MEMP_NETDB, ai); + ai = next; + } +} + +/** + * Translates the name of a service location (for example, a host name) and/or + * a service name and returns a set of socket addresses and associated + * information to be used in creating a socket with which to address the + * specified service. + * Memory for the result is allocated internally and must be freed by calling + * lwip_freeaddrinfo()! + * + * Due to a limitation in dns_gethostbyname, only the first address of a + * host is returned. + * Also, service names are not supported (only port numbers)! + * + * @param nodename descriptive name or address string of the host + * (may be NULL -> local address) + * @param servname port number as string of NULL + * @param hints structure containing input values that set socktype and protocol + * @param res pointer to a pointer where to store the result (set to NULL on failure) + * @return 0 on success, non-zero on failure + */ +int +lwip_getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + err_t err; + ip_addr_t addr; + struct addrinfo *ai; + struct sockaddr_in *sa = NULL; + int port_nr = 0; + size_t total_size; + size_t namelen = 0; + + if (res == NULL) { + return EAI_FAIL; + } + *res = NULL; + if ((nodename == NULL) && (servname == NULL)) { + return EAI_NONAME; + } + + if (servname != NULL) { + /* service name specified: convert to port number + * @todo?: currently, only ASCII integers (port numbers) are supported! */ + port_nr = atoi(servname); + if ((port_nr <= 0) || (port_nr > 0xffff)) { + return EAI_SERVICE; + } + } + + if (nodename != NULL) { + /* service location specified, try to resolve */ + err = netconn_gethostbyname(nodename, &addr); + if (err != ERR_OK) { + return EAI_FAIL; + } + } else { + /* service location specified, use loopback address */ + ip_addr_set_loopback(&addr); + } + + total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in); + if (nodename != NULL) { + namelen = strlen(nodename); + LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1); + total_size += namelen + 1; + } + /* If this fails, please report to lwip-devel! :-) */ + LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", + total_size <= NETDB_ELEM_SIZE); + ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); + if (ai == NULL) { + goto memerr; + } + memset(ai, 0, total_size); + sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo)); + /* set up sockaddr */ + inet_addr_from_ipaddr(&sa->sin_addr, &addr); + sa->sin_family = AF_INET; + sa->sin_len = sizeof(struct sockaddr_in); + sa->sin_port = htons((u16_t)port_nr); + + /* set up addrinfo */ + ai->ai_family = AF_INET; + if (hints != NULL) { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + if (nodename != NULL) { + /* copy nodename to canonname if specified */ + ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr = (struct sockaddr*)sa; + + *res = ai; + + return 0; +memerr: + if (ai != NULL) { + memp_free(MEMP_NETDB, ai); + } + return EAI_MEMORY; +} + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/ext/lwip/src/api/netifapi.c b/ext/lwip/src/api/netifapi.c new file mode 100644 index 000000000..43e47203a --- /dev/null +++ b/ext/lwip/src/api/netifapi.c @@ -0,0 +1,160 @@ +/** + * @file + * Network Interface Sequential API module + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netifapi.h" +#include "lwip/tcpip.h" + +/** + * Call netif_add() inside the tcpip_thread context. + */ +void +do_netifapi_netif_add(struct netifapi_msg_msg *msg) +{ + if (!netif_add( msg->netif, + msg->msg.add.ipaddr, + msg->msg.add.netmask, + msg->msg.add.gw, + msg->msg.add.state, + msg->msg.add.init, + msg->msg.add.input)) { + msg->err = ERR_IF; + } else { + msg->err = ERR_OK; + } + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call netif_set_addr() inside the tcpip_thread context. + */ +void +do_netifapi_netif_set_addr(struct netifapi_msg_msg *msg) +{ + netif_set_addr( msg->netif, + msg->msg.add.ipaddr, + msg->msg.add.netmask, + msg->msg.add.gw); + msg->err = ERR_OK; + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the + * tcpip_thread context. + */ +void +do_netifapi_netif_common(struct netifapi_msg_msg *msg) +{ + if (msg->msg.common.errtfunc != NULL) { + msg->err = msg->msg.common.errtfunc(msg->netif); + } else { + msg->err = ERR_OK; + msg->msg.common.voidfunc(msg->netif); + } + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call netif_add() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_add() + */ +err_t +netifapi_netif_add(struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw, + void *state, + netif_init_fn init, + netif_input_fn input) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_add; + msg.msg.netif = netif; + msg.msg.msg.add.ipaddr = ipaddr; + msg.msg.msg.add.netmask = netmask; + msg.msg.msg.add.gw = gw; + msg.msg.msg.add.state = state; + msg.msg.msg.add.init = init; + msg.msg.msg.add.input = input; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +/** + * Call netif_set_addr() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_set_addr() + */ +err_t +netifapi_netif_set_addr(struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_set_addr; + msg.msg.netif = netif; + msg.msg.msg.add.ipaddr = ipaddr; + msg.msg.msg.add.netmask = netmask; + msg.msg.msg.add.gw = gw; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +/** + * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe + * way by running that function inside the tcpip_thread context. + * + * @note use only for functions where there is only "netif" parameter. + */ +err_t +netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_common; + msg.msg.netif = netif; + msg.msg.msg.common.voidfunc = voidfunc; + msg.msg.msg.common.errtfunc = errtfunc; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +#endif /* LWIP_NETIF_API */ diff --git a/ext/lwip/src/api/sockets.c b/ext/lwip/src/api/sockets.c new file mode 100644 index 000000000..359919e78 --- /dev/null +++ b/ext/lwip/src/api/sockets.c @@ -0,0 +1,2374 @@ +/** + * @file + * Sockets BSD-Like API module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Improved by Marc Boucher and David Haas + * + */ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcpip.h" +#include "lwip/pbuf.h" +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +/** Contains all internal pointers and states used for a socket */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket */ + int err; + /** counter of how many threads are waiting for this socket using select */ + int select_waiting; +}; + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** Pointer to the previous waiting task */ + struct lwip_select_cb *prev; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + sys_sem_t sem; +}; + +/** This struct is used to pass data to the set/getsockopt_internal + * functions running in tcpip_thread context (only a void* is allowed) */ +struct lwip_setgetsockopt_data { + /** socket struct for which to change options */ + struct lwip_sock *sock; +#ifdef LWIP_DEBUG + /** socket index for which to change options */ + int s; +#endif /* LWIP_DEBUG */ + /** level of the option to process */ + int level; + /** name of the option to process */ + int optname; + /** set: value to set the option to + * get: value of the option is stored here */ + void *optval; + /** size of *optval */ + socklen_t *optlen; + /** if an error occures, it is temporarily stored here */ + err_t err; +}; + +/** The global array of available sockets */ +static struct lwip_sock sockets[NUM_SOCKETS]; +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; +/** This counter is increased from lwip_select when the list is chagned + and checked in event_callback to see if it has changed. */ +static volatile int select_cb_ctr; + +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ +static const int err_to_errno_table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + EALREADY, /* ERR_ISCONN -9 Already connected. */ + ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */ + ECONNRESET, /* ERR_RST -11 Connection reset. */ + ENOTCONN, /* ERR_CLSD -12 Connection closed. */ + ENOTCONN, /* ERR_CONN -13 Not connected. */ + EIO, /* ERR_ARG -14 Illegal argument. */ + -1, /* ERR_IF -15 Low-level netif error */ +}; + +#define ERR_TO_ERRNO_TABLE_SIZE \ + (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0])) + +#define err_to_errno(err) \ + ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ + err_to_errno_table[-(err)] : EIO) + +#ifdef ERRNO +#ifndef set_errno +#define set_errno(err) errno = (err) +#endif +#else /* ERRNO */ +#define set_errno(err) +#endif /* ERRNO */ + +#define sock_set_errno(sk, e) do { \ + sk->err = (e); \ + set_errno(sk->err); \ +} while (0) + +/* Forward delcaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +static void lwip_getsockopt_internal(void *arg); +static void lwip_setsockopt_internal(void *arg); + +/** + * Initialize this module. This function has to be called before any other + * functions in this module! + */ +void +lwip_socket_init(void) +{ +} + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +get_socket(int s) +{ + struct lwip_sock *sock; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Same as get_socket but doesn't set errno + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +tryget_socket(int s) +{ + if ((s < 0) || (s >= NUM_SOCKETS)) { + return NULL; + } + if (!sockets[s].conn) { + return NULL; + } + return &sockets[s]; +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @param accepted 1 if socket has been created by accept(), + * 0 if socket has been created by socket() + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn, int accepted) +{ + int i; + SYS_ARCH_DECL_PROTECT(lev); + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + if (!sockets[i].conn) { + sockets[i].conn = newconn; + /* The socket is not yet known to anyone, so no need to protect + after having marked it as used. */ + SYS_ARCH_UNPROTECT(lev); + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1); + sockets[i].errevent = 0; + sockets[i].err = 0; + sockets[i].select_waiting = 0; + return i; + } + SYS_ARCH_UNPROTECT(lev); + } + return -1; +} + +/** Free a socket. The socket's netconn must have been + * delete before! + * + * @param sock the socket to free + * @param is_tcp != 0 for TCP sockets, used to free lastdata + */ +static void +free_socket(struct lwip_sock *sock, int is_tcp) +{ + void *lastdata; + SYS_ARCH_DECL_PROTECT(lev); + + lastdata = sock->lastdata; + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->err = 0; + + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + sock->conn = NULL; + SYS_ARCH_UNPROTECT(lev); + /* don't use 'sock' after this line, as another task might have allocated it */ + + if (lastdata != NULL) { + if (is_tcp) { + pbuf_free((struct pbuf *)lastdata); + } else { + netbuf_delete((struct netbuf *)lastdata); + } + } +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_sock *sock, *nsock; + struct netconn *newconn; + ip_addr_t naddr; + u16_t port; + int newsock; + struct sockaddr_in sin; + err_t err; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* wait for a new connection */ + err = netconn_accept(sock->conn, &newconn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); + if (netconn_type(sock->conn) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return EOPNOTSUPP; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("newconn != NULL", newconn != NULL); + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(newconn, 1); + + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, &naddr, &port); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); + netconn_delete(newconn); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (NULL != addr) { + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + inet_addr_from_ipaddr(&sin.sin_addr, &naddr); + + if (*addrlen > sizeof(sin)) + *addrlen = sizeof(sin); + + MEMCPY(addr, &sin, *addrlen); + } + + newsock = alloc_socket(newconn, 1); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS)); + LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + nsock = &sockets[newsock]; + + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); + nsock->rcvevent += (s16_t)(-1 - newconn->socket); + newconn->socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); + ip_addr_debug_print(SOCKETS_DEBUG, &naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + + sock_set_errno(sock, 0); + return newsock; +} + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + ip_addr_t local_addr; + u16_t local_port; + err_t err; + const struct sockaddr_in *name_in; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* check size, familiy and alignment of 'name' */ + LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) && + ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + name_in = (const struct sockaddr_in *)(void*)name; + + inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr); + local_port = name_in->sin_port; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port))); + + err = netconn_bind(sock->conn, &local_addr, ntohs(local_port)); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_sock *sock; + int is_tcp = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if(sock->conn != NULL) { + is_tcp = netconn_type(sock->conn) == NETCONN_TCP; + } else { + LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); + } + + netconn_delete(sock->conn); + + free_socket(sock, is_tcp); + set_errno(0); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + err_t err; + const struct sockaddr_in *name_in; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* check size, familiy and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) && + ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + name_in = (const struct sockaddr_in *)(void*)name; + + if (name_in->sin_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + ip_addr_t remote_addr; + u16_t remote_port; + + inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr); + remote_port = name_in->sin_port; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port))); + + err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_sock *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); + + err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + if (netconn_type(sock->conn) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return EOPNOTSUPP; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_sock *sock; + void *buf = NULL; + struct pbuf *p; + u16_t buflen, copylen; + int off = 0; + ip_addr_t *addr; + u16_t port; + u8_t done = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && + (sock->rcvevent <= 0)) { + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + if (netconn_type(sock->conn) == NETCONN_TCP) { + err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); + } else { + err = netconn_recv(sock->conn, (struct netbuf **)&buf); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", + err, buf)); + + if (err != ERR_OK) { + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err))); + sock_set_errno(sock, err_to_errno(err)); + if (err == ERR_CLSD) { + return 0; + } else { + return -1; + } + } + LWIP_ASSERT("buf != NULL", buf != NULL); + sock->lastdata = buf; + } + + if (netconn_type(sock->conn) == NETCONN_TCP) { + p = (struct pbuf *)buf; + } else { + p = ((struct netbuf *)buf)->p; + } + buflen = p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ( (len <= 0) || + (p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK)!=0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { + ip_addr_t fromaddr; + if (from && fromlen) { + struct sockaddr_in sin; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + addr = &fromaddr; + netconn_getaddr(sock->conn, addr, &port, 0); + } else { + addr = netbuf_fromaddr((struct netbuf *)buf); + port = netbuf_fromport((struct netbuf *)buf); + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + inet_addr_from_ipaddr(&sin.sin_addr, addr); + + if (*fromlen > sizeof(sin)) { + *fromlen = sizeof(sin); + } + + MEMCPY(from, &sin, *fromlen); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); + } else { +#if SOCKETS_DEBUG + if (netconn_type(sock->conn) == NETCONN_TCP) { + addr = &fromaddr; + netconn_getaddr(sock->conn, addr, &port, 0); + } else { + addr = netbuf_fromaddr((struct netbuf *)buf); + port = netbuf_fromport((struct netbuf *)buf); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); +#endif /* SOCKETS_DEBUG */ + } + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK) == 0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + if (netconn_type(sock->conn) == NETCONN_TCP) { + pbuf_free((struct pbuf *)buf); + } else { + netbuf_delete((struct netbuf *)buf); + } + } + } + } while (!done); + + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + } + sock_set_errno(sock, 0); + return off; +} + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_sock *sock; + err_t err; + u8_t write_flags; + size_t written; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn->type != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else /* (LWIP_UDP || LWIP_RAW) */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + written = 0; + err = netconn_write_partly(sock->conn, data, size, write_flags, &written); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? (int)written : -1); +} + +int +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_sock *sock; + err_t err; + u16_t short_size; + const struct sockaddr_in *to_in; + u16_t remote_port; +#if !LWIP_TCPIP_CORE_LOCKING + struct netbuf buf; +#endif + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn->type == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + /* @todo: split into multiple sendto's? */ + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + ((tolen == sizeof(struct sockaddr_in)) && + ((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + to_in = (const struct sockaddr_in *)(void*)to; + +#if LWIP_TCPIP_CORE_LOCKING + /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */ + { + struct pbuf* p; + ip_addr_t *remote_addr; + +#if LWIP_NETIF_TX_SINGLE_PBUF + p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM); + if (p != NULL) { +#if LWIP_CHECKSUM_ON_COPY + u16_t chksum = 0; + if (sock->conn->type != NETCONN_RAW) { + chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + MEMCPY(p->payload, data, size); +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF); + if (p != NULL) { + p->payload = (void*)data; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + if (to_in != NULL) { + inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr); + remote_port = ntohs(to_in->sin_port); + } else { + remote_addr = &sock->conn->pcb.ip->remote_ip; +#if LWIP_UDP + if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_UDP) { + remote_port = sock->conn->pcb.udp->remote_port; + } else +#endif /* LWIP_UDP */ + { + remote_port = 0; + } + } + + LOCK_TCPIP_CORE(); + if (netconn_type(sock->conn) == NETCONN_RAW) { +#if LWIP_RAW + err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr); +#else /* LWIP_RAW */ + err = ERR_ARG; +#endif /* LWIP_RAW */ + } +#if LWIP_UDP && LWIP_RAW + else +#endif /* LWIP_UDP && LWIP_RAW */ + { +#if LWIP_UDP +#if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF + err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p, + remote_addr, remote_port, 1, chksum); +#else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ + err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p, + remote_addr, remote_port); +#endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ +#else /* LWIP_UDP */ + err = ERR_ARG; +#endif /* LWIP_UDP */ + } + UNLOCK_TCPIP_CORE(); + + pbuf_free(p); + } else { + err = ERR_MEM; + } + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + /* initialize a buffer */ + buf.p = buf.ptr = NULL; +#if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + if (to) { + inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr); + remote_port = ntohs(to_in->sin_port); + netbuf_fromport(&buf) = remote_port; + } else { + remote_port = 0; + ip_addr_set_any(&buf.addr); + netbuf_fromport(&buf) = 0; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { +#if LWIP_CHECKSUM_ON_COPY + if (sock->conn->type != NETCONN_RAW) { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + err = ERR_OK; + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + err = netbuf_take(&buf, data, short_size); + } + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + + LWIP_UNUSED_ARG(domain); + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ? + NETCONN_UDPLITE : NETCONN_UDP, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(NETCONN_TCP, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + if (conn != NULL) { + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(conn, 1); + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn, 0); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * exceptset is not used for now!!! + * + * @param maxfdp1 the highest socket index in the sets + * @param readset_in: set of sockets to check for read events + * @param writeset_in: set of sockets to check for write events + * @param exceptset_in: set of sockets to check for error events + * @param readset_out: set of sockets that had read events + * @param writeset_out: set of sockets that had write events + * @param exceptset_out: set os sockets that had error events + * @return number of sockets that had events (read/write/exception) (>= 0) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, + fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_sock *sock; + SYS_ARCH_DECL_PROTECT(lev); + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for(i = 0; i < maxfdp1; i++) { + void* lastdata = NULL; + s16_t rcvevent = 0; + u16_t sendevent = 0; + u16_t errevent = 0; + /* First get the socket's status (protected)... */ + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + lastdata = sock->lastdata; + rcvevent = sock->rcvevent; + sendevent = sock->sendevent; + errevent = sock->errevent; + } + SYS_ARCH_UNPROTECT(lev); + /* ... then examine it: */ + /* See if netconn of this socket is ready for read */ + if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + /* See if netconn of this socket is ready for write */ + if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + /* See if netconn of this socket had an error */ + if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { + FD_SET(i, &lexceptset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); + nready++; + } + } + /* copy local sets to the ones provided as arguments */ + *readset_out = lreadset; + *writeset_out = lwriteset; + *exceptset_out = lexceptset; + + LWIP_ASSERT("nready >= 0", nready >= 0); + return nready; +} + +/** + * Processing exceptset is not yet implemented. + */ +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + u32_t waitres = 0; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + err_t err; + int i; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, + timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* None ready: add our semaphore to list: + We don't actually need any dynamic memory. Our entry on the + list is only valid while we are in this function, so it's ok + to use local variables. */ + + select_cb.next = NULL; + select_cb.prev = NULL; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; + err = sys_sem_new(&select_cb.sem, 0); + if (err != ERR_OK) { + /* failed to create semaphore */ + set_errno(ENOMEM); + return -1; + } + + /* Protect the select_cb_list */ + SYS_ARCH_PROTECT(lev); + + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + if (select_cb_list != NULL) { + select_cb_list->prev = &select_cb; + } + select_cb_list = &select_cb; + /* Increasing this counter tells even_callback that the list has changed. */ + select_cb_ctr++; + + /* Now we can safely unprotect */ + SYS_ARCH_UNPROTECT(lev); + + /* Increase select_waiting for each socket we are interested in */ + for(i = 0; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock = tryget_socket(i); + LWIP_ASSERT("sock != NULL", sock != NULL); + SYS_ARCH_PROTECT(lev); + sock->select_waiting++; + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + SYS_ARCH_UNPROTECT(lev); + } + } + + /* Call lwip_selscan again: there could have been events between + the last scan (whithout us on the list) and putting us on the list! */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + if (!nready) { + /* Still none ready, just wait to be woken */ + if (timeout == 0) { + /* Wait forever */ + msectimeout = 0; + } else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if (msectimeout == 0) { + /* Wait 1ms at least (0 means wait forever) */ + msectimeout = 1; + } + } + + waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout); + } + /* Increase select_waiting for each socket we are interested in */ + for(i = 0; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock = tryget_socket(i); + LWIP_ASSERT("sock != NULL", sock != NULL); + SYS_ARCH_PROTECT(lev); + sock->select_waiting--; + LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0); + SYS_ARCH_UNPROTECT(lev); + } + } + /* Take us off the list */ + SYS_ARCH_PROTECT(lev); + if (select_cb.next != NULL) { + select_cb.next->prev = select_cb.prev; + } + if (select_cb_list == &select_cb) { + LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); + select_cb_list = select_cb.next; + } else { + LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); + select_cb.prev->next = select_cb.next; + } + /* Increasing this counter tells even_callback that the list has changed. */ + select_cb_ctr++; + SYS_ARCH_UNPROTECT(lev); + + sys_sem_free(&select_cb.sem); + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* See what's set */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); +return_copy_fdsets: + set_errno(0); + if (readset) { + *readset = lreadset; + } + if (writeset) { + *writeset = lwriteset; + } + if (exceptset) { + *exceptset = lexceptset; + } + + + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + struct lwip_select_cb *scb; + int last_select_cb_ctr; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->select_waiting == 0) { + /* noone is waiting for this socket, no need to check select_cb_list */ + SYS_ARCH_UNPROTECT(lev); + return; + } + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { + if (scb->readset && FD_ISSET(s, scb->readset)) { + do_signal = 1; + } + } + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidagin the semaphore. */ + sys_sem_signal(&scb->sem); + } + } + /* unlock interrupts with each step */ + last_select_cb_ctr = select_cb_ctr; + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; + } + } + SYS_ARCH_UNPROTECT(lev); +} + +/** + * Unimplemented: Close one end of a full-duplex connection. + * Currently, the full connection is closed. + */ +int +lwip_shutdown(int s, int how) +{ + struct lwip_sock *sock; + err_t err; + u8_t shut_rx = 0, shut_tx = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + if (netconn_type(sock->conn) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return EOPNOTSUPP; + } + } else { + sock_set_errno(sock, ENOTCONN); + return ENOTCONN; + } + + if (how == SHUT_RD) { + shut_rx = 1; + } else if (how == SHUT_WR) { + shut_tx = 1; + } else if(how == SHUT_RDWR) { + shut_rx = 1; + shut_tx = 1; + } else { + sock_set_errno(sock, EINVAL); + return EINVAL; + } + err = netconn_shutdown(sock->conn, shut_rx, shut_tx); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? 0 : -1); +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_sock *sock; + struct sockaddr_in sin; + ip_addr_t naddr; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + + /* get the IP address and port */ + netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port)); + + sin.sin_port = htons(sin.sin_port); + inet_addr_from_ipaddr(&sin.sin_addr, &naddr); + + if (*namelen > sizeof(sin)) { + *namelen = sizeof(sin); + } + + MEMCPY(name, &sin, *namelen); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + err_t err = ERR_OK; + struct lwip_sock *sock = get_socket(s); + struct lwip_setgetsockopt_data data; + + if (!sock) { + return -1; + } + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + + /* Do length and type checks for the various options first, to keep it readable. */ + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + case SO_ACCEPTCONN: + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_ERROR: + case SO_KEEPALIVE: + /* UNIMPL case SO_CONTIMEO: */ +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: +#endif /* LWIP_SO_RCVBUF */ + /* UNIMPL case SO_OOBINLINE: */ + /* UNIMPL case SO_SNDBUF: */ + /* UNIMPL case SO_RCVLOWAT: */ + /* UNIMPL case SO_SNDLOWAT: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + case SO_TYPE: + /* UNIMPL case SO_USELOOPBACK: */ + if (*optlen < sizeof(int)) { + err = EINVAL; + } + break; + + case SO_NO_CHECK: + if (*optlen < sizeof(int)) { + err = EINVAL; + } +#if LWIP_UDP + if ((sock->conn->type != NETCONN_UDP) || + ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { + /* this flag is only available for UDP, not for UDP lite */ + err = EAFNOSUPPORT; + } +#endif /* LWIP_UDP */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + /* UNIMPL case IP_HDRINCL: */ + /* UNIMPL case IP_RCVDSTADDR: */ + /* UNIMPL case IP_RCVIF: */ + case IP_TTL: + case IP_TOS: + if (*optlen < sizeof(int)) { + err = EINVAL; + } + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + if (*optlen < sizeof(u8_t)) { + err = EINVAL; + } + break; + case IP_MULTICAST_IF: + if (*optlen < sizeof(struct in_addr)) { + err = EINVAL; + } + break; + case IP_MULTICAST_LOOP: + if (*optlen < sizeof(u8_t)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; +#endif /* LWIP_IGMP */ + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + if (*optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no TCP socket, ignore any options. */ + if (sock->conn->type != NETCONN_TCP) + return 0; + + switch (optname) { + case TCP_NODELAY: + case TCP_KEEPALIVE: +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: +#endif /* LWIP_TCP_KEEPALIVE */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE +/* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + if (*optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no UDP lite socket, ignore any options. */ + if (sock->conn->type != NETCONN_UDPLITE) { + return 0; + } + + switch (optname) { + case UDPLITE_SEND_CSCOV: + case UDPLITE_RECV_CSCOV: + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP && LWIP_UDPLITE*/ +/* UNDEFINED LEVEL */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + } /* switch */ + + + if (err != ERR_OK) { + sock_set_errno(sock, err); + return -1; + } + + /* Now do the actual option processing */ + data.sock = sock; +#ifdef LWIP_DEBUG + data.s = s; +#endif /* LWIP_DEBUG */ + data.level = level; + data.optname = optname; + data.optval = optval; + data.optlen = optlen; + data.err = err; + tcpip_callback(lwip_getsockopt_internal, &data); + sys_arch_sem_wait(&sock->conn->op_completed, 0); + /* maybe lwip_getsockopt_internal has changed err */ + err = data.err; + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +static void +lwip_getsockopt_internal(void *arg) +{ + struct lwip_sock *sock; +#ifdef LWIP_DEBUG + int s; +#endif /* LWIP_DEBUG */ + int level, optname; + void *optval; + struct lwip_setgetsockopt_data *data; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + data = (struct lwip_setgetsockopt_data*)arg; + sock = data->sock; +#ifdef LWIP_DEBUG + s = data->s; +#endif /* LWIP_DEBUG */ + level = data->level; + optname = data->optname; + optval = data->optval; + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* The option flags */ + case SO_ACCEPTCONN: + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case SO_OOBINCLUDE: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /*case SO_USELOOPBACK: UNIMPL */ + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + switch (NETCONNTYPE_GROUP(sock->conn->type)) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = sock->conn->type; + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (sock->conn->type) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + /* only overwrite ERR_OK or tempoary errors */ + if ((sock->err == 0) || (sock->err == EINPROGRESS)) { + sock_set_errno(sock, err_to_errno(sock->conn->last_err)); + } + *(int *)optval = sock->err; + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + *(int *)optval = netconn_get_sendtimeout(sock->conn); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + *(int *)optval = netconn_get_recvtimeout(sock->conn); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + *(int *)optval = netconn_get_recvbufsize(sock->conn); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_UDP + case SO_NO_CHECK: + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + *(u8_t*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IP_MULTICAST_LOOP: + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_IGMP */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + default: + LWIP_ASSERT("unhandled level", 0); + break; + } /* switch (level) */ + sys_sem_signal(&sock->conn->op_completed); +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + struct lwip_sock *sock = get_socket(s); + err_t err = ERR_OK; + struct lwip_setgetsockopt_data data; + + if (!sock) { + return -1; + } + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + + /* Do length and type checks for the various options first, to keep it readable. */ + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case case SO_CONTIMEO: */ +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: +#endif /* LWIP_SO_RCVBUF */ + /* UNIMPL case SO_OOBINLINE: */ + /* UNIMPL case SO_SNDBUF: */ + /* UNIMPL case SO_RCVLOWAT: */ + /* UNIMPL case SO_SNDLOWAT: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /* UNIMPL case SO_USELOOPBACK: */ + if (optlen < sizeof(int)) { + err = EINVAL; + } + break; + case SO_NO_CHECK: + if (optlen < sizeof(int)) { + err = EINVAL; + } +#if LWIP_UDP + if ((sock->conn->type != NETCONN_UDP) || + ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { + /* this flag is only available for UDP, not for UDP lite */ + err = EAFNOSUPPORT; + } +#endif /* LWIP_UDP */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + /* UNIMPL case IP_HDRINCL: */ + /* UNIMPL case IP_RCVDSTADDR: */ + /* UNIMPL case IP_RCVIF: */ + case IP_TTL: + case IP_TOS: + if (optlen < sizeof(int)) { + err = EINVAL; + } + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + if (optlen < sizeof(u8_t)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_MULTICAST_IF: + if (optlen < sizeof(struct in_addr)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_MULTICAST_LOOP: + if (optlen < sizeof(u8_t)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + if (optlen < sizeof(struct ip_mreq)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + if (optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no TCP socket, ignore any options. */ + if (sock->conn->type != NETCONN_TCP) + return 0; + + switch (optname) { + case TCP_NODELAY: + case TCP_KEEPALIVE: +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: +#endif /* LWIP_TCP_KEEPALIVE */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE +/* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + if (optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no UDP lite socket, ignore any options. */ + if (sock->conn->type != NETCONN_UDPLITE) + return 0; + + switch (optname) { + case UDPLITE_SEND_CSCOV: + case UDPLITE_RECV_CSCOV: + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP && LWIP_UDPLITE */ +/* UNDEFINED LEVEL */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + } /* switch (level) */ + + + if (err != ERR_OK) { + sock_set_errno(sock, err); + return -1; + } + + + /* Now do the actual option processing */ + data.sock = sock; +#ifdef LWIP_DEBUG + data.s = s; +#endif /* LWIP_DEBUG */ + data.level = level; + data.optname = optname; + data.optval = (void*)optval; + data.optlen = &optlen; + data.err = err; + tcpip_callback(lwip_setsockopt_internal, &data); + sys_arch_sem_wait(&sock->conn->op_completed, 0); + /* maybe lwip_setsockopt_internal has changed err */ + err = data.err; + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +static void +lwip_setsockopt_internal(void *arg) +{ + struct lwip_sock *sock; +#ifdef LWIP_DEBUG + int s; +#endif /* LWIP_DEBUG */ + int level, optname; + const void *optval; + struct lwip_setgetsockopt_data *data; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + data = (struct lwip_setgetsockopt_data*)arg; + sock = data->sock; +#ifdef LWIP_DEBUG + s = data->s; +#endif /* LWIP_DEBUG */ + level = data->level; + optname = data->optname; + optval = data->optval; + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* The option flags */ + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case SO_OOBINCLUDE: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /* UNIMPL case SO_USELOOPBACK: */ + if (*(int*)optval) { + ip_set_option(sock->conn->pcb.ip, optname); + } else { + ip_reset_option(sock->conn->pcb.ip, optname); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + netconn_set_sendtimeout(sock->conn, (s32_t)*(int*)optval); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + netconn_set_recvtimeout(sock->conn, *(int*)optval); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + netconn_set_recvbufsize(sock->conn, *(int*)optval); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_UDP + case SO_NO_CHECK: + if (*(int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval); + break; + case IP_MULTICAST_IF: + inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval); + break; + case IP_MULTICAST_LOOP: + if (*(u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + struct ip_mreq *imr = (struct ip_mreq *)optval; + ip_addr_t if_addr; + ip_addr_t multi_addr; + inet_addr_to_ipaddr(&if_addr, &imr->imr_interface); + inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr); + if(optname == IP_ADD_MEMBERSHIP){ + data->err = igmp_joingroup(&if_addr, &multi_addr); + } else { + data->err = igmp_leavegroup(&if_addr, &multi_addr); + } + if(data->err != ERR_OK) { + data->err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + if (*(int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + default: + LWIP_ASSERT("unhandled level", 0); + break; + } /* switch (level) */ + sys_sem_signal(&sock->conn->op_completed); +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF + u16_t buflen = 0; + s16_t recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + if (!sock) { + return -1; + } + + switch (cmd) { +#if LWIP_SO_RCVBUF + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } + + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) { + recv_avail = 0; + } + *((u16_t*)argp) = (u16_t)recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + struct pbuf *p = (struct pbuf *)sock->lastdata; + if (netconn_type(sock->conn) != NETCONN_TCP) { + p = ((struct netbuf *)p)->p; + } + buflen = p->tot_len; + buflen -= sock->lastoffset; + + *((u16_t*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; +#endif /* LWIP_SO_RCVBUF */ + + case FIONBIO: + val = 0; + if (argp && *(u32_t*)argp) { + val = 1; + } + netconn_set_nonblocking(sock->conn, val); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); + sock_set_errno(sock, 0); + return 0; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; + } /* switch (cmd) */ +} + +/** A minimal implementation of fcntl. + * Currently only the commands F_GETFL and F_SETFL are implemented. + * Only the flag O_NONBLOCK is implemented. + */ +int +lwip_fcntl(int s, int cmd, int val) +{ + struct lwip_sock *sock = get_socket(s); + int ret = -1; + + if (!sock || !sock->conn) { + return -1; + } + + switch (cmd) { + case F_GETFL: + ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; + break; + case F_SETFL: + if ((val & ~O_NONBLOCK) == 0) { + /* only O_NONBLOCK, all other bits are zero */ + netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); + ret = 0; + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); + break; + } + return ret; +} + +#endif /* LWIP_SOCKET */ diff --git a/ext/lwip/src/api/tcpip.c b/ext/lwip/src/api/tcpip.c new file mode 100644 index 000000000..18d5f679f --- /dev/null +++ b/ext/lwip/src/api/tcpip.c @@ -0,0 +1,511 @@ +/** + * @file + * Sequential API Main thread module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/tcpip.h" +#include "lwip/init.h" +#include "netif/etharp.h" +#include "netif/ppp_oe.h" + +/* global variables */ +static tcpip_init_done_fn tcpip_init_done; +static void *tcpip_init_done_arg; +static sys_mbox_t mbox; + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +sys_mutex_t lock_tcpip_core; +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + +/** + * The main lwIP thread. This thread has exclusive access to lwIP core functions + * (unless access to them is not locked). Other threads communicate with this + * thread using message boxes. + * + * It also starts all the timers to make sure they are running in the right + * thread context. + * + * @param arg unused argument + */ +static void +tcpip_thread(void *arg) +{ + struct tcpip_msg *msg; + LWIP_UNUSED_ARG(arg); + + if (tcpip_init_done != NULL) { + tcpip_init_done(tcpip_init_done_arg); + } + + LOCK_TCPIP_CORE(); + while (1) { /* MAIN Loop */ + UNLOCK_TCPIP_CORE(); + LWIP_TCPIP_THREAD_ALIVE(); + /* wait for a message, timeouts are processed while waiting */ + sys_timeouts_mbox_fetch(&mbox, (void **)&msg); + LOCK_TCPIP_CORE(); + switch (msg->type) { +#if LWIP_NETCONN + case TCPIP_MSG_API: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); + msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); + break; +#endif /* LWIP_NETCONN */ + +#if !LWIP_TCPIP_CORE_LOCKING_INPUT + case TCPIP_MSG_INPKT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); +#if LWIP_ETHERNET + if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); + } else +#endif /* LWIP_ETHERNET */ + { + ip_input(msg->msg.inp.p, msg->msg.inp.netif); + } + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + break; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + +#if LWIP_NETIF_API + case TCPIP_MSG_NETIFAPI: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); + msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); + break; +#endif /* LWIP_NETIF_API */ + +#if LWIP_TCPIP_TIMEOUT + case TCPIP_MSG_TIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); + sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + case TCPIP_MSG_UNTIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); + sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; +#endif /* LWIP_TCPIP_TIMEOUT */ + + case TCPIP_MSG_CALLBACK: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + + case TCPIP_MSG_CALLBACK_STATIC: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + break; + + default: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + break; + } + } +} + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_input(struct pbuf *p, struct netif *inp) +{ +#if LWIP_TCPIP_CORE_LOCKING_INPUT + err_t ret; + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp)); + LOCK_TCPIP_CORE(); +#if LWIP_ETHERNET + if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + ret = ethernet_input(p, inp); + } else +#endif /* LWIP_ETHERNET */ + { + ret = ip_input(p, inp); + } + UNLOCK_TCPIP_CORE(); + return ret; +#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + struct tcpip_msg *msg; + + if (!sys_mbox_valid(&mbox)) { + return ERR_VAL; + } + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_INPKT; + msg->msg.inp.p = p; + msg->msg.inp.netif = inp; + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + return ERR_MEM; + } + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ +} + +/** + * Call a specific function in the thread context of + * tcpip_thread for easy access synchronization. + * A function called in that way may access lwIP core code + * without fearing concurrent access. + * + * @param f the function to call + * @param ctx parameter passed to f + * @param block 1 to block until the request is posted, 0 to non-blocking mode + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_CALLBACK; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + if (block) { + sys_mbox_post(&mbox, msg); + } else { + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_API, msg); + return ERR_MEM; + } + } + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_TCPIP_TIMEOUT +/** + * call sys_timeout in tcpip_thread + * + * @param msec time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_TIMEOUT; + msg->msg.tmo.msecs = msecs; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} + +/** + * call sys_untimeout in tcpip_thread + * + * @param msec time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_untimeout(sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_UNTIMEOUT; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} +#endif /* LWIP_TCPIP_TIMEOUT */ + +#if LWIP_NETCONN +/** + * Call the lower part of a netconn_* function + * This function is then running in the thread context + * of tcpip_thread and has exclusive access to lwIP core code. + * + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_apimsg(struct api_msg *apimsg) +{ + struct tcpip_msg msg; +#ifdef LWIP_DEBUG + /* catch functions that don't set err */ + apimsg->msg.err = ERR_VAL; +#endif + + if (sys_mbox_valid(&mbox)) { + msg.type = TCPIP_MSG_API; + msg.msg.apimsg = apimsg; + sys_mbox_post(&mbox, &msg); + sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0); + return apimsg->msg.err; + } + return ERR_VAL; +} + +#if LWIP_TCPIP_CORE_LOCKING +/** + * Call the lower part of a netconn_* function + * This function has exclusive access to lwIP core code by locking it + * before the function is called. + * + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK (only for compatibility fo tcpip_apimsg()) + */ +err_t +tcpip_apimsg_lock(struct api_msg *apimsg) +{ +#ifdef LWIP_DEBUG + /* catch functions that don't set err */ + apimsg->msg.err = ERR_VAL; +#endif + + LOCK_TCPIP_CORE(); + apimsg->function(&(apimsg->msg)); + UNLOCK_TCPIP_CORE(); + return apimsg->msg.err; + +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETCONN */ + +#if LWIP_NETIF_API +#if !LWIP_TCPIP_CORE_LOCKING +/** + * Much like tcpip_apimsg, but calls the lower part of a netifapi_* + * function. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return error code given back by the function that was called + */ +err_t +tcpip_netifapi(struct netifapi_msg* netifapimsg) +{ + struct tcpip_msg msg; + + if (sys_mbox_valid(&mbox)) { + err_t err = sys_sem_new(&netifapimsg->msg.sem, 0); + if (err != ERR_OK) { + netifapimsg->msg.err = err; + return err; + } + + msg.type = TCPIP_MSG_NETIFAPI; + msg.msg.netifapimsg = netifapimsg; + sys_mbox_post(&mbox, &msg); + sys_sem_wait(&netifapimsg->msg.sem); + sys_sem_free(&netifapimsg->msg.sem); + return netifapimsg->msg.err; + } + return ERR_VAL; +} +#else /* !LWIP_TCPIP_CORE_LOCKING */ +/** + * Call the lower part of a netifapi_* function + * This function has exclusive access to lwIP core code by locking it + * before the function is called. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return ERR_OK (only for compatibility fo tcpip_netifapi()) + */ +err_t +tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) +{ + LOCK_TCPIP_CORE(); + netifapimsg->function(&(netifapimsg->msg)); + UNLOCK_TCPIP_CORE(); + return netifapimsg->msg.err; +} +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +/** + * Allocate a structure for a static callback message and initialize it. + * This is intended to be used to send "static" messages from interrupt context. + * + * @param function the function to call + * @param ctx parameter passed to function + * @return a struct pointer to pass to tcpip_trycallback(). + */ +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) +{ + struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return NULL; + } + msg->type = TCPIP_MSG_CALLBACK_STATIC; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + return (struct tcpip_callback_msg*)msg; +} + +/** + * Free a callback message allocated by tcpip_callbackmsg_new(). + * + * @param msg the message to free + */ +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) +{ + memp_free(MEMP_TCPIP_MSG_API, msg); +} + +/** + * Try to post a callback-message to the tcpip_thread mbox + * This is intended to be used to send "static" messages from interrupt context. + * + * @param msg pointer to the message to post + * @return sys_mbox_trypost() return code + */ +err_t +tcpip_trycallback(struct tcpip_callback_msg* msg) +{ + if (!sys_mbox_valid(&mbox)) { + return ERR_VAL; + } + return sys_mbox_trypost(&mbox, msg); +} + +/** + * Initialize this module: + * - initialize all sub modules + * - start the tcpip_thread + * + * @param initfunc a function to call when tcpip_thread is running and finished initializing + * @param arg argument to pass to initfunc + */ +void +tcpip_init(tcpip_init_done_fn initfunc, void *arg) +{ + lwip_init(); + + tcpip_init_done = initfunc; + tcpip_init_done_arg = arg; + if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { + LWIP_ASSERT("failed to create tcpip_thread mbox", 0); + } +#if LWIP_TCPIP_CORE_LOCKING + if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) { + LWIP_ASSERT("failed to create lock_tcpip_core", 0); + } +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); +} + +/** + * Simple callback function used with tcpip_callback to free a pbuf + * (pbuf_free has a wrong signature for tcpip_callback) + * + * @param p The pbuf (chain) to be dereferenced. + */ +static void +pbuf_free_int(void *p) +{ + struct pbuf *q = (struct pbuf *)p; + pbuf_free(q); +} + +/** + * A simple wrapper function that allows you to free a pbuf from interrupt context. + * + * @param p The pbuf (chain) to be dereferenced. + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +pbuf_free_callback(struct pbuf *p) +{ + return tcpip_callback_with_block(pbuf_free_int, p, 0); +} + +/** + * A simple wrapper function that allows you to free heap memory from + * interrupt context. + * + * @param m the heap memory to free + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +mem_free_callback(void *m) +{ + return tcpip_callback_with_block(mem_free, m, 0); +} + +#endif /* !NO_SYS */ diff --git a/ext/lwip/src/core/def.c b/ext/lwip/src/core/def.c new file mode 100644 index 000000000..352b55241 --- /dev/null +++ b/ext/lwip/src/core/def.c @@ -0,0 +1,108 @@ +/** + * @file + * Common functions used throughout the stack. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/def.h" + +/** + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * #define LWIP_PLATFORM_BYTESWAP 1 + * #define LWIP_PLATFORM_HTONS(x) + * #define LWIP_PLATFORM_HTONL(x) + * + * Note ntohs() and ntohl() are merely references to the htonx counterparts. + */ + +#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) + +/** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +u16_t +lwip_htons(u16_t n) +{ + return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); +} + +/** + * Convert an u16_t from network- to host byte order. + * + * @param n u16_t in network byte order + * @return n in host byte order + */ +u16_t +lwip_ntohs(u16_t n) +{ + return lwip_htons(n); +} + +/** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +u32_t +lwip_htonl(u32_t n) +{ + return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); +} + +/** + * Convert an u32_t from network- to host byte order. + * + * @param n u32_t in network byte order + * @return n in host byte order + */ +u32_t +lwip_ntohl(u32_t n) +{ + return lwip_htonl(n); +} + +#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ diff --git a/ext/lwip/src/core/dhcp.c b/ext/lwip/src/core/dhcp.c new file mode 100644 index 000000000..cf864a8fe --- /dev/null +++ b/ext/lwip/src/core/dhcp.c @@ -0,0 +1,1770 @@ +/** + * @file + * Dynamic Host Configuration Protocol client + * + */ + +/* + * + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. + * + * Author: Leon Woestenberg + * + * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform + * with RFC 2131 and RFC 2132. + * + * TODO: + * - Support for interfaces other than Ethernet (SLIP, PPP, ...) + * + * Please coordinate changes and requests with Leon Woestenberg + * + * + * Integration with your code: + * + * In lwip/dhcp.h + * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) + * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) + * + * Then have your application call dhcp_coarse_tmr() and + * dhcp_fine_tmr() on the defined intervals. + * + * dhcp_start(struct netif *netif); + * starts a DHCP client instance which configures the interface by + * obtaining an IP address lease and maintaining it. + * + * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif) + * to remove the DHCP client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "netif/etharp.h" + +#include + +/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using + * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) + */ +#ifndef DHCP_CREATE_RAND_XID +#define DHCP_CREATE_RAND_XID 1 +#endif + +/** Default for DHCP_GLOBAL_XID is 0xABCD0000 + * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. + * #define DHCP_GLOBAL_XID_HEADER "stdlib.h" + * #define DHCP_GLOBAL_XID rand() + */ +#ifdef DHCP_GLOBAL_XID_HEADER +#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ +#endif + +/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU + * MTU is checked to be big enough in dhcp_start */ +#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) +#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 +/** Minimum length for reply before packet is parsed */ +#define DHCP_MIN_REPLY_LEN 44 + +#define REBOOT_TRIES 2 + +/** Option handling: options are parsed in dhcp_parse_reply + * and saved in an array where other functions can load them from. + * This might be moved into the struct dhcp (not necessarily since + * lwIP is single-threaded and the array is only used while in recv + * callback). */ +#define DHCP_OPTION_IDX_OVERLOAD 0 +#define DHCP_OPTION_IDX_MSG_TYPE 1 +#define DHCP_OPTION_IDX_SERVER_ID 2 +#define DHCP_OPTION_IDX_LEASE_TIME 3 +#define DHCP_OPTION_IDX_T1 4 +#define DHCP_OPTION_IDX_T2 5 +#define DHCP_OPTION_IDX_SUBNET_MASK 6 +#define DHCP_OPTION_IDX_ROUTER 7 +#define DHCP_OPTION_IDX_DNS_SERVER 8 +#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS) + +/** Holds the decoded option values, only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; +/** Holds a flag which option was received and is contained in dhcp_rx_options_val, + only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; + +#ifdef DHCP_GLOBAL_XID +static u32_t xid; +static u8_t xid_initialised; +#endif /* DHCP_GLOBAL_XID */ + +#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) +#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) +#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) +#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) +#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) +#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) + + +/* DHCP client state machine functions */ +static err_t dhcp_discover(struct netif *netif); +static err_t dhcp_select(struct netif *netif); +static void dhcp_bind(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +static err_t dhcp_decline(struct netif *netif); +#endif /* DHCP_DOES_ARP_CHECK */ +static err_t dhcp_rebind(struct netif *netif); +static err_t dhcp_reboot(struct netif *netif); +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); + +/* receive, unfold, parse and free incoming messages */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); + +/* set the DHCP timers */ +static void dhcp_timeout(struct netif *netif); +static void dhcp_t1_timeout(struct netif *netif); +static void dhcp_t2_timeout(struct netif *netif); + +/* build outgoing messages */ +/* create a DHCP message, fill in common headers */ +static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); +/* free a DHCP request */ +static void dhcp_delete_msg(struct dhcp *dhcp); +/* add a DHCP option (type, then length in bytes) */ +static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); +/* add option values */ +static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); +static void dhcp_option_short(struct dhcp *dhcp, u16_t value); +static void dhcp_option_long(struct dhcp *dhcp, u32_t value); +#if LWIP_NETIF_HOSTNAME +static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); +#endif /* LWIP_NETIF_HOSTNAME */ +/* always add the DHCP options trailer to end and pad */ +static void dhcp_option_trailer(struct dhcp *dhcp); + +/** + * Back-off the DHCP client (because of a received NAK response). + * + * Back-off the DHCP client because of a received NAK. Receiving a + * NAK means the client asked for something non-sensible, for + * example when it tries to renew a lease obtained on another network. + * + * We clear any existing set IP address and restart DHCP negotiation + * afresh (as per RFC2131 3.2.3). + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_nak(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Set the interface down since the address must no longer be used, as per RFC2131 */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + /* Change to a defined state */ + dhcp_set_state(dhcp, DHCP_BACKING_OFF); + /* We can immediately restart discovery */ + dhcp_discover(netif); +} + +#if DHCP_DOES_ARP_CHECK +/** + * Checks if the offered IP address is already in use. + * + * It does so by sending an ARP request for the offered address and + * entering CHECKING state. If no ARP reply is received within a small + * interval, the address is assumed to be free for use by us. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_check(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], + (s16_t)netif->name[1])); + dhcp_set_state(dhcp, DHCP_CHECKING); + /* create an ARP query for the offered IP address, expecting that no host + responds, as the IP address should not be in use. */ + result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); + if (result != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); + } + dhcp->tries++; + msecs = 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); +} +#endif /* DHCP_DOES_ARP_CHECK */ + +/** + * Remember the configuration offered by a DHCP server. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_offer(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* obtain the server address */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { + ip4_addr_set_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->server_ip_addr))); + /* remember offered address */ + ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); + } +} + +/** + * Select a DHCP server offer out of all offers. + * + * Simply select the first offer received. + * + * @param netif the netif under DHCP control + * @return lwIP specific error (see error.h) + */ +static err_t +dhcp_select(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + dhcp_set_state(dhcp, DHCP_REQUESTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + /* MUST request the offered IP address */ + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); + dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + /* shrink the pbuf to the actual content length */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* send broadcast to any DHCP server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * The DHCP timer that checks for lease renewal/rebind timeouts. + */ +void +dhcp_coarse_tmr() +{ + struct netif *netif = netif_list; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); + /* iterate through all network interfaces */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + /* timer is active (non zero), and triggers (zeroes) now? */ + if (netif->dhcp->t2_timeout-- == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(netif); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (netif->dhcp->t1_timeout-- == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(netif); + } + } + /* proceed to next netif */ + netif = netif->next; + } +} + +/** + * DHCP transaction timeout handling + * + * A DHCP server is expected to respond within a short period of time. + * This timer checks whether an outstanding DHCP request is timed out. + */ +void +dhcp_fine_tmr() +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + /* timer is active (non zero), and is about to trigger now */ + if (netif->dhcp->request_timeout > 1) { + netif->dhcp->request_timeout--; + } + else if (netif->dhcp->request_timeout == 1) { + netif->dhcp->request_timeout--; + /* { netif->dhcp->request_timeout == 0 } */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); + /* this client's request timeout triggered */ + dhcp_timeout(netif); + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * A DHCP negotiation transaction, or ARP request, has timed out. + * + * The timer that was started with the DHCP or ARP request has + * timed out, indicating no response was received in time. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); + dhcp_discover(netif); + /* receiving the requested lease timed out */ + } else if (dhcp->state == DHCP_REQUESTING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); + if (dhcp->tries <= 5) { + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); + dhcp_release(netif); + dhcp_discover(netif); + } +#if DHCP_DOES_ARP_CHECK + /* received no ARP reply for the offered address (which is good) */ + } else if (dhcp->state == DHCP_CHECKING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); + if (dhcp->tries <= 1) { + dhcp_check(netif); + /* no ARP replies on the offered address, + looks like the IP address is indeed free */ + } else { + /* bind the interface to the offered address */ + dhcp_bind(netif); + } +#endif /* DHCP_DOES_ARP_CHECK */ + } + /* did not get response to renew request? */ + else if (dhcp->state == DHCP_RENEWING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); + /* just retry renewal */ + /* note that the rebind timer will eventually time-out if renew does not work */ + dhcp_renew(netif); + /* did not get response to rebind request? */ + } else if (dhcp->state == DHCP_REBINDING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); + if (dhcp->tries <= 8) { + dhcp_rebind(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n")); + dhcp_release(netif); + dhcp_discover(netif); + } + } else if (dhcp->state == DHCP_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(netif); + } else { + dhcp_discover(netif); + } + } +} + +/** + * The renewal period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t1_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); + if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || + (dhcp->state == DHCP_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t1_timeout(): must renew\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_RENEWING, not DHCP_BOUND */ + dhcp_renew(netif); + } +} + +/** + * The rebind period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t2_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); + if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || + (dhcp->state == DHCP_RENEWING)) { + /* just retry to rebind */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t2_timeout(): must rebind\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_REBINDING, not DHCP_BOUND */ + dhcp_rebind(netif); + } +} + +/** + * Handle a DHCP ACK packet + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_ack(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; +#if LWIP_DNS + u8_t n; +#endif /* LWIP_DNS */ + + /* clear options we might not get from the ACK */ + ip_addr_set_zero(&dhcp->offered_sn_mask); + ip_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* lease time given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { + /* remember offered lease time */ + dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); + } + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { + /* remember given renewal period */ + dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); + } else { + /* calculate safe periods for renewal */ + dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; + } + + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { + /* remember given rebind period */ + dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); + } else { + /* calculate safe periods for rebinding */ + dhcp->offered_t2_rebind = dhcp->offered_t0_lease; + } + + /* (y)our internet address */ + ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + +#if LWIP_DHCP_BOOTP_FILE + /* copy boot server address, + boot file name copied in dhcp_parse_reply if not overloaded */ + ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* subnet mask given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { + /* remember given subnet mask */ + ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); + dhcp->subnet_mask_given = 1; + } else { + dhcp->subnet_mask_given = 0; + } + + /* gateway router */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { + ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); + } + +#if LWIP_DNS + /* DNS servers */ + n = 0; + while(dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n) && (n < DNS_MAX_SERVERS)) { + ip_addr_t dns_addr; + ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); + dns_setserver(n, &dns_addr); + n++; + } +#endif /* LWIP_DNS */ +} + +/** Set a statically allocated struct dhcp to work with. + * Using this prevents dhcp_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct dhcp + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("dhcp != NULL", dhcp != NULL); + LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_OFF); */ + netif->dhcp = dhcp; +} + +/** Removes a struct dhcp from a netif. + * + * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the + * struct dhcp since the memory is passed back to the heap. + * + * @param netif the netif from which to remove the struct dhcp + */ +void dhcp_cleanup(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + + if (netif->dhcp != NULL) { + mem_free(netif->dhcp); + netif->dhcp = NULL; + } +} + +/** + * Start DHCP negotiation for a network interface. + * + * If no DHCP client instance was attached to this interface, + * a new client is created first. If a DHCP client instance + * was already present, it restarts negotiation. + * + * @param netif The lwIP network interface + * @return lwIP error code + * - ERR_OK - No error + * - ERR_MEM - Out of memory + */ +err_t +dhcp_start(struct netif *netif) +{ + struct dhcp *dhcp; + err_t result = ERR_OK; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); + dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Remove the flag that says this netif is handled by DHCP, + it is set when we succeeded starting. */ + netif->flags &= ~NETIF_FLAG_DHCP; + + /* check hwtype of the netif */ + if ((netif->flags & NETIF_FLAG_ETHARP) == 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n")); + return ERR_ARG; + } + + /* check MTU of the netif */ + if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); + return ERR_MEM; + } + + /* no DHCP client attached yet? */ + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); + dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); + return ERR_MEM; + } + /* store this dhcp client in the netif */ + netif->dhcp = dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); + /* already has DHCP client attached */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); + if (dhcp->pcb != NULL) { + udp_remove(dhcp->pcb); + } + LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); + } + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_OFF); */ + /* allocate UDP PCB */ + dhcp->pcb = udp_new(); + if (dhcp->pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); + return ERR_MEM; + } + ip_set_option(dhcp->pcb, SOF_BROADCAST); + /* set up local and remote port for the pcb */ + udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + /* set up the recv callback and argument */ + udp_recv(dhcp->pcb, dhcp_recv, netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + /* (re)start the DHCP negotiation */ + result = dhcp_discover(netif); + if (result != ERR_OK) { + /* free resources allocated above */ + dhcp_stop(netif); + return ERR_MEM; + } + /* Set the flag that says this netif is handled by DHCP. */ + netif->flags |= NETIF_FLAG_DHCP; + return result; +} + +/** + * Inform a DHCP server of our manual configuration. + * + * This informs DHCP servers of our fixed IP address configuration + * by sending an INFORM message. It does not involve DHCP address + * configuration, it is just here to be nice to the network. + * + * @param netif The lwIP network interface + */ +void +dhcp_inform(struct netif *netif) +{ + struct dhcp dhcp; + err_t result = ERR_OK; + struct udp_pcb *pcb; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + memset(&dhcp, 0, sizeof(struct dhcp)); + dhcp_set_state(&dhcp, DHCP_INFORM); + + if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) { + /* re-use existing pcb */ + pcb = netif->dhcp->pcb; + } else { + pcb = udp_new(); + if (pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb")); + return; + } + dhcp.pcb = pcb; + ip_set_option(dhcp.pcb, SOF_BROADCAST); + udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); + } + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); + if (result == ERR_OK) { + dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option_trailer(&dhcp); + + pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); + udp_sendto_if(pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(&dhcp); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); + } + + if (dhcp.pcb != NULL) { + /* otherwise, the existing pcb was used */ + udp_remove(dhcp.pcb); + } +} + +/** Handle a possible change in the network configuration. + * + * This enters the REBOOTING state to verify that the currently bound + * address is still valid. + */ +void +dhcp_network_changed(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + if (!dhcp) + return; + switch (dhcp->state) { + case DHCP_REBINDING: + case DHCP_RENEWING: + case DHCP_BOUND: + case DHCP_REBOOTING: + netif_set_down(netif); + dhcp->tries = 0; + dhcp_reboot(netif); + break; + case DHCP_OFF: + /* stay off */ + break; + default: + dhcp->tries = 0; +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + dhcp_discover(netif); + break; + } +} + +#if DHCP_DOES_ARP_CHECK +/** + * Match an ARP reply with the offered IP address. + * + * @param netif the network interface on which the reply was received + * @param addr The IP address we received a reply from + */ +void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr) +{ + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); + /* is a DHCP client doing an ARP check? */ + if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", + ip4_addr_get_u32(addr))); + /* did a host respond with the address we + were offered by the DHCP server? */ + if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { + /* we will not accept the offered address */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); + dhcp_decline(netif); + } + } +} + +/** + * Decline an offered lease. + * + * Tell the DHCP server we do not accept the offered address. + * One reason to decline the lease is when we find out the address + * is already in use by another host (through ARP). + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_decline(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); + dhcp_set_state(dhcp, DHCP_BACKING_OFF); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + /* resize pbuf to reflect true size of options */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* per section 4.4.4, broadcast DECLINE messages */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_decline: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = 10*1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} +#endif /* DHCP_DOES_ARP_CHECK */ + + +/** + * Start the DHCP process, discover a DHCP server. + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_discover(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); + ip_addr_set_any(&dhcp->offered_ip_addr); + dhcp_set_state(dhcp, DHCP_SELECTING); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); + if (result == ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); + dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + + dhcp_option_trailer(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); + } + dhcp->tries++; +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; + autoip_start(netif); + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Bind the interface to the offered IP address. + * + * @param netif network interface to bind to the offered address + */ +static void +dhcp_bind(struct netif *netif) +{ + u32_t timeout; + struct dhcp *dhcp; + ip_addr_t sn_mask, gw_addr; + LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* temporary DHCP lease? */ + if (dhcp->offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); + timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t1_timeout = (u16_t)timeout; + if (dhcp->t1_timeout == 0) { + dhcp->t1_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); + } + /* set renewal period timer */ + if (dhcp->offered_t2_rebind != 0xffffffffUL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); + timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t2_timeout = (u16_t)timeout; + if (dhcp->t2_timeout == 0) { + dhcp->t2_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); + } + + /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ + if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { + dhcp->t1_timeout = 0; + } + + if (dhcp->subnet_mask_given) { + /* copy offered network mask */ + ip_addr_copy(sn_mask, dhcp->offered_sn_mask); + } else { + /* subnet mask not given, choose a safe subnet mask given the network class */ + u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); + if (first_octet <= 127) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); + } else if (first_octet >= 192) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); + } else { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); + } + } + + ip_addr_copy(gw_addr, dhcp->offered_gw_addr); + /* gateway address not given? */ + if (ip_addr_isany(&gw_addr)) { + /* copy network address */ + ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); + /* use first host address on network as gateway */ + ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); + } + +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + netif_set_ipaddr(netif, &dhcp->offered_ip_addr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", + ip4_addr_get_u32(&sn_mask))); + netif_set_netmask(netif, &sn_mask); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", + ip4_addr_get_u32(&gw_addr))); + netif_set_gw(netif, &gw_addr); + /* bring the interface up */ + netif_set_up(netif); + /* netif is now bound to DHCP leased address */ + dhcp_set_state(dhcp, DHCP_BOUND); +} + +/** + * Renew an existing DHCP lease at the involved DHCP server. + * + * @param netif network interface which must renew its lease + */ +err_t +dhcp_renew(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); + dhcp_set_state(dhcp, DHCP_RENEWING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); +#endif + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); +#endif + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + /* append DHCP message trailer */ + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); + } + dhcp->tries++; + /* back-off on retries, but to a maximum of 20 seconds */ + msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Rebind with a DHCP server for an existing DHCP lease. + * + * @param netif network interface which must rebind with a DHCP server + */ +static err_t +dhcp_rebind(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); + dhcp_set_state(dhcp, DHCP_REBINDING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); +#endif + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Enter REBOOTING state to verify an existing lease + * + * @param netif network interface which must reboot + */ +static err_t +dhcp_reboot(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); + dhcp_set_state(dhcp, DHCP_REBOOTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, 576); + + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Release a DHCP lease. + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_OFF); + /* clean old DHCP offer */ + ip_addr_set_zero(&dhcp->server_ip_addr); + ip_addr_set_zero(&dhcp->offered_ip_addr); + ip_addr_set_zero(&dhcp->offered_sn_mask); + ip_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); + if (result == ERR_OK) { + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); + /* bring the interface down */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + + return result; +} + +/** + * Remove the DHCP client from the interface. + * + * @param netif The network interface to stop DHCP on + */ +void +dhcp_stop(struct netif *netif) +{ + struct dhcp *dhcp; + LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + /* Remove the flag that says this netif is handled by DHCP. */ + netif->flags &= ~NETIF_FLAG_DHCP; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); + /* netif is DHCP configured? */ + if (dhcp != NULL) { +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + if (dhcp->pcb != NULL) { + udp_remove(dhcp->pcb); + dhcp->pcb = NULL; + } + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + dhcp_set_state(dhcp, DHCP_OFF); + } +} + +/* + * Set the DHCP state of a DHCP client. + * + * If the state changed, reset the number of tries. + */ +static void +dhcp_set_state(struct dhcp *dhcp, u8_t new_state) +{ + if (new_state != dhcp->state) { + dhcp->state = new_state; + dhcp->tries = 0; + dhcp->request_timeout = 0; + } +} + +/* + * Concatenate an option type and length field to the outgoing + * DHCP message. + * + */ +static void +dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) +{ + LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = option_type; + dhcp->msg_out->options[dhcp->options_out_len++] = option_len; +} +/* + * Concatenate a single byte to the outgoing DHCP message. + * + */ +static void +dhcp_option_byte(struct dhcp *dhcp, u8_t value) +{ + LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = value; +} + +static void +dhcp_option_short(struct dhcp *dhcp, u16_t value) +{ + LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); +} + +static void +dhcp_option_long(struct dhcp *dhcp, u32_t value) +{ + LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); +} + +#if LWIP_NETIF_HOSTNAME +static void +dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) +{ + if (netif->hostname != NULL) { + size_t namelen = strlen(netif->hostname); + if (namelen > 0) { + u8_t len; + const char *p = netif->hostname; + /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME + and 1 byte for trailer) */ + size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; + LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); + len = LWIP_MIN(namelen, available); + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, len); + while (len--) { + dhcp_option_byte(dhcp, *p++); + } + } + } +} +#endif /* LWIP_NETIF_HOSTNAME */ + +/** + * Extract the DHCP message and the DHCP options. + * + * Extract the DHCP message and the DHCP options, each into a contiguous + * piece of memory. As a DHCP message is variable sized by its options, + * and also allows overriding some fields for options, the easy approach + * is to first unfold the options into a conitguous piece of memory, and + * use that further on. + * + */ +static err_t +dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) +{ + u8_t *options; + u16_t offset; + u16_t offset_max; + u16_t options_idx; + u16_t options_idx_max; + struct pbuf *q; + int parse_file_as_options = 0; + int parse_sname_as_options = 0; + + /* clear received options */ + dhcp_clear_all_options(dhcp); + /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ + if (p->len < DHCP_SNAME_OFS) { + return ERR_BUF; + } + dhcp->msg_in = (struct dhcp_msg *)p->payload; +#if LWIP_DHCP_BOOTP_FILE + /* clear boot file name */ + dhcp->boot_file_name[0] = 0; +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* parse options */ + + /* start with options field */ + options_idx = DHCP_OPTIONS_OFS; + /* parse options to the end of the received packet */ + options_idx_max = p->tot_len; +again: + q = p; + while((q != NULL) && (options_idx >= q->len)) { + options_idx -= q->len; + options_idx_max -= q->len; + q = q->next; + } + if (q == NULL) { + return ERR_BUF; + } + offset = options_idx; + offset_max = options_idx_max; + options = (u8_t*)q->payload; + /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ + while((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) { + u8_t op = options[offset]; + u8_t len; + u8_t decode_len = 0; + int decode_idx = -1; + u16_t val_offset = offset + 2; + /* len byte might be in the next pbuf */ + if (offset + 1 < q->len) { + len = options[offset + 1]; + } else { + len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); + } + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ + decode_len = len; + switch(op) { + /* case(DHCP_OPTION_END): handled above */ + case(DHCP_OPTION_PAD): + /* special option: no len encoded */ + decode_len = len = 0; + /* will be increased below */ + offset--; + break; + case(DHCP_OPTION_SUBNET_MASK): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; + break; + case(DHCP_OPTION_ROUTER): + decode_len = 4; /* only copy the first given router */ + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_ROUTER; + break; + case(DHCP_OPTION_DNS_SERVER): + /* special case: there might be more than one server */ + LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of DNS servers */ + decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_DNS_SERVER; + break; + case(DHCP_OPTION_LEASE_TIME): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_LEASE_TIME; + break; + case(DHCP_OPTION_OVERLOAD): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_OVERLOAD; + break; + case(DHCP_OPTION_MESSAGE_TYPE): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_MSG_TYPE; + break; + case(DHCP_OPTION_SERVER_ID): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SERVER_ID; + break; + case(DHCP_OPTION_T1): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T1; + break; + case(DHCP_OPTION_T2): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T2; + break; + default: + decode_len = 0; + LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op)); + break; + } + offset += len + 2; + if (decode_len > 0) { + u32_t value = 0; + u16_t copy_len; +decode_next: + LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); + if (!dhcp_option_given(dhcp, decode_idx)) { + copy_len = LWIP_MIN(decode_len, 4); + pbuf_copy_partial(q, &value, copy_len, val_offset); + if (decode_len > 4) { + /* decode more than one u32_t */ + LWIP_ERROR("decode_len % 4 == 0", decode_len % 4 == 0, return ERR_VAL;); + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, htonl(value)); + decode_len -= 4; + val_offset += 4; + decode_idx++; + goto decode_next; + } else if (decode_len == 4) { + value = ntohl(value); + } else { + LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); + value = ((u8_t*)&value)[0]; + } + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, value); + } + } + if (offset >= q->len) { + offset -= q->len; + offset_max -= q->len; + if ((offset < offset_max) && offset_max) { + q = q->next; + LWIP_ASSERT("next pbuf was null", q); + options = (u8_t*)q->payload; + } else { + /* We've run out of bytes, probably no end marker. Don't proceed. */ + break; + } + } + } + /* is this an overloaded message? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { + u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); + dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); + if (overload == DHCP_OVERLOAD_FILE) { + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME) { + parse_sname_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { + parse_sname_as_options = 1; + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); + } +#if LWIP_DHCP_BOOTP_FILE + if (!parse_file_as_options) { + /* only do this for ACK messages */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && + (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) + /* copy bootp file name, don't care for sname (server hostname) */ + pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); + /* make sure the string is really NULL-terminated */ + dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; + } +#endif /* LWIP_DHCP_BOOTP_FILE */ + } + if (parse_file_as_options) { + /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ + parse_file_as_options = 0; + options_idx = DHCP_FILE_OFS; + options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; + goto again; + } else if (parse_sname_as_options) { + parse_sname_as_options = 0; + options_idx = DHCP_SNAME_OFS; + options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; + goto again; + } + return ERR_OK; +} + +/** + * If an incoming DHCP message is in response to us, then trigger the state machine + */ +static void +dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + struct netif *netif = (struct netif *)arg; + struct dhcp *dhcp = netif->dhcp; + struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; + u8_t msg_type; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + ip4_addr1_16(addr), ip4_addr2_16(addr), ip4_addr3_16(addr), ip4_addr4_16(addr), port)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + + if (p->len < DHCP_MIN_REPLY_LEN) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); + goto free_pbuf_and_return; + } + + if (reply_msg->op != DHCP_BOOTREPLY) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); + goto free_pbuf_and_return; + } + /* iterate through hardware address and match against DHCP message */ + for (i = 0; i < netif->hwaddr_len; i++) { + if (netif->hwaddr[i] != reply_msg->chaddr[i]) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", + (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); + goto free_pbuf_and_return; + } + } + /* match transaction ID against what we expected */ + if (ntohl(reply_msg->xid) != dhcp->xid) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid)); + goto free_pbuf_and_return; + } + /* option fields could be unfold? */ + if (dhcp_parse_reply(dhcp, p) != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("problem unfolding DHCP message - too short on memory?\n")); + goto free_pbuf_and_return; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); + /* obtain pointer to DHCP message type */ + if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); + goto free_pbuf_and_return; + } + + /* read DHCP message type */ + msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); + /* message type is DHCP ACK? */ + if (msg_type == DHCP_ACK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); + /* in requesting state? */ + if (dhcp->state == DHCP_REQUESTING) { + dhcp_handle_ack(netif); +#if DHCP_DOES_ARP_CHECK + /* check if the acknowledged lease address is already in use */ + dhcp_check(netif); +#else + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); +#endif + } + /* already bound to the given lease address? */ + else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) { + dhcp_bind(netif); + } + } + /* received a DHCP_NAK in appropriate state? */ + else if ((msg_type == DHCP_NAK) && + ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) || + (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); + dhcp_handle_nak(netif); + } + /* received a DHCP_OFFER in DHCP_SELECTING state? */ + else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n")); + dhcp->request_timeout = 0; + /* remember offered lease */ + dhcp_handle_offer(netif); + } +free_pbuf_and_return: + dhcp->msg_in = NULL; + pbuf_free(p); +} + +/** + * Create a DHCP request, fill in common headers + * + * @param netif the netif under DHCP control + * @param dhcp dhcp control struct + * @param message_type message type of the request + */ +static err_t +dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) +{ + u16_t i; +#ifndef DHCP_GLOBAL_XID + /** default global transaction identifier starting value (easy to match + * with a packet analyser). We simply increment for each new request. + * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one + * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + static u32_t xid; +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + static u32_t xid = 0xABCD0000; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ +#else + if (!xid_initialised) { + xid = DHCP_GLOBAL_XID; + xid_initialised = !xid_initialised; + } +#endif + LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); + LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); + LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); + dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); + if (dhcp->p_out == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_create_msg(): could not allocate pbuf\n")); + return ERR_MEM; + } + LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", + (dhcp->p_out->len >= sizeof(struct dhcp_msg))); + + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + xid = LWIP_RAND(); +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + xid++; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + } + dhcp->xid = xid; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("transaction id xid(%"X32_F")\n", xid)); + + dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; + + dhcp->msg_out->op = DHCP_BOOTREQUEST; + /* TODO: make link layer independent */ + dhcp->msg_out->htype = DHCP_HTYPE_ETH; + dhcp->msg_out->hlen = netif->hwaddr_len; + dhcp->msg_out->hops = 0; + dhcp->msg_out->xid = htonl(dhcp->xid); + dhcp->msg_out->secs = 0; + /* we don't need the broadcast flag since we can receive unicast traffic + before being fully configured! */ + dhcp->msg_out->flags = 0; + ip_addr_set_zero(&dhcp->msg_out->ciaddr); + /* set ciaddr to netif->ip_addr based on message_type and state */ + if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || + ((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */ + ((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING))) { + ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr); + } + ip_addr_set_zero(&dhcp->msg_out->yiaddr); + ip_addr_set_zero(&dhcp->msg_out->siaddr); + ip_addr_set_zero(&dhcp->msg_out->giaddr); + for (i = 0; i < DHCP_CHADDR_LEN; i++) { + /* copy netif hardware address, pad with zeroes */ + dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/; + } + for (i = 0; i < DHCP_SNAME_LEN; i++) { + dhcp->msg_out->sname[i] = 0; + } + for (i = 0; i < DHCP_FILE_LEN; i++) { + dhcp->msg_out->file[i] = 0; + } + dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); + dhcp->options_out_len = 0; + /* fill options field with an incrementing array (for debugging purposes) */ + for (i = 0; i < DHCP_OPTIONS_LEN; i++) { + dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ + } + /* Add option MESSAGE_TYPE */ + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, message_type); + return ERR_OK; +} + +/** + * Free previously allocated memory used to send a DHCP request. + * + * @param dhcp the dhcp struct to free the request from + */ +static void +dhcp_delete_msg(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); + LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); + if (dhcp->p_out != NULL) { + pbuf_free(dhcp->p_out); + } + dhcp->p_out = NULL; + dhcp->msg_out = NULL; +} + +/** + * Add a DHCP message trailer + * + * Adds the END option to the DHCP message, and if + * necessary, up to three padding bytes. + * + * @param dhcp DHCP state structure + */ +static void +dhcp_option_trailer(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); + LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; + /* packet is too small, or not 4 byte aligned? */ + while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && + (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { + /* add a fill/padding byte */ + dhcp->msg_out->options[dhcp->options_out_len++] = 0; + } +} + +#endif /* LWIP_DHCP */ diff --git a/ext/lwip/src/core/dns.c b/ext/lwip/src/core/dns.c new file mode 100644 index 000000000..d63361226 --- /dev/null +++ b/ext/lwip/src/core/dns.c @@ -0,0 +1,970 @@ +/** + * @file + * DNS - host name to IP address resolver. + * + */ + +/** + + * This file implements a DNS host name to IP address resolver. + + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * DNS.C + * + * The lwIP DNS resolver functions are used to lookup a host name and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the dns_lookup() function. + * New hostnames can be resolved using the dns_query() function. + * + * The lwIP version of the resolver also adds a non-blocking version of + * gethostbyname() that will work with a raw API application. This function + * checks for an IP address string first and converts it if it is valid. + * gethostbyname() then does a dns_lookup() to see if the name is + * already in the table. If so, the IP is returned. If not, a query is + * issued and the function returns with a ERR_INPROGRESS status. The app + * using the dns client must then go into a waiting state. + * + * Once a hostname has been resolved (or found to be non-existent), + * the resolver code calls a specified callback function (which + * must be implemented by the module that uses the resolver). + */ + +/*----------------------------------------------------------------------------- + * RFC 1035 - Domain names - implementation and specification + * RFC 2181 - Clarifications to the DNS Specification + *----------------------------------------------------------------------------*/ + +/** @todo: define good default values (rfc compliance) */ +/** @todo: improve answer parsing, more checkings... */ +/** @todo: check RFC1035 - 7.3. Processing responses */ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/dns.h" + +#include + +/** DNS server IP address */ +#ifndef DNS_SERVER_ADDRESS +#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */ +#endif + +/** DNS server port address */ +#ifndef DNS_SERVER_PORT +#define DNS_SERVER_PORT 53 +#endif + +/** DNS maximum number of retries when asking for a name, before "timeout". */ +#ifndef DNS_MAX_RETRIES +#define DNS_MAX_RETRIES 4 +#endif + +/** DNS resource record max. TTL (one week as default) */ +#ifndef DNS_MAX_TTL +#define DNS_MAX_TTL 604800 +#endif + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +/* DNS protocol states */ +#define DNS_STATE_UNUSED 0 +#define DNS_STATE_NEW 1 +#define DNS_STATE_ASKING 2 +#define DNS_STATE_DONE 3 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS message header */ +struct dns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u8_t flags1); + PACK_STRUCT_FIELD(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_HDR 12 + +/** DNS query message structure. + No packing needed: only used locally on the stack. */ +struct dns_query { + /* DNS query record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; +}; +#define SIZEOF_DNS_QUERY 4 + +/** DNS answer message structure. + No packing needed: only used locally on the stack. */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; + u32_t ttl; + u16_t len; +}; +#define SIZEOF_DNS_ANSWER 10 + +/** DNS table entry */ +struct dns_table_entry { + u8_t state; + u8_t numdns; + u8_t tmr; + u8_t retries; + u8_t seqno; + u8_t err; + u32_t ttl; + char name[DNS_MAX_NAME_LENGTH]; + ip_addr_t ipaddr; + /* pointer to callback on DNS query done */ + dns_found_callback found; + void *arg; +}; + +#if DNS_LOCAL_HOSTLIST + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Local host-list. For hostnames in this list, no + * external name resolution is performed */ +static struct local_hostlist_entry *local_hostlist_dynamic; +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE +#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST +#define DNS_LOCAL_HOSTLIST_STORAGE_POST +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ +DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] + DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; + +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +static void dns_init_local(); +#endif /* DNS_LOCAL_HOSTLIST */ + + +/* forward declarations */ +static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); +static void dns_check_entries(void); + +/*----------------------------------------------------------------------------- + * Globales + *----------------------------------------------------------------------------*/ + +/* DNS variables */ +static struct udp_pcb *dns_pcb; +static u8_t dns_seqno; +static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; +static ip_addr_t dns_servers[DNS_MAX_SERVERS]; +/** Contiguous buffer for processing responses */ +static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)]; +static u8_t* dns_payload; + +/** + * Initialize the resolver: set up the UDP pcb and configure the default server + * (DNS_SERVER_ADDRESS). + */ +void +dns_init() +{ + ip_addr_t dnsserver; + + dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer); + + /* initialize default DNS server address */ + DNS_SERVER_ADDRESS(&dnsserver); + + LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); + + /* if dns client not yet initialized... */ + if (dns_pcb == NULL) { + dns_pcb = udp_new(); + + if (dns_pcb != NULL) { + /* initialize DNS table not needed (initialized to zero since it is a + * global variable) */ + LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", + DNS_STATE_UNUSED == 0); + + /* initialize DNS client */ + udp_bind(dns_pcb, IP_ADDR_ANY, 0); + udp_recv(dns_pcb, dns_recv, NULL); + + /* initialize default DNS primary server */ + dns_setserver(0, &dnsserver); + } + } +#if DNS_LOCAL_HOSTLIST + dns_init_local(); +#endif +} + +/** + * Initialize one of the DNS servers. + * + * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS + * @param dnsserver IP address of the DNS server to set + */ +void +dns_setserver(u8_t numdns, ip_addr_t *dnsserver) +{ + if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) && + (dnsserver != NULL) && !ip_addr_isany(dnsserver)) { + dns_servers[numdns] = (*dnsserver); + } +} + +/** + * Obtain one of the currently configured DNS server. + * + * @param numdns the index of the DNS server + * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS + * server has not been configured. + */ +ip_addr_t +dns_getserver(u8_t numdns) +{ + if (numdns < DNS_MAX_SERVERS) { + return dns_servers[numdns]; + } else { + return *IP_ADDR_ANY; + } +} + +/** + * The DNS resolver client timer - handle retries and timeouts and should + * be called every DNS_TMR_INTERVAL milliseconds (every second by default). + */ +void +dns_tmr(void) +{ + if (dns_pcb != NULL) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); + dns_check_entries(); + } +} + +#if DNS_LOCAL_HOSTLIST +static void +dns_init_local() +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) + int i; + struct local_hostlist_entry *entry; + /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ + struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; + size_t namelen; + for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) { + struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; + LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); + namelen = strlen(init_entry->name); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); + if (entry != NULL) { + entry->name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY((char*)entry->name, init_entry->name, namelen); + ((char*)entry->name)[namelen] = 0; + entry->addr = init_entry->addr; + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ +} + +/** + * Scans the local host-list for a hostname. + * + * @param hostname Hostname to look for in the local host-list + * @return The first IP address for the hostname in the local host-list or + * IPADDR_NONE if not found. + */ +static u32_t +dns_lookup_local(const char *hostname) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + while(entry != NULL) { + if(strcmp(entry->name, hostname) == 0) { + return ip4_addr_get_u32(&entry->addr); + } + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + int i; + for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) { + if(strcmp(local_hostlist_static[i].name, hostname) == 0) { + return ip4_addr_get_u32(&local_hostlist_static[i].addr); + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return IPADDR_NONE; +} + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Remove all entries from the local host-list for a specific hostname + * and/or IP addess + * + * @param hostname hostname for which entries shall be removed from the local + * host-list + * @param addr address for which entries shall be removed from the local host-list + * @return the number of removed entries + */ +int +dns_local_removehost(const char *hostname, const ip_addr_t *addr) +{ + int removed = 0; + struct local_hostlist_entry *entry = local_hostlist_dynamic; + struct local_hostlist_entry *last_entry = NULL; + while (entry != NULL) { + if (((hostname == NULL) || !strcmp(entry->name, hostname)) && + ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { + struct local_hostlist_entry *free_entry; + if (last_entry != NULL) { + last_entry->next = entry->next; + } else { + local_hostlist_dynamic = entry->next; + } + free_entry = entry; + entry = entry->next; + memp_free(MEMP_LOCALHOSTLIST, free_entry); + removed++; + } else { + last_entry = entry; + entry = entry->next; + } + } + return removed; +} + +/** + * Add a hostname/IP address pair to the local host-list. + * Duplicates are not checked. + * + * @param hostname hostname of the new entry + * @param addr IP address of the new entry + * @return ERR_OK if succeeded or ERR_MEM on memory error + */ +err_t +dns_local_addhost(const char *hostname, const ip_addr_t *addr) +{ + struct local_hostlist_entry *entry; + size_t namelen; + LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); + namelen = strlen(hostname); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + if (entry == NULL) { + return ERR_MEM; + } + entry->name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY((char*)entry->name, hostname, namelen); + ((char*)entry->name)[namelen] = 0; + ip_addr_copy(entry->addr, *addr); + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + return ERR_OK; +} +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** + * Look up a hostname in the array of known hostnames. + * + * @note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function dns_enqueue() can be used to send a query + * for a hostname. + * + * @param name the hostname to look up + * @return the hostname's IP address, as u32_t (instead of ip_addr_t to + * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname + * was not found in the cached dns_table. + */ +static u32_t +dns_lookup(const char *name) +{ + u8_t i; +#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) + u32_t addr; +#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ +#if DNS_LOCAL_HOSTLIST + if ((addr = dns_lookup_local(name)) != IPADDR_NONE) { + return addr; + } +#endif /* DNS_LOCAL_HOSTLIST */ +#ifdef DNS_LOOKUP_LOCAL_EXTERN + if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) { + return addr; + } +#endif /* DNS_LOOKUP_LOCAL_EXTERN */ + + /* Walk through name list, return entry if found. If not, return NULL. */ + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + if ((dns_table[i].state == DNS_STATE_DONE) && + (strcmp(name, dns_table[i].name) == 0)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); + ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + return ip4_addr_get_u32(&dns_table[i].ipaddr); + } + } + + return IPADDR_NONE; +} + +#if DNS_DOES_NAME_CHECK +/** + * Compare the "dotted" name "query" with the encoded name "response" + * to make sure an answer from the DNS server matches the current dns_table + * entry (otherwise, answers might arrive late for hostname not on the list + * any more). + * + * @param query hostname (not encoded) from the dns_table + * @param response encoded hostname in the DNS response + * @return 0: names equal; 1: names differ + */ +static u8_t +dns_compare_name(unsigned char *query, unsigned char *response) +{ + unsigned char n; + + do { + n = *response++; + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + if ((*query) != (*response)) { + return 1; + } + ++response; + ++query; + --n; + }; + ++query; + } + } while (*response != 0); + + return 0; +} +#endif /* DNS_DOES_NAME_CHECK */ + +/** + * Walk through a compact encoded DNS name and return the end of the name. + * + * @param query encoded DNS name in the DNS server response + * @return end of the name + */ +static unsigned char * +dns_parse_name(unsigned char *query) +{ + unsigned char n; + + do { + n = *query++; + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + ++query; + --n; + }; + } + } while (*query != 0); + + return query + 1; +} + +/** + * Send a DNS query packet. + * + * @param numdns index of the DNS server in the dns_servers table + * @param name hostname to query + * @param id index of the hostname in dns_table, used as transaction ID in the + * DNS query packet + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t +dns_send(u8_t numdns, const char* name, u8_t id) +{ + err_t err; + struct dns_hdr *hdr; + struct dns_query qry; + struct pbuf *p; + char *query, *nptr; + const char *pHostname; + u8_t n; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", + (u16_t)(numdns), name)); + LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS); + LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns])); + + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH + + SIZEOF_DNS_QUERY, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); + /* fill dns header */ + hdr = (struct dns_hdr*)p->payload; + memset(hdr, 0, SIZEOF_DNS_HDR); + hdr->id = htons(id); + hdr->flags1 = DNS_FLAG1_RD; + hdr->numquestions = PP_HTONS(1); + query = (char*)hdr + SIZEOF_DNS_HDR; + pHostname = name; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while(*pHostname != 0); + *query++='\0'; + + /* fill dns query */ + qry.type = PP_HTONS(DNS_RRTYPE_A); + qry.cls = PP_HTONS(DNS_RRCLASS_IN); + SMEMCPY(query, &qry, SIZEOF_DNS_QUERY); + + /* resize pbuf to the exact dns query */ + pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload)))); + + /* connect to the server for faster receiving */ + udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT); + /* send dns packet */ + err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT); + + /* free pbuf */ + pbuf_free(p); + } else { + err = ERR_MEM; + } + + return err; +} + +/** + * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query. + * Check an entry in the dns_table: + * - send out query for new entries + * - retry old pending entries on timeout (also with different servers) + * - remove completed entries from the table if their TTL has expired + * + * @param i index of the dns_table entry to check + */ +static void +dns_check_entry(u8_t i) +{ + err_t err; + struct dns_table_entry *pEntry = &dns_table[i]; + + LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); + + switch(pEntry->state) { + + case DNS_STATE_NEW: { + /* initialize new entry */ + pEntry->state = DNS_STATE_ASKING; + pEntry->numdns = 0; + pEntry->tmr = 1; + pEntry->retries = 0; + + /* send DNS packet for this entry */ + err = dns_send(pEntry->numdns, pEntry->name, i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + break; + } + + case DNS_STATE_ASKING: { + if (--pEntry->tmr == 0) { + if (++pEntry->retries == DNS_MAX_RETRIES) { + if ((pEntry->numdns+1numdns+1])) { + /* change of server */ + pEntry->numdns++; + pEntry->tmr = 1; + pEntry->retries = 0; + break; + } else { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name)); + /* call specified callback function if provided */ + if (pEntry->found) + (*pEntry->found)(pEntry->name, NULL, pEntry->arg); + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + break; + } + } + + /* wait longer for the next retry */ + pEntry->tmr = pEntry->retries; + + /* send DNS packet for this entry */ + err = dns_send(pEntry->numdns, pEntry->name, i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + } + break; + } + + case DNS_STATE_DONE: { + /* if the time to live is nul */ + if (--pEntry->ttl == 0) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name)); + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + } + break; + } + case DNS_STATE_UNUSED: + /* nothing to do */ + break; + default: + LWIP_ASSERT("unknown dns_table entry state:", 0); + break; + } +} + +/** + * Call dns_check_entry for each entry in dns_table - check all entries. + */ +static void +dns_check_entries(void) +{ + u8_t i; + + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + dns_check_entry(i); + } +} + +/** + * Receive input function for DNS response packets arriving for the dns UDP pcb. + * + * @params see udp.h + */ +static void +dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + u16_t i; + char *pHostname; + struct dns_hdr *hdr; + struct dns_answer ans; + struct dns_table_entry *pEntry; + u16_t nquestions, nanswers; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + /* is the dns message too big ? */ + if (p->tot_len > DNS_MSG_SIZE) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n")); + /* free pbuf and return */ + goto memerr; + } + + /* is the dns message big enough ? */ + if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); + /* free pbuf and return */ + goto memerr; + } + + /* copy dns payload inside static buffer for processing */ + if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) { + /* The ID in the DNS header should be our entry into the name table. */ + hdr = (struct dns_hdr*)dns_payload; + i = htons(hdr->id); + if (i < DNS_TABLE_SIZE) { + pEntry = &dns_table[i]; + if(pEntry->state == DNS_STATE_ASKING) { + /* This entry is now completed. */ + pEntry->state = DNS_STATE_DONE; + pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = htons(hdr->numquestions); + nanswers = htons(hdr->numanswers); + + /* Check for error. If so, call callback to inform. */ + if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + +#if DNS_DOES_NAME_CHECK + /* Check if the name in the "question" part match with the name in the entry. */ + if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } +#endif /* DNS_DOES_NAME_CHECK */ + + /* Skip the name in the "question" part */ + pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY; + + while (nanswers > 0) { + /* skip answer resource record's host name */ + pHostname = (char *) dns_parse_name((unsigned char *)pHostname); + + /* Check for IP address type and Internet class. Others are discarded. */ + SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER); + if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) && + (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) { + /* read the answer resource record's TTL, and maximize it if needed */ + pEntry->ttl = ntohl(ans.ttl); + if (pEntry->ttl > DNS_MAX_TTL) { + pEntry->ttl = DNS_MAX_TTL; + } + /* read the IP address after answer resource record's header */ + SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t)); + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name)); + ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr))); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + /* call specified callback function if provided */ + if (pEntry->found) { + (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg); + } + /* deallocate memory and return */ + goto memerr; + } else { + pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len); + } + --nanswers; + } + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + } + } + + /* deallocate memory and return */ + goto memerr; + +responseerr: + /* ERROR: call specified callback function with NULL as name to indicate an error */ + if (pEntry->found) { + (*pEntry->found)(pEntry->name, NULL, pEntry->arg); + } + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + +memerr: + /* free pbuf */ + pbuf_free(p); + return; +} + +/** + * Queues a new hostname to resolve and sends out a DNS query for that hostname + * + * @param name the hostname that is to be queried + * @param found a callback founction to be called on success, failure or timeout + * @param callback_arg argument to pass to the callback function + * @return @return a err_t return code. + */ +static err_t +dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) +{ + u8_t i; + u8_t lseq, lseqi; + struct dns_table_entry *pEntry = NULL; + size_t namelen; + + /* search an unused entry, or the oldest one */ + lseq = lseqi = 0; + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + pEntry = &dns_table[i]; + /* is it an unused entry ? */ + if (pEntry->state == DNS_STATE_UNUSED) + break; + + /* check if this is the oldest completed entry */ + if (pEntry->state == DNS_STATE_DONE) { + if ((dns_seqno - pEntry->seqno) > lseq) { + lseq = dns_seqno - pEntry->seqno; + lseqi = i; + } + } + } + + /* if we don't have found an unused entry, use the oldest completed one */ + if (i == DNS_TABLE_SIZE) { + if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { + /* no entry can't be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); + return ERR_MEM; + } else { + /* use the oldest completed one */ + i = lseqi; + pEntry = &dns_table[i]; + } + } + + /* use this entry */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); + + /* fill the entry */ + pEntry->state = DNS_STATE_NEW; + pEntry->seqno = dns_seqno++; + pEntry->found = found; + pEntry->arg = callback_arg; + namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1); + MEMCPY(pEntry->name, name, namelen); + pEntry->name[namelen] = 0; + + /* force to send query without waiting timer */ + dns_check_entry(i); + + /* dns query is enqueued */ + return ERR_INPROGRESS; +} + +/** + * Resolve a hostname (string) into an IP address. + * NON-BLOCKING callback version for use with raw API!!! + * + * Returns immediately with one of err_t return codes: + * - ERR_OK if hostname is a valid IP address string or the host + * name is already in the local names table. + * - ERR_INPROGRESS enqueue a request to be sent to the DNS server + * for resolution if no errors are present. + * - ERR_ARG: dns client not initialized or invalid hostname + * + * @param hostname the hostname that is to be queried + * @param addr pointer to a ip_addr_t where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @return a err_t return code. + */ +err_t +dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg) +{ + u32_t ipaddr; + /* not initialized or no valid server yet, or invalid addr pointer + * or invalid hostname or invalid hostname length */ + if ((dns_pcb == NULL) || (addr == NULL) || + (!hostname) || (!hostname[0]) || + (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) { + return ERR_ARG; + } + +#if LWIP_HAVE_LOOPIF + if (strcmp(hostname, "localhost")==0) { + ip_addr_set_loopback(addr); + return ERR_OK; + } +#endif /* LWIP_HAVE_LOOPIF */ + + /* host name already in octet notation? set ip addr and return ERR_OK */ + ipaddr = ipaddr_addr(hostname); + if (ipaddr == IPADDR_NONE) { + /* already have this address cached? */ + ipaddr = dns_lookup(hostname); + } + if (ipaddr != IPADDR_NONE) { + ip4_addr_set_u32(addr, ipaddr); + return ERR_OK; + } + + /* queue query with specified callback */ + return dns_enqueue(hostname, found, callback_arg); +} + +#endif /* LWIP_DNS */ diff --git a/ext/lwip/src/core/init.c b/ext/lwip/src/core/init.c new file mode 100644 index 000000000..50cfff1ae --- /dev/null +++ b/ext/lwip/src/core/init.c @@ -0,0 +1,332 @@ +/** + * @file + * Modules initialization + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/init.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/sockets.h" +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp_msg.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/timers.h" +#include "netif/etharp.h" +#include "lwip/api.h" + +/* Compile-time sanity checks for configuration errors. + * These can be done independently of LWIP_DEBUG, without penalty. + */ +#ifndef BYTE_ORDER + #error "BYTE_ORDER is not defined, you have to define it in your cc.h" +#endif +#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) + #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_UDPLITE) + #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DHCP) + #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_IGMP) + #error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DNS) + #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ +#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) + #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" +#endif +#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) + #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) + #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) + #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) + #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" +#endif +#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) + #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" +#endif +/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ +#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT)) + #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#endif +#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) + #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" +#endif +#endif /* !MEMP_MEM_MALLOC */ +#if (LWIP_TCP && (TCP_WND > 0xffff)) + #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) + #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) + #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" +#endif +#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) + #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +#endif +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)) + #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" +#endif +#if (LWIP_NETIF_API && (NO_SYS==1)) + #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) + #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (!LWIP_NETCONN && LWIP_SOCKET) + #error "If you want to use Socket API, you have to define LWIP_NETCONN=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) + #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) + #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && LWIP_AUTOIP) + #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_CONCURRENT_REQUESTS<=0)) + #error "If you want to use SNMP, you have to define SNMP_CONCURRENT_REQUESTS>=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) + #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) + #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" +#endif +#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) + #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) + #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" +#endif +#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) + #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" +#endif +#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) + #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" +#endif +#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT + #error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on" +#endif +#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) + #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" +#endif +#if LWIP_IGMP && !defined(LWIP_RAND) + #error "When using IGMP, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value" +#endif +#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING + #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" +#endif +#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE + #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" +#endif +#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF + #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues" +#endif +#if LWIP_NETCONN && LWIP_TCP +#if NETCONN_COPY != TCP_WRITE_FLAG_COPY + #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" +#endif +#if NETCONN_MORE != TCP_WRITE_FLAG_MORE + #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" +#endif +#endif /* LWIP_NETCONN && LWIP_TCP */ +#if LWIP_SOCKET +/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ +#if SO_ACCEPTCONN != SOF_ACCEPTCONN + #error "SO_ACCEPTCONN != SOF_ACCEPTCONN" +#endif +#if SO_REUSEADDR != SOF_REUSEADDR + #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" +#endif +#if SO_KEEPALIVE != SOF_KEEPALIVE + #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" +#endif +#if SO_BROADCAST != SOF_BROADCAST + #error "WARNING: SO_BROADCAST != SOF_BROADCAST" +#endif +#if SO_LINGER != SOF_LINGER + #error "WARNING: SO_LINGER != SOF_LINGER" +#endif +#endif /* LWIP_SOCKET */ + + +/* Compile-time checks for deprecated options. + */ +#ifdef MEMP_NUM_TCPIP_MSG + #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef MEMP_NUM_API_MSG + #error "MEMP_NUM_API_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef TCP_REXMIT_DEBUG + #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef RAW_STATS + #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_QUEUE_FIRST + #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_ALWAYS_INSERT + #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." +#endif + +#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS +#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 +#endif +#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 +#endif + +/* MEMP sanity checks */ +#if !LWIP_DISABLE_MEMP_SANITY_CHECKS +#if LWIP_NETCONN +#if MEMP_MEM_MALLOC +#if !MEMP_NUM_NETCONN && LWIP_SOCKET +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" +#endif +#else /* MEMP_MEM_MALLOC */ +#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* MEMP_MEM_MALLOC */ +#endif /* LWIP_NETCONN */ +#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ + +/* TCP sanity checks */ +#if !LWIP_DISABLE_TCP_SANITY_CHECKS +#if LWIP_TCP +#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) + #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_BUF < (2 * TCP_MSS) + #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= TCP_SND_BUF + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN + #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) + #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_WND < TCP_MSS + #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* LWIP_TCP */ +#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ + +/** + * Perform Sanity check of user-configurable values, and initialize all modules. + */ +void +lwip_init(void) +{ + /* Modules initialization */ + stats_init(); +#if !NO_SYS + sys_init(); +#endif /* !NO_SYS */ + mem_init(); + memp_init(); + pbuf_init(); + netif_init(); +#if LWIP_SOCKET + //lwip_socket_init(); +#endif /* LWIP_SOCKET */ + ip_init(); +#if LWIP_ARP + etharp_init(); +#endif /* LWIP_ARP */ +#if LWIP_RAW + raw_init(); +#endif /* LWIP_RAW */ +#if LWIP_UDP + udp_init(); +#endif /* LWIP_UDP */ +#if LWIP_TCP + tcp_init(); +#endif /* LWIP_TCP */ +#if LWIP_SNMP + snmp_init(); +#endif /* LWIP_SNMP */ +#if LWIP_AUTOIP + autoip_init(); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + igmp_init(); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + dns_init(); +#endif /* LWIP_DNS */ + +#if LWIP_TIMERS + sys_timeouts_init(); +#endif /* LWIP_TIMERS */ +} diff --git a/ext/lwip/src/core/ipv4/autoip.c b/ext/lwip/src/core/ipv4/autoip.c new file mode 100644 index 000000000..b122da27e --- /dev/null +++ b/ext/lwip/src/core/ipv4/autoip.c @@ -0,0 +1,528 @@ +/** + * @file + * AutoIP Automatic LinkLocal IP Configuration + * + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +/******************************************************************************* + * USAGE: + * + * define LWIP_AUTOIP 1 in your lwipopts.h + * + * If you don't use tcpip.c (so, don't call, you don't call tcpip_init): + * - First, call autoip_init(). + * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces, + * that should be defined in autoip.h. + * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. + * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... + * + * Without DHCP: + * - Call autoip_start() after netif_add(). + * + * With DHCP: + * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. + * - Configure your DHCP Client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" + +#include +#include + +/* 169.254.0.0 */ +#define AUTOIP_NET 0xA9FE0000 +/* 169.254.1.0 */ +#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) +/* 169.254.254.255 */ +#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) + + +/** Pseudo random macro based on netif informations. + * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ +#ifndef LWIP_AUTOIP_RAND +#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ + ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ + ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ + ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ + (netif->autoip?netif->autoip->tried_llipaddr:0)) +#endif /* LWIP_AUTOIP_RAND */ + +/** + * Macro that generates the initial IP address to be tried by AUTOIP. + * If you want to override this, define it to something else in lwipopts.h. + */ +#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR +#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ + htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ + ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) +#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ + +/* static functions */ +static void autoip_handle_arp_conflict(struct netif *netif); + +/* creates a pseudo random LL IP-Address for a network interface */ +static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr); + +/* sends an ARP probe */ +static err_t autoip_arp_probe(struct netif *netif); + +/* sends an ARP announce */ +static err_t autoip_arp_announce(struct netif *netif); + +/* configure interface for use with current LL IP-Address */ +static err_t autoip_bind(struct netif *netif); + +/* start sending probes for llipaddr */ +static void autoip_start_probing(struct netif *netif); + + +/** Set a statically allocated struct autoip to work with. + * Using this prevents autoip_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct autoip + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +autoip_set_struct(struct netif *netif, struct autoip *autoip) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("autoip != NULL", autoip != NULL); + LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL); + + /* clear data structure */ + memset(autoip, 0, sizeof(struct autoip)); + /* autoip->state = AUTOIP_STATE_OFF; */ + netif->autoip = autoip; +} + +/** Restart AutoIP client and check the next address (conflict detected) + * + * @param netif The netif under AutoIP control + */ +static void +autoip_restart(struct netif *netif) +{ + netif->autoip->tried_llipaddr++; + autoip_start(netif); +} + +/** + * Handle a IP address conflict after an ARP conflict detection + */ +static void +autoip_handle_arp_conflict(struct netif *netif) +{ + /* Somehow detect if we are defending or retreating */ + unsigned char defend = 1; /* tbd */ + + if (defend) { + if (netif->autoip->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last + * DEFEND_INTERVAL seconds + */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); + + /* TODO: close all TCP sessions */ + autoip_restart(netif); + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); + autoip_arp_announce(netif); + netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we do not defend, retreating\n")); + /* TODO: close all TCP sessions */ + autoip_restart(netif); + } +} + +/** + * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * + * @param netif network interface on which create the IP-Address + * @param ipaddr ip address to initialize + */ +static void +autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr) +{ + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 + * We have 254 * 256 possibilities */ + + u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); + addr += netif->autoip->tried_llipaddr; + addr = AUTOIP_NET | (addr & 0xffff); + /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ + + if (addr < AUTOIP_RANGE_START) { + addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + if (addr > AUTOIP_RANGE_END) { + addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && + (addr <= AUTOIP_RANGE_END)); + ip4_addr_set_u32(ipaddr, htonl(addr)); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), + ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); +} + +/** + * Sends an ARP probe from a network interface + * + * @param netif network interface used to send the probe + */ +static err_t +autoip_arp_probe(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Sends an ARP announce from a network interface + * + * @param netif network interface used to send the announce + */ +static err_t +autoip_arp_announce(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Configure interface for use with current LL IP-Address + * + * @param netif network interface to configure with current LL IP-Address + */ +static err_t +autoip_bind(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + ip_addr_t sn_mask, gw_addr; + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + + IP4_ADDR(&sn_mask, 255, 255, 0, 0); + IP4_ADDR(&gw_addr, 0, 0, 0, 0); + + netif_set_ipaddr(netif, &autoip->llipaddr); + netif_set_netmask(netif, &sn_mask); + netif_set_gw(netif, &gw_addr); + + /* bring the interface up */ + netif_set_up(netif); + + return ERR_OK; +} + +/** + * Start AutoIP client + * + * @param netif network interface on which start the AutoIP client + */ +err_t +autoip_start(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + err_t result = ERR_OK; + + if (netif_is_up(netif)) { + netif_set_down(netif); + } + + /* Set IP-Address, Netmask and Gateway to 0 to make sure that + * ARP Packets are formed correctly + */ + ip_addr_set_zero(&netif->ip_addr); + ip_addr_set_zero(&netif->netmask); + ip_addr_set_zero(&netif->gw); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + if (autoip == NULL) { + /* no AutoIP client attached yet? */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): starting new AUTOIP client\n")); + autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); + if (autoip == NULL) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): could not allocate autoip\n")); + return ERR_MEM; + } + memset(autoip, 0, sizeof(struct autoip)); + /* store this AutoIP client in the netif */ + netif->autoip = autoip; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); + } else { + autoip->state = AUTOIP_STATE_OFF; + autoip->ttw = 0; + autoip->sent_num = 0; + ip_addr_set_zero(&autoip->llipaddr); + autoip->lastconflict = 0; + } + + autoip_create_addr(netif, &(autoip->llipaddr)); + autoip_start_probing(netif); + + return result; +} + +static void +autoip_start_probing(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + + autoip->state = AUTOIP_STATE_PROBING; + autoip->sent_num = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + + /* time to wait to first probe, this is randomly + * choosen out of 0 to PROBE_WAIT seconds. + * compliant to RFC 3927 Section 2.2.1 + */ + autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); + + /* + * if we tried more then MAX_CONFLICTS we must limit our rate for + * accquiring and probing address + * compliant to RFC 3927 Section 2.2.1 + */ + if (autoip->tried_llipaddr > MAX_CONFLICTS) { + autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Handle a possible change in the network configuration. + * + * If there is an AutoIP address configured, take the interface down + * and begin probing with the same address. + */ +void +autoip_network_changed(struct netif *netif) +{ + if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) { + netif_set_down(netif); + autoip_start_probing(netif); + } +} + +/** + * Stop AutoIP client + * + * @param netif network interface on which stop the AutoIP client + */ +err_t +autoip_stop(struct netif *netif) +{ + netif->autoip->state = AUTOIP_STATE_OFF; + netif_set_down(netif); + return ERR_OK; +} + +/** + * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds + */ +void +autoip_tmr() +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on AutoIP configured interfaces */ + if (netif->autoip != NULL) { + if (netif->autoip->lastconflict > 0) { + netif->autoip->lastconflict--; + } + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", + (u16_t)(netif->autoip->state), netif->autoip->ttw)); + + switch(netif->autoip->state) { + case AUTOIP_STATE_PROBING: + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if (netif->autoip->sent_num >= PROBE_NUM) { + netif->autoip->state = AUTOIP_STATE_ANNOUNCING; + netif->autoip->sent_num = 0; + netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + } else { + autoip_arp_probe(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() PROBING Sent Probe\n")); + netif->autoip->sent_num++; + /* calculate time to wait to next probe */ + netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + } + } + break; + + case AUTOIP_STATE_ANNOUNCING: + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if (netif->autoip->sent_num == 0) { + /* We are here the first time, so we waited ANNOUNCE_WAIT seconds + * Now we can bind to an IP address and use it. + * + * autoip_bind calls netif_set_up. This triggers a gratuitous ARP + * which counts as an announcement. + */ + autoip_bind(netif); + } else { + autoip_arp_announce(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() ANNOUNCING Sent Announce\n")); + } + netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + netif->autoip->sent_num++; + + if (netif->autoip->sent_num >= ANNOUNCE_NUM) { + netif->autoip->state = AUTOIP_STATE_BOUND; + netif->autoip->sent_num = 0; + netif->autoip->ttw = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + } + } + break; + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * Handles every incoming ARP Packet, called by etharp_arp_input. + * + * @param netif network interface to use for autoip processing + * @param hdr Incoming ARP packet + */ +void +autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) +{ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); + if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) { + /* when ip.src == llipaddr && hw.src != netif->hwaddr + * + * when probing ip.dst == llipaddr && hw.src != netif->hwaddr + * we have a conflict and must solve it + */ + ip_addr_t sipaddr, dipaddr; + struct eth_addr netifaddr; + ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); + + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). + */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + if ((netif->autoip->state == AUTOIP_STATE_PROBING) || + ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) && + (netif->autoip->sent_num == 0))) { + /* RFC 3927 Section 2.2.1: + * from beginning to after ANNOUNCE_WAIT + * seconds we have a conflict if + * ip.src == llipaddr OR + * ip.dst == llipaddr && hw.src != own hwaddr + */ + if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) || + (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Probe Conflict detected\n")); + autoip_restart(netif); + } + } else { + /* RFC 3927 Section 2.5: + * in any state we have a conflict if + * ip.src == llipaddr && hw.src != own hwaddr + */ + if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); + autoip_handle_arp_conflict(netif); + } + } + } +} + +#endif /* LWIP_AUTOIP */ diff --git a/ext/lwip/src/core/ipv4/icmp.c b/ext/lwip/src/core/ipv4/icmp.c new file mode 100644 index 000000000..47ba85713 --- /dev/null +++ b/ext/lwip/src/core/ipv4/icmp.c @@ -0,0 +1,339 @@ +/** + * @file + * ICMP - Internet Control Message Protocol + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include + +/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be + * used to modify and send a response packet (and to 1 if this is not the case, + * e.g. when link header is stripped of when receiving) */ +#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + +/* The amount of data from the original packet to return in a dest-unreachable */ +#define ICMP_DEST_UNREACH_DATASIZE 8 + +static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); + +/** + * Processes ICMP input packets, called from ip_input(). + * + * Currently only processes icmp echo requests and sends + * out the echo response. + * + * @param p the icmp echo request packet, p->payload pointing to the ip header + * @param inp the netif on which this packet was received + */ +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; +#ifdef LWIP_DEBUG + u8_t code; +#endif /* LWIP_DEBUG */ + struct icmp_echo_hdr *iecho; + struct ip_hdr *iphdr; + s16_t hlen; + + ICMP_STATS_INC(icmp.recv); + snmp_inc_icmpinmsgs(); + + + iphdr = (struct ip_hdr *)p->payload; + hlen = IPH_HL(iphdr) * 4; + if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); + goto lenerr; + } + + type = *((u8_t *)p->payload); +#ifdef LWIP_DEBUG + code = *(((u8_t *)p->payload)+1); +#endif /* LWIP_DEBUG */ + switch (type) { + case ICMP_ER: + /* This is OK, echo reply might have been parsed by a raw PCB + (as obviously, an echo request has been sent, too). */ + break; + case ICMP_ECHO: +#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING + { + int accepted = 1; +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip_addr_ismulticast(¤t_iphdr_dest)) { + accepted = 0; + } +#endif /* LWIP_MULTICAST_PING */ +#if !LWIP_BROADCAST_PING + /* broadcast destination address? */ + if (ip_addr_isbroadcast(¤t_iphdr_dest, inp)) { + accepted = 0; + } +#endif /* LWIP_BROADCAST_PING */ + /* broadcast or multicast destination address not acceptd? */ + if (!accepted) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n")); + ICMP_STATS_INC(icmp.err); + pbuf_free(p); + return; + } + } +#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + goto lenerr; + } + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); + pbuf_free(p); + ICMP_STATS_INC(icmp.chkerr); + snmp_inc_icmpinerrors(); + return; + } +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + /* p is not big enough to contain link headers + * allocate a new one and copy p into it + */ + struct pbuf *r; + /* switch p->payload to ip header */ + if (pbuf_header(p, hlen)) { + LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0); + goto memerr; + } + /* allocate new packet buffer with space for link headers */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); + goto memerr; + } + LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", + (r->len >= hlen + sizeof(struct icmp_echo_hdr))); + /* copy the whole packet including ip header */ + if (pbuf_copy(r, p) != ERR_OK) { + LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0); + goto memerr; + } + iphdr = (struct ip_hdr *)r->payload; + /* switch r->payload back to icmp header */ + if (pbuf_header(r, -hlen)) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + /* free the original p */ + pbuf_free(p); + /* we now have an identical copy of p that has room for link headers */ + p = r; + } else { + /* restore p->payload to point to icmp header */ + if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + } +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + /* At this point, all checks are OK. */ + /* We generate an answer by switching the dest and src ip addresses, + * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ + iecho = (struct icmp_echo_hdr *)p->payload; + ip_addr_copy(iphdr->src, *ip_current_dest_addr()); + ip_addr_copy(iphdr->dest, *ip_current_src_addr()); + ICMPH_TYPE_SET(iecho, ICMP_ER); +#if CHECKSUM_GEN_ICMP + /* adjust the checksum */ + if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; + } else { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8); + } +#else /* CHECKSUM_GEN_ICMP */ + iecho->chksum = 0; +#endif /* CHECKSUM_GEN_ICMP */ + + /* Set the correct TTL and recalculate the header checksum. */ + IPH_TTL_SET(iphdr, ICMP_TTL); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ + + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of echo replies attempted to send */ + snmp_inc_icmpoutechoreps(); + + if(pbuf_header(p, hlen)) { + LWIP_ASSERT("Can't move over header in packet", 0); + } else { + err_t ret; + /* send an ICMP packet, src addr is the dest addr of the curren packet */ + ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL, + ICMP_TTL, 0, IP_PROTO_ICMP, inp); + if (ret != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret)); + } + } + break; + default: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", + (s16_t)type, (s16_t)code)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + pbuf_free(p); + return; +lenerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + snmp_inc_icmpinerrors(); + return; +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +memerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.err); + snmp_inc_icmpinerrors(); + return; +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ +} + +/** + * Send an icmp 'destination unreachable' packet, called from ip_input() if + * the transport layer protocol is unknown and from udp_input() if the local + * port is not bound. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'unreachable' packet + */ +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + icmp_send_response(p, ICMP_DUR, t); +} + +#if IP_FORWARD || IP_REASSEMBLY +/** + * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. + * + * @param p the input packet for which the 'time exceeded' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'time exceeded' packet + */ +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + icmp_send_response(p, ICMP_TE, t); +} + +#endif /* IP_FORWARD || IP_REASSEMBLY */ + +/** + * Send an icmp packet in response to an incoming packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param type Type of the ICMP header + * @param code Code of the ICMP header + */ +static void +icmp_send_response(struct pbuf *p, u8_t type, u8_t code) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + /* we can use the echo header here */ + struct icmp_echo_hdr *icmphdr; + ip_addr_t iphdr_src; + + /* ICMP header + IP header + 8 bytes of data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + + iphdr = (struct ip_hdr *)p->payload; + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src)); + LWIP_DEBUGF(ICMP_DEBUG, (" to ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest)); + LWIP_DEBUGF(ICMP_DEBUG, ("\n")); + + icmphdr = (struct icmp_echo_hdr *)q->payload; + icmphdr->type = type; + icmphdr->code = code; + icmphdr->id = 0; + icmphdr->seqno = 0; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + + /* calculate checksum */ + icmphdr->chksum = 0; + icmphdr->chksum = inet_chksum(icmphdr, q->len); + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of destination unreachable messages attempted to send */ + snmp_inc_icmpouttimeexcds(); + ip_addr_copy(iphdr_src, iphdr->src); + ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP); + pbuf_free(q); +} + +#endif /* LWIP_ICMP */ diff --git a/ext/lwip/src/core/ipv4/igmp.c b/ext/lwip/src/core/ipv4/igmp.c new file mode 100644 index 000000000..45bb5d95c --- /dev/null +++ b/ext/lwip/src/core/ipv4/igmp.c @@ -0,0 +1,805 @@ +/** + * @file + * IGMP - Internet Group Management Protocol + * + */ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +/*------------------------------------------------------------- +Note 1) +Although the rfc requires V1 AND V2 capability +we will only support v2 since now V1 is very old (August 1989) +V1 can be added if required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 2) +A query for a specific group address (as opposed to ALLHOSTS) +has now been implemented as I am unsure if it is required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 3) +The router alert rfc 2113 is implemented in outgoing packets +but not checked rigorously incoming +------------------------------------------------------------- +Steve Reynolds +------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * RFC 988 - Host extensions for IP multicasting - V0 + * RFC 1054 - Host extensions for IP multicasting - + * RFC 1112 - Host extensions for IP multicasting - V1 + * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) + * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 + * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ + * RFC 2113 - IP Router Alert Option - + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/igmp.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/stats.h" + +#include "string.h" + +/* + * IGMP constants + */ +#define IGMP_TTL 1 +#define IGMP_MINLEN 8 +#define ROUTER_ALERT 0x9404U +#define ROUTER_ALERTLEN 4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY 0x11 /* Membership query */ +#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ + +/* Group membership states */ +#define IGMP_GROUP_NON_MEMBER 0 +#define IGMP_GROUP_DELAYING_MEMBER 1 +#define IGMP_GROUP_IDLE_MEMBER 2 + +/** + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FIELD(u8_t igmp_msgtype); + PACK_STRUCT_FIELD(u8_t igmp_maxresp); + PACK_STRUCT_FIELD(u16_t igmp_checksum); + PACK_STRUCT_FIELD(ip_addr_p_t igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr); +static err_t igmp_remove_group(struct igmp_group *group); +static void igmp_timeout( struct igmp_group *group); +static void igmp_start_timer(struct igmp_group *group, u8_t max_time); +static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); +static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif); +static void igmp_send(struct igmp_group *group, u8_t type); + + +static struct igmp_group* igmp_group_list; +static ip_addr_t allsystems; +static ip_addr_t allrouters; + + +/** + * Initialize the IGMP module + */ +void +igmp_init(void) +{ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); + + IP4_ADDR(&allsystems, 224, 0, 0, 1); + IP4_ADDR(&allrouters, 224, 0, 0, 2); +} + +#ifdef LWIP_DEBUG +/** + * Dump global IGMP groups list + */ +void +igmp_dump_group_list() +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state))); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); + group = group->next; + } + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); +} +#else +#define igmp_dump_group_list() +#endif /* LWIP_DEBUG */ + +/** + * Start IGMP processing on interface + * + * @param netif network interface on which start IGMP processing + */ +err_t +igmp_start(struct netif *netif) +{ + struct igmp_group* group; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif)); + + group = igmp_lookup_group(netif, &allsystems); + + if (group != NULL) { + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->use++; + + /* Allow the igmp messages at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); + ip_addr_debug_print(IGMP_DEBUG, &allsystems); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER); + } + + return ERR_OK; + } + + return ERR_MEM; +} + +/** + * Stop IGMP processing on interface + * + * @param netif network interface on which stop IGMP processing + */ +err_t +igmp_stop(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + struct igmp_group *prev = NULL; + struct igmp_group *next; + + /* look for groups joined on this interface further down the list */ + while (group != NULL) { + next = group->next; + /* is it a group joined on this interface? */ + if (group->netif == netif) { + /* is it the first group of the list? */ + if (group == igmp_group_list) { + igmp_group_list = next; + } + /* is there a "previous" group defined? */ + if (prev != NULL) { + prev->next = next; + } + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER); + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + } else { + /* change the "previous" */ + prev = group; + } + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report IGMP memberships for this interface + * + * @param netif network interface on which report IGMP memberships + */ +void +igmp_report_groups(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif)); + + while (group != NULL) { + if (group->netif == netif) { + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + } + group = group->next; + } +} + +/** + * Search for a group in the global igmp_group_list + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search for + * @return a struct igmp_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct igmp_group * +igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if ((group->netif == ifp) && (ip_addr_cmp(&(group->group_address), addr))) { + return group; + } + group = group->next; + } + + /* to be clearer, we return NULL here instead of + * 'group' (which is also NULL at this point). + */ + return NULL; +} + +/** + * Search for a specific igmp group and create a new one if not found- + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search + * @return a struct igmp_group*, + * NULL on memory error. + */ +struct igmp_group * +igmp_lookup_group(struct netif *ifp, ip_addr_t *addr) +{ + struct igmp_group *group = igmp_group_list; + + /* Search if the group already exists */ + group = igmp_lookfor_group(ifp, addr); + if (group != NULL) { + /* Group already exists. */ + return group; + } + + /* Group doesn't exist yet, create a new one */ + group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); + if (group != NULL) { + group->netif = ifp; + ip_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = IGMP_GROUP_NON_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = igmp_group_list; + + igmp_group_list = group; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); + ip_addr_debug_print(IGMP_DEBUG, addr); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp)); + + return group; +} + +/** + * Remove a group in the global igmp_group_list + * + * @param group the group to remove from the global igmp_group_list + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +igmp_remove_group(struct igmp_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (igmp_group_list == group) { + igmp_group_list = group->next; + } else { + /* look for group further down the list */ + struct igmp_group *tmpGroup; + for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not found in the global igmp_group_list */ + if (tmpGroup == NULL) + err = ERR_ARG; + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + + return err; +} + +/** + * Called from ip_input() if a new IGMP packet is received. + * + * @param p received igmp packet, p->payload pointing to the ip header + * @param inp network interface on which the packet was received + * @param dest destination ip address of the igmp packet + */ +void +igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest) +{ + struct ip_hdr * iphdr; + struct igmp_msg* igmp; + struct igmp_group* group; + struct igmp_group* groupref; + + IGMP_STATS_INC(igmp.recv); + + /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ + iphdr = (struct ip_hdr *)p->payload; + if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.lenerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); + return; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); + ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src)); + LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); + ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp)); + + /* Now calculate and check the checksum */ + igmp = (struct igmp_msg *)p->payload; + if (inet_chksum(igmp, p->len)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.chkerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); + return; + } + + /* Packet is ok so find an existing group */ + group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ + + /* If group can be found or create... */ + if (!group) { + pbuf_free(p); + IGMP_STATS_INC(igmp.drop); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); + return; + } + + /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ + switch (igmp->igmp_msgtype) { + case IGMP_MEMB_QUERY: { + /* IGMP_MEMB_QUERY to the "all systems" address ? */ + if ((ip_addr_cmp(dest, &allsystems)) && ip_addr_isany(&igmp->igmp_group_address)) { + /* THIS IS THE GENERAL QUERY */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + + if (igmp->igmp_maxresp == 0) { + IGMP_STATS_INC(igmp.rx_v1); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); + igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; + } else { + IGMP_STATS_INC(igmp.rx_general); + } + + groupref = igmp_group_list; + while (groupref) { + /* Do not send messages on the all systems group address! */ + if ((groupref->netif == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) { + igmp_delaying_member(groupref, igmp->igmp_maxresp); + } + groupref = groupref->next; + } + } else { + /* IGMP_MEMB_QUERY to a specific group ? */ + if (!ip_addr_isany(&igmp->igmp_group_address)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); + ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); + if (ip_addr_cmp(dest, &allsystems)) { + ip_addr_t groupaddr; + LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + /* we first need to re-look for the group since we used dest last time */ + ip_addr_copy(groupaddr, igmp->igmp_group_address); + group = igmp_lookfor_group(inp, &groupaddr); + } else { + LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + } + + if (group != NULL) { + IGMP_STATS_INC(igmp.rx_group); + igmp_delaying_member(group, igmp->igmp_maxresp); + } else { + IGMP_STATS_INC(igmp.drop); + } + } else { + IGMP_STATS_INC(igmp.proterr); + } + } + break; + } + case IGMP_V2_MEMB_REPORT: { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); + IGMP_STATS_INC(igmp.rx_report); + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + /* This is on a specific group we have already looked up */ + group->timer = 0; /* stopped */ + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + break; + } + default: { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", + igmp->igmp_msgtype, group->group_state, &group, group->netif)); + IGMP_STATS_INC(igmp.proterr); + break; + } + } + + pbuf_free(p); + return; +} + +/** + * Join a group on one network interface. + * + * @param ifaddr ip address of the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct igmp_group *group; + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { + /* find group or create a new one if not found */ + group = igmp_lookup_group(netif, groupaddr); + + if (group != NULL) { + /* This should create a new group, check the state to make sure */ + if (group->group_state != IGMP_GROUP_NON_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n")); + } else { + /* OK - it was new group */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If first use of the group, allow the group at the MAC level */ + if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER); + } + + IGMP_STATS_INC(igmp.tx_join); + igmp_send(group, IGMP_V2_MEMB_REPORT); + + igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + + /* Need to work out where this timer comes from */ + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } + /* Increment group use */ + group->use++; + /* Join on this interface */ + err = ERR_OK; + } else { + /* Return an error even if some network interfaces are joined */ + /** @todo undo any other netif already joined */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n")); + return ERR_MEM; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Leave a group on one network interface. + * + * @param ifaddr ip address of the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct igmp_group *group; + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { + /* find group */ + group = igmp_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Only send a leave if the flag is set according to the state diagram */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If there is no other use of the group */ + if (group->use <= 1) { + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n")); + IGMP_STATS_INC(igmp.tx_leave); + igmp_send(group, IGMP_LEAVE_GROUP); + } + + /* Disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* Free the group */ + igmp_remove_group(group); + } else { + /* Decrement group use */ + group->use--; + } + /* Leave on this interface */ + err = ERR_OK; + } else { + /* It's not a fatal error on "leavegroup" */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n")); + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * The igmp timer function (both for NO_SYS=1 and =0) + * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). + */ +void +igmp_tmr(void) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + igmp_timeout(group); + } + } + group = group->next; + } +} + +/** + * Called if a timeout for one group is reached. + * Sends a report for this group. + * + * @param group an igmp_group for which a timeout is reached + */ +static void +igmp_timeout(struct igmp_group *group) +{ + /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */ + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); + ip_addr_debug_print(IGMP_DEBUG, &(group->group_address)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); + + IGMP_STATS_INC(igmp.tx_report); + igmp_send(group, IGMP_V2_MEMB_REPORT); + } +} + +/** + * Start a timer for an igmp group + * + * @param group the igmp_group for which to start a timer + * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with + * every call to igmp_tmr()) + */ +static void +igmp_start_timer(struct igmp_group *group, u8_t max_time) +{ + /* ensure the input value is > 0 */ + if (max_time == 0) { + max_time = 1; + } + /* ensure the random value is > 0 */ + group->timer = (LWIP_RAND() % (max_time - 1)) + 1; +} + +/** + * Delaying membership report for a group if necessary + * + * @param group the igmp_group for which "delaying" membership report + * @param maxresp query delay + */ +static void +igmp_delaying_member(struct igmp_group *group, u8_t maxresp) +{ + if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || + ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + igmp_start_timer(group, maxresp); + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } +} + + +/** + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + */ +static err_t +igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif) +{ + /* This is the "router alert" option */ + u16_t ra[2]; + ra[0] = PP_HTONS(ROUTER_ALERT); + ra[1] = 0x0000; /* Router shall examine packet */ + IGMP_STATS_INC(igmp.xmit); + return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); +} + +/** + * Send an igmp packet to a specific group. + * + * @param group the group to which to send the packet + * @param type the type of igmp packet to send + */ +static void +igmp_send(struct igmp_group *group, u8_t type) +{ + struct pbuf* p = NULL; + struct igmp_msg* igmp = NULL; + ip_addr_t src = *IP_ADDR_ANY; + ip_addr_t* dest = NULL; + + /* IP header + "router alert" option + IGMP header */ + p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); + + if (p) { + igmp = (struct igmp_msg *)p->payload; + LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", + (p->len >= sizeof(struct igmp_msg))); + ip_addr_copy(src, group->netif->ip_addr); + + if (type == IGMP_V2_MEMB_REPORT) { + dest = &(group->group_address); + ip_addr_copy(igmp->igmp_group_address, group->group_address); + group->last_reporter_flag = 1; /* Remember we were the last to report */ + } else { + if (type == IGMP_LEAVE_GROUP) { + dest = &allrouters; + ip_addr_copy(igmp->igmp_group_address, group->group_address); + } + } + + if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { + igmp->igmp_msgtype = type; + igmp->igmp_maxresp = 0; + igmp->igmp_checksum = 0; + igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); + + igmp_ip_output_if(p, &src, dest, group->netif); + } + + pbuf_free(p); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); + IGMP_STATS_INC(igmp.memerr); + } +} + +#endif /* LWIP_IGMP */ diff --git a/ext/lwip/src/core/ipv4/inet.c b/ext/lwip/src/core/ipv4/inet.c new file mode 100644 index 000000000..e283a5766 --- /dev/null +++ b/ext/lwip/src/core/ipv4/inet.c @@ -0,0 +1,42 @@ +/** + * @file + * Functions common to all TCP/IPv4 modules, such as the byte order functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet.h" + diff --git a/ext/lwip/src/core/ipv4/inet_chksum.c b/ext/lwip/src/core/ipv4/inet_chksum.c new file mode 100644 index 000000000..960252f64 --- /dev/null +++ b/ext/lwip/src/core/ipv4/inet_chksum.c @@ -0,0 +1,450 @@ +/** + * @file + * Incluse internet checksum functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet_chksum.h" +#include "lwip/def.h" + +#include +#include + +/* These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * #define LWIP_CHKSUM + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. + */ + +#ifndef LWIP_CHKSUM +# define LWIP_CHKSUM lwip_standard_chksum +# ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 2 +# endif +#endif +/* If none set: */ +#ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 0 +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable length to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ +static u16_t +lwip_standard_chksum(void *dataptr, u16_t len) +{ + u32_t acc; + u16_t src; + u8_t *octetptr; + + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (u8_t*)dataptr; + while (len > 1) { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000UL) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using htons() + instead of ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return htons((u16_t)acc); +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + */ + +static u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = (u8_t *)dataptr; + u16_t *ps, t = 0; + u32_t sum = 0; + int odd = ((mem_ptr_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + /* Add the bulk of the data */ + ps = (u16_t *)(void *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* Consume left-over byte, if any */ + if (len > 0) { + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + /* Swap if alignment was odd */ + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ + +static u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = (u8_t *)dataptr; + u16_t *ps, t = 0; + u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((mem_ptr_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (u16_t *)pb; + + if (((mem_ptr_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (u32_t *)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) { + tmp++; /* add back carry */ + } + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) { + sum++; /* add back carry */ + } + + len -= 8; + } + + /* make room in upper bits */ + sum = FOLD_U32T(sum); + + ps = (u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) { /* include odd byte */ + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + sum += t; /* add end bytes */ + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len) +{ + u32_t acc; + u32_t addr; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + /* iterate through all pbuf in chain */ + for(q = p; q != NULL; q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* just executing this next line is probably faster that the if statement needed + to check whether we really need to execute it, and does no harm */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + addr = ip4_addr_get_u32(src); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo_partial(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len, u16_t chksum_len) +{ + u32_t acc; + u32_t addr; + struct pbuf *q; + u8_t swapped; + u16_t chklen; + + acc = 0; + swapped = 0; + /* iterate through all pbuf in chain */ + for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + chklen = q->len; + if (chklen > chksum_len) { + chklen = chksum_len; + } + acc += LWIP_CHKSUM(q->payload, chklen); + chksum_len -= chklen; + LWIP_ASSERT("delete me", chksum_len < 0x7fff); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* fold the upper bit down */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + addr = ip4_addr_get_u32(src); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarily for IP + * and ICMP. + * + * @param dataptr start of the buffer to calculate the checksum (no alignment needed) + * @param len length of the buffer to calculate the checksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ + +u16_t +inet_chksum(void *dataptr, u16_t len) +{ + return ~LWIP_CHKSUM(dataptr, len); +} + +/** + * Calculate a checksum over a chain of pbufs (without pseudo-header, much like + * inet_chksum only pbufs are used). + * + * @param p pbuf chain over that the checksum should be calculated + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += LWIP_CHKSUM(q->payload, q->len); + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + return (u16_t)~(acc & 0xffffUL); +} + +/* These are some implementations for LWIP_CHKSUM_COPY, which copies data + * like MEMCPY but generates a checksum at the same time. Since this is a + * performance-sensitive function, you might want to create your own version + * in assembly targeted at your hardware by defining it in lwipopts.h: + * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) + */ + +#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ +/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. + * For architectures with big caches, data might still be in cache when + * generating the checksum after copying. + */ +u16_t +lwip_chksum_copy(void *dst, const void *src, u16_t len) +{ + MEMCPY(dst, src, len); + return LWIP_CHKSUM(dst, len); +} +#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/ext/lwip/src/core/ipv4/ip.c b/ext/lwip/src/core/ipv4/ip.c new file mode 100644 index 000000000..0e09b3c04 --- /dev/null +++ b/ext/lwip/src/core/ipv4/ip.c @@ -0,0 +1,924 @@ +/** + * @file + * This is the IPv4 layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip_frag.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/igmp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/stats.h" +#include "arch/perf.h" + +#include + +/** Set this to 0 in the rare case of wanting to call an extra function to + * generate the IP checksum (in contrast to calculating it on-the-fly). */ +#ifndef LWIP_INLINE_IP_CHKSUM +#define LWIP_INLINE_IP_CHKSUM 1 +#endif +#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP_INLINE 1 +#else +#define CHECKSUM_GEN_IP_INLINE 0 +#endif + +#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 + +/** Some defines for DHCP to let link-layer-addressed packets through while the + * netif is down. + * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT + * to return 1 if the port is accepted and 0 if the port is not accepted. + */ +#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) +/* accept DHCP client port and custom port */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ + || (LWIP_IP_ACCEPT_UDP_PORT(port))) +#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept custom port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) +#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept DHCP client port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) +#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ + +#else /* LWIP_DHCP */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 +#endif /* LWIP_DHCP */ + +/** + * The interface that provided the packet for the current callback + * invocation. + */ +struct netif *current_netif; + +/** + * Header of the input packet currently being processed. + */ +const struct ip_hdr *current_header; +/** Source IP address of current_header */ +ip_addr_t current_iphdr_src; +/** Destination IP address of current_header */ +ip_addr_t current_iphdr_dest; + +/** The IP header ID of the next outgoing IP packet */ +static u16_t ip_id; + +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip_route(ip_addr_t *dest) +{ + struct netif *netif; + +#ifdef LWIP_HOOK_IP4_ROUTE + netif = LWIP_HOOK_IP4_ROUTE(dest); + if (netif != NULL) { + return netif; + } +#endif + + /* iterate through netifs */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + /* network mask matches? */ + if (netif_is_up(netif)) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + if ((netif_default == NULL) || (!netif_is_up(netif_default))) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + snmp_inc_ipoutnoroutes(); + return NULL; + } + /* no matching netif found, use default netif */ + return netif_default; +} + +#if IP_FORWARD +/** + * Determine whether an IP address is in a reserved set of addresses + * that may not be forwarded, or whether datagrams to that destination + * may be forwarded. + * @param p the packet to forward + * @param dest the destination IP address + * @return 1: can forward 0: discard + */ +static int +ip_canforward(struct pbuf *p) +{ + u32_t addr = ip4_addr_get_u32(ip_current_dest_addr()); + + if (p->flags & PBUF_FLAG_LLBCAST) { + /* don't route link-layer broadcasts */ + return 0; + } + if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { + /* don't route link-layer multicasts unless the destination address is an IP + multicast address */ + return 0; + } + if (IP_EXPERIMENTAL(addr)) { + return 0; + } + if (IP_CLASSA(addr)) { + u32_t net = addr & IP_CLASSA_NET; + if ((net == 0) || (net == (IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { + /* don't route loopback packets */ + return 0; + } + } + return 1; +} + +/** + * Forwards an IP packet. It finds an appropriate route for the + * packet, decrements the TTL value of the packet, adjusts the + * checksum and outputs the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IP header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + PERF_START; + + if (!ip_canforward(p)) { + goto return_noroute; + } + + /* RFC3927 2.7: do not forward link-local addresses */ + if (ip_addr_islinklocal(¤t_iphdr_dest)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest), + ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest))); + goto return_noroute; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip_route(¤t_iphdr_dest); + if (netif == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", + ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest), + ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest))); + /* @todo: send ICMP_DUR_NET? */ + goto return_noroute; + } +#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); + goto return_noroute; + } +#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ + + /* decrement TTL */ + IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); + /* send ICMP if TTL == 0 */ + if (IPH_TTL(iphdr) == 0) { + snmp_inc_ipinhdrerrors(); +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + return; + } + + /* Incrementally update the IP checksum. */ + if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); + } else { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); + } + + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest), + ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest))); + + IP_STATS_INC(ip.fw); + IP_STATS_INC(ip.xmit); + snmp_inc_ipforwdatagrams(); + + PERF_STOP("ip_forward"); + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { +#if IP_FRAG + ip_frag(p, netif, ip_current_dest_addr()); +#else /* IP_FRAG */ + /* @todo: send ICMP Destination Unreacheable code 13 "Communication administratively prohibited"? */ +#endif /* IP_FRAG */ + } else { + /* send ICMP Destination Unreacheable code 4: "Fragmentation Needed and DF Set" */ + icmp_dest_unreach(p, ICMP_DUR_FRAG); + } + return; + } + /* transmit pbuf on chosen interface */ + netif->output(netif, p, ¤t_iphdr_dest); + return; +return_noroute: + snmp_inc_ipoutnoroutes(); +} +#endif /* IP_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IP packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IP packet (p->payload points to IP header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdr_hlen; + u16_t iphdr_len; +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + int check_ip_src=1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + IP_STATS_INC(ip.recv); + snmp_inc_ipinreceives(); + + /* identify the IP header */ + iphdr = (struct ip_hdr *)p->payload; + if (IPH_V(iphdr) != 4) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP4_INPUT + if (LWIP_HOOK_IP4_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* obtain IP header length in number of 32-bit words */ + iphdr_hlen = IPH_HL(iphdr); + /* calculate IP header length in bytes */ + iphdr_hlen *= 4; + /* obtain ip length in bytes */ + iphdr_len = ntohs(IPH_LEN(iphdr)); + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { + if (iphdr_hlen > p->len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_hlen, p->len)); + } + if (iphdr_len > p->tot_len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_len, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.lenerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipindiscards(); + return ERR_OK; + } + + /* verify checksum */ +#if CHECKSUM_CHECK_IP + if (inet_chksum(iphdr, iphdr_hlen) != 0) { + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.chkerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } +#endif + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, iphdr_len); + + /* copy IP addresses to aligned ip_addr_t */ + ip_addr_copy(current_iphdr_dest, iphdr->dest); + ip_addr_copy(current_iphdr_src, iphdr->src); + + /* match packet against an interface, i.e. is this packet for us? */ +#if LWIP_IGMP + if (ip_addr_ismulticast(¤t_iphdr_dest)) { + if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ¤t_iphdr_dest))) { + netif = inp; + } else { + netif = NULL; + } + } else +#endif /* LWIP_IGMP */ + { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr), + ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask), + ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask), + ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask))); + + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { + /* unicast to this interface address? */ + if (ip_addr_cmp(¤t_iphdr_dest, &(netif->ip_addr)) || + /* or broadcast on this interface network address? */ + ip_addr_isbroadcast(¤t_iphdr_dest, netif)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#if LWIP_AUTOIP + /* connections to link-local addresses must persist after changing + the netif's address (RFC3927 ch. 1.9) */ + if ((netif->autoip != NULL) && + ip_addr_cmp(¤t_iphdr_dest, &(netif->autoip->llipaddr))) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#endif /* LWIP_AUTOIP */ + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while(netif != NULL); + } + +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + * + * If you want to accept private broadcast communication while a netif is down, + * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: + * + * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", + ntohs(udphdr->dest))); + if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ + if (check_ip_src && !ip_addr_isany(¤t_iphdr_src)) +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + { if ((ip_addr_isbroadcast(¤t_iphdr_src, inp)) || + (ip_addr_ismulticast(¤t_iphdr_src))) { + /* packet source is not valid */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n")); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.drop); + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + return ERR_OK; + } + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n")); +#if IP_FORWARD + /* non-broadcast packet? */ + if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp)) { + /* try to forward IP packet on (other) interfaces */ + ip_forward(p, iphdr, inp); + } else +#endif /* IP_FORWARD */ + { + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + } + pbuf_free(p); + return ERR_OK; + } + /* packet consists of multiple fragments? */ + if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n", + ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); + /* reassemble the packet*/ + p = ip_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + return ERR_OK; + } + iphdr = (struct ip_hdr *)p->payload; +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + ntohs(IPH_OFFSET(iphdr)))); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; +#endif /* IP_REASSEMBLY */ + } + +#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ + +#if LWIP_IGMP + /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ + if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { +#else + if (iphdr_hlen > IP_HLEN) { +#endif /* LWIP_IGMP */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); + pbuf_free(p); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; + } +#endif /* IP_OPTIONS_ALLOWED == 0 */ + + /* send to upper layers */ + LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); + ip_debug_print(p); + LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + current_netif = inp; + current_header = iphdr; + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP + case IP_PROTO_UDP: +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif /* LWIP_UDPLITE */ + snmp_inc_ipindelivers(); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP_PROTO_TCP: + snmp_inc_ipindelivers(); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP + case IP_PROTO_ICMP: + snmp_inc_ipindelivers(); + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ +#if LWIP_IGMP + case IP_PROTO_IGMP: + igmp_input(p, inp, ¤t_iphdr_dest); + break; +#endif /* LWIP_IGMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable unless is was a broadcast */ + if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp) && + !ip_addr_ismulticast(¤t_iphdr_dest)) { + p->payload = iphdr; + icmp_dest_unreach(p, ICMP_DUR_PROTO); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinunknownprotos(); + } + } + + current_netif = NULL; + current_header = NULL; + ip_addr_set_any(¤t_iphdr_src); + ip_addr_set_any(¤t_iphdr_dest); + + return ERR_OK; +} + +/** + * Sends an IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. If the source + * IP address is NULL, the IP address of the outgoing network + * interface is filled in as source address. + * If the destination IP address is IP_HDRINCL, p is assumed to already + * include an IP header and p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + * + * @note ip_id: RFC791 "some host may be able to simply use + * unique identifiers independent of destination" + */ +err_t +ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if() but with the possibility to include IP options: + * + * @ param ip_options pointer to the IP options, copied into the IP header + * @ param optlen length of ip_options + */ +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + struct ip_hdr *iphdr; + ip_addr_t dest_addr; +#if CHECKSUM_GEN_IP_INLINE + u32_t chk_sum = 0; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + snmp_inc_ipoutrequests(); + + /* Should the IP header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + u16_t ip_hlen = IP_HLEN; +#if IP_OPTIONS_SEND + u16_t optlen_aligned = 0; + if (optlen != 0) { +#if CHECKSUM_GEN_IP_INLINE + int i; +#endif /* CHECKSUM_GEN_IP_INLINE */ + /* round up to a multiple of 4 */ + optlen_aligned = ((optlen + 3) & ~3); + ip_hlen += optlen_aligned; + /* First write in the IP options */ + if (pbuf_header(p, optlen_aligned)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + MEMCPY(p->payload, ip_options, optlen); + if (optlen < optlen_aligned) { + /* zero the remaining bytes */ + memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + } +#if CHECKSUM_GEN_IP_INLINE + for (i = 0; i < optlen_aligned/2; i++) { + chk_sum += ((u16_t*)p->payload)[i]; + } +#endif /* CHECKSUM_GEN_IP_INLINE */ + } +#endif /* IP_OPTIONS_SEND */ + /* generate IP header */ + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); + + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + + iphdr = (struct ip_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", + (p->len >= sizeof(struct ip_hdr))); + + IPH_TTL_SET(iphdr, ttl); + IPH_PROTO_SET(iphdr, proto); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(proto, ttl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* dest cannot be NULL here */ + ip_addr_copy(iphdr->dest, *dest); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + IPH_VHL_SET(iphdr, 4, ip_hlen / 4); + IPH_TOS_SET(iphdr, tos); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_LEN_SET(iphdr, htons(p->tot_len)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_len; +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_OFFSET_SET(iphdr, 0); + IPH_ID_SET(iphdr, htons(ip_id)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_id; +#endif /* CHECKSUM_GEN_IP_INLINE */ + ++ip_id; + + if (ip_addr_isany(src)) { + ip_addr_copy(iphdr->src, netif->ip_addr); + } else { + /* src cannot be NULL here */ + ip_addr_copy(iphdr->src, *src); + } + +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; + chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); + chk_sum = (chk_sum >> 16) + chk_sum; + chk_sum = ~chk_sum; + iphdr->_chksum = chk_sum; /* network order */ +#else /* CHECKSUM_GEN_IP_INLINE */ + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); +#endif +#endif /* CHECKSUM_GEN_IP_INLINE */ + } else { + /* IP header already included in p */ + iphdr = (struct ip_hdr *)p->payload; + ip_addr_copy(dest_addr, iphdr->dest); + dest = &dest_addr; + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip_debug_print(p); + +#if ENABLE_LOOPBACK + if (ip_addr_cmp(dest, &netif->ip_addr)) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); + return netif_loop_output(netif, p, dest); + } +#if LWIP_IGMP + if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { + netif_loop_output(netif, p, dest); + } +#endif /* LWIP_IGMP */ +#endif /* ENABLE_LOOPBACK */ +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + return ip_frag(p, netif, dest); + } +#endif /* IP_FRAG */ + + LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); + return netif->output(netif, p, dest); +} + +/** + * Simple interface to ip_output_if. It finds the outgoing network + * interface and calls upon ip_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto) +{ + struct netif *netif; + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip_output_if(p, src, dest, ttl, tos, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip_output_if(p, src, dest, ttl, tos, proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +/* Print an IP header by using LWIP_DEBUGF + * @param p an IP packet, p->payload pointing to the IP header + */ +void +ip_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", + IPH_V(iphdr), + IPH_HL(iphdr), + IPH_TOS(iphdr), + ntohs(IPH_LEN(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", + ntohs(IPH_ID(iphdr)), + ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, + ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", + IPH_TTL(iphdr), + IPH_PROTO(iphdr), + ntohs(IPH_CHKSUM(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1_16(&iphdr->src), + ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), + ip4_addr4_16(&iphdr->src))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1_16(&iphdr->dest), + ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), + ip4_addr4_16(&iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ diff --git a/ext/lwip/src/core/ipv4/ip_addr.c b/ext/lwip/src/core/ipv4/ip_addr.c new file mode 100644 index 000000000..8f633ff23 --- /dev/null +++ b/ext/lwip/src/core/ipv4/ip_addr.c @@ -0,0 +1,312 @@ +/** + * @file + * This is the IPv4 address tools implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +const ip_addr_t ip_addr_any = { IPADDR_ANY }; +const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; + +/** + * Determine if an address is a broadcast address on a network interface + * + * @param addr address to be checked + * @param netif the network interface against which the address is checked + * @return returns non-zero if the address is a broadcast address + */ +u8_t +ip4_addr_isbroadcast(u32_t addr, const struct netif *netif) +{ + ip_addr_t ipaddr; + ip4_addr_set_u32(&ipaddr, addr); + + /* all ones (broadcast) or all zeroes (old skool broadcast) */ + if ((~addr == IPADDR_ANY) || + (addr == IPADDR_ANY)) { + return 1; + /* no broadcast support on this network interface? */ + } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { + /* the given address cannot be a broadcast address + * nor can we check against any broadcast addresses */ + return 0; + /* address matches network interface address exactly? => no broadcast */ + } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) { + return 0; + /* on the same (sub) network... */ + } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr & ~ip4_addr_get_u32(&netif->netmask)) == + (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) { + /* => network broadcast address */ + return 1; + } else { + return 0; + } +} + +/** Checks if a netmask is valid (starting with ones, then only zeros) + * + * @param netmask the IPv4 netmask to check (in network byte order!) + * @return 1 if the netmask is valid, 0 if it is not + */ +u8_t +ip4_addr_netmask_valid(u32_t netmask) +{ + u32_t mask; + u32_t nm_hostorder = lwip_htonl(netmask); + + /* first, check for the first zero */ + for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) == 0) { + break; + } + } + /* then check that there is no one */ + for (; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) != 0) { + /* there is a one after the first zero -> invalid */ + return 0; + } + } + /* no one after the first zero -> valid */ + return 1; +} + +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IP address in ascii represenation (e.g. "127.0.0.1") + * @return ip address in network order + */ +u32_t +ipaddr_addr(const char *cp) +{ + ip_addr_t val; + + if (ipaddr_aton(cp, &val)) { + return ip4_addr_get_u32(&val); + } + return (IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + * + * @param cp IP address in ascii represenation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ipaddr_aton(const char *cp, ip_addr_t *addr) +{ + u32_t val; + u8_t base; + char c; + u32_t parts[4]; + u32_t *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; + base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') { + base = 16; + c = *++cp; + } else + base = 8; + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (int)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) { + return (0); + } + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) { + return (0); + } + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) { + return (0); + } + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) { + return (0); + } + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) { + return (0); + } + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + LWIP_ASSERT("unhandled", 0); + break; + } + if (addr) { + ip4_addr_set_u32(addr, htonl(val)); + } + return (1); +} + +/** + * Convert numeric IP address into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * represenation of addr + */ +char * +ipaddr_ntoa(const ip_addr_t *addr) +{ + static char str[16]; + return ipaddr_ntoa_r(addr, str, 16); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen) +{ + u32_t s_addr; + char inv[3]; + char *rp; + u8_t *ap; + u8_t rem; + u8_t n; + u8_t i; + int len = 0; + + s_addr = ip4_addr_get_u32(addr); + + rp = buf; + ap = (u8_t *)&s_addr; + for(n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (u8_t)10; + *ap /= (u8_t)10; + inv[i++] = '0' + rem; + } while(*ap); + while(i--) { + if (len++ >= buflen) { + return NULL; + } + *rp++ = inv[i]; + } + if (len++ >= buflen) { + return NULL; + } + *rp++ = '.'; + ap++; + } + *--rp = 0; + return buf; +} diff --git a/ext/lwip/src/core/ipv4/ip_frag.c b/ext/lwip/src/core/ipv4/ip_frag.c new file mode 100644 index 000000000..8d184345d --- /dev/null +++ b/ext/lwip/src/core/ipv4/ip_frag.c @@ -0,0 +1,863 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_frag.h" +#include "lwip/def.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + snmp_inc_ipreasmfails(); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reass struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param root_p points to the 'root' pbuf for the current datagram being assembled. + * @param new_p points to the pbuf for the current fragment + * @return 0 if invalid, >0 otherwise + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset,len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + } else { + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if(iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if(iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no wholes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { + /* and had no wholes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if (((struct ip_reass_helper*)ipr->p->payload)->start != 0) { + valid = 0; + } else { + /* and check that there are no wholes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + LWIP_ASSERT("validate_datagram:datagram end!=datagram len", + iprh->end == ipr->datagram_len); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid; + } + /* If we come here, not all fragments were received, yet! */ + return 0; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return 0; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len; + u8_t clen; + struct ip_reassdata *ipr_prev = NULL; + + IPFRAG_STATS_INC(ip_frag.recv); + snmp_inc_ipreasmreqds(); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n", + ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if(ipr == NULL) { + goto nullreturn; + } + } else { + if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip_reass_pbufcount += clen; + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + ipr->datagram_len = offset + len; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set calculate the correct checksum? */ + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while(r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if IP_FRAG_USES_STATIC_BUF +static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; +#else /* IP_FRAG_USES_STATIC_BUF */ + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by using a fixed size static memory buffer (PBUF_REF) or + * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest) +{ + struct pbuf *rambuf; +#if IP_FRAG_USES_STATIC_BUF + struct pbuf *header; +#else +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; +#endif + struct ip_hdr *original_iphdr; +#endif + struct ip_hdr *iphdr; + u16_t nfb; + u16_t left, cop; + u16_t mtu = netif->mtu; + u16_t ofo, omf; + u16_t last; + u16_t poff = IP_HLEN; + u16_t tmp; +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + + /* Get a RAM based MTU sized pbuf */ +#if IP_FRAG_USES_STATIC_BUF + /* When using a static buffer, we use a PBUF_REF, which we will + * use to reference the packet (without link header). + * Layer and length is irrelevant. + */ + rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); + if (rambuf == NULL) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); + return ERR_MEM; + } + rambuf->tot_len = rambuf->len = mtu; + rambuf->payload = LWIP_MEM_ALIGN((void *)buf); + + /* Copy the IP header in it */ + iphdr = (struct ip_hdr *)rambuf->payload; + SMEMCPY(iphdr, p->payload, IP_HLEN); +#else /* IP_FRAG_USES_STATIC_BUF */ + original_iphdr = (struct ip_hdr *)p->payload; + iphdr = original_iphdr; +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Save original offset */ + tmp = ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + omf = tmp & IP_MF; + + left = p->tot_len - IP_HLEN; + + nfb = (mtu - IP_HLEN) / 8; + + while (left) { + last = (left <= mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = omf | (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + + /* Fill this fragment */ + cop = last ? left : nfb * 8; + +#if IP_FRAG_USES_STATIC_BUF + poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); +#else /* IP_FRAG_USES_STATIC_BUF */ +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); + /* make room for the IP header */ + if(pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr *)rambuf->payload; + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Correct header */ + IPH_OFFSET_SET(iphdr, htons(tmp)); + IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + +#if IP_FRAG_USES_STATIC_BUF + if (last) { + pbuf_realloc(rambuf, left + IP_HLEN); + } + + /* This part is ugly: we alloc a RAM based pbuf for + * the link level header for each chunk and then + * free it.A PBUF_ROM style pbuf for which pbuf_header + * worked would make things simpler. + */ + header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); + if (header != NULL) { + pbuf_chain(header, rambuf); + netif->output(netif, header, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + snmp_inc_ipfragcreates(); + pbuf_free(header); + } else { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); + pbuf_free(rambuf); + return ERR_MEM; + } +#else /* IP_FRAG_USES_STATIC_BUF */ + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + left -= cop; + ofo += nfb; + } +#if IP_FRAG_USES_STATIC_BUF + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + snmp_inc_ipfragoks(); + return ERR_OK; +} +#endif /* IP_FRAG */ diff --git a/ext/lwip/src/core/ipv6/README b/ext/lwip/src/core/ipv6/README new file mode 100644 index 000000000..362000486 --- /dev/null +++ b/ext/lwip/src/core/ipv6/README @@ -0,0 +1 @@ +IPv6 support in lwIP is very experimental. diff --git a/ext/lwip/src/core/ipv6/icmp6.c b/ext/lwip/src/core/ipv6/icmp6.c new file mode 100644 index 000000000..4fcc89551 --- /dev/null +++ b/ext/lwip/src/core/ipv6/icmp6.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" + +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; + struct icmp_echo_hdr *iecho; + struct ip_hdr *iphdr; + struct ip_addr tmpaddr; + + ICMP_STATS_INC(icmp.recv); + + /* TODO: check length before accessing payload! */ + + type = ((u8_t *)p->payload)[0]; + + switch (type) { + case ICMP6_ECHO: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + return; + } + iecho = p->payload; + iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN); + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len))); + ICMP_STATS_INC(icmp.chkerr); + /* return;*/ + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len)); + ip_addr_set(&tmpaddr, &(iphdr->src)); + ip_addr_set(&(iphdr->src), &(iphdr->dest)); + ip_addr_set(&(iphdr->dest), &tmpaddr); + iecho->type = ICMP6_ER; + /* adjust the checksum */ + if (iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) { + iecho->chksum += htons(ICMP6_ECHO << 8) + 1; + } else { + iecho->chksum += htons(ICMP6_ECHO << 8); + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len))); + ICMP_STATS_INC(icmp.xmit); + + /* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/ + ip_output_if (p, &(iphdr->src), IP_HDRINCL, + iphdr->hoplim, IP_PROTO_ICMP, inp); + break; + default: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + + pbuf_free(p); +} + +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + struct icmp_dur_hdr *idur; + + /* @todo: can this be PBUF_LINK instead of PBUF_IP? */ + q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM); + /* ICMP header + IP header + 8 bytes of data */ + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n")); + pbuf_free(p); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (8 + IP_HLEN + 8))); + + iphdr = p->payload; + + idur = q->payload; + idur->type = (u8_t)ICMP6_DUR; + idur->icode = (u8_t)t; + + SMEMCPY((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8); + + /* calculate checksum */ + idur->chksum = 0; + idur->chksum = inet_chksum(idur, q->len); + ICMP_STATS_INC(icmp.xmit); + + ip_output(q, NULL, + (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP); + pbuf_free(q); +} + +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + struct icmp_te_hdr *tehdr; + + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n")); + + /* @todo: can this be PBUF_LINK instead of PBUF_IP? */ + q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM); + /* ICMP header + IP header + 8 bytes of data */ + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n")); + pbuf_free(p); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (8 + IP_HLEN + 8))); + + iphdr = p->payload; + + tehdr = q->payload; + tehdr->type = (u8_t)ICMP6_TE; + tehdr->icode = (u8_t)t; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8); + + /* calculate checksum */ + tehdr->chksum = 0; + tehdr->chksum = inet_chksum(tehdr, q->len); + ICMP_STATS_INC(icmp.xmit); + ip_output(q, NULL, + (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP); + pbuf_free(q); +} + +#endif /* LWIP_ICMP */ diff --git a/ext/lwip/src/core/ipv6/inet6.c b/ext/lwip/src/core/ipv6/inet6.c new file mode 100644 index 000000000..c3de85c09 --- /dev/null +++ b/ext/lwip/src/core/ipv6/inet6.c @@ -0,0 +1,163 @@ +/** + * @file + * Functions common to all TCP/IPv6 modules, such as the Internet checksum and the + * byte order functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/inet.h" + +/* chksum: + * + * Sums up all 16 bit words in a memory portion. Also includes any odd byte. + * This function is used by the other checksum functions. + * + * For now, this is not optimized. Must be optimized for the particular processor + * arcitecture on which it is to run. Preferebly coded in assembler. + */ + +static u32_t +chksum(void *dataptr, u16_t len) +{ + u16_t *sdataptr = dataptr; + u32_t acc; + + + for(acc = 0; len > 1; len -= 2) { + acc += *sdataptr++; + } + + /* add up any odd byte */ + if (len == 1) { + acc += htons((u16_t)(*(u8_t *)dataptr) << 8); + } + + return acc; + +} + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + */ + +u16_t +inet_chksum_pseudo(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u32_t proto_len) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped, i; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += chksum(q->payload, q->len); + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + } + + if (swapped) { + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + + for(i = 0; i < 8; i++) { + acc += ((u16_t *)src->addr)[i] & 0xffff; + acc += ((u16_t *)dest->addr)[i] & 0xffff; + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + } + acc += (u16_t)htons((u16_t)proto); + acc += ((u16_t *)&proto_len)[0] & 0xffff; + acc += ((u16_t *)&proto_len)[1] & 0xffff; + + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + return ~(acc & 0xffff); +} + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarely for IP + * and ICMP. + */ + +u16_t +inet_chksum(void *dataptr, u16_t len) +{ + u32_t acc, sum; + + acc = chksum(dataptr, len); + sum = (acc & 0xffff) + (acc >> 16); + sum += (sum >> 16); + return ~(sum & 0xffff); +} + +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += chksum(q->payload, q->len); + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8); + } + } + + if (swapped) { + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + return ~(acc & 0xffff); +} diff --git a/ext/lwip/src/core/ipv6/ip6.c b/ext/lwip/src/core/ipv6/ip6.c new file mode 100644 index 000000000..ad59b725c --- /dev/null +++ b/ext/lwip/src/core/ipv6/ip6.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + + +/* ip.c + * + * This is the code for the IP layer for IPv6. + * + */ + + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" + +#include "lwip/stats.h" + +#include "arch/perf.h" + +/* ip_init: + * + * Initializes the IP layer. + */ + +void +ip_init(void) +{ +} + +/* ip_route: + * + * Finds the appropriate network interface for a given IP address. It searches the + * list of network interfaces linearly. A match is found if the masked IP address of + * the network interface equals the masked IP address given to the function. + */ + +struct netif * +ip_route(struct ip_addr *dest) +{ + struct netif *netif; + + for(netif = netif_list; netif != NULL; netif = netif->next) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + return netif; + } + } + + return netif_default; +} + +/* ip_forward: + * + * Forwards an IP packet. It finds an appropriate route for the packet, decrements + * the TTL value of the packet, adjusts the checksum and outputs the packet on the + * appropriate interface. + */ + +static void +ip_forward(struct pbuf *p, struct ip_hdr *iphdr) +{ + struct netif *netif; + + PERF_START; + + if ((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) { + + LWIP_DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for ")); +#if IP_DEBUG + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); +#endif /* IP_DEBUG */ + LWIP_DEBUGF(IP_DEBUG, ("\n")); + pbuf_free(p); + return; + } + /* Decrement TTL and send ICMP if ttl == 0. */ + if (--iphdr->hoplim == 0) { +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (iphdr->nexthdr != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + return; + } + + /* Incremental update of the IP checksum. */ + /* if (iphdr->chksum >= htons(0xffff - 0x100)) { + iphdr->chksum += htons(0x100) + 1; + } else { + iphdr->chksum += htons(0x100); + }*/ + + + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to ")); +#if IP_DEBUG + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); +#endif /* IP_DEBUG */ + LWIP_DEBUGF(IP_DEBUG, ("\n")); + + IP_STATS_INC(ip.fw); + IP_STATS_INC(ip.xmit); + + PERF_STOP("ip_forward"); + + netif->output(netif, p, (struct ip_addr *)&(iphdr->dest)); +} + +/* ip_input: + * + * This function is called by the network interface device driver when an IP packet is + * received. The function does the basic checks of the IP header such as packet size + * being at least larger than the header size etc. If the packet was not destined for + * us, the packet is forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + */ + +void +ip_input(struct pbuf *p, struct netif *inp) { + struct ip_hdr *iphdr; + struct netif *netif; + + + PERF_START; + +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + + + IP_STATS_INC(ip.recv); + + /* identify the IP header */ + iphdr = p->payload; + + + if (iphdr->v != 6) { + LWIP_DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n")); +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + return; + } + + /* is this packet for us? */ + for(netif = netif_list; netif != NULL; netif = netif->next) { +#if IP_DEBUG + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest ")); + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr ")); + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("\n")); +#endif /* IP_DEBUG */ + if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) { + break; + } + } + + + if (netif == NULL) { + /* packet not for us, route or discard */ +#if IP_FORWARD + ip_forward(p, iphdr); +#endif + pbuf_free(p); + return; + } + + pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len)); + + /* send to upper layers */ +#if IP_DEBUG + /* LWIP_DEBUGF("ip_input: \n"); + ip_debug_print(p); + LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/ +#endif /* IP_DEBUG */ + + if(pbuf_header(p, -IP_HLEN)) { + LWIP_ASSERT("Can't move over header in packet", 0); + return; + } + + switch (iphdr->nexthdr) { + case IP_PROTO_UDP: + udp_input(p, inp); + break; + case IP_PROTO_TCP: + tcp_input(p, inp); + break; +#if LWIP_ICMP + case IP_PROTO_ICMP: + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable */ + icmp_dest_unreach(p, ICMP_DUR_PROTO); +#endif /* LWIP_ICMP */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n", + iphdr->nexthdr)); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + } + PERF_STOP("ip_input"); +} + + +/* ip_output_if: + * + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + */ + +err_t +ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, + u8_t proto, struct netif *netif) +{ + struct ip_hdr *iphdr; + + PERF_START; + + LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len)); + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n")); + IP_STATS_INC(ip.err); + + return ERR_BUF; + } + LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len)); + + iphdr = p->payload; + + + if (dest != IP_HDRINCL) { + LWIP_DEBUGF(IP_DEBUG, ("!IP_HDRLINCL\n")); + iphdr->hoplim = ttl; + iphdr->nexthdr = proto; + iphdr->len = htons(p->tot_len - IP_HLEN); + ip_addr_set(&(iphdr->dest), dest); + + iphdr->v = 6; + + if (ip_addr_isany(src)) { + ip_addr_set(&(iphdr->src), &(netif->ip_addr)); + } else { + ip_addr_set(&(iphdr->src), src); + } + + } else { + dest = &(iphdr->dest); + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len)); +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + + PERF_STOP("ip_output_if"); + return netif->output(netif, p, dest); +} + +/* ip_output: + * + * Simple interface to ip_output_if. It finds the outgoing network interface and + * calls upon ip_output_if to do the actual work. + */ + +err_t +ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto) +{ + struct netif *netif; + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip_output_if (p, src, dest, ttl, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +err_t +ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + LWIP_NETIF_HWADDRHINT(netif, addr_hint); + err = ip_output_if(p, src, dest, ttl, tos, proto, netif); + LWIP_NETIF_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +void +ip_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" | %"X16_F"%"X16_F" | %"X16_F"%"X16_F" | (v, traffic class, flow label)\n", + iphdr->v, + iphdr->tclass1, iphdr->tclass2, + iphdr->flow1, iphdr->flow2)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" | %2"U16_F" | %2"U16_F" | (len, nexthdr, hoplim)\n", + ntohs(iphdr->len), + iphdr->nexthdr, + iphdr->hoplim)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[0]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[0]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[1]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[1]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[2]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[2]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[3]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[3]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[0]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[0]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[1]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[1]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[2]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[2]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[3]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[3]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ diff --git a/ext/lwip/src/core/ipv6/ip6_addr.c b/ext/lwip/src/core/ipv6/ip6_addr.c new file mode 100644 index 000000000..2da6cea42 --- /dev/null +++ b/ext/lwip/src/core/ipv6/ip6_addr.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +u8_t +ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2, + struct ip_addr *mask) +{ + return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) && + (addr1->addr[1] & mask->addr[1]) == (addr2->addr[1] & mask->addr[1]) && + (addr1->addr[2] & mask->addr[2]) == (addr2->addr[2] & mask->addr[2]) && + (addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3])); + +} + +u8_t +ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2) +{ + return(addr1->addr[0] == addr2->addr[0] && + addr1->addr[1] == addr2->addr[1] && + addr1->addr[2] == addr2->addr[2] && + addr1->addr[3] == addr2->addr[3]); +} + +void +ip_addr_set(struct ip_addr *dest, struct ip_addr *src) +{ + SMEMCPY(dest, src, sizeof(struct ip_addr)); + /* dest->addr[0] = src->addr[0]; + dest->addr[1] = src->addr[1]; + dest->addr[2] = src->addr[2]; + dest->addr[3] = src->addr[3];*/ +} + +u8_t +ip_addr_isany(struct ip_addr *addr) +{ + if (addr == NULL) return 1; + return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0); +} diff --git a/ext/lwip/src/core/mem.c b/ext/lwip/src/core/mem.c new file mode 100644 index 000000000..f1bb3595d --- /dev/null +++ b/ext/lwip/src/core/mem.c @@ -0,0 +1,675 @@ +/** + * @file + * Dynamic memory manager + * + * This is a lightweight replacement for the standard C library malloc(). + * + * If you want to use the standard C library malloc() instead, define + * MEM_LIBC_MALLOC to 1 in your lwipopts.h + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/err.h" + +#include + +#if MEM_USE_POOLS +/* lwIP head implemented with different sized pools */ + +/** + * Allocate memory: determine the smallest pool that is big enough + * to contain an element of 'size' and get an element from that pool. + * + * @param size the size in bytes of the memory needed + * @return a pointer to the allocated memory or NULL if the pool is empty + */ +void * +mem_malloc(mem_size_t size) +{ + void *ret; + struct memp_malloc_helper *element; + memp_t poolnr; + mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { +#if MEM_USE_POOLS_TRY_BIGGER_POOL +again: +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + /* is this pool big enough to hold an element of the required size + plus a struct memp_malloc_helper that saves the pool this element came from? */ + if (required_size <= memp_sizes[poolnr]) { + break; + } + } + if (poolnr > MEMP_POOL_LAST) { + LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); + return NULL; + } + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already + taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + poolnr++; + goto again; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + return NULL; + } + + /* save the pool number this element came from */ + element->poolnr = poolnr; + /* and return a pointer to the memory directly after the struct memp_malloc_helper */ + ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + return ret; +} + +/** + * Free memory previously allocated by mem_malloc. Loads the pool number + * and calls memp_free with that pool number to put the element back into + * its pool + * + * @param rmem the memory element to free + */ +void +mem_free(void *rmem) +{ + struct memp_malloc_helper *hmem; + + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); + + /* get the original struct memp_malloc_helper */ + hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); + + LWIP_ASSERT("hmem != NULL", (hmem != NULL)); + LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); + LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); + + /* and put it in the pool we saved earlier */ + memp_free(hmem->poolnr, hmem); +} + +#else /* MEM_USE_POOLS */ +/* lwIP replacement for your libc malloc() */ + +/** + * The heap is made up as a list of structs of this type. + * This does not have to be aligned since for getting its size, + * we only use the macro SIZEOF_STRUCT_MEM, which automatically alignes. + */ +struct mem { + /** index (-> ram[next]) of the next struct */ + mem_size_t next; + /** index (-> ram[prev]) of the previous struct */ + mem_size_t prev; + /** 1: this area is used; 0: this area is unused */ + u8_t used; +}; + +/** All allocated blocks will be MIN_SIZE bytes big, at least! + * MIN_SIZE can be overridden to suit your needs. Smaller values save space, + * larger values could prevent too small blocks to fragment the RAM too much. */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif /* MIN_SIZE */ +/* some alignment macros: we define them here for better source code layout */ +#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) +#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) +#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) + +/** If you want to relocate the heap to external memory, simply define + * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. + * If so, make sure the memory at that location is big enough (see below on + * how that space is calculated). */ +#ifndef LWIP_RAM_HEAP_POINTER +/** the heap. we need one struct mem at the end and some room for alignment */ +u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT]; +#define LWIP_RAM_HEAP_POINTER ram_heap +#endif /* LWIP_RAM_HEAP_POINTER */ + +/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ +static u8_t *ram; +/** the last entry, always unused! */ +static struct mem *ram_end; +/** pointer to the lowest free block, this is used for faster search */ +static struct mem *lfree; + +/** concurrent access protection */ +#if !NO_SYS +static sys_mutex_t mem_mutex; +#endif + +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + +static volatile u8_t mem_free_count; + +/* Allow mem_free from other (e.g. interrupt) context */ +#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) +#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) +#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) +#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) + +#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +/* Protect the heap only by using a semaphore */ +#define LWIP_MEM_FREE_DECL_PROTECT() +#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) +#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) +/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ +#define LWIP_MEM_ALLOC_DECL_PROTECT() +#define LWIP_MEM_ALLOC_PROTECT() +#define LWIP_MEM_ALLOC_UNPROTECT() + +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + +/** + * "Plug holes" by combining adjacent empty struct mems. + * After this function is through, there should not exist + * one empty struct mem pointing to another empty struct mem. + * + * @param mem this points to a struct mem which just has been freed + * @internal this function is only called by mem_free() and mem_trim() + * + * This assumes access to the heap is protected by the calling function + * already. + */ +static void +plug_holes(struct mem *mem) +{ + struct mem *nmem; + struct mem *pmem; + + LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); + LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); + LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); + + /* plug hole forward */ + LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); + + nmem = (struct mem *)(void *)&ram[mem->next]; + if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { + /* if mem->next is unused and not end of ram, combine mem and mem->next */ + if (lfree == nmem) { + lfree = mem; + } + mem->next = nmem->next; + ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); + } + + /* plug hole backward */ + pmem = (struct mem *)(void *)&ram[mem->prev]; + if (pmem != mem && pmem->used == 0) { + /* if mem->prev is unused, combine mem and mem->prev */ + if (lfree == mem) { + lfree = pmem; + } + pmem->next = mem->next; + ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); + } +} + +/** + * Zero the heap and initialize start, end and lowest-free + */ +void +mem_init(void) +{ + struct mem *mem; + + LWIP_ASSERT("Sanity check alignment", + (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); + + /* align the heap */ + ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); + /* initialize the start of the heap */ + mem = (struct mem *)(void *)ram; + mem->next = MEM_SIZE_ALIGNED; + mem->prev = 0; + mem->used = 0; + /* initialize the end of the heap */ + ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; + ram_end->used = 1; + ram_end->next = MEM_SIZE_ALIGNED; + ram_end->prev = MEM_SIZE_ALIGNED; + + /* initialize the lowest-free pointer to the start of the heap */ + lfree = (struct mem *)(void *)ram; + + MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); + + if(sys_mutex_new(&mem_mutex) != ERR_OK) { + LWIP_ASSERT("failed to create mem_mutex", 0); + } +} + +/** + * Put a struct mem back on the heap + * + * @param rmem is the data portion of a struct mem as returned by a previous + * call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + struct mem *mem; + LWIP_MEM_FREE_DECL_PROTECT(); + + if (rmem == NULL) { + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); + return; + } + LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); + + LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return; + } + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... which has to be in a used state ... */ + LWIP_ASSERT("mem_free: mem->used", mem->used); + /* ... and is now unused. */ + mem->used = 0; + + if (mem < lfree) { + /* the newly freed struct is now the lowest */ + lfree = mem; + } + + MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); + + /* finally, see if prev or next are free also */ + plug_holes(mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); +} + +/** + * Shrink memory returned by mem_malloc(). + * + * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param newsize required size after shrinking (needs to be smaller than or + * equal to the previous size) + * @return for compatibility reasons: is always == rmem, at the moment + * or NULL if newsize is > old size, in which case rmem is NOT touched + * or freed! + */ +void * +mem_trim(void *rmem, mem_size_t newsize) +{ + mem_size_t size; + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; + /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ + LWIP_MEM_FREE_DECL_PROTECT(); + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + newsize = LWIP_MEM_ALIGN_SIZE(newsize); + + if(newsize < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + newsize = MIN_SIZE_ALIGNED; + } + + if (newsize > MEM_SIZE_ALIGNED) { + return NULL; + } + + LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return rmem; + } + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... and its offset pointer */ + ptr = (mem_size_t)((u8_t *)mem - ram); + + size = mem->next - ptr - SIZEOF_STRUCT_MEM; + LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); + if (newsize > size) { + /* not supported */ + return NULL; + } + if (newsize == size) { + /* No change in size, simply return */ + return rmem; + } + + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + + mem2 = (struct mem *)(void *)&ram[mem->next]; + if(mem2->used == 0) { + /* The next struct is unused, we can simply move it at little */ + mem_size_t next; + /* remember the old next pointer */ + next = mem2->next; + /* create new struct mem which is moved directly after the shrinked mem */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + if (lfree == mem2) { + lfree = (struct mem *)(void *)&ram[ptr2]; + } + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + /* restore the next pointer */ + mem2->next = next; + /* link it back to mem */ + mem2->prev = ptr; + /* link mem to it */ + mem->next = ptr2; + /* last thing to restore linked list: as we have moved mem2, + * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not + * the end of the heap */ + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* no need to plug holes, we've already done that */ + } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { + /* Next struct is used but there's room for another struct mem with + * at least MIN_SIZE_ALIGNED of data. + * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem + * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + mem2 = (struct mem *)(void *)&ram[ptr2]; + if (mem2 < lfree) { + lfree = mem2; + } + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + mem->next = ptr2; + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* the original mem->next is used, so no need to plug holes! */ + } + /* else { + next struct mem is used but size between mem and mem2 is not big enough + to create another struct mem + -> don't do anyhting. + -> the remaining space stays unused since it is too small + } */ +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); + return rmem; +} + +/** + * Adam's mem_malloc() plus solution for bug #17922 + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). + */ + #include + +void * +mem_malloc(mem_size_t size) +{ + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + u8_t local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_ALLOC_DECL_PROTECT(); + + if (size == 0) { + return NULL; + } + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + size = LWIP_MEM_ALIGN_SIZE(size); + + if(size < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + size = MIN_SIZE_ALIGNED; + } + + if (size > MEM_SIZE_ALIGNED) { + return NULL; + } + + /* protect the heap from concurrent access */ + sys_mutex_lock(&mem_mutex); + LWIP_MEM_ALLOC_PROTECT(); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* run as long as a mem_free disturbed mem_malloc or mem_trim */ + do { + local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + /* Scan through the heap searching for a free block that is big enough, + * beginning with the lowest free block. + */ + printf("ptr = (mem_size_t)((u8_t *)lfree - ram) = %d\n", (mem_size_t)((u8_t *)lfree - ram)); + printf("MEM_SIZE_ALIGNED - size = %d\n", MEM_SIZE_ALIGNED - size); + //printf("\n", ); + + for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; + ptr = ((struct mem *)(void *)&ram[ptr])->next) { + +printf("ptr = 0x%x\n", ptr); + mem = (struct mem *)(void *)&ram[ptr]; + printf("mem = 0x%x\n", mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + printf("A\n"); + LWIP_MEM_ALLOC_UNPROTECT(); + /* allow mem_free or mem_trim to run */ + printf("B\n"); + LWIP_MEM_ALLOC_PROTECT(); + printf("C\n"); + if (mem_free_count != 0) { + printf("mem_free_count != 0\n"); + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem. */ + local_mem_free_count = 1; + break; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +if(mem == NULL) + printf("mem == NULL\n"); + + if ((!mem->used) && + (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { + /* mem is not used and at least perfect fit is possible: + * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ + + if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { + /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing + * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') + * -> split large block, create empty remainder, + * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if + * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, + * struct mem would fit in but no data between mem2 and mem2->next + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory + */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + size; + /* create mem2 struct */ + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + /* and insert it between mem and mem->next */ + mem->next = ptr2; + mem->used = 1; + + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); + } else { + /* (a mem2 struct does no fit into the user data space of mem and mem->next will always + * be used at this point: if not we have 2 unused structs in a row, plug_holes should have + * take care of this). + * -> near fit or excact fit: do not split, no mem2 creation + * also can't move mem->next directly behind mem, since mem->next + * will always be used at this point! + */ + mem->used = 1; + MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +mem_malloc_adjust_lfree: +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + if (mem == lfree) { + struct mem *cur = lfree; + /* Find next free block after mem and update lowest free pointer */ + while (cur->used && cur != ram_end) { +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* prevent high interrupt latency... */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem or lfree. */ + goto mem_malloc_adjust_lfree; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + cur = (struct mem *)(void *)&ram[cur->next]; + } + lfree = cur; + LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); + } + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", + (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: sanity check alignment", + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + + return (u8_t *)mem + SIZEOF_STRUCT_MEM; + } + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* if we got interrupted by a mem_free, try again */ + } while(local_mem_free_count != 0); +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); + MEM_STATS_INC(err); + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + return NULL; +} + +#endif /* MEM_USE_POOLS */ +/** + * Contiguously allocates enough space for count objects that are size bytes + * of memory each and returns a pointer to the allocated memory. + * + * The allocated memory is filled with bytes of value zero. + * + * @param count number of objects to allocate + * @param size size of the objects to allocate + * @return pointer to allocated memory / NULL pointer if there is an error + */ +void *mem_calloc(mem_size_t count, mem_size_t size) +{ + void *p; + + /* allocate 'count' objects of size 'size' */ + p = mem_malloc(count * size); + if (p) { + /* zero the memory */ + memset(p, 0, count * size); + } + return p; +} + +#endif /* !MEM_LIBC_MALLOC */ diff --git a/ext/lwip/src/core/memp.c b/ext/lwip/src/core/memp.c new file mode 100644 index 000000000..9f680e244 --- /dev/null +++ b/ext/lwip/src/core/memp.c @@ -0,0 +1,470 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "lwip/raw.h" +#include "lwip/tcp_impl.h" +#include "lwip/igmp.h" +#include "lwip/api.h" +#include "lwip/api_msg.h" +#include "lwip/tcpip.h" +#include "lwip/sys.h" +#include "lwip/timers.h" +#include "lwip/stats.h" +#include "netif/etharp.h" +#include "lwip/ip_frag.h" +#include "lwip/snmp_structs.h" +#include "lwip/snmp_msg.h" +#include "lwip/dns.h" +#include "netif/ppp_oe.h" + +#include + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +/** This array holds the first free element of each pool. + * Elements form a linked list. */ +static struct memp *memp_tab[MEMP_MAX]; + +#else /* MEMP_MEM_MALLOC */ + +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_MEM_MALLOC */ + +/** This array holds the element sizes of each pool. */ +#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC +static +#endif +const u16_t memp_sizes[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), +#include "lwip/memp_std.h" +}; + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +/** This array holds the number of elements in each pool. */ +static const u16_t memp_num[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (num), +#include "lwip/memp_std.h" +}; + +/** This array holds a textual description of each pool. */ +#ifdef LWIP_DEBUG +static const char *memp_desc[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (desc), +#include "lwip/memp_std.h" +}; +#endif /* LWIP_DEBUG */ + +#if MEMP_SEPARATE_POOLS + +/** This creates each memory pool. These are named memp_memory_XXX_base (where + * XXX is the name of the pool defined in memp_std.h). + * To relocate a pool, declare it as extern in cc.h. Example for GCC: + * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[]; + */ +#define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ + [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; +#include "lwip/memp_std.h" + +/** This array holds the base of each memory pool. */ +static u8_t *const memp_bases[] = { +#define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base, +#include "lwip/memp_std.h" +}; + +#else /* MEMP_SEPARATE_POOLS */ + +/** This is the actual memory used by the pools (all pools in one big block). */ +static u8_t memp_memory[MEM_ALIGNMENT - 1 +#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) +#include "lwip/memp_std.h" +]; + +#endif /* MEMP_SEPARATE_POOLS */ + +#if MEMP_SANITY_CHECK +/** + * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". + */ +static int +memp_sanity(void) +{ + s16_t i; + struct memp *t, *h; + + for (i = 0; i < MEMP_MAX; i++) { + t = memp_tab[i]; + if(t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) { + if (t == h) { + return 0; + } + } + } + } + return 1; +} +#endif /* MEMP_SANITY_CHECK*/ +#if MEMP_OVERFLOW_CHECK +#if defined(LWIP_DEBUG) && MEMP_STATS +static const char * memp_overflow_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) "/"desc, +#include "lwip/memp_std.h" + }; +#endif + +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type]; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp overflow in pool "; + char digit[] = "0"; + if(memp_type >= 10) { + digit[0] = '0' + (memp_type/10); + strcat(errstr, digit); + } + digit[0] = '0' + (memp_type%10); + strcat(errstr, digit); +#if defined(LWIP_DEBUG) && MEMP_STATS + strcat(errstr, memp_overflow_names[memp_type]); +#endif + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Check if a memp element was victim of an underflow + * (e.g. the restricted area before it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp underflow in pool "; + char digit[] = "0"; + if(memp_type >= 10) { + digit[0] = '0' + (memp_type/10); + strcat(errstr, digit); + } + digit[0] = '0' + (memp_type%10); + strcat(errstr, digit); +#if defined(LWIP_DEBUG) && MEMP_STATS + strcat(errstr, memp_overflow_names[memp_type]); +#endif + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); + for (i = 0; i < MEMP_MAX; ++i) { + p = p; + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element_overflow(p, i); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); + for (i = 0; i < MEMP_MAX; ++i) { + p = p; + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element_underflow(p, i); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} + +/** + * Initialize the restricted areas of all memp elements in every pool. + */ +static void +memp_overflow_init(void) +{ + u16_t i, j; + struct memp *p; + u8_t *m; + + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); + for (i = 0; i < MEMP_MAX; ++i) { + p = p; + for (j = 0; j < memp_num[i]; ++j) { +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} +#endif /* MEMP_OVERFLOW_CHECK */ + +/** + * Initialize this module. + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + struct memp *memp; + u16_t i, j; + + for (i = 0; i < MEMP_MAX; ++i) { + MEMP_STATS_AVAIL(used, i, 0); + MEMP_STATS_AVAIL(max, i, 0); + MEMP_STATS_AVAIL(err, i, 0); + MEMP_STATS_AVAIL(avail, i, memp_num[i]); + } + +#if !MEMP_SEPARATE_POOLS + memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + /* for every pool: */ + for (i = 0; i < MEMP_MAX; ++i) { + memp_tab[i] = NULL; +#if MEMP_SEPARATE_POOLS + memp = (struct memp*)memp_bases[i]; +#endif /* MEMP_SEPARATE_POOLS */ + /* create a linked list of memp elements */ + for (j = 0; j < memp_num[i]; ++j) { + memp->next = memp_tab[i]; + memp_tab[i] = memp; + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } + } +#if MEMP_OVERFLOW_CHECK + memp_overflow_init(); + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK */ +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * the debug version has two more parameters: + * @param file file name calling this function + * @param line number of line where this function is called + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + + memp = memp_tab[type]; + + if (memp != NULL) { + memp_tab[type] = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; + memp->file = file; + memp->line = line; +#endif /* MEMP_OVERFLOW_CHECK */ + MEMP_STATS_INC_USED(used, type); + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); + memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); + MEMP_STATS_INC(err, type); + } + + SYS_ARCH_UNPROTECT(old_level); + + return memp; +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + if (mem == NULL) { + return; + } + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#else + memp_overflow_check_element_overflow(memp, type); + memp_overflow_check_element_underflow(memp, type); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +#endif /* MEMP_OVERFLOW_CHECK */ + + MEMP_STATS_DEC(used, type); + + memp->next = memp_tab[type]; + memp_tab[type] = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity()); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +} + +#endif /* MEMP_MEM_MALLOC */ diff --git a/ext/lwip/src/core/netif.c b/ext/lwip/src/core/netif.c new file mode 100644 index 000000000..8c1e4e58a --- /dev/null +++ b/ext/lwip/src/core/netif.c @@ -0,0 +1,774 @@ +/** + * @file + * lwIP network interface abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp.h" +#include "lwip/igmp.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#if ENABLE_LOOPBACK +#include "lwip/sys.h" +#if LWIP_NETIF_LOOPBACK_MULTITHREADING +#include "lwip/tcpip.h" +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif /* LWIP_DHCP */ + +#if LWIP_NETIF_STATUS_CALLBACK +#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +#else +#define NETIF_STATUS_CALLBACK(n) +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) +#else +#define NETIF_LINK_CALLBACK(n) +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +struct netif *netif_list; +struct netif *netif_default; + +static u8_t netif_num; + +#if LWIP_HAVE_LOOPIF +static struct netif loop_netif; + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +static err_t +netif_loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; + netif->output = netif_loop_output; + return ERR_OK; +} +#endif /* LWIP_HAVE_LOOPIF */ + +void +netif_init(void) +{ +#if LWIP_HAVE_LOOPIF + ip_addr_t loop_ipaddr, loop_netmask, loop_gw; + IP4_ADDR(&loop_gw, 127,0,0,1); + IP4_ADDR(&loop_ipaddr, 127,0,0,1); + IP4_ADDR(&loop_netmask, 255,0,0,0); + +#if NO_SYS + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input); +#else /* NO_SYS */ + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); +#endif /* NO_SYS */ + netif_set_up(&loop_netif); + +#endif /* LWIP_HAVE_LOOPIF */ +} + +/** + * Add a network interface to the list of lwIP netifs. + * + * @param netif a pre-allocated netif structure + * @param ipaddr IP address for the new netif + * @param netmask network mask for the new netif + * @param gw default gateway IP address for the new netif + * @param state opaque data passed to the new netif + * @param init callback function that initializes the interface + * @param input callback function that is called to pass + * ingress packets up in the protocol layer stack. + * + * @return netif, or NULL if failed. + */ +struct netif * +netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input) +{ + + LWIP_ASSERT("No init function given", init != NULL); + + /* reset new interface configuration state */ + ip_addr_set_zero(&netif->ip_addr); + ip_addr_set_zero(&netif->netmask); + ip_addr_set_zero(&netif->gw); + netif->flags = 0; +#if LWIP_DHCP + /* netif not under DHCP control by default */ + netif->dhcp = NULL; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /* netif not under AutoIP control by default */ + netif->autoip = NULL; +#endif /* LWIP_AUTOIP */ +#if LWIP_NETIF_STATUS_CALLBACK + netif->status_callback = NULL; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif->link_callback = NULL; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_IGMP + netif->igmp_mac_filter = NULL; +#endif /* LWIP_IGMP */ +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#endif /* ENABLE_LOOPBACK */ + + /* remember netif specific state information data */ + netif->state = state; + netif->num = netif_num++; + netif->input = input; + NETIF_SET_HWADDRHINT(netif, NULL); +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ + + netif_set_addr(netif, ipaddr, netmask, gw); + + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; + } + + /* add this netif to the list */ + netif->next = netif_list; + netif_list = netif; + snmp_inc_iflist(); + +#if LWIP_IGMP + /* start IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start(netif); + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", + netif->name[0], netif->name[1])); + ip_addr_debug_print(NETIF_DEBUG, ipaddr); + LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); + ip_addr_debug_print(NETIF_DEBUG, netmask); + LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); + ip_addr_debug_print(NETIF_DEBUG, gw); + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + return netif; +} + +/** + * Change IP address configuration for a network interface (including netmask + * and default gateway). + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * @param netmask the new netmask + * @param gw the new default gateway + */ +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw) +{ + netif_set_ipaddr(netif, ipaddr); + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); +} + +/** + * Remove a network interface from the list of lwIP netifs. + * + * @param netif the network interface to remove + */ +void +netif_remove(struct netif *netif) +{ + if (netif == NULL) { + return; + } + +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop(netif); + } +#endif /* LWIP_IGMP */ + if (netif_is_up(netif)) { + /* set netif down before removing (call callback function) */ + netif_set_down(netif); + } + + snmp_delete_ipaddridx_tree(netif); + + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + } else { + /* look for netif further down the list */ + struct netif * tmpNetif; + for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { + if (tmpNetif->next == netif) { + tmpNetif->next = netif->next; + break; + } + } + if (tmpNetif == NULL) + return; /* we didn't find any netif today */ + } + snmp_dec_iflist(); + /* this netif is default? */ + if (netif_default == netif) { + /* reset default netif */ + netif_set_default(NULL); + } +#if LWIP_NETIF_REMOVE_CALLBACK + if (netif->remove_callback) { + netif->remove_callback(netif); + } +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); +} + +/** + * Find a network interface by searching for its name + * + * @param name the name of the netif (like netif->name) plus concatenated number + * in ascii representation (e.g. 'en0') + */ +struct netif * +netif_find(char *name) +{ + struct netif *netif; + u8_t num; + + if (name == NULL) { + return NULL; + } + + num = name[2] - '0'; + + for(netif = netif_list; netif != NULL; netif = netif->next) { + if (num == netif->num && + name[0] == netif->name[0] && + name[1] == netif->name[1]) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + return netif; + } + } + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + return NULL; +} + +/** + * Change the IP address of a network interface + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * + * @note call netif_set_addr() if you also want to change netmask and + * default gateway + */ +void +netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr) +{ + /* TODO: Handling of obsolete pcbs */ + /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ +#if LWIP_TCP + struct tcp_pcb *pcb; + struct tcp_pcb_listen *lpcb; + + /* address is actually being changed? */ + if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { + /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); + pcb = tcp_active_pcbs; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr)) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && !ip_addr_islinklocal(&(pcb->local_ip)) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + /* PCB bound to current local interface address? */ + if ((!(ip_addr_isany(&(lpcb->local_ip)))) && + (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_set(&(lpcb->local_ip), ipaddr); + } + } + } +#endif + snmp_delete_ipaddridx_tree(netif); + snmp_delete_iprteidx_tree(0,netif); + /* set new IP address to netif */ + ip_addr_set(&(netif->ip_addr), ipaddr); + snmp_insert_ipaddridx_tree(netif); + snmp_insert_iprteidx_tree(0,netif); + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->ip_addr), + ip4_addr2_16(&netif->ip_addr), + ip4_addr3_16(&netif->ip_addr), + ip4_addr4_16(&netif->ip_addr))); +} + +/** + * Change the default gateway for a network interface + * + * @param netif the network interface to change + * @param gw the new default gateway + * + * @note call netif_set_addr() if you also want to change ip address and netmask + */ +void +netif_set_gw(struct netif *netif, ip_addr_t *gw) +{ + ip_addr_set(&(netif->gw), gw); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->gw), + ip4_addr2_16(&netif->gw), + ip4_addr3_16(&netif->gw), + ip4_addr4_16(&netif->gw))); +} + +/** + * Change the netmask of a network interface + * + * @param netif the network interface to change + * @param netmask the new netmask + * + * @note call netif_set_addr() if you also want to change ip address and + * default gateway + */ +void +netif_set_netmask(struct netif *netif, ip_addr_t *netmask) +{ + snmp_delete_iprteidx_tree(0, netif); + /* set new netmask to netif */ + ip_addr_set(&(netif->netmask), netmask); + snmp_insert_iprteidx_tree(0, netif); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->netmask), + ip4_addr2_16(&netif->netmask), + ip4_addr3_16(&netif->netmask), + ip4_addr4_16(&netif->netmask))); +} + +/** + * Set a network interface as the default network interface + * (used to output all packets for which no specific route is found) + * + * @param netif the default network interface + */ +void +netif_set_default(struct netif *netif) +{ + if (netif == NULL) { + /* remove default route */ + snmp_delete_iprteidx_tree(1, netif); + } else { + /* install default route */ + snmp_insert_iprteidx_tree(1, netif); + } + netif_default = netif; + LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", + netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); +} + +/** + * Bring an interface up, available for processing + * traffic. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_UP)) { + netif->flags |= NETIF_FLAG_UP; + +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif /* LWIP_SNMP */ + + NETIF_STATUS_CALLBACK(netif); + + if (netif->flags & NETIF_FLAG_LINK_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & (NETIF_FLAG_ETHARP)) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ + } + } +} + +/** + * Bring an interface down, disabling any traffic processing. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_down(struct netif *netif) +{ + if (netif->flags & NETIF_FLAG_UP) { + netif->flags &= ~NETIF_FLAG_UP; +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif + +#if LWIP_ARP + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_cleanup_netif(netif); + } +#endif /* LWIP_ARP */ + NETIF_STATUS_CALLBACK(netif); + } +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * Set callback to be called when interface is brought up/down + */ +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) +{ + if (netif) { + netif->status_callback = status_callback; + } +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_REMOVE_CALLBACK +/** + * Set callback to be called when the interface has been removed + */ +void +netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) +{ + if (netif) { + netif->remove_callback = remove_callback; + } +} +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +/** + * Called by a driver when its link goes up + */ +void netif_set_link_up(struct netif *netif ) +{ + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + netif->flags |= NETIF_FLAG_LINK_UP; + +#if LWIP_DHCP + if (netif->dhcp) { + dhcp_network_changed(netif); + } +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + if (netif->autoip) { + autoip_network_changed(netif); + } +#endif /* LWIP_AUTOIP */ + + if (netif->flags & NETIF_FLAG_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ + } + NETIF_LINK_CALLBACK(netif); + } +} + +/** + * Called by a driver when its link goes down + */ +void netif_set_link_down(struct netif *netif ) +{ + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); + } +} + +#if LWIP_NETIF_LINK_CALLBACK +/** + * Set callback to be called when link is brought up/down + */ +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) +{ + if (netif) { + netif->link_callback = link_callback; + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if ENABLE_LOOPBACK +/** + * Send an IP packet to be received on the same netif (loopif-like). + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by netif_poll(). + * + * @param netif the lwip network interface structure + * @param p the (IP) packet to 'send' + * @param ipaddr the ip address to send the packet to (not used) + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +err_t +netif_loop_output(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr) +{ + struct pbuf *r; + err_t err; + struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ + SYS_ARCH_DECL_PROTECT(lev); + LWIP_UNUSED_ARG(ipaddr); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; + } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return err; + } + + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next); + + SYS_ARCH_PROTECT(lev); + if(netif->loop_first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); + netif->loop_last->next = r; + netif->loop_last = last; + } else { + netif->loop_first = r; + netif->loop_last = last; + } + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.xmit); + snmp_add_ifoutoctets(stats_if, p->tot_len); + snmp_inc_ifoutucastpkts(stats_if); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback((tcpip_callback_fn)netif_poll, netif); +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ + + return ERR_OK; +} + +/** + * Call netif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * netif_loop_output() are put on a list that is passed to netif->input() by + * netif_poll(). + */ +void +netif_poll(struct netif *netif) +{ + struct pbuf *in; + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ + SYS_ARCH_DECL_PROTECT(lev); + + do { + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + in = netif->loop_first; + if (in != NULL) { + struct pbuf *in_end = in; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = pbuf_clen(in); + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + while (in_end->len != in_end->tot_len) { + LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); + in_end = in_end->next; + } + /* 'in_end' now points to the last pbuf from 'in' */ + if (in_end == netif->loop_last) { + /* this was the last pbuf in the list */ + netif->loop_first = netif->loop_last = NULL; + } else { + /* pop the pbuf off the list */ + netif->loop_first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); + } + /* De-queue the pbuf from its successors on the 'loop_' list. */ + in_end->next = NULL; + } + SYS_ARCH_UNPROTECT(lev); + + if (in != NULL) { + LINK_STATS_INC(link.recv); + snmp_add_ifinoctets(stats_if, in->tot_len); + snmp_inc_ifinucastpkts(stats_if); + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); + } + /* Don't reference the packet any more! */ + in = NULL; + } + /* go on while there is a packet on the list */ + } while (netif->loop_first != NULL); +} + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ diff --git a/ext/lwip/src/core/pbuf.c b/ext/lwip/src/core/pbuf.c new file mode 100644 index 000000000..bd9bf916f --- /dev/null +++ b/ext/lwip/src/core/pbuf.c @@ -0,0 +1,1179 @@ +/** + * @file + * Packet buffer management + * + * Packets are built from the pbuf data structure. It supports dynamic + * memory allocation for packet contents or can reference externally + * managed packet contents both in RAM and ROM. Quick allocation for + * incoming packets is provided through pools with fixed sized pbufs. + * + * A packet may span over multiple pbufs, chained as a singly linked + * list. This is called a "pbuf chain". + * + * Multiple packets may be queued, also using this singly linked list. + * This is called a "packet queue". + * + * So, a packet queue consists of one or more pbuf chains, each of + * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE + * NOT SUPPORTED!!! Use helper structs to queue multiple packets. + * + * The differences between a pbuf chain and a packet queue are very + * precise but subtle. + * + * The last pbuf of a packet has a ->tot_len field that equals the + * ->len field. It can be found by traversing the list. If the last + * pbuf of a packet has a ->next field other than NULL, more packets + * are on the queue. + * + * Therefore, looping through a pbuf of a single packet, has an + * loop end condition (tot_len == p->len), NOT (next == NULL). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "arch/perf.h" +#if LWIP_TCP && TCP_QUEUE_OOSEQ +#include "lwip/tcp_impl.h" +#endif +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) +/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically + aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ +#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_IS_EMPTY() +#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +#if !NO_SYS +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL +#include "lwip/tcpip.h" +#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ + if(tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ + SYS_ARCH_PROTECT(old_level); \ + pbuf_free_ooseq_pending = 0; \ + SYS_ARCH_UNPROTECT(old_level); \ + } } while(0) +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +#endif /* !NO_SYS */ + +volatile u8_t pbuf_free_ooseq_pending; +#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() + +/** + * Attempt to reclaim some memory from queued out-of-sequence TCP segments + * if we run out of pool pbufs. It's better to give priority to new packets + * if we're running out. + * + * This must be done in the correct thread context therefore this function + * can only be used with NO_SYS=0 and through tcpip_callback. + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +void +pbuf_free_ooseq(void) +{ + struct tcp_pcb* pcb; + SYS_ARCH_DECL_PROTECT(old_level); + + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_pending = 0; + SYS_ARCH_UNPROTECT(old_level); + + for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { + if (NULL != pcb->ooseq) { + /** Free the ooseq pbufs of one PCB only */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + return; + } + } +} + +#if !NO_SYS +/** + * Just a callback function for tcpip_timeout() that calls pbuf_free_ooseq(). + */ +static void +pbuf_free_ooseq_callback(void *arg) +{ + LWIP_UNUSED_ARG(arg); + pbuf_free_ooseq(); +} +#endif /* !NO_SYS */ + +/** Queue a call to pbuf_free_ooseq if not already queued. */ +static void +pbuf_pool_is_empty(void) +{ +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); +#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ + u8_t queued; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + queued = pbuf_free_ooseq_pending; + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); + + if(!queued) { + /* queue a call to pbuf_free_ooseq if not already queued */ + //PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); + } +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +} +#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +/** + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). + * + * The actual memory allocated for the pbuf is determined by the + * layer at which the pbuf is allocated and the requested size + * (from the size parameter). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type this parameter decides how and where the pbuf + * should be allocated as follows: + * + * - PBUF_RAM: buffer memory for pbuf is allocated as one large + * chunk. This includes protocol headers as well. + * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for + * protocol headers. Additional headers must be prepended + * by allocating another pbuf and chain in to the front of + * the ROM pbuf. It is assumed that the memory used is really + * similar to ROM in that it is immutable and will not be + * changed. Memory which is dynamic should generally not + * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. + * - PBUF_REF: no buffer memory is allocated for the pbuf, even for + * protocol headers. It is assumed that the pbuf is only + * being used in a single thread. If the pbuf gets queued, + * then pbuf_take should be called to copy the buffer. + * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from + * the pbuf pool that is allocated during pbuf_init(). + * + * @return the allocated pbuf. If multiple pbufs where allocated, this + * is the first pbuf of a pbuf chain. + */ +struct pbuf * +pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p, *q, *r; + u16_t offset; + s32_t rem_len; /* remaining length */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (layer) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); + return NULL; + } + + switch (type) { + case PBUF_POOL: + /* allocate head of pbuf chain into p */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); + if (p == NULL) { + PBUF_POOL_IS_EMPTY(); + return NULL; + } + p->type = type; + p->next = NULL; + + /* make the payload pointer point 'offset' bytes into pbuf data memory */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); + LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + /* the total length of the pbuf chain is the requested size */ + p->tot_len = length; + /* set the length of the first pbuf in the chain */ + p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", + (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); + /* set reference count (needed here in case we fail) */ + p->ref = 1; + + /* now allocate the tail of the pbuf chain */ + + /* remember first pbuf for linkage in next iteration */ + r = p; + /* remaining length to be allocated */ + rem_len = length - p->len; + /* any remaining pbufs to be allocated? */ + while (rem_len > 0) { + q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + if (q == NULL) { + PBUF_POOL_IS_EMPTY(); + /* free chain so far allocated */ + pbuf_free(p); + /* bail out unsuccesfully */ + return NULL; + } + q->type = type; + q->flags = 0; + q->next = NULL; + /* make previous pbuf point to this pbuf */ + r->next = q; + /* set total length of this pbuf and next in chain */ + LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); + q->tot_len = (u16_t)rem_len; + /* this pbuf length is pool size, unless smaller sized tail */ + q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); + q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); + LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", + ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + q->ref = 1; + /* calculate remaining length to be allocated */ + rem_len -= q->len; + /* remember this pbuf for linkage in next iteration */ + r = q; + } + /* end of chain */ + /*r->next = NULL;*/ + + break; + case PBUF_RAM: + /* If pbuf is to be allocated in RAM, allocate memory for it. */ + p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); + if (p == NULL) { + return NULL; + } + /* Set up internal structure of the pbuf. */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + + LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + break; + /* pbuf references existing (non-volatile static constant) ROM payload? */ + case PBUF_ROM: + /* pbuf references existing (externally allocated) RAM payload? */ + case PBUF_REF: + /* only allocate memory for the pbuf structure */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF); + if (p == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", + (type == PBUF_ROM) ? "ROM" : "REF")); + return NULL; + } + /* caller must set this field properly, afterwards */ + p->payload = NULL; + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + break; + default: + LWIP_ASSERT("pbuf_alloc: erroneous type", 0); + return NULL; + } + /* set reference count */ + p->ref = 1; + /* set flags */ + p->flags = 0; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; +} + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Initialize a custom pbuf (already allocated). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type type of the pbuf (only used to treat the pbuf accordingly, as + * this function allocates no memory) + * @param p pointer to the custom pbuf to initialize (already allocated) + * @param payload_mem pointer to the buffer that is used for payload and headers, + * must be at least big enough to hold 'length' plus the header size, + * may be NULL if set later. + * ATTENTION: The caller is responsible for correct alignment of this buffer!! + * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least + * big enough to hold 'length' plus the header size + */ +struct pbuf* +pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, + void *payload_mem, u16_t payload_mem_len) +{ + u16_t offset; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (l) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); + return NULL; + } + + if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); + return NULL; + } + + p->pbuf.next = NULL; + if (payload_mem != NULL) { + p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); + } else { + p->pbuf.payload = NULL; + } + p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; + p->pbuf.len = p->pbuf.tot_len = length; + p->pbuf.type = type; + p->pbuf.ref = 1; + return &p->pbuf; +} +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** + * Shrink a pbuf chain to a desired length. + * + * @param p pbuf to shrink. + * @param new_len desired new length of pbuf chain + * + * Depending on the desired length, the first few pbufs in a chain might + * be skipped and left unchanged. The new last pbuf in the chain will be + * resized, and any remaining pbufs will be freed. + * + * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. + * @note May not be called on a packet queue. + * + * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). + */ +void +pbuf_realloc(struct pbuf *p, u16_t new_len) +{ + struct pbuf *q; + u16_t rem_len; /* remaining length */ + s32_t grow; + + LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || + p->type == PBUF_ROM || + p->type == PBUF_RAM || + p->type == PBUF_REF); + + /* desired length larger than current length? */ + if (new_len >= p->tot_len) { + /* enlarging not yet supported */ + return; + } + + /* the pbuf chain grows by (new_len - p->tot_len) bytes + * (which may be negative in case of shrinking) */ + grow = new_len - p->tot_len; + + /* first, step over any pbufs that should remain in the chain */ + rem_len = new_len; + q = p; + /* should this pbuf be kept? */ + while (rem_len > q->len) { + /* decrease remaining length by pbuf length */ + rem_len -= q->len; + /* decrease total length indicator */ + LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); + q->tot_len += (u16_t)grow; + /* proceed to next pbuf in chain */ + q = q->next; + LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); + } + /* we have now reached the new last pbuf (in q) */ + /* rem_len == desired length for pbuf q */ + + /* shrink allocated memory for PBUF_RAM */ + /* (other types merely adjust their length fields */ + if ((q->type == PBUF_RAM) && (rem_len != q->len)) { + /* reallocate and adjust the length of the pbuf that will be split */ + q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); + LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + } + /* adjust length fields for new last pbuf */ + q->len = rem_len; + q->tot_len = q->len; + + /* any remaining pbufs in chain? */ + if (q->next != NULL) { + /* free remaining pbufs in chain */ + pbuf_free(q->next); + } + /* q is last packet in chain */ + q->next = NULL; + +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * + * Adjusts the ->payload pointer so that space for a header + * (dis)appears in the pbuf payload. + * + * The ->payload, ->tot_len and ->len fields are adjusted. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size which + * increases the size of the pbuf. New space is on the front. + * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns succesful. + * + * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so + * the call will fail. A check is made that the increase in header size does + * not move the payload pointer in front of the start of the buffer. + * @return non-zero on failure, zero on success. + * + */ +u8_t +pbuf_header(struct pbuf *p, s16_t header_size_increment) +{ + u16_t type; + void *payload; + u16_t increment_magnitude; + + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) { + return 0; + } + + if (header_size_increment < 0){ + increment_magnitude = -header_size_increment; + /* Check that we aren't going to move off the end of the pbuf */ + LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); + } else { + increment_magnitude = header_size_increment; +#if 0 + /* Can't assert these as some callers speculatively call + pbuf_header() to see if it's OK. Will return 1 below instead. */ + /* Check that we've got the correct type of pbuf to work with */ + LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", + p->type == PBUF_RAM || p->type == PBUF_POOL); + /* Check that we aren't going to move off the beginning of the pbuf */ + LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", + (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); +#endif + } + + type = p->type; + /* remember current payload pointer */ + payload = p->payload; + + /* pbuf types containing payloads? */ + if (type == PBUF_RAM || type == PBUF_POOL) { + /* set new payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + /* boundary check fails? */ + if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, (void *)(p + 1))); + /* restore old payload pointer */ + p->payload = payload; + /* bail out unsuccesfully */ + return 1; + } + /* pbuf types refering to external payloads? */ + } else if (type == PBUF_REF || type == PBUF_ROM) { + /* hide a header in the payload? */ + if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { + /* increase payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + } else { + /* cannot expand payload to front (yet!) + * bail out unsuccesfully */ + return 1; + } + } else { + /* Unknown type */ + LWIP_ASSERT("bad pbuf type", 0); + return 1; + } + /* modify pbuf length fields */ + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); + + return 0; +} + +/** + * Dereference a pbuf chain or queue and deallocate any no-longer-used + * pbufs at the head of this chain or queue. + * + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. + * + * For a pbuf chain, this is repeated for each pbuf in the chain, + * up to the first pbuf which has a non-zero reference count after + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. + * + * @param p The pbuf (chain) to be dereferenced. + * + * @return the number of pbufs that were de-allocated + * from the head of the chain. + * + * @note MUST NOT be called on a packet queue (Not verified to work yet). + * @note the reference counter of a pbuf equals the number of pointers + * that refer to the pbuf (or into the pbuf). + * + * @internal examples: + * + * Assuming existing chains a->b->c with the following reference + * counts, calling pbuf_free(a) results in: + * + * 1->2->3 becomes ...1->3 + * 3->3->3 becomes 2->3->3 + * 1->1->2 becomes ......1 + * 2->1->1 becomes 1->1->1 + * 1->1->1 becomes ....... + * + */ +u8_t +pbuf_free(struct pbuf *p) +{ + u16_t type; + struct pbuf *q; + u8_t count; + + if (p == NULL) { + LWIP_ASSERT("p != NULL", p != NULL); + /* if assertions are disabled, proceed with debug output */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_free(p == NULL) was called.\n")); + return 0; + } + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); + + PERF_START; + + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_RAM || p->type == PBUF_ROM || + p->type == PBUF_REF || p->type == PBUF_POOL); + + count = 0; + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + while (p != NULL) { + u16_t ref; + SYS_ARCH_DECL_PROTECT(old_level); + /* Since decrementing ref cannot be guaranteed to be a single machine operation + * we must protect it. We put the new ref into a local variable to prevent + * further protection. */ + SYS_ARCH_PROTECT(old_level); + /* all pbufs in a chain are referenced at least once */ + LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); + /* decrease reference count (number of pointers to pbuf) */ + ref = --(p->ref); + SYS_ARCH_UNPROTECT(old_level); + /* this pbuf is no longer referenced to? */ + if (ref == 0) { + /* remember next pbuf in chain for next iteration */ + q = p->next; + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); + type = p->type; +#if LWIP_SUPPORT_CUSTOM_PBUF + /* is this a custom pbuf? */ + if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { + struct pbuf_custom *pc = (struct pbuf_custom*)p; + LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); + pc->custom_free_function(p); + } else +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + { + /* is this a pbuf from the pool? */ + if (type == PBUF_POOL) { + memp_free(MEMP_PBUF_POOL, p); + /* is this a ROM or RAM referencing pbuf? */ + } else if (type == PBUF_ROM || type == PBUF_REF) { + memp_free(MEMP_PBUF, p); + /* type == PBUF_RAM */ + } else { + mem_free(p); + } + } + count++; + /* proceed to next pbuf */ + p = q; + /* p->ref > 0, this pbuf is still referenced to */ + /* (and so the remaining pbufs in chain as well) */ + } else { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); + /* stop walking through the chain */ + p = NULL; + } + } + PERF_STOP("pbuf_free"); + /* return number of de-allocated pbufs */ + return count; +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ + +u8_t +pbuf_clen(struct pbuf *p) +{ + u8_t len; + + len = 0; + while (p != NULL) { + ++len; + p = p->next; + } + return len; +} + +/** + * Increment the reference count of the pbuf. + * + * @param p pbuf to increase reference counter of + * + */ +void +pbuf_ref(struct pbuf *p) +{ + SYS_ARCH_DECL_PROTECT(old_level); + /* pbuf given? */ + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + ++(p->ref); + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Concatenate two pbufs (each may be a pbuf chain) and take over + * the caller's reference of the tail pbuf. + * + * @note The caller MAY NOT reference the tail pbuf afterwards. + * Use pbuf_chain() for that purpose. + * + * @see pbuf_chain() + */ + +void +pbuf_cat(struct pbuf *h, struct pbuf *t) +{ + struct pbuf *p; + + LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", + ((h != NULL) && (t != NULL)), return;); + + /* proceed to last pbuf of chain */ + for (p = h; p->next != NULL; p = p->next) { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + /* { p is last pbuf of first h chain, p->next == NULL } */ + LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + /* chain last pbuf of head (p) with first of tail (t) */ + p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +/** + * Chain two pbufs (or pbuf chains) together. + * + * The caller MUST call pbuf_free(t) once it has stopped + * using it. Use pbuf_cat() instead if you no longer use t. + * + * @param h head pbuf (chain) + * @param t tail pbuf (chain) + * @note The pbufs MUST belong to the same packet. + * @note MAY NOT be called on a packet queue. + * + * The ->tot_len fields of all pbufs of the head chain are adjusted. + * The ->next field of the last pbuf of the head chain is adjusted. + * The ->ref field of the first pbuf of the tail chain is adjusted. + * + */ +void +pbuf_chain(struct pbuf *h, struct pbuf *t) +{ + pbuf_cat(h, t); + /* t is now referenced by h */ + pbuf_ref(t); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); +} + +/** + * Dechains the first pbuf from its succeeding pbufs in the chain. + * + * Makes p->tot_len field equal to p->len. + * @param p pbuf to dechain + * @return remainder of the pbuf chain, or NULL if it was de-allocated. + * @note May not be called on a packet queue. + */ +struct pbuf * +pbuf_dechain(struct pbuf *p) +{ + struct pbuf *q; + u8_t tail_gone = 1; + /* tail */ + q = p->next; + /* pbuf has successor in chain? */ + if (q != NULL) { + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); + /* enforce invariant if assertion is disabled */ + q->tot_len = p->tot_len - p->len; + /* decouple pbuf from remainder */ + p->next = NULL; + /* total length of pbuf p is its own length only */ + p->tot_len = p->len; + /* q is no longer referenced by p, free it */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); + tail_gone = pbuf_free(q); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } + /* return remaining tail or NULL if deallocated */ + } + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); + return ((tail_gone > 0) ? NULL : q); +} + +/** + * + * Create PBUF_RAM copies of pbufs. + * + * Used to queue packets on behalf of the lwIP stack, such as + * ARP based queueing. + * + * @note You MUST explicitly use p = pbuf_take(p); + * + * @note Only one packet is copied, no packet queue! + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * + * @return ERR_OK if pbuf was copied + * ERR_ARG if one of the pbufs is NULL or p_to is not big + * enough to hold p_from + */ +err_t +pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) +{ + u16_t offset_to=0, offset_from=0, len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", + (void*)p_to, (void*)p_from)); + + /* is the target big enough to hold the source? */ + LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && + (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + + /* iterate through pbuf chain */ + do + { + /* copy one part of the original chain */ + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { + /* complete current p_from fits into current p_to */ + len = p_from->len - offset_from; + } else { + /* current p_from does not fit into current p_to */ + len = p_to->len - offset_to; + } + MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); + offset_to += len; + offset_from += len; + LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); + LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); + if (offset_from >= p_from->len) { + /* on to next p_from (if any) */ + offset_from = 0; + p_from = p_from->next; + } + if (offset_to == p_to->len) { + /* on to next p_to (if any) */ + offset_to = 0; + p_to = p_to->next; + LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); + } + + if((p_from != NULL) && (p_from->len == p_from->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + (p_from->next == NULL), return ERR_VAL;); + } + if((p_to != NULL) && (p_to->len == p_to->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + (p_to->next == NULL), return ERR_VAL;); + } + } while (p_from); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + return ERR_OK; +} + +/** + * Copy (part of) the contents of a packet buffer + * to an application supplied buffer. + * + * @param buf the pbuf from which to copy data + * @param dataptr the application supplied buffer + * @param len length of data to copy (dataptr must be big enough). No more + * than buf->tot_len will be copied, irrespective of len + * @param offset offset into the packet buffer from where to begin copying len bytes + * @return the number of bytes copied, or 0 on failure + */ +u16_t +pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +{ + struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if((buf == NULL) || (dataptr == NULL)) { + return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) + buf_copy_len = len; + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; +} + +/** + * Copy application supplied data into a pbuf. + * This function can only be used to copy the equivalent of buf->tot_len data. + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + struct pbuf *p; + u16_t buf_copy_len; + u16_t total_copy_len = len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;); + + if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { + return ERR_ARG; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; total_copy_len != 0; p = p->next) { + LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); + buf_copy_len = total_copy_len; + if (buf_copy_len > p->len) { + /* this pbuf cannot hold all remaining data */ + buf_copy_len = p->len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len); + total_copy_len -= buf_copy_len; + copied_total += buf_copy_len; + } + LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); + return ERR_OK; +} + +/** + * Creates a single pbuf out of a queue of pbufs. + * + * @remark: Either the source pbuf 'p' is freed by this function or the original + * pbuf 'p' is returned, therefore the caller has to check the result! + * + * @param p the source pbuf + * @param layer pbuf_layer of the new pbuf + * + * @return a new, single pbuf (p->next is NULL) + * or the old pbuf if allocation fails + */ +struct pbuf* +pbuf_coalesce(struct pbuf *p, pbuf_layer layer) +{ + struct pbuf *q; + err_t err; + if (p->next == NULL) { + return p; + } + q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); + if (q == NULL) { + /* @todo: what do we do now? */ + return p; + } + err = pbuf_copy(q, p); + LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + pbuf_free(p); + return q; +} + +#if LWIP_CHECKSUM_ON_COPY +/** + * Copies data into a single pbuf (*not* into a pbuf queue!) and updates + * the checksum while copying + * + * @param p the pbuf to copy data into + * @param start_offset offset of p->payload where to copy the data to + * @param dataptr data to copy into the pbuf + * @param len length of data to copy into the pbuf + * @param chksum pointer to the checksum which is updated + * @return ERR_OK if successful, another error if the data does not fit + * within the (first) pbuf (no pbuf queues!) + */ +err_t +pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum) +{ + u32_t acc; + u16_t copy_chksum; + char *dst_ptr; + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("dataptr != NULL", dataptr != NULL); + LWIP_ASSERT("chksum != NULL", chksum != NULL); + LWIP_ASSERT("len != 0", len != 0); + + if ((start_offset >= p->len) || (start_offset + len > p->len)) { + return ERR_ARG; + } + + dst_ptr = ((char*)p->payload) + start_offset; + copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); + if ((start_offset & 1) != 0) { + copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); + } + acc = *chksum; + acc += copy_chksum; + *chksum = FOLD_U32T(acc); + return ERR_OK; +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /** Get one byte from the specified position in a pbuf + * WARNING: returns zero for offset >= p->tot_len + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len + */ +u8_t +pbuf_get_at(struct pbuf* p, u16_t offset) +{ + u16_t copy_from = offset; + struct pbuf* q = p; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= copy_from)) { + copy_from -= q->len; + q = q->next; + } + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > copy_from)) { + return ((u8_t*)q->payload)[copy_from]; + } + return 0; +} + +/** Compare pbuf contents at specified offset with memory s2, both of length n + * + * @param p pbuf to compare + * @param offset offset into p at wich to start comparing + * @param s2 buffer to compare + * @param n length of buffer to compare + * @return zero if equal, nonzero otherwise + * (0xffff if p is too short, diffoffset+1 otherwise) + */ +u16_t +pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n) +{ + u16_t start = offset; + struct pbuf* q = p; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= start)) { + start -= q->len; + q = q->next; + } + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > start)) { + u16_t i; + for(i = 0; i < n; i++) { + u8_t a = pbuf_get_at(q, start + i); + u8_t b = ((u8_t*)s2)[i]; + if (a != b) { + return i+1; + } + } + return 0; + } + return 0xffff; +} + +/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset + * start_offset. + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param mem search for the contents of this buffer + * @param mem_len length of 'mem' + * @param start_offset offset into p at which to start searching + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) +{ + u16_t i; + u16_t max = p->tot_len - mem_len; + if (p->tot_len >= mem_len + start_offset) { + for(i = start_offset; i <= max; ) { + u16_t plus = pbuf_memcmp(p, i, mem, mem_len); + if (plus == 0) { + return i; + } else { + i += plus; + } + } + } + return 0xFFFF; +} + +/** Find occurrence of substr with length substr_len in pbuf p, start at offset + * start_offset + * WARNING: in contrast to strstr(), this one does not stop at the first \0 in + * the pbuf/source string! + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param substr string to search for in p, maximum length is 0xFFFE + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_strstr(struct pbuf* p, const char* substr) +{ + size_t substr_len; + if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { + return 0xFFFF; + } + substr_len = strlen(substr); + if (substr_len >= 0xFFFF) { + return 0xFFFF; + } + return pbuf_memfind(p, substr, (u16_t)substr_len, 0); +} diff --git a/ext/lwip/src/core/raw.c b/ext/lwip/src/core/raw.c new file mode 100644 index 000000000..7160c0fbd --- /dev/null +++ b/ext/lwip/src/core/raw.c @@ -0,0 +1,350 @@ +/** + * @file + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/raw.h" +#include "lwip/stats.h" +#include "arch/perf.h" + +#include + +/** The list of RAW PCBs */ +static struct raw_pcb *raw_pcbs; + +/** + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. + * + * Given an incoming IP datagram (as a chain of pbufs) this function + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. + * + * @param p pbuf to be demultiplexed to a RAW PCB. + * @param inp network interface on which the datagram was received. + * @return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). + * + */ +u8_t +raw_input(struct pbuf *p, struct netif *inp) +{ + struct raw_pcb *pcb, *prev; + struct ip_hdr *iphdr; + s16_t proto; + u8_t eaten = 0; + + LWIP_UNUSED_ARG(inp); + + iphdr = (struct ip_hdr *)p->payload; + proto = IPH_PROTO(iphdr); + + prev = NULL; + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { + if ((pcb->protocol == proto) && + (ip_addr_isany(&pcb->local_ip) || + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest))) { +#if IP_SOF_BROADCAST_RECV + /* broadcast filter? */ + if (ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(¤t_iphdr_dest, inp)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + /* receive callback function available? */ + if (pcb->recv != NULL) { + /* the receive callback function did not eat the packet? */ + if (pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()) != 0) { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + if (prev != NULL) { + /* move the pcb to the front of raw_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + } + } + /* no receive callback function was set for this raw PCB */ + } + /* drop the packet */ + } + prev = pcb; + pcb = pcb->next; + } + return eaten; +} + +/** + * Bind a RAW PCB. + * + * @param pcb RAW PCB to be bound with a local address ipaddr. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_USE. The specified IP address is already bound to by + * another RAW PCB. + * + * @see raw_disconnect() + */ +err_t +raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr) +{ + ip_addr_set(&pcb->local_ip, ipaddr); + return ERR_OK; +} + +/** + * Connect an RAW PCB. This function is required by upper layers + * of lwip. Using the raw api you could use raw_sendto() instead + * + * This will associate the RAW PCB with the remote address. + * + * @param pcb RAW PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * + * @return lwIP error code + * + * @see raw_disconnect() and raw_sendto() + */ +err_t +raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr) +{ + ip_addr_set(&pcb->remote_ip, ipaddr); + return ERR_OK; +} + + +/** + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + * + * @return non-zero if the packet was free()d, zero if the packet remains + * available for others. + */ +void +raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Send the raw IP packet to the given address. Note that actually you cannot + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet + * + */ +err_t +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) +{ + err_t err; + struct netif *netif; + ip_addr_t *src_ip; + struct pbuf *q; /* q will be sent down the stack */ + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); + + /* not enough space to add an IP header to first pbuf in given p chain? */ + if (pbuf_header(p, IP_HLEN)) { + /* allocate header in new pbuf */ + q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + } + /* { first pbuf q points to header pbuf } */ + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* first pbuf q equals given pbuf */ + q = p; + if(pbuf_header(q, -IP_HLEN)) { + LWIP_ASSERT("Can't restore header we just removed!", 0); + return ERR_MEM; + } + } + + if ((netif = ip_route(ipaddr)) == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } + +#if IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_VAL; + } +#endif /* IP_SOF_BROADCAST */ + + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* use RAW PCB local IP address as source address */ + src_ip = &(pcb->local_ip); + } + + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* did we chain a header earlier? */ + if (q != p) { + /* free the header */ + pbuf_free(q); + } + return err; +} + +/** + * Send the raw IP packet to the address given by raw_connect() + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * + */ +err_t +raw_send(struct raw_pcb *pcb, struct pbuf *p) +{ + return raw_sendto(pcb, p, &pcb->remote_ip); +} + +/** + * Remove an RAW PCB. + * + * @param pcb RAW PCB to be removed. The PCB is removed from the list of + * RAW PCB's and the data structure is freed from memory. + * + * @see raw_new() + */ +void +raw_remove(struct raw_pcb *pcb) +{ + struct raw_pcb *pcb2; + /* pcb to be removed is first in list? */ + if (raw_pcbs == pcb) { + /* make list start at 2nd pcb */ + raw_pcbs = raw_pcbs->next; + /* pcb not 1st in list */ + } else { + for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in raw_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + } + memp_free(MEMP_RAW_PCB, pcb); +} + +/** + * Create a RAW PCB. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new(u8_t proto) +{ + struct raw_pcb *pcb; + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); + + pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); + /* could allocate RAW PCB? */ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); + pcb->protocol = proto; + pcb->ttl = RAW_TTL; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + return pcb; +} + +#endif /* LWIP_RAW */ diff --git a/ext/lwip/src/core/snmp/asn1_dec.c b/ext/lwip/src/core/snmp/asn1_dec.c new file mode 100644 index 000000000..1d5658207 --- /dev/null +++ b/ext/lwip/src/core/snmp/asn1_dec.c @@ -0,0 +1,657 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) decoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_asn1.h" + +/** + * Retrieves type field from incoming pbuf chain. + * + * @param p points to a pbuf holding an ASN1 coded type field + * @param ofs points to the offset within the pbuf chain of the ASN1 coded type field + * @param type return ASN1 type + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + *type = *msg_ptr; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes length field from incoming pbuf chain into host length. + * + * @param p points to a pbuf holding an ASN1 coded length + * @param ofs points to the offset within the pbuf chain of the ASN1 coded length + * @param octets_used returns number of octets used by the length code + * @param length return host order length, upto 64k + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (*msg_ptr < 0x80) + { + /* primitive definite length format */ + *octets_used = 1; + *length = *msg_ptr; + return ERR_OK; + } + else if (*msg_ptr == 0x80) + { + /* constructed indefinite length format, termination with two zero octets */ + u8_t zeros; + u8_t i; + + *length = 0; + zeros = 0; + while (zeros != 2) + { + i = 2; + while (i > 0) + { + i--; + (*length) += 1; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (*msg_ptr == 0) + { + zeros++; + if (zeros == 2) + { + /* stop while (i > 0) */ + i = 0; + } + } + else + { + zeros = 0; + } + } + } + *octets_used = 1; + return ERR_OK; + } + else if (*msg_ptr == 0x81) + { + /* constructed definite length format, one octet */ + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + *length = *msg_ptr; + *octets_used = 2; + return ERR_OK; + } + else if (*msg_ptr == 0x82) + { + u8_t i; + + /* constructed definite length format, two octets */ + i = 2; + while (i > 0) + { + i--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (i == 0) + { + /* least significant length octet */ + *length |= *msg_ptr; + } + else + { + /* most significant length octet */ + *length = (*msg_ptr) << 8; + } + } + *octets_used = 3; + return ERR_OK; + } + else + { + /* constructed definite length format 3..127 octets, this is too big (>64k) */ + /** @todo: do we need to accept inefficient codings with many leading zero's? */ + *octets_used = 1 + ((*msg_ptr) & 0x7f); + return ERR_ARG; + } + } + p = p->next; + } + + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes positive integer (counter, gauge, timeticks) into u32_t. + * + * @param p points to a pbuf holding an ASN1 coded integer + * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if ((len > 0) && (len < 6)) + { + /* start from zero */ + *value = 0; + if (*msg_ptr & 0x80) + { + /* negative, expecting zero sign bit! */ + return ERR_ARG; + } + else + { + /* positive */ + if ((len > 1) && (*msg_ptr == 0)) + { + /* skip leading "sign byte" octet 0x00 */ + len--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + } + /* OR octets with value */ + while (len > 1) + { + len--; + *value |= *msg_ptr; + *value <<= 8; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + *value |= *msg_ptr; + return ERR_OK; + } + else + { + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes integer into s32_t. + * + * @param p points to a pbuf holding an ASN1 coded integer + * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed! + */ +err_t +snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value) +{ + u16_t plen, base; + u8_t *msg_ptr; +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t *lsb_ptr = (u8_t*)value; +#endif +#if BYTE_ORDER == BIG_ENDIAN + u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; +#endif + u8_t sign; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if ((len > 0) && (len < 5)) + { + if (*msg_ptr & 0x80) + { + /* negative, start from -1 */ + *value = -1; + sign = 1; + } + else + { + /* positive, start from 0 */ + *value = 0; + sign = 0; + } + /* OR/AND octets with value */ + while (len > 1) + { + len--; + if (sign) + { + *lsb_ptr &= *msg_ptr; + *value <<= 8; + *lsb_ptr |= 255; + } + else + { + *lsb_ptr |= *msg_ptr; + *value <<= 8; + } + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (sign) + { + *lsb_ptr &= *msg_ptr; + } + else + { + *lsb_ptr |= *msg_ptr; + } + return ERR_OK; + } + else + { + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes object identifier from incoming message into array of s32_t. + * + * @param p points to a pbuf holding an ASN1 coded object identifier + * @param ofs points to the offset within the pbuf chain of the ASN1 coded object identifier + * @param len length of the coded object identifier + * @param oid return object identifier struct + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid) +{ + u16_t plen, base; + u8_t *msg_ptr; + s32_t *oid_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + oid->len = 0; + oid_ptr = &oid->id[0]; + if (len > 0) + { + /* first compressed octet */ + if (*msg_ptr == 0x2B) + { + /* (most) common case 1.3 (iso.org) */ + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = 3; + oid_ptr++; + } + else if (*msg_ptr < 40) + { + *oid_ptr = 0; + oid_ptr++; + *oid_ptr = *msg_ptr; + oid_ptr++; + } + else if (*msg_ptr < 80) + { + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = (*msg_ptr) - 40; + oid_ptr++; + } + else + { + *oid_ptr = 2; + oid_ptr++; + *oid_ptr = (*msg_ptr) - 80; + oid_ptr++; + } + oid->len = 2; + } + else + { + /* accepting zero length identifiers e.g. for + getnext operation. uncommon but valid */ + return ERR_OK; + } + len--; + if (len > 0) + { + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + while ((len > 0) && (oid->len < LWIP_SNMP_OBJ_ID_LEN)) + { + /* sub-identifier uses multiple octets */ + if (*msg_ptr & 0x80) + { + s32_t sub_id = 0; + + while ((*msg_ptr & 0x80) && (len > 1)) + { + len--; + sub_id = (sub_id << 7) + (*msg_ptr & ~0x80); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (!(*msg_ptr & 0x80) && (len > 0)) + { + /* last octet sub-identifier */ + len--; + sub_id = (sub_id << 7) + *msg_ptr; + *oid_ptr = sub_id; + } + } + else + { + /* !(*msg_ptr & 0x80) sub-identifier uses single octet */ + len--; + *oid_ptr = *msg_ptr; + } + if (len > 0) + { + /* remaining oid bytes available ... */ + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + oid_ptr++; + oid->len++; + } + if (len == 0) + { + /* len == 0, end of oid */ + return ERR_OK; + } + else + { + /* len > 0, oid->len == LWIP_SNMP_OBJ_ID_LEN or malformed encoding */ + return ERR_ARG; + } + + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) + * from incoming message into array. + * + * @param p points to a pbuf holding an ASN1 coded raw data + * @param ofs points to the offset within the pbuf chain of the ASN1 coded raw data + * @param len length of the coded raw data (zero is valid, e.g. empty string!) + * @param raw_len length of the raw return value + * @param raw return raw bytes + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw) +{ + u16_t plen, base; + u8_t *msg_ptr; + + if (len > 0) + { + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if (raw_len >= len) + { + while (len > 1) + { + /* copy len - 1 octets */ + len--; + *raw = *msg_ptr; + raw++; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* copy last octet */ + *raw = *msg_ptr; + return ERR_OK; + } + else + { + /* raw_len < len, not enough dst space */ + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; + } + else + { + /* len == 0, empty string */ + return ERR_OK; + } +} + +#endif /* LWIP_SNMP */ diff --git a/ext/lwip/src/core/snmp/asn1_enc.c b/ext/lwip/src/core/snmp/asn1_enc.c new file mode 100644 index 000000000..64dfc5f6e --- /dev/null +++ b/ext/lwip/src/core/snmp/asn1_enc.c @@ -0,0 +1,611 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) encoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_asn1.h" + +/** + * Returns octet count for length. + * + * @param length + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) +{ + if (length < 0x80U) + { + *octets_needed = 1; + } + else if (length < 0x100U) + { + *octets_needed = 2; + } + else + { + *octets_needed = 3; + } +} + +/** + * Returns octet count for an u32_t. + * + * @param value + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) +{ + if (value < 0x80UL) + { + *octets_needed = 1; + } + else if (value < 0x8000UL) + { + *octets_needed = 2; + } + else if (value < 0x800000UL) + { + *octets_needed = 3; + } + else if (value < 0x80000000UL) + { + *octets_needed = 4; + } + else + { + *octets_needed = 5; + } +} + +/** + * Returns octet count for an s32_t. + * + * @param value + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. + */ +void +snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) +{ + if (value < 0) + { + value = ~value; + } + if (value < 0x80L) + { + *octets_needed = 1; + } + else if (value < 0x8000L) + { + *octets_needed = 2; + } + else if (value < 0x800000L) + { + *octets_needed = 3; + } + else + { + *octets_needed = 4; + } +} + +/** + * Returns octet count for an object identifier. + * + * @param ident_len object identifier array length + * @param ident points to object identifier array + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed) +{ + s32_t sub_id; + u8_t cnt; + + cnt = 0; + if (ident_len > 1) + { + /* compressed prefix in one octet */ + cnt++; + ident_len -= 2; + ident += 2; + } + while(ident_len > 0) + { + ident_len--; + sub_id = *ident; + + sub_id >>= 7; + cnt++; + while(sub_id > 0) + { + sub_id >>= 7; + cnt++; + } + ident++; + } + *octets_needed = cnt; +} + +/** + * Encodes ASN type field into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param type input ASN1 type + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + *msg_ptr = type; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes host order length field into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode length into + * @param ofs points to the offset within the pbuf chain + * @param length is the host order length to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (length < 0x80) + { + *msg_ptr = (u8_t)length; + return ERR_OK; + } + else if (length < 0x100) + { + *msg_ptr = 0x81; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + *msg_ptr = (u8_t)length; + return ERR_OK; + } + else + { + u8_t i; + + /* length >= 0x100 && length <= 0xFFFF */ + *msg_ptr = 0x82; + i = 2; + while (i > 0) + { + i--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (i == 0) + { + /* least significant length octet */ + *msg_ptr = (u8_t)length; + } + else + { + /* most significant length octet */ + *msg_ptr = (u8_t)(length >> 8); + } + } + return ERR_OK; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u32t_cnt() + */ +err_t +snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (octets_needed == 5) + { + /* not enough bits in 'value' add leading 0x00 */ + octets_needed--; + *msg_ptr = 0x00; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + while (octets_needed > 1) + { + octets_needed--; + *msg_ptr = (u8_t)(value >> (octets_needed << 3)); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* (only) one least significant octet */ + *msg_ptr = (u8_t)value; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes s32_t integer into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) + * @param value is the host order s32_t value to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_s32t_cnt() + */ +err_t +snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + while (octets_needed > 1) + { + octets_needed--; + *msg_ptr = (u8_t)(value >> (octets_needed << 3)); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* (only) one least significant octet */ + *msg_ptr = (u8_t)value; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes object identifier into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode oid into + * @param ofs points to the offset within the pbuf chain + * @param ident_len object identifier array length + * @param ident points to object identifier array + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (ident_len > 1) + { + if ((ident[0] == 1) && (ident[1] == 3)) + { + /* compressed (most common) prefix .iso.org */ + *msg_ptr = 0x2b; + } + else + { + /* calculate prefix */ + *msg_ptr = (u8_t)((ident[0] * 40) + ident[1]); + } + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + ident_len -= 2; + ident += 2; + } + else + { +/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ + /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ + return ERR_ARG; + } + while (ident_len > 0) + { + s32_t sub_id; + u8_t shift, tail; + + ident_len--; + sub_id = *ident; + tail = 0; + shift = 28; + while(shift > 0) + { + u8_t code; + + code = (u8_t)(sub_id >> shift); + if ((code != 0) || (tail != 0)) + { + tail = 1; + *msg_ptr = code | 0x80; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + shift -= 7; + } + *msg_ptr = (u8_t)sub_id & 0x7F; + if (ident_len > 0) + { + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* proceed to next sub-identifier */ + ident++; + } + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode raw data into + * @param ofs points to the offset within the pbuf chain + * @param raw_len raw data length + * @param raw points raw data + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + while (raw_len > 1) + { + /* copy raw_len - 1 octets */ + raw_len--; + *msg_ptr = *raw; + raw++; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (raw_len > 0) + { + /* copy last or single octet */ + *msg_ptr = *raw; + } + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +#endif /* LWIP_SNMP */ diff --git a/ext/lwip/src/core/snmp/mib2.c b/ext/lwip/src/core/snmp/mib2.c new file mode 100644 index 000000000..4775ba993 --- /dev/null +++ b/ext/lwip/src/core/snmp/mib2.c @@ -0,0 +1,4146 @@ +/** + * @file + * Management Information Base II (RFC1213) objects and functions. + * + * @note the object identifiers for this MIB-2 and private MIB tree + * must be kept in sorted ascending order. This to ensure correct getnext operation. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/ip_frag.h" +#include "lwip/mem.h" +#include "lwip/tcp_impl.h" +#include "lwip/udp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_structs.h" +#include "lwip/sys.h" +#include "netif/etharp.h" + +/** + * IANA assigned enterprise ID for lwIP is 26381 + * @see http://www.iana.org/assignments/enterprise-numbers + * + * @note this enterprise ID is assigned to the lwIP project, + * all object identifiers living under this ID are assigned + * by the lwIP maintainers (contact Christiaan Simons)! + * @note don't change this define, use snmp_set_sysobjid() + * + * If you need to create your own private MIB you'll need + * to apply for your own enterprise ID with IANA: + * http://www.iana.org/numbers.html + */ +#define SNMP_ENTERPRISE_ID 26381 +#define SNMP_SYSOBJID_LEN 7 +#define SNMP_SYSOBJID {1, 3, 6, 1, 4, 1, SNMP_ENTERPRISE_ID} + +#ifndef SNMP_SYSSERVICES +#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) +#endif + +#ifndef SNMP_GET_SYSUPTIME +#define SNMP_GET_SYSUPTIME(sysuptime) (sysuptime = (sys_now() / 10)) +#endif + +static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void system_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t system_set_test(struct obj_def *od, u16_t len, void *value); +static void system_set_value(struct obj_def *od, u16_t len, void *value); +static void interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void interfaces_get_value(struct obj_def *od, u16_t len, void *value); +static void ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ifentry_get_value(struct obj_def *od, u16_t len, void *value); +#if !SNMP_SAFE_REQUESTS +static u8_t ifentry_set_test (struct obj_def *od, u16_t len, void *value); +static void ifentry_set_value (struct obj_def *od, u16_t len, void *value); +#endif /* SNMP_SAFE_REQUESTS */ +static void atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void atentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t ip_set_test(struct obj_def *od, u16_t len, void *value); +static void ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value); +static void icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void icmp_get_value(struct obj_def *od, u16_t len, void *value); +#if LWIP_TCP +static void tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void tcp_get_value(struct obj_def *od, u16_t len, void *value); +#ifdef THIS_SEEMS_UNUSED +static void tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value); +#endif +#endif +static void udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void udp_get_value(struct obj_def *od, u16_t len, void *value); +static void udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void udpentry_get_value(struct obj_def *od, u16_t len, void *value); +static void snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void snmp_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t snmp_set_test(struct obj_def *od, u16_t len, void *value); +static void snmp_set_value(struct obj_def *od, u16_t len, void *value); + + +/* snmp .1.3.6.1.2.1.11 */ +const mib_scalar_node snmp_scalar = { + &snmp_get_object_def, + &snmp_get_value, + &snmp_set_test, + &snmp_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t snmp_ids[28] = { + 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30 +}; +struct mib_node* const snmp_nodes[28] = { + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar +}; +const struct mib_array_node snmp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 28, + snmp_ids, + snmp_nodes +}; + +/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ +/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ +/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ + +/* udp .1.3.6.1.2.1.7 */ +/** index root node for udpTable */ +struct mib_list_rootnode udp_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t udpentry_ids[2] = { 1, 2 }; +struct mib_node* const udpentry_nodes[2] = { + (struct mib_node*)&udp_root, (struct mib_node*)&udp_root, +}; +const struct mib_array_node udpentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + udpentry_ids, + udpentry_nodes +}; + +s32_t udptable_id = 1; +struct mib_node* udptable_node = (struct mib_node*)&udpentry; +struct mib_ram_array_node udptable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &udptable_id, + &udptable_node +}; + +const mib_scalar_node udp_scalar = { + &udp_get_object_def, + &udp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const udp_nodes[5] = { + (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar, + (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar, + (struct mib_node*)&udptable +}; +const struct mib_array_node udp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + udp_ids, + udp_nodes +}; + +/* tcp .1.3.6.1.2.1.6 */ +#if LWIP_TCP +/* only if the TCP protocol is available may implement this group */ +/** index root node for tcpConnTable */ +struct mib_list_rootnode tcpconntree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t tcpconnentry_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const tcpconnentry_nodes[5] = { + (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root, + (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root, + (struct mib_node*)&tcpconntree_root +}; +const struct mib_array_node tcpconnentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + tcpconnentry_ids, + tcpconnentry_nodes +}; + +s32_t tcpconntable_id = 1; +struct mib_node* tcpconntable_node = (struct mib_node*)&tcpconnentry; +struct mib_ram_array_node tcpconntable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, +/** @todo update maxlength when inserting / deleting from table + 0 when table is empty, 1 when more than one entry */ + 0, + &tcpconntable_id, + &tcpconntable_node +}; + +const mib_scalar_node tcp_scalar = { + &tcp_get_object_def, + &tcp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; +struct mib_node* const tcp_nodes[15] = { + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcpconntable, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar +}; +const struct mib_array_node tcp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 15, + tcp_ids, + tcp_nodes +}; +#endif + +/* icmp .1.3.6.1.2.1.5 */ +const mib_scalar_node icmp_scalar = { + &icmp_get_object_def, + &icmp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t icmp_ids[26] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }; +struct mib_node* const icmp_nodes[26] = { + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar +}; +const struct mib_array_node icmp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 26, + icmp_ids, + icmp_nodes +}; + +/** index root node for ipNetToMediaTable */ +struct mib_list_rootnode ipntomtree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ipntomentry_ids[4] = { 1, 2, 3, 4 }; +struct mib_node* const ipntomentry_nodes[4] = { + (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root, + (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root +}; +const struct mib_array_node ipntomentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 4, + ipntomentry_ids, + ipntomentry_nodes +}; + +s32_t ipntomtable_id = 1; +struct mib_node* ipntomtable_node = (struct mib_node*)&ipntomentry; +struct mib_ram_array_node ipntomtable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &ipntomtable_id, + &ipntomtable_node +}; + +/** index root node for ipRouteTable */ +struct mib_list_rootnode iprtetree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t iprteentry_ids[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; +struct mib_node* const iprteentry_nodes[13] = { + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root +}; +const struct mib_array_node iprteentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 13, + iprteentry_ids, + iprteentry_nodes +}; + +s32_t iprtetable_id = 1; +struct mib_node* iprtetable_node = (struct mib_node*)&iprteentry; +struct mib_ram_array_node iprtetable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &iprtetable_id, + &iprtetable_node +}; + +/** index root node for ipAddrTable */ +struct mib_list_rootnode ipaddrtree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ipaddrentry_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const ipaddrentry_nodes[5] = { + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root +}; +const struct mib_array_node ipaddrentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + ipaddrentry_ids, + ipaddrentry_nodes +}; + +s32_t ipaddrtable_id = 1; +struct mib_node* ipaddrtable_node = (struct mib_node*)&ipaddrentry; +struct mib_ram_array_node ipaddrtable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &ipaddrtable_id, + &ipaddrtable_node +}; + +/* ip .1.3.6.1.2.1.4 */ +const mib_scalar_node ip_scalar = { + &ip_get_object_def, + &ip_get_value, + &ip_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; +struct mib_node* const ip_nodes[23] = { + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ipaddrtable, + (struct mib_node*)&iprtetable, (struct mib_node*)&ipntomtable, + (struct mib_node*)&ip_scalar +}; +const struct mib_array_node mib2_ip = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 23, + ip_ids, + ip_nodes +}; + +/** index root node for atTable */ +struct mib_list_rootnode arptree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t atentry_ids[3] = { 1, 2, 3 }; +struct mib_node* const atentry_nodes[3] = { + (struct mib_node*)&arptree_root, + (struct mib_node*)&arptree_root, + (struct mib_node*)&arptree_root +}; +const struct mib_array_node atentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 3, + atentry_ids, + atentry_nodes +}; + +const s32_t attable_id = 1; +struct mib_node* const attable_node = (struct mib_node*)&atentry; +const struct mib_array_node attable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + &attable_id, + &attable_node +}; + +/* at .1.3.6.1.2.1.3 */ +s32_t at_id = 1; +struct mib_node* mib2_at_node = (struct mib_node*)&attable; +struct mib_ram_array_node at = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &at_id, + &mib2_at_node +}; + +/** index root node for ifTable */ +struct mib_list_rootnode iflist_root = { + &ifentry_get_object_def, + &ifentry_get_value, +#if SNMP_SAFE_REQUESTS + &noleafs_set_test, + &noleafs_set_value, +#else /* SNMP_SAFE_REQUESTS */ + &ifentry_set_test, + &ifentry_set_value, +#endif /* SNMP_SAFE_REQUESTS */ + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }; +struct mib_node* const ifentry_nodes[22] = { + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root +}; +const struct mib_array_node ifentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 22, + ifentry_ids, + ifentry_nodes +}; + +s32_t iftable_id = 1; +struct mib_node* iftable_node = (struct mib_node*)&ifentry; +struct mib_ram_array_node iftable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &iftable_id, + &iftable_node +}; + +/* interfaces .1.3.6.1.2.1.2 */ +const mib_scalar_node interfaces_scalar = { + &interfaces_get_object_def, + &interfaces_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t interfaces_ids[2] = { 1, 2 }; +struct mib_node* const interfaces_nodes[2] = { + (struct mib_node*)&interfaces_scalar, (struct mib_node*)&iftable +}; +const struct mib_array_node interfaces = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + interfaces_ids, + interfaces_nodes +}; + + +/* 0 1 2 3 4 5 6 */ +/* system .1.3.6.1.2.1.1 */ +const mib_scalar_node sys_tem_scalar = { + &system_get_object_def, + &system_get_value, + &system_set_test, + &system_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 }; +struct mib_node* const sys_tem_nodes[7] = { + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar +}; +/* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */ +const struct mib_array_node sys_tem = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 7, + sys_tem_ids, + sys_tem_nodes +}; + +/* mib-2 .1.3.6.1.2.1 */ +#if LWIP_TCP +#define MIB2_GROUPS 8 +#else +#define MIB2_GROUPS 7 +#endif +const s32_t mib2_ids[MIB2_GROUPS] = +{ + 1, + 2, + 3, + 4, + 5, +#if LWIP_TCP + 6, +#endif + 7, + 11 +}; +struct mib_node* const mib2_nodes[MIB2_GROUPS] = { + (struct mib_node*)&sys_tem, + (struct mib_node*)&interfaces, + (struct mib_node*)&at, + (struct mib_node*)&mib2_ip, + (struct mib_node*)&icmp, +#if LWIP_TCP + (struct mib_node*)&tcp, +#endif + (struct mib_node*)&udp, + (struct mib_node*)&snmp +}; + +const struct mib_array_node mib2 = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + MIB2_GROUPS, + mib2_ids, + mib2_nodes +}; + +/* mgmt .1.3.6.1.2 */ +const s32_t mgmt_ids[1] = { 1 }; +struct mib_node* const mgmt_nodes[1] = { (struct mib_node*)&mib2 }; +const struct mib_array_node mgmt = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + mgmt_ids, + mgmt_nodes +}; + +/* internet .1.3.6.1 */ +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +s32_t internet_ids[2] = { 2, 4 }; +struct mib_node* const internet_nodes[2] = { (struct mib_node*)&mgmt, (struct mib_node*)&mib_private }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + internet_ids, + internet_nodes +}; +#else +const s32_t internet_ids[1] = { 2 }; +struct mib_node* const internet_nodes[1] = { (struct mib_node*)&mgmt }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + internet_ids, + internet_nodes +}; +#endif + +/** mib-2.system.sysObjectID */ +static struct snmp_obj_id sysobjid = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; +/** enterprise ID for generic TRAPs, .iso.org.dod.internet.mgmt.mib-2.snmp */ +static struct snmp_obj_id snmpgrp_id = {7,{1,3,6,1,2,1,11}}; +/** mib-2.system.sysServices */ +static const s32_t sysservices = SNMP_SYSSERVICES; + +/** mib-2.system.sysDescr */ +static const u8_t sysdescr_len_default = 4; +static const u8_t sysdescr_default[] = "lwIP"; +static u8_t* sysdescr_len_ptr = (u8_t*)&sysdescr_len_default; +static u8_t* sysdescr_ptr = (u8_t*)&sysdescr_default[0]; +/** mib-2.system.sysContact */ +static const u8_t syscontact_len_default = 0; +static const u8_t syscontact_default[] = ""; +static u8_t* syscontact_len_ptr = (u8_t*)&syscontact_len_default; +static u8_t* syscontact_ptr = (u8_t*)&syscontact_default[0]; +/** mib-2.system.sysName */ +static const u8_t sysname_len_default = 8; +static const u8_t sysname_default[] = "FQDN-unk"; +static u8_t* sysname_len_ptr = (u8_t*)&sysname_len_default; +static u8_t* sysname_ptr = (u8_t*)&sysname_default[0]; +/** mib-2.system.sysLocation */ +static const u8_t syslocation_len_default = 0; +static const u8_t syslocation_default[] = ""; +static u8_t* syslocation_len_ptr = (u8_t*)&syslocation_len_default; +static u8_t* syslocation_ptr = (u8_t*)&syslocation_default[0]; +/** mib-2.snmp.snmpEnableAuthenTraps */ +static const u8_t snmpenableauthentraps_default = 2; /* disabled */ +static u8_t* snmpenableauthentraps_ptr = (u8_t*)&snmpenableauthentraps_default; + +/** mib-2.interfaces.ifTable.ifEntry.ifSpecific (zeroDotZero) */ +static const struct snmp_obj_id ifspecific = {2, {0, 0}}; +/** mib-2.ip.ipRouteTable.ipRouteEntry.ipRouteInfo (zeroDotZero) */ +static const struct snmp_obj_id iprouteinfo = {2, {0, 0}}; + + + +/* mib-2.system counter(s) */ +static u32_t sysuptime = 0; + +/* mib-2.ip counter(s) */ +static u32_t ipinreceives = 0, + ipinhdrerrors = 0, + ipinaddrerrors = 0, + ipforwdatagrams = 0, + ipinunknownprotos = 0, + ipindiscards = 0, + ipindelivers = 0, + ipoutrequests = 0, + ipoutdiscards = 0, + ipoutnoroutes = 0, + ipreasmreqds = 0, + ipreasmoks = 0, + ipreasmfails = 0, + ipfragoks = 0, + ipfragfails = 0, + ipfragcreates = 0, + iproutingdiscards = 0; +/* mib-2.icmp counter(s) */ +static u32_t icmpinmsgs = 0, + icmpinerrors = 0, + icmpindestunreachs = 0, + icmpintimeexcds = 0, + icmpinparmprobs = 0, + icmpinsrcquenchs = 0, + icmpinredirects = 0, + icmpinechos = 0, + icmpinechoreps = 0, + icmpintimestamps = 0, + icmpintimestampreps = 0, + icmpinaddrmasks = 0, + icmpinaddrmaskreps = 0, + icmpoutmsgs = 0, + icmpouterrors = 0, + icmpoutdestunreachs = 0, + icmpouttimeexcds = 0, + icmpoutparmprobs = 0, + icmpoutsrcquenchs = 0, + icmpoutredirects = 0, + icmpoutechos = 0, + icmpoutechoreps = 0, + icmpouttimestamps = 0, + icmpouttimestampreps = 0, + icmpoutaddrmasks = 0, + icmpoutaddrmaskreps = 0; +/* mib-2.tcp counter(s) */ +static u32_t tcpactiveopens = 0, + tcppassiveopens = 0, + tcpattemptfails = 0, + tcpestabresets = 0, + tcpinsegs = 0, + tcpoutsegs = 0, + tcpretranssegs = 0, + tcpinerrs = 0, + tcpoutrsts = 0; +/* mib-2.udp counter(s) */ +static u32_t udpindatagrams = 0, + udpnoports = 0, + udpinerrors = 0, + udpoutdatagrams = 0; +/* mib-2.snmp counter(s) */ +static u32_t snmpinpkts = 0, + snmpoutpkts = 0, + snmpinbadversions = 0, + snmpinbadcommunitynames = 0, + snmpinbadcommunityuses = 0, + snmpinasnparseerrs = 0, + snmpintoobigs = 0, + snmpinnosuchnames = 0, + snmpinbadvalues = 0, + snmpinreadonlys = 0, + snmpingenerrs = 0, + snmpintotalreqvars = 0, + snmpintotalsetvars = 0, + snmpingetrequests = 0, + snmpingetnexts = 0, + snmpinsetrequests = 0, + snmpingetresponses = 0, + snmpintraps = 0, + snmpouttoobigs = 0, + snmpoutnosuchnames = 0, + snmpoutbadvalues = 0, + snmpoutgenerrs = 0, + snmpoutgetrequests = 0, + snmpoutgetnexts = 0, + snmpoutsetrequests = 0, + snmpoutgetresponses = 0, + snmpouttraps = 0; + + + +/* prototypes of the following functions are in lwip/src/include/lwip/snmp.h */ +/** + * Copy octet string. + * + * @param dst points to destination + * @param src points to source + * @param n number of octets to copy. + */ +static void ocstrncpy(u8_t *dst, u8_t *src, u16_t n) +{ + u16_t i = n; + while (i > 0) { + i--; + *dst++ = *src++; + } +} + +/** + * Copy object identifier (s32_t) array. + * + * @param dst points to destination + * @param src points to source + * @param n number of sub identifiers to copy. + */ +void objectidncpy(s32_t *dst, s32_t *src, u8_t n) +{ + u8_t i = n; + while(i > 0) { + i--; + *dst++ = *src++; + } +} + +/** + * Initializes sysDescr pointers. + * + * @param str if non-NULL then copy str pointer + * @param len points to string length, excluding zero terminator + */ +void snmp_set_sysdesr(u8_t *str, u8_t *len) +{ + if (str != NULL) + { + sysdescr_ptr = str; + sysdescr_len_ptr = len; + } +} + +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid) +{ + *oid = &sysobjid; +} + +/** + * Initializes sysObjectID value. + * + * @param oid points to stuct snmp_obj_id to copy + */ +void snmp_set_sysobjid(struct snmp_obj_id *oid) +{ + sysobjid = *oid; +} + +/** + * Must be called at regular 10 msec interval from a timer interrupt + * or signal handler depending on your runtime environment. + */ +void snmp_inc_sysuptime(void) +{ + sysuptime++; +} + +void snmp_add_sysuptime(u32_t value) +{ + sysuptime+=value; +} + +void snmp_get_sysuptime(u32_t *value) +{ + SNMP_GET_SYSUPTIME(sysuptime); + *value = sysuptime; +} + +/** + * Initializes sysContact pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + syscontact_ptr = ocstr; + syscontact_len_ptr = ocstrlen; + } +} + +/** + * Initializes sysName pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + sysname_ptr = ocstr; + sysname_len_ptr = ocstrlen; + } +} + +/** + * Initializes sysLocation pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + syslocation_ptr = ocstr; + syslocation_len_ptr = ocstrlen; + } +} + + +void snmp_add_ifinoctets(struct netif *ni, u32_t value) +{ + ni->ifinoctets += value; +} + +void snmp_inc_ifinucastpkts(struct netif *ni) +{ + (ni->ifinucastpkts)++; +} + +void snmp_inc_ifinnucastpkts(struct netif *ni) +{ + (ni->ifinnucastpkts)++; +} + +void snmp_inc_ifindiscards(struct netif *ni) +{ + (ni->ifindiscards)++; +} + +void snmp_add_ifoutoctets(struct netif *ni, u32_t value) +{ + ni->ifoutoctets += value; +} + +void snmp_inc_ifoutucastpkts(struct netif *ni) +{ + (ni->ifoutucastpkts)++; +} + +void snmp_inc_ifoutnucastpkts(struct netif *ni) +{ + (ni->ifoutnucastpkts)++; +} + +void snmp_inc_ifoutdiscards(struct netif *ni) +{ + (ni->ifoutdiscards)++; +} + +void snmp_inc_iflist(void) +{ + struct mib_list_node *if_node = NULL; + + snmp_mib_node_insert(&iflist_root, iflist_root.count + 1, &if_node); + /* enable getnext traversal on filled table */ + iftable.maxlength = 1; +} + +void snmp_dec_iflist(void) +{ + snmp_mib_node_delete(&iflist_root, iflist_root.tail); + /* disable getnext traversal on empty table */ + if(iflist_root.count == 0) iftable.maxlength = 0; +} + +/** + * Inserts ARP table indexes (.xIfIndex.xNetAddress) + * into arp table index trees (both atTable and ipNetToMediaTable). + */ +void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip) +{ + struct mib_list_rootnode *at_rn; + struct mib_list_node *at_node; + s32_t arpidx[5]; + u8_t level, tree; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_netiftoifindex(ni, &arpidx[0]); + snmp_iptooid(ip, &arpidx[1]); + + for (tree = 0; tree < 2; tree++) + { + if (tree == 0) + { + at_rn = &arptree_root; + } + else + { + at_rn = &ipntomtree_root; + } + for (level = 0; level < 5; level++) + { + at_node = NULL; + snmp_mib_node_insert(at_rn, arpidx[level], &at_node); + if ((level != 4) && (at_node != NULL)) + { + if (at_node->nptr == NULL) + { + at_rn = snmp_mib_lrn_alloc(); + at_node->nptr = (struct mib_node*)at_rn; + if (at_rn != NULL) + { + if (level == 3) + { + if (tree == 0) + { + at_rn->get_object_def = atentry_get_object_def; + at_rn->get_value = atentry_get_value; + } + else + { + at_rn->get_object_def = ip_ntomentry_get_object_def; + at_rn->get_value = ip_ntomentry_get_value; + } + at_rn->set_test = noleafs_set_test; + at_rn->set_value = noleafs_set_value; + } + } + else + { + /* at_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_arpidx_tree() insert failed, mem full")); + break; + } + } + else + { + at_rn = (struct mib_list_rootnode*)at_node->nptr; + } + } + } + } + /* enable getnext traversal on filled tables */ + at.maxlength = 1; + ipntomtable.maxlength = 1; +} + +/** + * Removes ARP table indexes (.xIfIndex.xNetAddress) + * from arp table index trees. + */ +void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip) +{ + struct mib_list_rootnode *at_rn, *next, *del_rn[5]; + struct mib_list_node *at_n, *del_n[5]; + s32_t arpidx[5]; + u8_t fc, tree, level, del_cnt; + + snmp_netiftoifindex(ni, &arpidx[0]); + snmp_iptooid(ip, &arpidx[1]); + + for (tree = 0; tree < 2; tree++) + { + /* mark nodes for deletion */ + if (tree == 0) + { + at_rn = &arptree_root; + } + else + { + at_rn = &ipntomtree_root; + } + level = 0; + del_cnt = 0; + while ((level < 5) && (at_rn != NULL)) + { + fc = snmp_mib_node_find(at_rn, arpidx[level], &at_n); + if (fc == 0) + { + /* arpidx[level] does not exist */ + del_cnt = 0; + at_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = at_rn; + del_n[del_cnt] = at_n; + del_cnt++; + at_rn = (struct mib_list_rootnode*)(at_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + at_rn = (struct mib_list_rootnode*)(at_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + at_rn = del_rn[del_cnt]; + at_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(at_rn, at_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty tables */ + if(arptree_root.count == 0) at.maxlength = 0; + if(ipntomtree_root.count == 0) ipntomtable.maxlength = 0; +} + +void snmp_inc_ipinreceives(void) +{ + ipinreceives++; +} + +void snmp_inc_ipinhdrerrors(void) +{ + ipinhdrerrors++; +} + +void snmp_inc_ipinaddrerrors(void) +{ + ipinaddrerrors++; +} + +void snmp_inc_ipforwdatagrams(void) +{ + ipforwdatagrams++; +} + +void snmp_inc_ipinunknownprotos(void) +{ + ipinunknownprotos++; +} + +void snmp_inc_ipindiscards(void) +{ + ipindiscards++; +} + +void snmp_inc_ipindelivers(void) +{ + ipindelivers++; +} + +void snmp_inc_ipoutrequests(void) +{ + ipoutrequests++; +} + +void snmp_inc_ipoutdiscards(void) +{ + ipoutdiscards++; +} + +void snmp_inc_ipoutnoroutes(void) +{ + ipoutnoroutes++; +} + +void snmp_inc_ipreasmreqds(void) +{ + ipreasmreqds++; +} + +void snmp_inc_ipreasmoks(void) +{ + ipreasmoks++; +} + +void snmp_inc_ipreasmfails(void) +{ + ipreasmfails++; +} + +void snmp_inc_ipfragoks(void) +{ + ipfragoks++; +} + +void snmp_inc_ipfragfails(void) +{ + ipfragfails++; +} + +void snmp_inc_ipfragcreates(void) +{ + ipfragcreates++; +} + +void snmp_inc_iproutingdiscards(void) +{ + iproutingdiscards++; +} + +/** + * Inserts ipAddrTable indexes (.ipAdEntAddr) + * into index tree. + */ +void snmp_insert_ipaddridx_tree(struct netif *ni) +{ + struct mib_list_rootnode *ipa_rn; + struct mib_list_node *ipa_node; + s32_t ipaddridx[4]; + u8_t level; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_iptooid(&ni->ip_addr, &ipaddridx[0]); + + level = 0; + ipa_rn = &ipaddrtree_root; + while (level < 4) + { + ipa_node = NULL; + snmp_mib_node_insert(ipa_rn, ipaddridx[level], &ipa_node); + if ((level != 3) && (ipa_node != NULL)) + { + if (ipa_node->nptr == NULL) + { + ipa_rn = snmp_mib_lrn_alloc(); + ipa_node->nptr = (struct mib_node*)ipa_rn; + if (ipa_rn != NULL) + { + if (level == 2) + { + ipa_rn->get_object_def = ip_addrentry_get_object_def; + ipa_rn->get_value = ip_addrentry_get_value; + ipa_rn->set_test = noleafs_set_test; + ipa_rn->set_value = noleafs_set_value; + } + } + else + { + /* ipa_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_ipaddridx_tree() insert failed, mem full")); + break; + } + } + else + { + ipa_rn = (struct mib_list_rootnode*)ipa_node->nptr; + } + } + level++; + } + /* enable getnext traversal on filled table */ + ipaddrtable.maxlength = 1; +} + +/** + * Removes ipAddrTable indexes (.ipAdEntAddr) + * from index tree. + */ +void snmp_delete_ipaddridx_tree(struct netif *ni) +{ + struct mib_list_rootnode *ipa_rn, *next, *del_rn[4]; + struct mib_list_node *ipa_n, *del_n[4]; + s32_t ipaddridx[4]; + u8_t fc, level, del_cnt; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_iptooid(&ni->ip_addr, &ipaddridx[0]); + + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + ipa_rn = &ipaddrtree_root; + while ((level < 4) && (ipa_rn != NULL)) + { + fc = snmp_mib_node_find(ipa_rn, ipaddridx[level], &ipa_n); + if (fc == 0) + { + /* ipaddridx[level] does not exist */ + del_cnt = 0; + ipa_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = ipa_rn; + del_n[del_cnt] = ipa_n; + del_cnt++; + ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + ipa_rn = del_rn[del_cnt]; + ipa_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(ipa_rn, ipa_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + /* disable getnext traversal on empty table */ + if (ipaddrtree_root.count == 0) ipaddrtable.maxlength = 0; +} + +/** + * Inserts ipRouteTable indexes (.ipRouteDest) + * into index tree. + * + * @param dflt non-zero for the default rte, zero for network rte + * @param ni points to network interface for this rte + * + * @todo record sysuptime for _this_ route when it is installed + * (needed for ipRouteAge) in the netif. + */ +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni) +{ + u8_t insert = 0; + ip_addr_t dst; + + if (dflt != 0) + { + /* the default route 0.0.0.0 */ + ip_addr_set_any(&dst); + insert = 1; + } + else + { + /* route to the network address */ + ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); + /* exclude 0.0.0.0 network (reserved for default rte) */ + if (!ip_addr_isany(&dst)) { + insert = 1; + } + } + if (insert) + { + struct mib_list_rootnode *iprte_rn; + struct mib_list_node *iprte_node; + s32_t iprteidx[4]; + u8_t level; + + snmp_iptooid(&dst, &iprteidx[0]); + level = 0; + iprte_rn = &iprtetree_root; + while (level < 4) + { + iprte_node = NULL; + snmp_mib_node_insert(iprte_rn, iprteidx[level], &iprte_node); + if ((level != 3) && (iprte_node != NULL)) + { + if (iprte_node->nptr == NULL) + { + iprte_rn = snmp_mib_lrn_alloc(); + iprte_node->nptr = (struct mib_node*)iprte_rn; + if (iprte_rn != NULL) + { + if (level == 2) + { + iprte_rn->get_object_def = ip_rteentry_get_object_def; + iprte_rn->get_value = ip_rteentry_get_value; + iprte_rn->set_test = noleafs_set_test; + iprte_rn->set_value = noleafs_set_value; + } + } + else + { + /* iprte_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_iprteidx_tree() insert failed, mem full")); + break; + } + } + else + { + iprte_rn = (struct mib_list_rootnode*)iprte_node->nptr; + } + } + level++; + } + } + /* enable getnext traversal on filled table */ + iprtetable.maxlength = 1; +} + +/** + * Removes ipRouteTable indexes (.ipRouteDest) + * from index tree. + * + * @param dflt non-zero for the default rte, zero for network rte + * @param ni points to network interface for this rte or NULL + * for default route to be removed. + */ +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni) +{ + u8_t del = 0; + ip_addr_t dst; + + if (dflt != 0) + { + /* the default route 0.0.0.0 */ + ip_addr_set_any(&dst); + del = 1; + } + else + { + /* route to the network address */ + ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); + /* exclude 0.0.0.0 network (reserved for default rte) */ + if (!ip_addr_isany(&dst)) { + del = 1; + } + } + if (del) + { + struct mib_list_rootnode *iprte_rn, *next, *del_rn[4]; + struct mib_list_node *iprte_n, *del_n[4]; + s32_t iprteidx[4]; + u8_t fc, level, del_cnt; + + snmp_iptooid(&dst, &iprteidx[0]); + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + iprte_rn = &iprtetree_root; + while ((level < 4) && (iprte_rn != NULL)) + { + fc = snmp_mib_node_find(iprte_rn, iprteidx[level], &iprte_n); + if (fc == 0) + { + /* iprteidx[level] does not exist */ + del_cnt = 0; + iprte_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = iprte_rn; + del_n[del_cnt] = iprte_n; + del_cnt++; + iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + iprte_rn = del_rn[del_cnt]; + iprte_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(iprte_rn, iprte_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty table */ + if (iprtetree_root.count == 0) iprtetable.maxlength = 0; +} + + +void snmp_inc_icmpinmsgs(void) +{ + icmpinmsgs++; +} + +void snmp_inc_icmpinerrors(void) +{ + icmpinerrors++; +} + +void snmp_inc_icmpindestunreachs(void) +{ + icmpindestunreachs++; +} + +void snmp_inc_icmpintimeexcds(void) +{ + icmpintimeexcds++; +} + +void snmp_inc_icmpinparmprobs(void) +{ + icmpinparmprobs++; +} + +void snmp_inc_icmpinsrcquenchs(void) +{ + icmpinsrcquenchs++; +} + +void snmp_inc_icmpinredirects(void) +{ + icmpinredirects++; +} + +void snmp_inc_icmpinechos(void) +{ + icmpinechos++; +} + +void snmp_inc_icmpinechoreps(void) +{ + icmpinechoreps++; +} + +void snmp_inc_icmpintimestamps(void) +{ + icmpintimestamps++; +} + +void snmp_inc_icmpintimestampreps(void) +{ + icmpintimestampreps++; +} + +void snmp_inc_icmpinaddrmasks(void) +{ + icmpinaddrmasks++; +} + +void snmp_inc_icmpinaddrmaskreps(void) +{ + icmpinaddrmaskreps++; +} + +void snmp_inc_icmpoutmsgs(void) +{ + icmpoutmsgs++; +} + +void snmp_inc_icmpouterrors(void) +{ + icmpouterrors++; +} + +void snmp_inc_icmpoutdestunreachs(void) +{ + icmpoutdestunreachs++; +} + +void snmp_inc_icmpouttimeexcds(void) +{ + icmpouttimeexcds++; +} + +void snmp_inc_icmpoutparmprobs(void) +{ + icmpoutparmprobs++; +} + +void snmp_inc_icmpoutsrcquenchs(void) +{ + icmpoutsrcquenchs++; +} + +void snmp_inc_icmpoutredirects(void) +{ + icmpoutredirects++; +} + +void snmp_inc_icmpoutechos(void) +{ + icmpoutechos++; +} + +void snmp_inc_icmpoutechoreps(void) +{ + icmpoutechoreps++; +} + +void snmp_inc_icmpouttimestamps(void) +{ + icmpouttimestamps++; +} + +void snmp_inc_icmpouttimestampreps(void) +{ + icmpouttimestampreps++; +} + +void snmp_inc_icmpoutaddrmasks(void) +{ + icmpoutaddrmasks++; +} + +void snmp_inc_icmpoutaddrmaskreps(void) +{ + icmpoutaddrmaskreps++; +} + +void snmp_inc_tcpactiveopens(void) +{ + tcpactiveopens++; +} + +void snmp_inc_tcppassiveopens(void) +{ + tcppassiveopens++; +} + +void snmp_inc_tcpattemptfails(void) +{ + tcpattemptfails++; +} + +void snmp_inc_tcpestabresets(void) +{ + tcpestabresets++; +} + +void snmp_inc_tcpinsegs(void) +{ + tcpinsegs++; +} + +void snmp_inc_tcpoutsegs(void) +{ + tcpoutsegs++; +} + +void snmp_inc_tcpretranssegs(void) +{ + tcpretranssegs++; +} + +void snmp_inc_tcpinerrs(void) +{ + tcpinerrs++; +} + +void snmp_inc_tcpoutrsts(void) +{ + tcpoutrsts++; +} + +void snmp_inc_udpindatagrams(void) +{ + udpindatagrams++; +} + +void snmp_inc_udpnoports(void) +{ + udpnoports++; +} + +void snmp_inc_udpinerrors(void) +{ + udpinerrors++; +} + +void snmp_inc_udpoutdatagrams(void) +{ + udpoutdatagrams++; +} + +/** + * Inserts udpTable indexes (.udpLocalAddress.udpLocalPort) + * into index tree. + */ +void snmp_insert_udpidx_tree(struct udp_pcb *pcb) +{ + struct mib_list_rootnode *udp_rn; + struct mib_list_node *udp_node; + s32_t udpidx[5]; + u8_t level; + + LWIP_ASSERT("pcb != NULL", pcb != NULL); + snmp_iptooid(&pcb->local_ip, &udpidx[0]); + udpidx[4] = pcb->local_port; + + udp_rn = &udp_root; + for (level = 0; level < 5; level++) + { + udp_node = NULL; + snmp_mib_node_insert(udp_rn, udpidx[level], &udp_node); + if ((level != 4) && (udp_node != NULL)) + { + if (udp_node->nptr == NULL) + { + udp_rn = snmp_mib_lrn_alloc(); + udp_node->nptr = (struct mib_node*)udp_rn; + if (udp_rn != NULL) + { + if (level == 3) + { + udp_rn->get_object_def = udpentry_get_object_def; + udp_rn->get_value = udpentry_get_value; + udp_rn->set_test = noleafs_set_test; + udp_rn->set_value = noleafs_set_value; + } + } + else + { + /* udp_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_udpidx_tree() insert failed, mem full")); + break; + } + } + else + { + udp_rn = (struct mib_list_rootnode*)udp_node->nptr; + } + } + } + udptable.maxlength = 1; +} + +/** + * Removes udpTable indexes (.udpLocalAddress.udpLocalPort) + * from index tree. + */ +void snmp_delete_udpidx_tree(struct udp_pcb *pcb) +{ + struct udp_pcb *npcb; + struct mib_list_rootnode *udp_rn, *next, *del_rn[5]; + struct mib_list_node *udp_n, *del_n[5]; + s32_t udpidx[5]; + u8_t bindings, fc, level, del_cnt; + + LWIP_ASSERT("pcb != NULL", pcb != NULL); + snmp_iptooid(&pcb->local_ip, &udpidx[0]); + udpidx[4] = pcb->local_port; + + /* count PCBs for a given binding + (e.g. when reusing ports or for temp output PCBs) */ + bindings = 0; + npcb = udp_pcbs; + while ((npcb != NULL)) + { + if (ip_addr_cmp(&npcb->local_ip, &pcb->local_ip) && + (npcb->local_port == udpidx[4])) + { + bindings++; + } + npcb = npcb->next; + } + if (bindings == 1) + { + /* selectively remove */ + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + udp_rn = &udp_root; + while ((level < 5) && (udp_rn != NULL)) + { + fc = snmp_mib_node_find(udp_rn, udpidx[level], &udp_n); + if (fc == 0) + { + /* udpidx[level] does not exist */ + del_cnt = 0; + udp_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = udp_rn; + del_n[del_cnt] = udp_n; + del_cnt++; + udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + udp_rn = del_rn[del_cnt]; + udp_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(udp_rn, udp_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty table */ + if (udp_root.count == 0) udptable.maxlength = 0; +} + + +void snmp_inc_snmpinpkts(void) +{ + snmpinpkts++; +} + +void snmp_inc_snmpoutpkts(void) +{ + snmpoutpkts++; +} + +void snmp_inc_snmpinbadversions(void) +{ + snmpinbadversions++; +} + +void snmp_inc_snmpinbadcommunitynames(void) +{ + snmpinbadcommunitynames++; +} + +void snmp_inc_snmpinbadcommunityuses(void) +{ + snmpinbadcommunityuses++; +} + +void snmp_inc_snmpinasnparseerrs(void) +{ + snmpinasnparseerrs++; +} + +void snmp_inc_snmpintoobigs(void) +{ + snmpintoobigs++; +} + +void snmp_inc_snmpinnosuchnames(void) +{ + snmpinnosuchnames++; +} + +void snmp_inc_snmpinbadvalues(void) +{ + snmpinbadvalues++; +} + +void snmp_inc_snmpinreadonlys(void) +{ + snmpinreadonlys++; +} + +void snmp_inc_snmpingenerrs(void) +{ + snmpingenerrs++; +} + +void snmp_add_snmpintotalreqvars(u8_t value) +{ + snmpintotalreqvars += value; +} + +void snmp_add_snmpintotalsetvars(u8_t value) +{ + snmpintotalsetvars += value; +} + +void snmp_inc_snmpingetrequests(void) +{ + snmpingetrequests++; +} + +void snmp_inc_snmpingetnexts(void) +{ + snmpingetnexts++; +} + +void snmp_inc_snmpinsetrequests(void) +{ + snmpinsetrequests++; +} + +void snmp_inc_snmpingetresponses(void) +{ + snmpingetresponses++; +} + +void snmp_inc_snmpintraps(void) +{ + snmpintraps++; +} + +void snmp_inc_snmpouttoobigs(void) +{ + snmpouttoobigs++; +} + +void snmp_inc_snmpoutnosuchnames(void) +{ + snmpoutnosuchnames++; +} + +void snmp_inc_snmpoutbadvalues(void) +{ + snmpoutbadvalues++; +} + +void snmp_inc_snmpoutgenerrs(void) +{ + snmpoutgenerrs++; +} + +void snmp_inc_snmpoutgetrequests(void) +{ + snmpoutgetrequests++; +} + +void snmp_inc_snmpoutgetnexts(void) +{ + snmpoutgetnexts++; +} + +void snmp_inc_snmpoutsetrequests(void) +{ + snmpoutsetrequests++; +} + +void snmp_inc_snmpoutgetresponses(void) +{ + snmpoutgetresponses++; +} + +void snmp_inc_snmpouttraps(void) +{ + snmpouttraps++; +} + +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid) +{ + *oid = &snmpgrp_id; +} + +void snmp_set_snmpenableauthentraps(u8_t *value) +{ + if (value != NULL) + { + snmpenableauthentraps_ptr = value; + } +} + +void snmp_get_snmpenableauthentraps(u8_t *value) +{ + *value = *snmpenableauthentraps_ptr; +} + +void +noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + LWIP_UNUSED_ARG(ident_len); + LWIP_UNUSED_ARG(ident); + od->instance = MIB_OBJECT_NONE; +} + +void +noleafs_get_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); +} + +u8_t +noleafs_set_test(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); + /* can't set */ + return 0; +} + +void +noleafs_set_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); +} + + +/** + * Returns systems object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param od points to object definition. + */ +static void +system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def system.%"U16_F".0\n",(u16_t)id)); + switch (id) + { + case 1: /* sysDescr */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *sysdescr_len_ptr; + break; + case 2: /* sysObjectID */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = sysobjid.len * sizeof(s32_t); + break; + case 3: /* sysUpTime */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 4: /* sysContact */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *syscontact_len_ptr; + break; + case 5: /* sysName */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *sysname_len_ptr; + break; + case 6: /* sysLocation */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *syslocation_len_ptr; + break; + case 7: /* sysServices */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns system object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +system_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* sysDescr */ + ocstrncpy((u8_t*)value, sysdescr_ptr, len); + break; + case 2: /* sysObjectID */ + objectidncpy((s32_t*)value, (s32_t*)sysobjid.id, (u8_t)(len / sizeof(s32_t))); + break; + case 3: /* sysUpTime */ + { + snmp_get_sysuptime((u32_t*)value); + } + break; + case 4: /* sysContact */ + ocstrncpy((u8_t*)value, syscontact_ptr, len); + break; + case 5: /* sysName */ + ocstrncpy((u8_t*)value, sysname_ptr, len); + break; + case 6: /* sysLocation */ + ocstrncpy((u8_t*)value, syslocation_ptr, len); + break; + case 7: /* sysServices */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = sysservices; + } + break; + }; +} + +static u8_t +system_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + + LWIP_UNUSED_ARG(value); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 4: /* sysContact */ + if ((syscontact_ptr != syscontact_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + case 5: /* sysName */ + if ((sysname_ptr != sysname_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + case 6: /* sysLocation */ + if ((syslocation_ptr != syslocation_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + }; + return set_ok; +} + +static void +system_set_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_ASSERT("invalid len", len <= 0xff); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 4: /* sysContact */ + ocstrncpy(syscontact_ptr, (u8_t*)value, len); + *syscontact_len_ptr = (u8_t)len; + break; + case 5: /* sysName */ + ocstrncpy(sysname_ptr, (u8_t*)value, len); + *sysname_len_ptr = (u8_t)len; + break; + case 6: /* sysLocation */ + ocstrncpy(syslocation_ptr, (u8_t*)value, len); + *syslocation_len_ptr = (u8_t)len; + break; + }; +} + +/** + * Returns interfaces.ifnumber object definition. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("interfaces_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns interfaces.ifnumber object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +interfaces_get_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(len); + if (od->id_inst_ptr[0] == 1) + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = iflist_root.count; + } +} + +/** + * Returns ifentry object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ifentry.%"U16_F"\n",(u16_t)id)); + switch (id) + { + case 1: /* ifIndex */ + case 3: /* ifType */ + case 4: /* ifMtu */ + case 8: /* ifOperStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ifDescr */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + /** @todo this should be some sort of sizeof(struct netif.name) */ + od->v_len = 2; + break; + case 5: /* ifSpeed */ + case 21: /* ifOutQLen */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + case 6: /* ifPhysAddress */ + { + struct netif *netif; + + snmp_ifindextonetif(ident[1], &netif); + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = netif->hwaddr_len; + } + break; + case 7: /* ifAdminStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ifLastChange */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 10: /* ifInOctets */ + case 11: /* ifInUcastPkts */ + case 12: /* ifInNUcastPkts */ + case 13: /* ifInDiscarts */ + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + case 16: /* ifOutOctets */ + case 17: /* ifOutUcastPkts */ + case 18: /* ifOutNUcastPkts */ + case 19: /* ifOutDiscarts */ + case 20: /* ifOutErrors */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 22: /* ifSpecific */ + /** @note returning zeroDotZero (0.0) no media specific MIB support */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = ifspecific.len * sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns ifentry object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +ifentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id; + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ifIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* ifDescr */ + ocstrncpy((u8_t*)value, (u8_t*)netif->name, len); + break; + case 3: /* ifType */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = netif->link_type; + } + break; + case 4: /* ifMtu */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = netif->mtu; + } + break; + case 5: /* ifSpeed */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->link_speed; + } + break; + case 6: /* ifPhysAddress */ + ocstrncpy((u8_t*)value, netif->hwaddr, len); + break; + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (netif_is_up(netif)) + { + if (netif_is_link_up(netif)) + { + *sint_ptr = 1; /* up */ + } + else + { + *sint_ptr = 7; /* lowerLayerDown */ + } + } + else + { + *sint_ptr = 2; /* down */ + } + } + break; + case 8: /* ifOperStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (netif_is_up(netif)) + { + *sint_ptr = 1; + } + else + { + *sint_ptr = 2; + } + } + break; + case 9: /* ifLastChange */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ts; + } + break; + case 10: /* ifInOctets */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinoctets; + } + break; + case 11: /* ifInUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinucastpkts; + } + break; + case 12: /* ifInNUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinnucastpkts; + } + break; + case 13: /* ifInDiscarts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifindiscards; + } + break; + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + /** @todo add these counters! */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 16: /* ifOutOctets */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutoctets; + } + break; + case 17: /* ifOutUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutucastpkts; + } + break; + case 18: /* ifOutNUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutnucastpkts; + } + break; + case 19: /* ifOutDiscarts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutdiscards; + } + break; + case 20: /* ifOutErrors */ + /** @todo add this counter! */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 21: /* ifOutQLen */ + /** @todo figure out if this must be 0 (no queue) or 1? */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 22: /* ifSpecific */ + objectidncpy((s32_t*)value, (s32_t*)ifspecific.id, (u8_t)(len / sizeof(s32_t))); + break; + }; +} + +#if !SNMP_SAFE_REQUESTS +static u8_t +ifentry_set_test(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id, set_ok; + LWIP_UNUSED_ARG(len); + + set_ok = 0; + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (*sint_ptr == 1 || *sint_ptr == 2) + set_ok = 1; + } + break; + } + return set_ok; +} + +static void +ifentry_set_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id; + LWIP_UNUSED_ARG(len); + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (*sint_ptr == 1) + { + netif_set_up(netif); + } + else if (*sint_ptr == 2) + { + netif_set_down(netif); + } + } + break; + } +} +#endif /* SNMP_SAFE_REQUESTS */ + +/** + * Returns atentry object definitions. + * + * @param ident_len the address length (6) + * @param ident points to objectname.atifindex.atnetaddress + * @param od points to object definition. + */ +static void +atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + switch (ident[0]) + { + case 1: /* atIfIndex */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* atPhysAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = 6; /** @todo try to use netif::hwaddr_len */ + break; + case 3: /* atNetAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +atentry_get_value(struct obj_def *od, u16_t len, void *value) +{ +#if LWIP_ARP + u8_t id; + struct eth_addr* ethaddr_ret; + ip_addr_t* ipaddr_ret; +#endif /* LWIP_ARP */ + ip_addr_t ip; + struct netif *netif; + + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + snmp_oidtoip(&od->id_inst_ptr[2], &ip); + +#if LWIP_ARP /** @todo implement a netif_find_addr */ + if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* atIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* atPhysAddress */ + { + struct eth_addr *dst = (struct eth_addr*)value; + + *dst = *ethaddr_ret; + } + break; + case 3: /* atNetAddress */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + *dst = *ipaddr_ret; + } + break; + } + } +#endif /* LWIP_ARP */ +} + +static void +ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ip.%"U16_F".0\n",(u16_t)id)); + switch (id) + { + case 1: /* ipForwarding */ + case 2: /* ipDefaultTTL */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 3: /* ipInReceives */ + case 4: /* ipInHdrErrors */ + case 5: /* ipInAddrErrors */ + case 6: /* ipForwDatagrams */ + case 7: /* ipInUnknownProtos */ + case 8: /* ipInDiscards */ + case 9: /* ipInDelivers */ + case 10: /* ipOutRequests */ + case 11: /* ipOutDiscards */ + case 12: /* ipOutNoRoutes */ + case 14: /* ipReasmReqds */ + case 15: /* ipReasmOKs */ + case 16: /* ipReasmFails */ + case 17: /* ipFragOKs */ + case 18: /* ipFragFails */ + case 19: /* ipFragCreates */ + case 23: /* ipRoutingDiscards */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 13: /* ipReasmTimeout */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipForwarding */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_FORWARD + /* forwarding */ + *sint_ptr = 1; +#else + /* not-forwarding */ + *sint_ptr = 2; +#endif + } + break; + case 2: /* ipDefaultTTL */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = IP_DEFAULT_TTL; + } + break; + case 3: /* ipInReceives */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinreceives; + } + break; + case 4: /* ipInHdrErrors */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinhdrerrors; + } + break; + case 5: /* ipInAddrErrors */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinaddrerrors; + } + break; + case 6: /* ipForwDatagrams */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipforwdatagrams; + } + break; + case 7: /* ipInUnknownProtos */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinunknownprotos; + } + break; + case 8: /* ipInDiscards */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipindiscards; + } + break; + case 9: /* ipInDelivers */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipindelivers; + } + break; + case 10: /* ipOutRequests */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutrequests; + } + break; + case 11: /* ipOutDiscards */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutdiscards; + } + break; + case 12: /* ipOutNoRoutes */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutnoroutes; + } + break; + case 13: /* ipReasmTimeout */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_REASSEMBLY + *sint_ptr = IP_REASS_MAXAGE; +#else + *sint_ptr = 0; +#endif + } + break; + case 14: /* ipReasmReqds */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmreqds; + } + break; + case 15: /* ipReasmOKs */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmoks; + } + break; + case 16: /* ipReasmFails */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmfails; + } + break; + case 17: /* ipFragOKs */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragoks; + } + break; + case 18: /* ipFragFails */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragfails; + } + break; + case 19: /* ipFragCreates */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragcreates; + } + break; + case 23: /* ipRoutingDiscards */ + /** @todo can lwIP discard routes at all?? hardwire this to 0?? */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = iproutingdiscards; + } + break; + }; +} + +/** + * Test ip object value before setting. + * + * @param od is the object definition + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + * + * @note we allow set if the value matches the hardwired value, + * otherwise return badvalue. + */ +static u8_t +ip_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + s32_t *sint_ptr = (s32_t*)value; + + LWIP_UNUSED_ARG(len); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipForwarding */ +#if IP_FORWARD + /* forwarding */ + if (*sint_ptr == 1) +#else + /* not-forwarding */ + if (*sint_ptr == 2) +#endif + { + set_ok = 1; + } + break; + case 2: /* ipDefaultTTL */ + if (*sint_ptr == IP_DEFAULT_TTL) + { + set_ok = 1; + } + break; + }; + return set_ok; +} + +static void +ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (4) */ + ident_len += 4; + ident -= 4; + + if (ident_len == 5) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipAdEntAddr */ + case 3: /* ipAdEntNetMask */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* ipAdEntIfIndex */ + case 4: /* ipAdEntBcastAddr */ + case 5: /* ipAdEntReasmMaxSize */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + u16_t ifidx; + ip_addr_t ip; + struct netif *netif = netif_list; + + LWIP_UNUSED_ARG(len); + snmp_oidtoip(&od->id_inst_ptr[1], &ip); + ifidx = 0; + while ((netif != NULL) && !ip_addr_cmp(&ip, &netif->ip_addr)) + { + netif = netif->next; + ifidx++; + } + + if (netif != NULL) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipAdEntAddr */ + { + ip_addr_t *dst = (ip_addr_t*)value; + *dst = netif->ip_addr; + } + break; + case 2: /* ipAdEntIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = ifidx + 1; + } + break; + case 3: /* ipAdEntNetMask */ + { + ip_addr_t *dst = (ip_addr_t*)value; + *dst = netif->netmask; + } + break; + case 4: /* ipAdEntBcastAddr */ + { + s32_t *sint_ptr = (s32_t*)value; + + /* lwIP oddity, there's no broadcast + address in the netif we can rely on */ + *sint_ptr = IPADDR_BROADCAST & 1; + } + break; + case 5: /* ipAdEntReasmMaxSize */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_REASSEMBLY + /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, + * but only if receiving one fragmented packet at a time. + * The current solution is to calculate for 2 simultaneous packets... + */ + *sint_ptr = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * + (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - IP_HLEN))); +#else + /** @todo returning MTU would be a bad thing and + returning a wild guess like '576' isn't good either */ + *sint_ptr = 0; +#endif + } + break; + } + } +} + +/** + * @note + * lwIP IP routing is currently using the network addresses in netif_list. + * if no suitable network IP is found in netif_list, the default_netif is used. + */ +static void +ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (4) */ + ident_len += 4; + ident -= 4; + + if (ident_len == 5) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipRouteDest */ + case 7: /* ipRouteNextHop */ + case 11: /* ipRouteMask */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* ipRouteIfIndex */ + case 3: /* ipRouteMetric1 */ + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + case 8: /* ipRouteType */ + case 10: /* ipRouteAge */ + case 12: /* ipRouteMetric5 */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ipRouteProto */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 13: /* ipRouteInfo */ + /** @note returning zeroDotZero (0.0) no routing protocol specific MIB */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = iprouteinfo.len * sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + ip_addr_t dest; + s32_t *ident; + u8_t id; + + ident = od->id_inst_ptr; + snmp_oidtoip(&ident[1], &dest); + + if (ip_addr_isany(&dest)) + { + /* ip_route() uses default netif for default route */ + netif = netif_default; + } + else + { + /* not using ip_route(), need exact match! */ + netif = netif_list; + while ((netif != NULL) && + !ip_addr_netcmp(&dest, &(netif->ip_addr), &(netif->netmask)) ) + { + netif = netif->next; + } + } + if (netif != NULL) + { + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipRouteDest */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte has 0.0.0.0 dest */ + ip_addr_set_zero(dst); + } + else + { + /* netifs have netaddress dest */ + ip_addr_get_network(dst, &netif->ip_addr, &netif->netmask); + } + } + break; + case 2: /* ipRouteIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + + snmp_netiftoifindex(netif, sint_ptr); + } + break; + case 3: /* ipRouteMetric1 */ + { + s32_t *sint_ptr = (s32_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte has metric 1 */ + *sint_ptr = 1; + } + else + { + /* other rtes have metric 0 */ + *sint_ptr = 0; + } + } + break; + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + case 12: /* ipRouteMetric5 */ + { + s32_t *sint_ptr = (s32_t*)value; + /* not used */ + *sint_ptr = -1; + } + break; + case 7: /* ipRouteNextHop */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte: gateway */ + *dst = netif->gw; + } + else + { + /* other rtes: netif ip_addr */ + *dst = netif->ip_addr; + } + } + break; + case 8: /* ipRouteType */ + { + s32_t *sint_ptr = (s32_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte is indirect */ + *sint_ptr = 4; + } + else + { + /* other rtes are direct */ + *sint_ptr = 3; + } + } + break; + case 9: /* ipRouteProto */ + { + s32_t *sint_ptr = (s32_t*)value; + /* locally defined routes */ + *sint_ptr = 2; + } + break; + case 10: /* ipRouteAge */ + { + s32_t *sint_ptr = (s32_t*)value; + /** @todo (sysuptime - timestamp last change) / 100 + @see snmp_insert_iprteidx_tree() */ + *sint_ptr = 0; + } + break; + case 11: /* ipRouteMask */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte use 0.0.0.0 mask */ + ip_addr_set_zero(dst); + } + else + { + /* other rtes use netmask */ + *dst = netif->netmask; + } + } + break; + case 13: /* ipRouteInfo */ + objectidncpy((s32_t*)value, (s32_t*)iprouteinfo.id, (u8_t)(len / sizeof(s32_t))); + break; + } + } +} + +static void +ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipNetToMediaIfIndex */ + case 4: /* ipNetToMediaType */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ipNetToMediaPhysAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = 6; /** @todo try to use netif::hwaddr_len */ + break; + case 3: /* ipNetToMediaNetAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value) +{ +#if LWIP_ARP + u8_t id; + struct eth_addr* ethaddr_ret; + ip_addr_t* ipaddr_ret; +#endif /* LWIP_ARP */ + ip_addr_t ip; + struct netif *netif; + + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + snmp_oidtoip(&od->id_inst_ptr[2], &ip); + +#if LWIP_ARP /** @todo implement a netif_find_addr */ + if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipNetToMediaIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* ipNetToMediaPhysAddress */ + { + struct eth_addr *dst = (struct eth_addr*)value; + + *dst = *ethaddr_ret; + } + break; + case 3: /* ipNetToMediaNetAddress */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + *dst = *ipaddr_ret; + } + break; + case 4: /* ipNetToMediaType */ + { + s32_t *sint_ptr = (s32_t*)value; + /* dynamic (?) */ + *sint_ptr = 3; + } + break; + } + } +#endif /* LWIP_ARP */ +} + +static void +icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if ((ident_len == 2) && + (ident[0] > 0) && (ident[0] < 27)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +icmp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* icmpInMsgs */ + *uint_ptr = icmpinmsgs; + break; + case 2: /* icmpInErrors */ + *uint_ptr = icmpinerrors; + break; + case 3: /* icmpInDestUnreachs */ + *uint_ptr = icmpindestunreachs; + break; + case 4: /* icmpInTimeExcds */ + *uint_ptr = icmpintimeexcds; + break; + case 5: /* icmpInParmProbs */ + *uint_ptr = icmpinparmprobs; + break; + case 6: /* icmpInSrcQuenchs */ + *uint_ptr = icmpinsrcquenchs; + break; + case 7: /* icmpInRedirects */ + *uint_ptr = icmpinredirects; + break; + case 8: /* icmpInEchos */ + *uint_ptr = icmpinechos; + break; + case 9: /* icmpInEchoReps */ + *uint_ptr = icmpinechoreps; + break; + case 10: /* icmpInTimestamps */ + *uint_ptr = icmpintimestamps; + break; + case 11: /* icmpInTimestampReps */ + *uint_ptr = icmpintimestampreps; + break; + case 12: /* icmpInAddrMasks */ + *uint_ptr = icmpinaddrmasks; + break; + case 13: /* icmpInAddrMaskReps */ + *uint_ptr = icmpinaddrmaskreps; + break; + case 14: /* icmpOutMsgs */ + *uint_ptr = icmpoutmsgs; + break; + case 15: /* icmpOutErrors */ + *uint_ptr = icmpouterrors; + break; + case 16: /* icmpOutDestUnreachs */ + *uint_ptr = icmpoutdestunreachs; + break; + case 17: /* icmpOutTimeExcds */ + *uint_ptr = icmpouttimeexcds; + break; + case 18: /* icmpOutParmProbs */ + *uint_ptr = icmpoutparmprobs; + break; + case 19: /* icmpOutSrcQuenchs */ + *uint_ptr = icmpoutsrcquenchs; + break; + case 20: /* icmpOutRedirects */ + *uint_ptr = icmpoutredirects; + break; + case 21: /* icmpOutEchos */ + *uint_ptr = icmpoutechos; + break; + case 22: /* icmpOutEchoReps */ + *uint_ptr = icmpoutechoreps; + break; + case 23: /* icmpOutTimestamps */ + *uint_ptr = icmpouttimestamps; + break; + case 24: /* icmpOutTimestampReps */ + *uint_ptr = icmpouttimestampreps; + break; + case 25: /* icmpOutAddrMasks */ + *uint_ptr = icmpoutaddrmasks; + break; + case 26: /* icmpOutAddrMaskReps */ + *uint_ptr = icmpoutaddrmaskreps; + break; + } +} + +#if LWIP_TCP +/** @todo tcp grp */ +static void +tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); + + switch (id) + { + case 1: /* tcpRtoAlgorithm */ + case 2: /* tcpRtoMin */ + case 3: /* tcpRtoMax */ + case 4: /* tcpMaxConn */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 5: /* tcpActiveOpens */ + case 6: /* tcpPassiveOpens */ + case 7: /* tcpAttemptFails */ + case 8: /* tcpEstabResets */ + case 10: /* tcpInSegs */ + case 11: /* tcpOutSegs */ + case 12: /* tcpRetransSegs */ + case 14: /* tcpInErrs */ + case 15: /* tcpOutRsts */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 9: /* tcpCurrEstab */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +tcp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + s32_t *sint_ptr = (s32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* tcpRtoAlgorithm, vanj(4) */ + *sint_ptr = 4; + break; + case 2: /* tcpRtoMin */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 1000; + break; + case 3: /* tcpRtoMax */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 60000; + break; + case 4: /* tcpMaxConn */ + *sint_ptr = MEMP_NUM_TCP_PCB; + break; + case 5: /* tcpActiveOpens */ + *uint_ptr = tcpactiveopens; + break; + case 6: /* tcpPassiveOpens */ + *uint_ptr = tcppassiveopens; + break; + case 7: /* tcpAttemptFails */ + *uint_ptr = tcpattemptfails; + break; + case 8: /* tcpEstabResets */ + *uint_ptr = tcpestabresets; + break; + case 9: /* tcpCurrEstab */ + { + u16_t tcpcurrestab = 0; + struct tcp_pcb *pcb = tcp_active_pcbs; + while (pcb != NULL) + { + if ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT)) + { + tcpcurrestab++; + } + pcb = pcb->next; + } + *uint_ptr = tcpcurrestab; + } + break; + case 10: /* tcpInSegs */ + *uint_ptr = tcpinsegs; + break; + case 11: /* tcpOutSegs */ + *uint_ptr = tcpoutsegs; + break; + case 12: /* tcpRetransSegs */ + *uint_ptr = tcpretranssegs; + break; + case 14: /* tcpInErrs */ + *uint_ptr = tcpinerrs; + break; + case 15: /* tcpOutRsts */ + *uint_ptr = tcpoutrsts; + break; + } +} +#ifdef THIS_SEEMS_UNUSED +static void +tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (10) */ + ident_len += 10; + ident -= 10; + + if (ident_len == 11) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); + + switch (id) + { + case 1: /* tcpConnState */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* tcpConnLocalAddress */ + case 4: /* tcpConnRemAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 3: /* tcpConnLocalPort */ + case 5: /* tcpConnRemPort */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + ip_addr_t lip, rip; + u16_t lport, rport; + s32_t *ident; + + ident = od->id_inst_ptr; + snmp_oidtoip(&ident[1], &lip); + lport = ident[5]; + snmp_oidtoip(&ident[6], &rip); + rport = ident[10]; + + /** @todo find matching PCB */ +} +#endif /* if 0 */ +#endif + +static void +udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if ((ident_len == 2) && + (ident[0] > 0) && (ident[0] < 6)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +udp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* udpInDatagrams */ + *uint_ptr = udpindatagrams; + break; + case 2: /* udpNoPorts */ + *uint_ptr = udpnoports; + break; + case 3: /* udpInErrors */ + *uint_ptr = udpinerrors; + break; + case 4: /* udpOutDatagrams */ + *uint_ptr = udpoutdatagrams; + break; + } +} + +static void +udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + switch (ident[0]) + { + case 1: /* udpLocalAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* udpLocalPort */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +udpentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + struct udp_pcb *pcb; + ip_addr_t ip; + u16_t port; + + LWIP_UNUSED_ARG(len); + snmp_oidtoip(&od->id_inst_ptr[1], &ip); + LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff)); + port = (u16_t)od->id_inst_ptr[5]; + + pcb = udp_pcbs; + while ((pcb != NULL) && + !(ip_addr_cmp(&pcb->local_ip, &ip) && + (pcb->local_port == port))) + { + pcb = pcb->next; + } + + if (pcb != NULL) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* udpLocalAddress */ + { + ip_addr_t *dst = (ip_addr_t*)value; + *dst = pcb->local_ip; + } + break; + case 2: /* udpLocalPort */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = pcb->local_port; + } + break; + } + } +} + +static void +snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* snmpInPkts */ + case 2: /* snmpOutPkts */ + case 3: /* snmpInBadVersions */ + case 4: /* snmpInBadCommunityNames */ + case 5: /* snmpInBadCommunityUses */ + case 6: /* snmpInASNParseErrs */ + case 8: /* snmpInTooBigs */ + case 9: /* snmpInNoSuchNames */ + case 10: /* snmpInBadValues */ + case 11: /* snmpInReadOnlys */ + case 12: /* snmpInGenErrs */ + case 13: /* snmpInTotalReqVars */ + case 14: /* snmpInTotalSetVars */ + case 15: /* snmpInGetRequests */ + case 16: /* snmpInGetNexts */ + case 17: /* snmpInSetRequests */ + case 18: /* snmpInGetResponses */ + case 19: /* snmpInTraps */ + case 20: /* snmpOutTooBigs */ + case 21: /* snmpOutNoSuchNames */ + case 22: /* snmpOutBadValues */ + case 24: /* snmpOutGenErrs */ + case 25: /* snmpOutGetRequests */ + case 26: /* snmpOutGetNexts */ + case 27: /* snmpOutSetRequests */ + case 28: /* snmpOutGetResponses */ + case 29: /* snmpOutTraps */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 30: /* snmpEnableAuthenTraps */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +snmp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* snmpInPkts */ + *uint_ptr = snmpinpkts; + break; + case 2: /* snmpOutPkts */ + *uint_ptr = snmpoutpkts; + break; + case 3: /* snmpInBadVersions */ + *uint_ptr = snmpinbadversions; + break; + case 4: /* snmpInBadCommunityNames */ + *uint_ptr = snmpinbadcommunitynames; + break; + case 5: /* snmpInBadCommunityUses */ + *uint_ptr = snmpinbadcommunityuses; + break; + case 6: /* snmpInASNParseErrs */ + *uint_ptr = snmpinasnparseerrs; + break; + case 8: /* snmpInTooBigs */ + *uint_ptr = snmpintoobigs; + break; + case 9: /* snmpInNoSuchNames */ + *uint_ptr = snmpinnosuchnames; + break; + case 10: /* snmpInBadValues */ + *uint_ptr = snmpinbadvalues; + break; + case 11: /* snmpInReadOnlys */ + *uint_ptr = snmpinreadonlys; + break; + case 12: /* snmpInGenErrs */ + *uint_ptr = snmpingenerrs; + break; + case 13: /* snmpInTotalReqVars */ + *uint_ptr = snmpintotalreqvars; + break; + case 14: /* snmpInTotalSetVars */ + *uint_ptr = snmpintotalsetvars; + break; + case 15: /* snmpInGetRequests */ + *uint_ptr = snmpingetrequests; + break; + case 16: /* snmpInGetNexts */ + *uint_ptr = snmpingetnexts; + break; + case 17: /* snmpInSetRequests */ + *uint_ptr = snmpinsetrequests; + break; + case 18: /* snmpInGetResponses */ + *uint_ptr = snmpingetresponses; + break; + case 19: /* snmpInTraps */ + *uint_ptr = snmpintraps; + break; + case 20: /* snmpOutTooBigs */ + *uint_ptr = snmpouttoobigs; + break; + case 21: /* snmpOutNoSuchNames */ + *uint_ptr = snmpoutnosuchnames; + break; + case 22: /* snmpOutBadValues */ + *uint_ptr = snmpoutbadvalues; + break; + case 24: /* snmpOutGenErrs */ + *uint_ptr = snmpoutgenerrs; + break; + case 25: /* snmpOutGetRequests */ + *uint_ptr = snmpoutgetrequests; + break; + case 26: /* snmpOutGetNexts */ + *uint_ptr = snmpoutgetnexts; + break; + case 27: /* snmpOutSetRequests */ + *uint_ptr = snmpoutsetrequests; + break; + case 28: /* snmpOutGetResponses */ + *uint_ptr = snmpoutgetresponses; + break; + case 29: /* snmpOutTraps */ + *uint_ptr = snmpouttraps; + break; + case 30: /* snmpEnableAuthenTraps */ + *uint_ptr = *snmpenableauthentraps_ptr; + break; + }; +} + +/** + * Test snmp object value before setting. + * + * @param od is the object definition + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + */ +static u8_t +snmp_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + + LWIP_UNUSED_ARG(len); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + if (id == 30) + { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = (s32_t*)value; + + if (snmpenableauthentraps_ptr != &snmpenableauthentraps_default) + { + /* we should have writable non-volatile mem here */ + if ((*sint_ptr == 1) || (*sint_ptr == 2)) + { + set_ok = 1; + } + } + else + { + /* const or hardwired value */ + if (*sint_ptr == snmpenableauthentraps_default) + { + set_ok = 1; + } + } + } + return set_ok; +} + +static void +snmp_set_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + if (id == 30) + { + /* snmpEnableAuthenTraps */ + /* @todo @fixme: which kind of pointer is 'value'? s32_t or u8_t??? */ + u8_t *ptr = (u8_t*)value; + *snmpenableauthentraps_ptr = *ptr; + } +} + +#endif /* LWIP_SNMP */ diff --git a/ext/lwip/src/core/snmp/mib_structs.c b/ext/lwip/src/core/snmp/mib_structs.c new file mode 100644 index 000000000..2f185cb43 --- /dev/null +++ b/ext/lwip/src/core/snmp/mib_structs.c @@ -0,0 +1,1174 @@ +/** + * @file + * MIB tree access/construction functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_structs.h" +#include "lwip/memp.h" +#include "lwip/netif.h" + +/** .iso.org.dod.internet address prefix, @see snmp_iso_*() */ +const s32_t prefix[4] = {1, 3, 6, 1}; + +#define NODE_STACK_SIZE (LWIP_SNMP_OBJ_ID_LEN) +/** node stack entry (old news?) */ +struct nse +{ + /** right child */ + struct mib_node* r_ptr; + /** right child identifier */ + s32_t r_id; + /** right child next level */ + u8_t r_nl; +}; +static u8_t node_stack_cnt; +static struct nse node_stack[NODE_STACK_SIZE]; + +/** + * Pushes nse struct onto stack. + */ +static void +push_node(struct nse* node) +{ + LWIP_ASSERT("node_stack_cnt < NODE_STACK_SIZE",node_stack_cnt < NODE_STACK_SIZE); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("push_node() node=%p id=%"S32_F"\n",(void*)(node->r_ptr),node->r_id)); + if (node_stack_cnt < NODE_STACK_SIZE) + { + node_stack[node_stack_cnt] = *node; + node_stack_cnt++; + } +} + +/** + * Pops nse struct from stack. + */ +static void +pop_node(struct nse* node) +{ + if (node_stack_cnt > 0) + { + node_stack_cnt--; + *node = node_stack[node_stack_cnt]; + } + LWIP_DEBUGF(SNMP_MIB_DEBUG,("pop_node() node=%p id=%"S32_F"\n",(void *)(node->r_ptr),node->r_id)); +} + +/** + * Conversion from ifIndex to lwIP netif + * @param ifindex is a s32_t object sub-identifier + * @param netif points to returned netif struct pointer + */ +void +snmp_ifindextonetif(s32_t ifindex, struct netif **netif) +{ + struct netif *nif = netif_list; + s32_t i, ifidx; + + ifidx = ifindex - 1; + i = 0; + while ((nif != NULL) && (i < ifidx)) + { + nif = nif->next; + i++; + } + *netif = nif; +} + +/** + * Conversion from lwIP netif to ifIndex + * @param netif points to a netif struct + * @param ifidx points to s32_t object sub-identifier + */ +void +snmp_netiftoifindex(struct netif *netif, s32_t *ifidx) +{ + struct netif *nif = netif_list; + u16_t i; + + i = 0; + while ((nif != NULL) && (nif != netif)) + { + nif = nif->next; + i++; + } + *ifidx = i+1; +} + +/** + * Conversion from oid to lwIP ip_addr + * @param ident points to s32_t ident[4] input + * @param ip points to output struct + */ +void +snmp_oidtoip(s32_t *ident, ip_addr_t *ip) +{ + IP4_ADDR(ip, ident[0], ident[1], ident[2], ident[3]); +} + +/** + * Conversion from lwIP ip_addr to oid + * @param ip points to input struct + * @param ident points to s32_t ident[4] output + */ +void +snmp_iptooid(ip_addr_t *ip, s32_t *ident) +{ + ident[0] = ip4_addr1(ip); + ident[1] = ip4_addr2(ip); + ident[2] = ip4_addr3(ip); + ident[3] = ip4_addr4(ip); +} + +struct mib_list_node * +snmp_mib_ln_alloc(s32_t id) +{ + struct mib_list_node *ln; + + ln = (struct mib_list_node *)memp_malloc(MEMP_SNMP_NODE); + if (ln != NULL) + { + ln->prev = NULL; + ln->next = NULL; + ln->objid = id; + ln->nptr = NULL; + } + return ln; +} + +void +snmp_mib_ln_free(struct mib_list_node *ln) +{ + memp_free(MEMP_SNMP_NODE, ln); +} + +struct mib_list_rootnode * +snmp_mib_lrn_alloc(void) +{ + struct mib_list_rootnode *lrn; + + lrn = (struct mib_list_rootnode*)memp_malloc(MEMP_SNMP_ROOTNODE); + if (lrn != NULL) + { + lrn->get_object_def = noleafs_get_object_def; + lrn->get_value = noleafs_get_value; + lrn->set_test = noleafs_set_test; + lrn->set_value = noleafs_set_value; + lrn->node_type = MIB_NODE_LR; + lrn->maxlength = 0; + lrn->head = NULL; + lrn->tail = NULL; + lrn->count = 0; + } + return lrn; +} + +void +snmp_mib_lrn_free(struct mib_list_rootnode *lrn) +{ + memp_free(MEMP_SNMP_ROOTNODE, lrn); +} + +/** + * Inserts node in idx list in a sorted + * (ascending order) fashion and + * allocates the node if needed. + * + * @param rn points to the root node + * @param objid is the object sub identifier + * @param insn points to a pointer to the inserted node + * used for constructing the tree. + * @return -1 if failed, 1 if inserted, 2 if present. + */ +s8_t +snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn) +{ + struct mib_list_node *nn; + s8_t insert; + + LWIP_ASSERT("rn != NULL",rn != NULL); + + /* -1 = malloc failure, 0 = not inserted, 1 = inserted, 2 = was present */ + insert = 0; + if (rn->head == NULL) + { + /* empty list, add first node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc empty list objid==%"S32_F"\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + rn->head = nn; + rn->tail = nn; + *insn = nn; + insert = 1; + } + else + { + insert = -1; + } + } + else + { + struct mib_list_node *n; + /* at least one node is present */ + n = rn->head; + while ((n != NULL) && (insert == 0)) + { + if (n->objid == objid) + { + /* node is already there */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node already there objid==%"S32_F"\n",objid)); + *insn = n; + insert = 2; + } + else if (n->objid < objid) + { + if (n->next == NULL) + { + /* alloc and insert at the tail */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins tail objid==%"S32_F"\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + nn->next = NULL; + nn->prev = n; + n->next = nn; + rn->tail = nn; + *insn = nn; + insert = 1; + } + else + { + /* insertion failure */ + insert = -1; + } + } + else + { + /* there's more to explore: traverse list */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("traverse list\n")); + n = n->next; + } + } + else + { + /* n->objid > objid */ + /* alloc and insert between n->prev and n */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins n->prev, objid==%"S32_F", n\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + if (n->prev == NULL) + { + /* insert at the head */ + nn->next = n; + nn->prev = NULL; + rn->head = nn; + n->prev = nn; + } + else + { + /* insert in the middle */ + nn->next = n; + nn->prev = n->prev; + n->prev->next = nn; + n->prev = nn; + } + *insn = nn; + insert = 1; + } + else + { + /* insertion failure */ + insert = -1; + } + } + } + } + if (insert == 1) + { + rn->count += 1; + } + LWIP_ASSERT("insert != 0",insert != 0); + return insert; +} + +/** + * Finds node in idx list and returns deletion mark. + * + * @param rn points to the root node + * @param objid is the object sub identifier + * @param fn returns pointer to found node + * @return 0 if not found, 1 if deletable, + * 2 can't delete (2 or more children), 3 not a list_node + */ +s8_t +snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn) +{ + s8_t fc; + struct mib_list_node *n; + + LWIP_ASSERT("rn != NULL",rn != NULL); + n = rn->head; + while ((n != NULL) && (n->objid != objid)) + { + n = n->next; + } + if (n == NULL) + { + fc = 0; + } + else if (n->nptr == NULL) + { + /* leaf, can delete node */ + fc = 1; + } + else + { + struct mib_list_rootnode *r; + + if (n->nptr->node_type == MIB_NODE_LR) + { + r = (struct mib_list_rootnode *)n->nptr; + if (r->count > 1) + { + /* can't delete node */ + fc = 2; + } + else + { + /* count <= 1, can delete node */ + fc = 1; + } + } + else + { + /* other node type */ + fc = 3; + } + } + *fn = n; + return fc; +} + +/** + * Removes node from idx list + * if it has a single child left. + * + * @param rn points to the root node + * @param n points to the node to delete + * @return the nptr to be freed by caller + */ +struct mib_list_rootnode * +snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n) +{ + struct mib_list_rootnode *next; + + LWIP_ASSERT("rn != NULL",rn != NULL); + LWIP_ASSERT("n != NULL",n != NULL); + + /* caller must remove this sub-tree */ + next = (struct mib_list_rootnode*)(n->nptr); + rn->count -= 1; + + if (n == rn->head) + { + rn->head = n->next; + if (n->next != NULL) + { + /* not last node, new list begin */ + n->next->prev = NULL; + } + } + else if (n == rn->tail) + { + rn->tail = n->prev; + if (n->prev != NULL) + { + /* not last node, new list end */ + n->prev->next = NULL; + } + } + else + { + /* node must be in the middle */ + n->prev->next = n->next; + n->next->prev = n->prev; + } + LWIP_DEBUGF(SNMP_MIB_DEBUG,("free list objid==%"S32_F"\n",n->objid)); + snmp_mib_ln_free(n); + if (rn->count == 0) + { + rn->head = NULL; + rn->tail = NULL; + } + return next; +} + + + +/** + * Searches tree for the supplied (scalar?) object identifier. + * + * @param node points to the root of the tree ('.internet') + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param np points to the found object instance (return) + * @return pointer to the requested parent (!) node if success, NULL otherwise + */ +struct mib_node * +snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np) +{ + u8_t node_type, ext_level; + + ext_level = 0; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident)); + while (node != NULL) + { + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + if (ident_len > 0) + { + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + i = 0; + while ((i < an->maxlength) && (an->objid[i] != *ident)) + { + i++; + } + if (i < an->maxlength) + { + /* found it, if available proceed to child, otherwise inspect leaf */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); + if (an->nptr[i] == NULL) + { + /* a scalar leaf OR table, + inspect remaining instance number / table index */ + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)an; + } + else + { + /* follow next child pointer */ + ident++; + ident_len--; + node = an->nptr[i]; + } + } + else + { + /* search failed, identifier mismatch (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n")); + return NULL; + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + if (ident_len > 0) + { + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid != *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + /* found it, proceed to child */; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); + if (ln->nptr == NULL) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)lrn; + } + else + { + /* follow next child pointer */ + ident_len--; + ident++; + node = ln->nptr; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n")); + return NULL; + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + u16_t i, len; + + if (ident_len > 0) + { + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + + i = 0; + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0)) + { + i++; + } + if (i < len) + { + s32_t debug_id; + + en->get_objid(en->addr_inf,ext_level,i,&debug_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident)); + if ((ext_level + 1) == en->tree_levels) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)en; + } + else + { + /* found it, proceed to child */ + ident_len--; + ident++; + ext_level++; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed, short object identifier\n")); + return NULL; + } + } + else if (node_type == MIB_NODE_SC) + { + mib_scalar_node *sn; + + sn = (mib_scalar_node *)node; + if ((ident_len == 1) && (*ident == 0)) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)sn; + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, invalid object identifier length\n")); + return NULL; + } + } + else + { + /* unknown node_type */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node_type %"U16_F" unkown\n",(u16_t)node_type)); + return NULL; + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node==%p\n",(void*)node)); + return NULL; +} + +/** + * Test table for presence of at least one table entry. + */ +static u8_t +empty_table(struct mib_node *node) +{ + u8_t node_type; + u8_t empty = 0; + + if (node != NULL) + { + node_type = node->node_type; + if (node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + lrn = (struct mib_list_rootnode *)node; + if ((lrn->count == 0) || (lrn->head == NULL)) + { + empty = 1; + } + } + else if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + an = (struct mib_array_node *)node; + if ((an->maxlength == 0) || (an->nptr == NULL)) + { + empty = 1; + } + } + else if (node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + en = (struct mib_external_node *)node; + if (en->tree_levels == 0) + { + empty = 1; + } + } + } + return empty; +} + +/** + * Tree expansion. + */ +struct mib_node * +snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) +{ + u8_t node_type, ext_level, climb_tree; + + ext_level = 0; + /* reset node stack */ + node_stack_cnt = 0; + while (node != NULL) + { + climb_tree = 0; + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + if (ident_len > 0) + { + i = 0; + while ((i < an->maxlength) && (an->objid[i] < *ident)) + { + i++; + } + if (i < an->maxlength) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); + /* add identifier to oidret */ + oidret->id[oidret->len] = an->objid[i]; + (oidret->len)++; + + if (an->nptr[i] == NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); + /* leaf node (e.g. in a fixed size table) */ + if (an->objid[i] > *ident) + { + return (struct mib_node*)an; + } + else if ((i + 1) < an->maxlength) + { + /* an->objid[i] == *ident */ + (oidret->len)--; + oidret->id[oidret->len] = an->objid[i + 1]; + (oidret->len)++; + return (struct mib_node*)an; + } + else + { + /* (i + 1) == an->maxlength */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + u8_t j; + struct nse cur_node; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); + /* non-leaf, store right child ptr and id */ + LWIP_ASSERT("i < 0xff", i < 0xff); + j = (u8_t)i + 1; + while ((j < an->maxlength) && (empty_table(an->nptr[j]))) + { + j++; + } + if (j < an->maxlength) + { + cur_node.r_ptr = an->nptr[j]; + cur_node.r_id = an->objid[j]; + cur_node.r_nl = 0; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (an->objid[i] == *ident) + { + ident_len--; + ident++; + } + else + { + /* an->objid[i] < *ident */ + ident_len = 0; + } + /* follow next child pointer */ + node = an->nptr[i]; + } + } + else + { + /* i == an->maxlength */ + climb_tree = 1; + } + } + else + { + u8_t j; + /* ident_len == 0, complete with leftmost '.thing' */ + j = 0; + while ((j < an->maxlength) && empty_table(an->nptr[j])) + { + j++; + } + if (j < an->maxlength) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left an->objid[j]==%"S32_F"\n",an->objid[j])); + oidret->id[oidret->len] = an->objid[j]; + (oidret->len)++; + if (an->nptr[j] == NULL) + { + /* leaf node */ + return (struct mib_node*)an; + } + else + { + /* no leaf, continue */ + node = an->nptr[j]; + } + } + else + { + /* j == an->maxlength */ + climb_tree = 1; + } + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + if (ident_len > 0) + { + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid < *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); + oidret->id[oidret->len] = ln->objid; + (oidret->len)++; + if (ln->nptr == NULL) + { + /* leaf node */ + if (ln->objid > *ident) + { + return (struct mib_node*)lrn; + } + else if (ln->next != NULL) + { + /* ln->objid == *ident */ + (oidret->len)--; + oidret->id[oidret->len] = ln->next->objid; + (oidret->len)++; + return (struct mib_node*)lrn; + } + else + { + /* ln->next == NULL */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + struct mib_list_node *jn; + struct nse cur_node; + + /* non-leaf, store right child ptr and id */ + jn = ln->next; + while ((jn != NULL) && empty_table(jn->nptr)) + { + jn = jn->next; + } + if (jn != NULL) + { + cur_node.r_ptr = jn->nptr; + cur_node.r_id = jn->objid; + cur_node.r_nl = 0; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (ln->objid == *ident) + { + ident_len--; + ident++; + } + else + { + /* ln->objid < *ident */ + ident_len = 0; + } + /* follow next child pointer */ + node = ln->nptr; + } + + } + else + { + /* ln == NULL */ + climb_tree = 1; + } + } + else + { + struct mib_list_node *jn; + /* ident_len == 0, complete with leftmost '.thing' */ + jn = lrn->head; + while ((jn != NULL) && empty_table(jn->nptr)) + { + jn = jn->next; + } + if (jn != NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left jn->objid==%"S32_F"\n",jn->objid)); + oidret->id[oidret->len] = jn->objid; + (oidret->len)++; + if (jn->nptr == NULL) + { + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("jn->nptr == NULL\n")); + return (struct mib_node*)lrn; + } + else + { + /* no leaf, continue */ + node = jn->nptr; + } + } + else + { + /* jn == NULL */ + climb_tree = 1; + } + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + s32_t ex_id; + + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + if (ident_len > 0) + { + u16_t i, len; + + i = 0; + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) < 0)) + { + i++; + } + if (i < len) + { + /* add identifier to oidret */ + en->get_objid(en->addr_inf,ext_level,i,&ex_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,ex_id,*ident)); + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + + if ((ext_level + 1) == en->tree_levels) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); + /* leaf node */ + if (ex_id > *ident) + { + return (struct mib_node*)en; + } + else if ((i + 1) < len) + { + /* ex_id == *ident */ + en->get_objid(en->addr_inf,ext_level,i + 1,&ex_id); + (oidret->len)--; + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + return (struct mib_node*)en; + } + else + { + /* (i + 1) == len */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + u8_t j; + struct nse cur_node; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); + /* non-leaf, store right child ptr and id */ + LWIP_ASSERT("i < 0xff", i < 0xff); + j = (u8_t)i + 1; + if (j < len) + { + /* right node is the current external node */ + cur_node.r_ptr = node; + en->get_objid(en->addr_inf,ext_level,j,&cur_node.r_id); + cur_node.r_nl = ext_level + 1; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (en->ident_cmp(en->addr_inf,ext_level,i,*ident) == 0) + { + ident_len--; + ident++; + } + else + { + /* external id < *ident */ + ident_len = 0; + } + /* proceed to child */ + ext_level++; + } + } + else + { + /* i == len (en->level_len()) */ + climb_tree = 1; + } + } + else + { + /* ident_len == 0, complete with leftmost '.thing' */ + en->get_objid(en->addr_inf,ext_level,0,&ex_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left en->objid==%"S32_F"\n",ex_id)); + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + if ((ext_level + 1) == en->tree_levels) + { + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("(ext_level + 1) == en->tree_levels\n")); + return (struct mib_node*)en; + } + else + { + /* no leaf, proceed to child */ + ext_level++; + } + } + } + else if(node_type == MIB_NODE_SC) + { + mib_scalar_node *sn; + + /* scalar node */ + sn = (mib_scalar_node *)node; + if (ident_len > 0) + { + /* at .0 */ + climb_tree = 1; + } + else + { + /* ident_len == 0, complete object identifier */ + oidret->id[oidret->len] = 0; + (oidret->len)++; + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("completed scalar leaf\n")); + return (struct mib_node*)sn; + } + } + else + { + /* unknown/unhandled node_type */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node_type %"U16_F" unkown\n",(u16_t)node_type)); + return NULL; + } + + if (climb_tree) + { + struct nse child; + + /* find right child ptr */ + child.r_ptr = NULL; + child.r_id = 0; + child.r_nl = 0; + while ((node_stack_cnt > 0) && (child.r_ptr == NULL)) + { + pop_node(&child); + /* trim returned oid */ + (oidret->len)--; + } + if (child.r_ptr != NULL) + { + /* incoming ident is useless beyond this point */ + ident_len = 0; + oidret->id[oidret->len] = child.r_id; + oidret->len++; + node = child.r_ptr; + ext_level = child.r_nl; + } + else + { + /* tree ends here ... */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed, tree ends here\n")); + return NULL; + } + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node==%p\n",(void*)node)); + return NULL; +} + +/** + * Test object identifier for the iso.org.dod.internet prefix. + * + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @return 1 if it matches, 0 otherwise + */ +u8_t +snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident) +{ + if ((ident_len > 3) && + (ident[0] == 1) && (ident[1] == 3) && + (ident[2] == 6) && (ident[3] == 1)) + { + return 1; + } + else + { + return 0; + } +} + +/** + * Expands object identifier to the iso.org.dod.internet + * prefix for use in getnext operation. + * + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param oidret points to returned expanded object identifier + * @return 1 if it matches, 0 otherwise + * + * @note ident_len 0 is allowed, expanding to the first known object id!! + */ +u8_t +snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) +{ + const s32_t *prefix_ptr; + s32_t *ret_ptr; + u8_t i; + + i = 0; + prefix_ptr = &prefix[0]; + ret_ptr = &oidret->id[0]; + ident_len = ((ident_len < 4)?ident_len:4); + while ((i < ident_len) && ((*ident) <= (*prefix_ptr))) + { + *ret_ptr++ = *prefix_ptr++; + ident++; + i++; + } + if (i == ident_len) + { + /* match, complete missing bits */ + while (i < 4) + { + *ret_ptr++ = *prefix_ptr++; + i++; + } + oidret->len = i; + return 1; + } + else + { + /* i != ident_len */ + return 0; + } +} + +#endif /* LWIP_SNMP */ diff --git a/ext/lwip/src/core/snmp/msg_in.c b/ext/lwip/src/core/snmp/msg_in.c new file mode 100644 index 000000000..be940c62d --- /dev/null +++ b/ext/lwip/src/core/snmp/msg_in.c @@ -0,0 +1,1453 @@ +/** + * @file + * SNMP input message processing (RFC1157). + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_msg.h" +#include "lwip/snmp_structs.h" +#include "lwip/ip_addr.h" +#include "lwip/memp.h" +#include "lwip/udp.h" +#include "lwip/stats.h" + +#include + +/* public (non-static) constants */ +/** SNMP v1 == 0 */ +const s32_t snmp_version = 0; +/** default SNMP community string */ +const char snmp_publiccommunity[7] = "public"; + +/* statically allocated buffers for SNMP_CONCURRENT_REQUESTS */ +struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS]; +/* UDP Protocol Control Block */ +struct udp_pcb *snmp1_pcb; + +static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); +static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); +static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); + + +/** + * Starts SNMP Agent. + * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. + */ +void +snmp_init(void) +{ + struct snmp_msg_pstat *msg_ps; + u8_t i; + + snmp1_pcb = udp_new(); + if (snmp1_pcb != NULL) + { + udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT); + udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT); + } + msg_ps = &msg_input_list[0]; + for (i=0; istate = SNMP_MSG_EMPTY; + msg_ps->error_index = 0; + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps++; + } + trap_msg.pcb = snmp1_pcb; + +#ifdef SNMP_PRIVATE_MIB_INIT + /* If defined, this must be a function-like define to initialize the + * private MIB after the stack has been initialized. + * The private MIB can also be initialized in tcpip_callback (or after + * the stack is initialized), this define is only for convenience. */ + SNMP_PRIVATE_MIB_INIT(); +#endif /* SNMP_PRIVATE_MIB_INIT */ + + /* The coldstart trap will only be output + if our outgoing interface is up & configured */ + snmp_coldstart_trap(); +} + +static void +snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error) +{ + /* move names back from outvb to invb */ + int v; + struct snmp_varbind *vbi = msg_ps->invb.head; + struct snmp_varbind *vbo = msg_ps->outvb.head; + for (v=0; vvb_idx; v++) { + vbi->ident_len = vbo->ident_len; + vbo->ident_len = 0; + vbi->ident = vbo->ident; + vbo->ident = NULL; + vbi = vbi->next; + vbo = vbo->next; + } + /* free outvb */ + snmp_varbind_list_free(&msg_ps->outvb); + /* we send invb back */ + msg_ps->outvb = msg_ps->invb; + msg_ps->invb.head = NULL; + msg_ps->invb.tail = NULL; + msg_ps->invb.count = 0; + msg_ps->error_status = error; + /* error index must be 0 for error too big */ + msg_ps->error_index = (error != SNMP_ES_TOOBIG) ? (1 + msg_ps->vb_idx) : 0; + snmp_send_response(msg_ps); + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->state = SNMP_MSG_EMPTY; +} + +static void +snmp_ok_response(struct snmp_msg_pstat *msg_ps) +{ + err_t err_ret; + + err_ret = snmp_send_response(msg_ps); + if (err_ret == ERR_MEM) + { + /* serious memory problem, can't return tooBig */ + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event = %"S32_F"\n",msg_ps->error_status)); + } + /* free varbinds (if available) */ + snmp_varbind_list_free(&msg_ps->invb); + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->state = SNMP_MSG_EMPTY; +} + +/** + * Service an internal or external event for SNMP GET. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_get_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if ((msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) && + (msg_ps->ext_object_def.access & MIB_ACCESS_READ)) + { + msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; + en->get_value_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) + { + struct mib_external_node *en; + struct snmp_varbind *vb; + + /* get_value() answer */ + en = msg_ps->ext_mib_node; + + /* allocate output varbind */ + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + vb->next = NULL; + vb->prev = NULL; + + /* move name from invb to outvb */ + vb->ident = msg_ps->vb_ptr->ident; + vb->ident_len = msg_ps->vb_ptr->ident_len; + /* ensure this memory is refereced once only */ + msg_ps->vb_ptr->ident = NULL; + msg_ps->vb_ptr->ident_len = 0; + + vb->value_type = msg_ps->ext_object_def.asn_type; + LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff); + vb->value_len = (u8_t)msg_ps->ext_object_def.v_len; + if (vb->value_len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE); + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value != NULL) + { + en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + /* search again (if vb_idx < msg_ps->invb.count) */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n")); + msg_ps->vb_ptr->ident = vb->ident; + msg_ps->vb_ptr->ident_len = vb->ident_len; + memp_free(MEMP_SNMP_VARBIND, vb); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + else + { + /* vb->value_len == 0, empty value (e.g. empty string) */ + en->get_value_a(request_id, &msg_ps->ext_object_def, 0, NULL); + vb->value = NULL; + snmp_varbind_tail_add(&msg_ps->outvb, vb); + /* search again (if vb_idx < msg_ps->invb.count) */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /** test object identifier for .iso.org.dod.internet prefix */ + if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) + { + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if ((object_def.instance != MIB_OBJECT_NONE) && + (object_def.access & MIB_ACCESS_READ)) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + if (mn != NULL) + { + struct snmp_varbind *vb; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; + /* allocate output varbind */ + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + vb->next = NULL; + vb->prev = NULL; + + /* move name from invb to outvb */ + vb->ident = msg_ps->vb_ptr->ident; + vb->ident_len = msg_ps->vb_ptr->ident_len; + /* ensure this memory is refereced once only */ + msg_ps->vb_ptr->ident = NULL; + msg_ps->vb_ptr->ident_len = 0; + + vb->value_type = object_def.asn_type; + LWIP_ASSERT("invalid length", object_def.v_len <= 0xff); + vb->value_len = (u8_t)object_def.v_len; + if (vb->value_len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", + vb->value_len <= SNMP_MAX_VALUE_SIZE); + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value != NULL) + { + mn->get_value(&object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n")); + msg_ps->vb_ptr->ident = vb->ident; + msg_ps->vb_ptr->ident_len = vb->ident_len; + vb->ident = NULL; + vb->ident_len = 0; + memp_free(MEMP_SNMP_VARBIND, vb); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + else + { + /* vb->value_len == 0, empty value (e.g. empty string) */ + vb->value = NULL; + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + } + } + } + else + { + mn = NULL; + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + snmp_ok_response(msg_ps); + } +} + +/** + * Service an internal or external event for SNMP GETNEXT. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1], &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; + en->get_value_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1]); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) + { + struct mib_external_node *en; + struct snmp_varbind *vb; + + /* get_value() answer */ + en = msg_ps->ext_mib_node; + + LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff); + vb = snmp_varbind_alloc(&msg_ps->ext_oid, + msg_ps->ext_object_def.asn_type, + (u8_t)msg_ps->ext_object_def.v_len); + if (vb != NULL) + { + en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_obj_id oid; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + if (snmp_iso_prefix_expand(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident, &oid)) + { + if (msg_ps->vb_ptr->ident_len > 3) + { + /* can offset ident_len and ident */ + mn = snmp_expand_tree((struct mib_node*)&internet, + msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &oid); + } + else + { + /* can't offset ident_len -4, ident + 4 */ + mn = snmp_expand_tree((struct mib_node*)&internet, 0, NULL, &oid); + } + } + else + { + mn = NULL; + } + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_oid = oid; + + en->get_object_def_q(en->addr_inf, request_id, 1, &oid.id[oid.len - 1]); + } + else + { + /* internal object */ + struct obj_def object_def; + struct snmp_varbind *vb; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(1, &oid.id[oid.len - 1], &object_def); + + LWIP_ASSERT("invalid length", object_def.v_len <= 0xff); + vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len); + if (vb != NULL) + { + msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; + mn->get_value(&object_def, object_def.v_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + snmp_ok_response(msg_ps); + } +} + +/** + * Service an internal or external event for SNMP SET. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST; + en->set_test_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST) + { + struct mib_external_node *en; + + /* set_test() answer*/ + en = msg_ps->ext_mib_node; + + if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE) + { + if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) && + (en->set_test_a(request_id,&msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) + { + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->set_test_pc(request_id,&msg_ps->ext_object_def); + /* bad value */ + snmp_error_response(msg_ps,SNMP_ES_BADVALUE); + } + } + else + { + en->set_test_pc(request_id,&msg_ps->ext_object_def); + /* object not available for set */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE; + en->set_value_q(request_id, &msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* set_value failed, object has disappeared for some odd reason?? */ + snmp_error_response(msg_ps,SNMP_ES_GENERROR); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE) + { + struct mib_external_node *en; + + /** set_value_a() */ + en = msg_ps->ext_mib_node; + en->set_value_a(request_id, &msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value); + + /** @todo use set_value_pc() if toobig */ + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + msg_ps->vb_idx += 1; + } + + /* test all values before setting */ + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /** test object identifier for .iso.org.dod.internet prefix */ + if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) + { + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + if (mn != NULL) + { + msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST; + + if (object_def.access & MIB_ACCESS_WRITE) + { + if ((object_def.asn_type == msg_ps->vb_ptr->value_type) && + (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) + { + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + /* bad value */ + snmp_error_response(msg_ps,SNMP_ES_BADVALUE); + } + } + else + { + /* object not available for set */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + } + } + } + else + { + mn = NULL; + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + msg_ps->vb_idx = 0; + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + } + + /* set all values "atomically" (be as "atomic" as possible) */ + while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /* skip iso prefix test, was done previously while settesting() */ + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + /* check if object is still available + (e.g. external hot-plug thingy present?) */ + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S; + mn->get_object_def(np.ident_len, np.ident, &object_def); + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); + msg_ps->vb_idx += 1; + } + } + } + if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + /* simply echo the input if we can set it + @todo do we need to return the actual value? + e.g. if value is silently modified or behaves sticky? */ + msg_ps->outvb = msg_ps->invb; + msg_ps->invb.head = NULL; + msg_ps->invb.tail = NULL; + msg_ps->invb.count = 0; + snmp_ok_response(msg_ps); + } +} + + +/** + * Handle one internal or external event. + * Called for one async event. (recv external/private answer) + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + */ +void +snmp_msg_event(u8_t request_id) +{ + struct snmp_msg_pstat *msg_ps; + + if (request_id < SNMP_CONCURRENT_REQUESTS) + { + msg_ps = &msg_input_list[request_id]; + if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) + { + snmp_msg_getnext_event(request_id, msg_ps); + } + else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) + { + snmp_msg_get_event(request_id, msg_ps); + } + else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ) + { + snmp_msg_set_event(request_id, msg_ps); + } + } +} + + +/* lwIP UDP receive callback function */ +static void +snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + struct snmp_msg_pstat *msg_ps; + u8_t req_idx; + err_t err_ret; + u16_t payload_len = p->tot_len; + u16_t payload_ofs = 0; + u16_t varbind_ofs = 0; + + /* suppress unused argument warning */ + LWIP_UNUSED_ARG(arg); + + /* traverse input message process list, look for SNMP_MSG_EMPTY */ + msg_ps = &msg_input_list[0]; + req_idx = 0; + while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY)) + { + req_idx++; + msg_ps++; + } + if (req_idx == SNMP_CONCURRENT_REQUESTS) + { + /* exceeding number of concurrent requests */ + pbuf_free(p); + return; + } + + /* accepting request */ + snmp_inc_snmpinpkts(); + /* record used 'protocol control block' */ + msg_ps->pcb = pcb; + /* source address (network order) */ + msg_ps->sip = *addr; + /* source port (host order (lwIP oddity)) */ + msg_ps->sp = port; + + /* check total length, version, community, pdu type */ + err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps); + /* Only accept requests and requests without error (be robust) */ + /* Reject response and trap headers or error requests as input! */ + if ((err_ret != ERR_OK) || + ((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) && + (msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) && + (msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) || + ((msg_ps->error_status != SNMP_ES_NOERROR) || + (msg_ps->error_index != 0)) ) + { + /* header check failed drop request silently, do not return error! */ + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n")); + return; + } + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community)); + + /* Builds a list of variable bindings. Copy the varbinds from the pbuf + chain to glue them when these are divided over two or more pbuf's. */ + err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps); + /* we've decoded the incoming message, release input msg now */ + pbuf_free(p); + if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0)) + { + /* varbind-list decode failed, or varbind list empty. + drop request silently, do not return error! + (errors are only returned for a specific varbind failure) */ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n")); + return; + } + + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps->error_index = 0; + /* find object for each variable binding */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + /* first variable binding from list to inspect */ + msg_ps->vb_idx = 0; + + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count)); + + /* handle input event and as much objects as possible in one go */ + snmp_msg_event(req_idx); +} + +/** + * Checks and decodes incoming SNMP message header, logs header errors. + * + * @param p points to pbuf chain of SNMP message (UDP payload) + * @param ofs points to first octet of SNMP message + * @param pdu_len the length of the UDP payload + * @param ofs_ret returns the ofset of the variable bindings + * @param m_stat points to the current message request state return + * @return + * - ERR_OK SNMP header is sane and accepted + * - ERR_ARG SNMP header is either malformed or rejected + */ +static err_t +snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) +{ + err_t derr; + u16_t len, ofs_base; + u8_t len_octets; + u8_t type; + s32_t version; + + ofs_base = ofs; + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || + (pdu_len != (1 + len_octets + len)) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (version) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + if (version != 0) + { + /* not version 1 */ + snmp_inc_snmpinbadversions(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR))) + { + /* can't decode or no octet string (community) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community); + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* add zero terminator */ + len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN)); + m_stat->community[len] = 0; + m_stat->com_strlen = (u8_t)len; + if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) + { + /** @todo: move this if we need to check more names */ + snmp_inc_snmpinbadcommunitynames(); + snmp_authfail_trap(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + switch(type) + { + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_REQ): + /* GetRequest PDU */ + snmp_inc_snmpingetrequests(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_NEXT_REQ): + /* GetNextRequest PDU */ + snmp_inc_snmpingetnexts(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP): + /* GetResponse PDU */ + snmp_inc_snmpingetresponses(); + derr = ERR_ARG; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ): + /* SetRequest PDU */ + snmp_inc_snmpinsetrequests(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP): + /* Trap PDU */ + snmp_inc_snmpintraps(); + derr = ERR_ARG; + break; + default: + snmp_inc_snmpinasnparseerrs(); + derr = ERR_ARG; + break; + } + if (derr != ERR_OK) + { + /* unsupported input PDU for this agent (no parse error) */ + return ERR_ARG; + } + m_stat->rt = type & 0x1F; + ofs += (1 + len_octets); + if (len != (pdu_len - (ofs - ofs_base))) + { + /* decoded PDU length does not equal actual payload length */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (request ID) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->rid); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (error-status) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* must be noError (0) for incoming requests. + log errors for mib-2 completeness and for debug purposes */ + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_status); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + switch (m_stat->error_status) + { + case SNMP_ES_TOOBIG: + snmp_inc_snmpintoobigs(); + break; + case SNMP_ES_NOSUCHNAME: + snmp_inc_snmpinnosuchnames(); + break; + case SNMP_ES_BADVALUE: + snmp_inc_snmpinbadvalues(); + break; + case SNMP_ES_READONLY: + snmp_inc_snmpinreadonlys(); + break; + case SNMP_ES_GENERROR: + snmp_inc_snmpingenerrs(); + break; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (error-index) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* must be 0 for incoming requests. + decode anyway to catch bad integers (and dirty tricks) */ + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_index); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + *ofs_ret = ofs; + return ERR_OK; +} + +static err_t +snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) +{ + err_t derr; + u16_t len, vb_len; + u8_t len_octets; + u8_t type; + + /* variable binding list */ + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &vb_len); + if ((derr != ERR_OK) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets); + + /* start with empty list */ + m_stat->invb.count = 0; + m_stat->invb.head = NULL; + m_stat->invb.tail = NULL; + + while (vb_len > 0) + { + struct snmp_obj_id oid, oid_value; + struct snmp_varbind *vb; + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) || + (len == 0) || (len > vb_len)) + { + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets); + vb_len -= (1 + len_octets); + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID))) + { + /* can't decode object name length */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid); + if (derr != ERR_OK) + { + /* can't decode object name */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + vb_len -= (1 + len_octets + len); + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if (derr != ERR_OK) + { + /* can't decode object value length */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + + switch (type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t)); + if (vb != NULL) + { + s32_t *vptr = (s32_t*)vb->value; + + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t)); + if (vb != NULL) + { + u32_t *vptr = (u32_t*)vb->value; + + derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + LWIP_ASSERT("invalid length", len <= 0xff); + vb = snmp_varbind_alloc(&oid, type, (u8_t)len); + if (vb != NULL) + { + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + vb = snmp_varbind_alloc(&oid, type, 0); + if (vb != NULL) + { + snmp_varbind_tail_add(&m_stat->invb, vb); + derr = ERR_OK; + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid_value); + if (derr == ERR_OK) + { + vb = snmp_varbind_alloc(&oid, type, oid_value.len * sizeof(s32_t)); + if (vb != NULL) + { + u8_t i = oid_value.len; + s32_t *vptr = (s32_t*)vb->value; + + while(i > 0) + { + i--; + vptr[i] = oid_value.id[i]; + } + snmp_varbind_tail_add(&m_stat->invb, vb); + derr = ERR_OK; + } + else + { + derr = ERR_ARG; + } + } + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + if (len == 4) + { + /* must be exactly 4 octets! */ + vb = snmp_varbind_alloc(&oid, type, 4); + if (vb != NULL) + { + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + } + else + { + derr = ERR_ARG; + } + break; + default: + derr = ERR_ARG; + break; + } + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + vb_len -= (1 + len_octets + len); + } + + if (m_stat->rt == SNMP_ASN1_PDU_SET_REQ) + { + snmp_add_snmpintotalsetvars(m_stat->invb.count); + } + else + { + snmp_add_snmpintotalreqvars(m_stat->invb.count); + } + + *ofs_ret = ofs; + return ERR_OK; +} + +struct snmp_varbind* +snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len) +{ + struct snmp_varbind *vb; + + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + u8_t i; + + vb->next = NULL; + vb->prev = NULL; + i = oid->len; + vb->ident_len = i; + if (i > 0) + { + LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH); + /* allocate array of s32_t for our object identifier */ + vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE); + if (vb->ident == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate ident value space\n")); + memp_free(MEMP_SNMP_VARBIND, vb); + return NULL; + } + while(i > 0) + { + i--; + vb->ident[i] = oid->id[i]; + } + } + else + { + /* i == 0, pass zero length object identifier */ + vb->ident = NULL; + } + vb->value_type = type; + vb->value_len = len; + if (len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE); + /* allocate raw bytes for our object value */ + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate value space\n")); + if (vb->ident != NULL) + { + memp_free(MEMP_SNMP_VALUE, vb->ident); + } + memp_free(MEMP_SNMP_VARBIND, vb); + return NULL; + } + } + else + { + /* ASN1_NUL type, or zero length ASN1_OC_STR */ + vb->value = NULL; + } + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate varbind space\n")); + } + return vb; +} + +void +snmp_varbind_free(struct snmp_varbind *vb) +{ + if (vb->value != NULL ) + { + memp_free(MEMP_SNMP_VALUE, vb->value); + } + if (vb->ident != NULL ) + { + memp_free(MEMP_SNMP_VALUE, vb->ident); + } + memp_free(MEMP_SNMP_VARBIND, vb); +} + +void +snmp_varbind_list_free(struct snmp_varbind_root *root) +{ + struct snmp_varbind *vb, *prev; + + vb = root->tail; + while ( vb != NULL ) + { + prev = vb->prev; + snmp_varbind_free(vb); + vb = prev; + } + root->count = 0; + root->head = NULL; + root->tail = NULL; +} + +void +snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb) +{ + if (root->count == 0) + { + /* add first varbind to list */ + root->head = vb; + root->tail = vb; + } + else + { + /* add nth varbind to list tail */ + root->tail->next = vb; + vb->prev = root->tail; + root->tail = vb; + } + root->count += 1; +} + +struct snmp_varbind* +snmp_varbind_tail_remove(struct snmp_varbind_root *root) +{ + struct snmp_varbind* vb; + + if (root->count > 0) + { + /* remove tail varbind */ + vb = root->tail; + root->tail = vb->prev; + vb->prev->next = NULL; + root->count -= 1; + } + else + { + /* nothing to remove */ + vb = NULL; + } + return vb; +} + +#endif /* LWIP_SNMP */ diff --git a/ext/lwip/src/core/snmp/msg_out.c b/ext/lwip/src/core/snmp/msg_out.c new file mode 100644 index 000000000..485f076a5 --- /dev/null +++ b/ext/lwip/src/core/snmp/msg_out.c @@ -0,0 +1,674 @@ +/** + * @file + * SNMP output message processing (RFC1157). + * + * Output responses and traps are build in two passes: + * + * Pass 0: iterate over the output message backwards to determine encoding lengths + * Pass 1: the actual forward encoding of internal form into ASN1 + * + * The single-pass encoding method described by Comer & Stevens + * requires extra buffer space and copying for reversal of the packet. + * The buffer requirement can be prohibitively large for big payloads + * (>= 484) therefore we use the two encoding passes. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_msg.h" + +struct snmp_trap_dst +{ + /* destination IP address in network order */ + ip_addr_t dip; + /* set to 0 when disabled, >0 when enabled */ + u8_t enable; +}; +struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; + +/** TRAP message structure */ +struct snmp_msg_trap trap_msg; + +static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len); +static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len); +static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root); + +static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p); +static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p); +static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs); + +/** + * Sets enable switch for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param enable switch if 0 destination is disabled >0 enabled. + */ +void +snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + trap_dst[dst_idx].enable = enable; + } +} + +/** + * Sets IPv4 address for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param dst IPv4 address in host order. + */ +void +snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + ip_addr_set(&trap_dst[dst_idx].dip, dst); + } +} + +/** + * Sends a 'getresponse' message to the request originator. + * + * @param m_stat points to the current message request state source + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the caller is responsible for filling in outvb in the m_stat + * and provide error-status and index (except for tooBig errors) ... + */ +err_t +snmp_send_response(struct snmp_msg_pstat *m_stat) +{ + struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0}; + struct pbuf *p; + u16_t tot_len; + err_t err; + + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&m_stat->outvb); + tot_len = snmp_resp_header_sum(m_stat, tot_len); + + /* try allocating pbuf(s) for complete response */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n")); + + /* can't construct reply, return error-status tooBig */ + m_stat->error_status = SNMP_ES_TOOBIG; + m_stat->error_index = 0; + /* pass 0, recalculate lengths, for empty varbind-list */ + tot_len = snmp_varbind_list_sum(&emptyvb); + tot_len = snmp_resp_header_sum(m_stat, tot_len); + /* retry allocation once for header and empty varbind-list */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + } + if (p != NULL) + { + /* first pbuf alloc try or retry alloc success */ + u16_t ofs; + + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n")); + + /* pass 1, size error, encode packet ino the pbuf(s) */ + ofs = snmp_resp_header_enc(m_stat, p); + snmp_varbind_list_enc(&m_stat->outvb, p, ofs); + + switch (m_stat->error_status) + { + case SNMP_ES_TOOBIG: + snmp_inc_snmpouttoobigs(); + break; + case SNMP_ES_NOSUCHNAME: + snmp_inc_snmpoutnosuchnames(); + break; + case SNMP_ES_BADVALUE: + snmp_inc_snmpoutbadvalues(); + break; + case SNMP_ES_GENERROR: + snmp_inc_snmpoutgenerrs(); + break; + } + snmp_inc_snmpoutgetresponses(); + snmp_inc_snmpoutpkts(); + + /** @todo do we need separate rx and tx pcbs for threaded case? */ + /** connect to the originating source */ + udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp); + err = udp_send(m_stat->pcb, p); + if (err == ERR_MEM) + { + /** @todo release some memory, retry and return tooBig? tooMuchHassle? */ + err = ERR_MEM; + } + else + { + err = ERR_OK; + } + /** disassociate remote address and port with this pcb */ + udp_disconnect(m_stat->pcb); + + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n")); + return err; + } + else + { + /* first pbuf alloc try or retry alloc failed + very low on memory, couldn't return tooBig */ + return ERR_MEM; + } +} + + +/** + * Sends an generic or enterprise specific trap message. + * + * @param generic_trap is the trap code + * @param eoid points to enterprise object identifier + * @param specific_trap used for enterprise traps when generic_trap == 6 + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the caller is responsible for filling in outvb in the trap_msg + * @note the use of the enterpise identifier field + * is per RFC1215. + * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps + * and .iso.org.dod.internet.private.enterprises.yourenterprise + * (sysObjectID) for specific traps. + */ +err_t +snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap) +{ + struct snmp_trap_dst *td; + struct netif *dst_if; + ip_addr_t dst_ip; + struct pbuf *p; + u16_t i,tot_len; + + for (i=0, td = &trap_dst[0]; ienable != 0) && !ip_addr_isany(&td->dip)) + { + /* network order trap destination */ + ip_addr_copy(trap_msg.dip, td->dip); + /* lookup current source address for this dst */ + dst_if = ip_route(&td->dip); + ip_addr_copy(dst_ip, dst_if->ip_addr); + /* @todo: what about IPv6? */ + trap_msg.sip_raw[0] = ip4_addr1(&dst_ip); + trap_msg.sip_raw[1] = ip4_addr2(&dst_ip); + trap_msg.sip_raw[2] = ip4_addr3(&dst_ip); + trap_msg.sip_raw[3] = ip4_addr4(&dst_ip); + trap_msg.gen_trap = generic_trap; + trap_msg.spc_trap = specific_trap; + if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC) + { + /* enterprise-Specific trap */ + trap_msg.enterprise = eoid; + } + else + { + /* generic (MIB-II) trap */ + snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); + } + snmp_get_sysuptime(&trap_msg.ts); + + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&trap_msg.outvb); + tot_len = snmp_trap_header_sum(&trap_msg, tot_len); + + /* allocate pbuf(s) */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p != NULL) + { + u16_t ofs; + + /* pass 1, encode packet ino the pbuf(s) */ + ofs = snmp_trap_header_enc(&trap_msg, p); + snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); + + snmp_inc_snmpouttraps(); + snmp_inc_snmpoutpkts(); + + /** send to the TRAP destination */ + udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT); + + pbuf_free(p); + } + else + { + return ERR_MEM; + } + } + } + return ERR_OK; +} + +void +snmp_coldstart_trap(void) +{ + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0); +} + +void +snmp_authfail_trap(void) +{ + u8_t enable; + snmp_get_snmpenableauthentraps(&enable); + if (enable == 1) + { + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0); + } +} + +/** + * Sums response header field lengths from tail to head and + * returns resp_header_lengths for second encoding pass. + * + * @param vb_len varbind-list length + * @param rhl points to returned header lengths + * @return the required lenght for encoding the response header + */ +static u16_t +snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) +{ + u16_t tot_len; + struct snmp_resp_header_lengths *rhl; + + rhl = &m_stat->rhl; + tot_len = vb_len; + snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen); + snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen); + tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen; + + snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen); + snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen); + tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen; + + snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen); + snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen); + tot_len += 1 + rhl->ridlenlen + rhl->ridlen; + + rhl->pdulen = tot_len; + snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen); + tot_len += 1 + rhl->pdulenlen; + + rhl->comlen = m_stat->com_strlen; + snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen); + tot_len += 1 + rhl->comlenlen + rhl->comlen; + + snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen); + snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen); + tot_len += 1 + rhl->verlen + rhl->verlenlen; + + rhl->seqlen = tot_len; + snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen); + tot_len += 1 + rhl->seqlenlen; + + return tot_len; +} + +/** + * Sums trap header field lengths from tail to head and + * returns trap_header_lengths for second encoding pass. + * + * @param vb_len varbind-list length + * @param thl points to returned header lengths + * @return the required lenght for encoding the trap header + */ +static u16_t +snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) +{ + u16_t tot_len; + struct snmp_trap_header_lengths *thl; + + thl = &m_trap->thl; + tot_len = vb_len; + + snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen); + snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen); + tot_len += 1 + thl->tslen + thl->tslenlen; + + snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen); + snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen); + tot_len += 1 + thl->strplen + thl->strplenlen; + + snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen); + snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen); + tot_len += 1 + thl->gtrplen + thl->gtrplenlen; + + thl->aaddrlen = 4; + snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen); + tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen; + + snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen); + snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen); + tot_len += 1 + thl->eidlen + thl->eidlenlen; + + thl->pdulen = tot_len; + snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); + tot_len += 1 + thl->pdulenlen; + + thl->comlen = sizeof(snmp_publiccommunity) - 1; + snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); + tot_len += 1 + thl->comlenlen + thl->comlen; + + snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen); + snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen); + tot_len += 1 + thl->verlen + thl->verlenlen; + + thl->seqlen = tot_len; + snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen); + tot_len += 1 + thl->seqlenlen; + + return tot_len; +} + +/** + * Sums varbind lengths from tail to head and + * annotates lengths in varbind for second encoding pass. + * + * @param root points to the root of the variable binding list + * @return the required lenght for encoding the variable bindings + */ +static u16_t +snmp_varbind_list_sum(struct snmp_varbind_root *root) +{ + struct snmp_varbind *vb; + u32_t *uint_ptr; + s32_t *sint_ptr; + u16_t tot_len; + + tot_len = 0; + vb = root->tail; + while ( vb != NULL ) + { + /* encoded value lenght depends on type */ + switch (vb->value_type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen); + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + uint_ptr = (u32_t*)vb->value; + snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + vb->vlen = vb->value_len; + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen); + break; + default: + /* unsupported type */ + vb->vlen = 0; + break; + }; + /* encoding length of value length field */ + snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen); + snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen); + snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen); + + vb->seqlen = 1 + vb->vlenlen + vb->vlen; + vb->seqlen += 1 + vb->olenlen + vb->olen; + snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen); + + /* varbind seq */ + tot_len += 1 + vb->seqlenlen + vb->seqlen; + + vb = vb->prev; + } + + /* varbind-list seq */ + root->seqlen = tot_len; + snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen); + tot_len += 1 + root->seqlenlen; + + return tot_len; +} + +/** + * Encodes response header from head to tail. + */ +static u16_t +snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) +{ + u16_t ofs; + + ofs = 0; + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen); + ofs += m_stat->rhl.seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen); + ofs += m_stat->rhl.verlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version); + ofs += m_stat->rhl.verlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen); + ofs += m_stat->rhl.comlenlen; + snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community); + ofs += m_stat->rhl.comlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen); + ofs += m_stat->rhl.pdulenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen); + ofs += m_stat->rhl.ridlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid); + ofs += m_stat->rhl.ridlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen); + ofs += m_stat->rhl.errstatlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status); + ofs += m_stat->rhl.errstatlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen); + ofs += m_stat->rhl.erridxlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index); + ofs += m_stat->rhl.erridxlen; + + return ofs; +} + +/** + * Encodes trap header from head to tail. + */ +static u16_t +snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) +{ + u16_t ofs; + + ofs = 0; + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen); + ofs += m_trap->thl.seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen); + ofs += m_trap->thl.verlenlen; + snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version); + ofs += m_trap->thl.verlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); + ofs += m_trap->thl.comlenlen; + snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]); + ofs += m_trap->thl.comlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen); + ofs += m_trap->thl.pdulenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen); + ofs += m_trap->thl.eidlenlen; + snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]); + ofs += m_trap->thl.eidlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen); + ofs += m_trap->thl.aaddrlenlen; + snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]); + ofs += m_trap->thl.aaddrlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen); + ofs += m_trap->thl.gtrplenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap); + ofs += m_trap->thl.gtrplen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen); + ofs += m_trap->thl.strplenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap); + ofs += m_trap->thl.strplen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen); + ofs += m_trap->thl.tslenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts); + ofs += m_trap->thl.tslen; + + return ofs; +} + +/** + * Encodes varbind list from head to tail. + */ +static u16_t +snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs) +{ + struct snmp_varbind *vb; + s32_t *sint_ptr; + u32_t *uint_ptr; + u8_t *raw_ptr; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, root->seqlen); + ofs += root->seqlenlen; + + vb = root->head; + while ( vb != NULL ) + { + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->seqlen); + ofs += vb->seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->olen); + ofs += vb->olenlen; + snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]); + ofs += vb->olen; + + snmp_asn1_enc_type(p, ofs, vb->value_type); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->vlen); + ofs += vb->vlenlen; + + switch (vb->value_type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr); + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + uint_ptr = (u32_t*)vb->value; + snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + raw_ptr = (u8_t*)vb->value; + snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr); + break; + default: + /* unsupported type */ + break; + }; + ofs += vb->vlen; + vb = vb->next; + } + return ofs; +} + +#endif /* LWIP_SNMP */ diff --git a/ext/lwip/src/core/stats.c b/ext/lwip/src/core/stats.c new file mode 100644 index 000000000..8ea824976 --- /dev/null +++ b/ext/lwip/src/core/stats.c @@ -0,0 +1,176 @@ +/** + * @file + * Statistics module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" + +#include + +struct stats_ lwip_stats; + +void stats_init(void) +{ +#ifdef LWIP_DEBUG +#if MEMP_STATS + const char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + int i; + for (i = 0; i < MEMP_MAX; i++) { + lwip_stats.memp[i].name = memp_names[i]; + } +#endif /* MEMP_STATS */ +#if MEM_STATS + lwip_stats.mem.name = "MEM"; +#endif /* MEM_STATS */ +#endif /* LWIP_DEBUG */ +} + +#if LWIP_STATS_DISPLAY +void +stats_display_proto(struct stats_proto *proto, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); + LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); + LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); + LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); + LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); + LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); +} + +#if IGMP_STATS +void +stats_display_igmp(struct stats_igmp *igmp) +{ + LWIP_PLATFORM_DIAG(("\nIGMP\n\t")); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); + LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); + LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n", igmp->rx_group)); + LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n", igmp->rx_general)); + LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); + LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); + LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); + LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report)); +} +#endif /* IGMP_STATS */ + +#if MEM_STATS || MEMP_STATS +void +stats_display_mem(struct stats_mem *mem, const char *name) +{ + LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); + LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); + LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); + LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); + LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); +} + +#if MEMP_STATS +void +stats_display_memp(struct stats_mem *mem, int index) +{ + char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + if(index < MEMP_MAX) { + stats_display_mem(mem, memp_names[index]); + } +} +#endif /* MEMP_STATS */ +#endif /* MEM_STATS || MEMP_STATS */ + +#if SYS_STATS +void +stats_display_sys(struct stats_sys *sys) +{ + LWIP_PLATFORM_DIAG(("\nSYS\n\t")); + LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); + LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); + LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); + LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); + LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); + LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); + LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); + LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); + LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err)); +} +#endif /* SYS_STATS */ + +void +stats_display(void) +{ + s16_t i; + + LINK_STATS_DISPLAY(); + ETHARP_STATS_DISPLAY(); + IPFRAG_STATS_DISPLAY(); + IP_STATS_DISPLAY(); + IGMP_STATS_DISPLAY(); + ICMP_STATS_DISPLAY(); + UDP_STATS_DISPLAY(); + TCP_STATS_DISPLAY(); + MEM_STATS_DISPLAY(); + for (i = 0; i < MEMP_MAX; i++) { + MEMP_STATS_DISPLAY(i); + } + SYS_STATS_DISPLAY(); +} +#endif /* LWIP_STATS_DISPLAY */ + +#endif /* LWIP_STATS */ + diff --git a/ext/lwip/src/core/sys.c b/ext/lwip/src/core/sys.c new file mode 100644 index 000000000..f17773726 --- /dev/null +++ b/ext/lwip/src/core/sys.c @@ -0,0 +1,68 @@ +/** + * @file + * lwIP Operating System abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/sys.h" + +/* Most of the functions defined in sys.h must be implemented in the + * architecture-dependent file sys_arch.c */ + +#if !NO_SYS + +#ifndef sys_msleep +/** + * Sleep for some ms. Timeouts are NOT processed while sleeping. + * + * @param ms number of milliseconds to sleep + */ +void +sys_msleep(u32_t ms) +{ + if (ms > 0) { + sys_sem_t delaysem; + err_t err = sys_sem_new(&delaysem, 0); + if (err == ERR_OK) { + sys_arch_sem_wait(&delaysem, ms); + sys_sem_free(&delaysem); + } + } +} +#endif /* sys_msleep */ + +#endif /* !NO_SYS */ diff --git a/ext/lwip/src/core/tcp.c b/ext/lwip/src/core/tcp.c new file mode 100644 index 000000000..105b68e74 --- /dev/null +++ b/ext/lwip/src/core/tcp.c @@ -0,0 +1,1742 @@ +/** + * @file + * Transmission Control Protocol for IP + * + * This file contains common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/snmp.h" +#include "lwip/tcp.h" +#include "lwip/tcp_impl.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + +#include + +#ifndef TCP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define TCP_LOCAL_PORT_RANGE_START 0xc000 +#define TCP_LOCAL_PORT_RANGE_END 0xffff +#define TCP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START) +#endif + +#if LWIP_TCP_KEEPALIVE +#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) +#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) +#else /* LWIP_TCP_KEEPALIVE */ +#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE +#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT +#endif /* LWIP_TCP_KEEPALIVE */ + +const char * const tcp_state_str[] = { + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" +}; + +/* last local TCP port */ +static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; + +/* Incremented every coarse grained timer shot (typically every 500 ms). */ +u32_t tcp_ticks; +const u8_t tcp_backoff[13] = + { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; + /* Times per slowtmr hits */ +const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; + +/* The TCP PCB lists. */ + +/** List of all TCP PCBs bound but not yet (connected || listening) */ +struct tcp_pcb *tcp_bound_pcbs; +/** List of all TCP PCBs in LISTEN state */ +union tcp_listen_pcbs_t tcp_listen_pcbs; +/** List of all TCP PCBs that are in a state in which + * they accept or send data. */ +struct tcp_pcb *tcp_active_pcbs; +/** List of all TCP PCBs in TIME-WAIT state */ +struct tcp_pcb *tcp_tw_pcbs; + +#define NUM_TCP_PCB_LISTS 4 +#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 +/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + &tcp_active_pcbs, &tcp_tw_pcbs}; + +/** Only used for temporary storage. */ +struct tcp_pcb *tcp_tmp_pcb; + +u8_t tcp_active_pcbs_changed; + +/** Timer counter to handle calling slow-timer from tcp_tmr() */ +static u8_t tcp_timer; +static u8_t tcp_timer_ctr; +static u16_t tcp_new_port(void); + +/** + * Initialize this module. + */ +void +tcp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Called periodically to dispatch TCP timers. + */ +void +tcp_tmr(void) +{ + /* Call tcp_fasttmr() every 250 ms */ + tcp_fasttmr(); + + if (++tcp_timer & 1) { + /* Call tcp_tmr() every 500 ms, i.e., every other timer + tcp_tmr() is called. */ + tcp_slowtmr(); + } +} + +/** + * Closes the TX side of a connection held by the PCB. + * For tcp_close(), a RST is sent if the application didn't receive all data + * (tcp_recved() not called for all data passed to recv callback). + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it. + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +static err_t +tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) +{ + err_t err; + + if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { + if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) { + /* Not all data received by application, send RST to tell the remote + side about this. */ + LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); + + /* don't call tcp_abort here: we must not deallocate the pcb since + that might not be expected when calling tcp_close */ + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + if (pcb->state == ESTABLISHED) { + /* move to TIME_WAIT since we close actively */ + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ + memp_free(MEMP_TCP_PCB, pcb); + } + return ERR_OK; + } + } + + switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + err = ERR_OK; + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + break; + case LISTEN: + err = ERR_OK; + tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); + memp_free(MEMP_TCP_PCB_LISTEN, pcb); + pcb = NULL; + break; + case SYN_SENT: + err = ERR_OK; + TCP_PCB_REMOVE_ACTIVE(pcb); + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + snmp_inc_tcpattemptfails(); + break; + case SYN_RCVD: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpattemptfails(); + pcb->state = FIN_WAIT_1; + } + break; + case ESTABLISHED: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = FIN_WAIT_1; + } + break; + case CLOSE_WAIT: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = LAST_ACK; + } + break; + default: + /* Has already been closed, do nothing. */ + err = ERR_OK; + pcb = NULL; + break; + } + + if (pcb != NULL && err == ERR_OK) { + /* To ensure all data has been sent when tcp_close returns, we have + to make sure tcp_output doesn't fail. + Since we don't really have to ensure all data has been sent when tcp_close + returns (unsent data is sent from tcp timer functions, also), we don't care + for the return value of tcp_output for now. */ + /* @todo: When implementing SO_LINGER, this must be changed somehow: + If SOF_LINGER is set, the data should be sent and acked before close returns. + This can only be valid for sequential APIs, not for the raw API. */ + tcp_output(pcb); + } + return err; +} + +/** + * Closes the connection held by the PCB. + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it (unless an error is returned). + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +err_t +tcp_close(struct tcp_pcb *pcb) +{ +#if TCP_DEBUG + LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ + + if (pcb->state != LISTEN) { + /* Set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + } + /* ... and close */ + return tcp_close_shutdown(pcb, 1); +} + +/** + * Causes all or part of a full-duplex connection of this PCB to be shut down. + * This doesn't deallocate the PCB unless shutting down both sides! + * Shutting down both sides is the same as calling tcp_close, so if it succeds, + * the PCB should not be referenced any more. + * + * @param pcb PCB to shutdown + * @param shut_rx shut down receive side if this is != 0 + * @param shut_tx shut down send side if this is != 0 + * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) + * another err_t on error. + */ +err_t +tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) +{ + if (pcb->state == LISTEN) { + return ERR_CONN; + } + if (shut_rx) { + /* shut down the receive side: set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + if (shut_tx) { + /* shutting down the tx AND rx side is the same as closing for the raw API */ + return tcp_close_shutdown(pcb, 1); + } + /* ... and free buffered data */ + if (pcb->refused_data != NULL) { + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + } + if (shut_tx) { + /* This can't happen twice since if it succeeds, the pcb's state is changed. + Only close in these states as the others directly deallocate the PCB */ + switch (pcb->state) { + case SYN_RCVD: + case ESTABLISHED: + case CLOSE_WAIT: + return tcp_close_shutdown(pcb, shut_rx); + default: + /* Not (yet?) connected, cannot shutdown the TX side as that would bring us + into CLOSED state, where the PCB is deallocated. */ + return ERR_CONN; + } + } + return ERR_OK; +} + +/** + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. + * + * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent + */ +void +tcp_abandon(struct tcp_pcb *pcb, int reset) +{ + u32_t seqno, ackno; +#if LWIP_CALLBACK_API + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + void *errf_arg; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", + pcb->state != LISTEN); + /* Figure out on which TCP PCB list we are, and remove us. If we + are in an active state, call the receive function associated with + the PCB with a NULL argument, and send an RST to the remote end. */ + if (pcb->state == TIME_WAIT) { + tcp_pcb_remove(&tcp_tw_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + seqno = pcb->snd_nxt; + ackno = pcb->rcv_nxt; +#if LWIP_CALLBACK_API + errf = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + errf_arg = pcb->callback_arg; + TCP_PCB_REMOVE_ACTIVE(pcb); + if (pcb->unacked != NULL) { + tcp_segs_free(pcb->unacked); + } + if (pcb->unsent != NULL) { + tcp_segs_free(pcb->unsent); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + tcp_segs_free(pcb->ooseq); + } +#endif /* TCP_QUEUE_OOSEQ */ + if (reset) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port); + } + memp_free(MEMP_TCP_PCB, pcb); + TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); + } +} + +/** + * Aborts the connection by sending a RST (reset) segment to the remote + * host. The pcb is deallocated. This function never fails. + * + * ATTENTION: When calling this from one of the TCP callbacks, make + * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + * or you will risk accessing deallocated memory or memory leaks! + * + * @param pcb the tcp pcb to abort + */ +void +tcp_abort(struct tcp_pcb *pcb) +{ + tcp_abandon(pcb, 1); +} + +/** + * Binds the connection to a local portnumber and IP address. If the + * IP address is not given (i.e., ipaddr == NULL), the IP address of + * the outgoing network interface is used instead. + * + * @param pcb the tcp_pcb to bind (no check is done whether this pcb is + * already bound!) + * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind + * to any local address + * @param port the local port to bind to + * @return ERR_USE if the port is already in use + * ERR_VAL if bind failed because the PCB is not in a valid state + * ERR_OK if bound + */ +err_t +tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + int i; + int max_pcb_list = NUM_TCP_PCB_LISTS; + struct tcp_pcb *cpcb; + + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); + +#if SO_REUSE + /* Unless the REUSEADDR flag is set, + we have to check the pcbs in TIME-WAIT state, also. + We do not dump TIME_WAIT pcb's; they can still be matched by incoming + packets using both local and remote IP addresses and ports to distinguish. + */ + if (ip_get_option(pcb, SOF_REUSEADDR)) { + max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; + } +#endif /* SO_REUSE */ + + if (port == 0) { + port = tcp_new_port(); + if (port == 0) { + return ERR_BUF; + } + } + + /* Check if the address already is in use (on all lists) */ + for (i = 0; i < max_pcb_list; i++) { + for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { +#if SO_REUSE + /* Omit checking for the same port if both pcbs have REUSEADDR set. + For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in + tcp_connect. */ + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(cpcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + if (ip_addr_isany(&(cpcb->local_ip)) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { + return ERR_USE; + } + } + } + } + } + + if (!ip_addr_isany(ipaddr)) { + pcb->local_ip = *ipaddr; + } + pcb->local_port = port; + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); + return ERR_OK; +} +#if LWIP_CALLBACK_API +/** + * Default accept callback if no accept callback is specified by the user. + */ +static err_t +tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(err); + + return ERR_ABRT; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen(tpcb); + */ +struct tcp_pcb * +tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + struct tcp_pcb_listen *lpcb; + + LWIP_UNUSED_ARG(backlog); + LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); + + /* already listening? */ + if (pcb->state == LISTEN) { + return pcb; + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage + is declared (listen-/connection-pcb), we have to make sure now that + this port is only used once for every local IP. */ + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == pcb->local_port) { + if (ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { + /* this address/port is already used */ + return NULL; + } + } + } + } +#endif /* SO_REUSE */ + lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); + if (lpcb == NULL) { + return NULL; + } + lpcb->callback_arg = pcb->callback_arg; + lpcb->local_port = pcb->local_port; + lpcb->state = LISTEN; + lpcb->prio = pcb->prio; + lpcb->so_options = pcb->so_options; + ip_set_option(lpcb, SOF_ACCEPTCONN); + lpcb->ttl = pcb->ttl; + lpcb->tos = pcb->tos; + ip_addr_copy(lpcb->local_ip, pcb->local_ip); + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); +#if LWIP_CALLBACK_API + lpcb->accept = tcp_accept_null; +#endif /* LWIP_CALLBACK_API */ +#if TCP_LISTEN_BACKLOG + lpcb->accepts_pending = 0; + lpcb->backlog = (backlog ? backlog : 1); +#endif /* TCP_LISTEN_BACKLOG */ + TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); + return (struct tcp_pcb *)lpcb; +} + +/** + * Update the state that tracks the available window space to advertise. + * + * Returns how much extra window would be advertised if we sent an + * update now. + */ +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) +{ + u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; + + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + /* we can advertise more window */ + pcb->rcv_ann_wnd = pcb->rcv_wnd; + return new_right_edge - pcb->rcv_ann_right_edge; + } else { + if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { + /* Can happen due to other end sending out of advertised window, + * but within actual available (but not yet advertised) window */ + pcb->rcv_ann_wnd = 0; + } else { + /* keep the right edge of window constant */ + u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; + LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); + pcb->rcv_ann_wnd = (u16_t)new_rcv_ann_wnd; + } + return 0; + } +} + +/** + * This function should be called by the application when it has + * processed the data. The purpose is to advertise a larger window + * when the data has been processed. + * + * @param pcb the tcp_pcb for which data is read + * @param len the amount of bytes that have been read by the application + */ +void +tcp_recved(struct tcp_pcb *pcb, u16_t len) +{ + int wnd_inflation; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_recved for listen-pcbs", + pcb->state != LISTEN); + LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", + len <= 0xffff - pcb->rcv_wnd ); + + pcb->rcv_wnd += len; + if (pcb->rcv_wnd > TCP_WND) { + pcb->rcv_wnd = TCP_WND; + } + + wnd_inflation = tcp_update_rcv_ann_wnd(pcb); + + /* If the change in the right edge of window is significant (default + * watermark is TCP_WND/4), then send an explicit update now. + * Otherwise wait for a packet to be sent in the normal course of + * events (or more window to be available later) */ + if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { + tcp_ack_now(pcb); + tcp_output(pcb); + } + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", + len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); +} + +/** + * Allocate a new local TCP port. + * + * @return a new (free) local TCP port number + */ +static u16_t +tcp_new_port(void) +{ + u8_t i; + u16_t n = 0; + struct tcp_pcb *pcb; + +again: + if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { + tcp_port = TCP_LOCAL_PORT_RANGE_START; + } + /* Check all PCB lists. */ + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { + for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == tcp_port) { + if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + } + return tcp_port; +} + +/** + * Connects to another host. The function given as the "connected" + * argument will be called when the connection has been established. + * + * @param pcb the tcp_pcb used to establish the connection + * @param ipaddr the remote ip address to connect to + * @param port the remote tcp port to connect to + * @param connected callback function to call when connected (or on error) + * @return ERR_VAL if invalid arguments are given + * ERR_OK if connect request has been sent + * other err_t values if connect request couldn't be sent + */ +err_t +tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, + tcp_connected_fn connected) +{ + err_t ret; + u32_t iss; + u16_t old_local_port; + + LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); + if (ipaddr != NULL) { + pcb->remote_ip = *ipaddr; + } else { + return ERR_VAL; + } + pcb->remote_port = port; + + /* check if we have a route to the remote host */ + if (ip_addr_isany(&(pcb->local_ip))) { + /* no local IP address set, yet. */ + struct netif *netif = ip_route(&(pcb->remote_ip)); + if (netif == NULL) { + /* Don't even try to send a SYN packet if we have no route + since that will fail. */ + return ERR_RTE; + } + /* Use the netif's IP address as local address. */ + ip_addr_copy(pcb->local_ip, netif->ip_addr); + } + + old_local_port = pcb->local_port; + if (pcb->local_port == 0) { + pcb->local_port = tcp_new_port(); + if (pcb->local_port == 0) { + return ERR_BUF; + } + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure + now that the 5-tuple is unique. */ + struct tcp_pcb *cpcb; + int i; + /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ + for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { + for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if ((cpcb->local_port == pcb->local_port) && + (cpcb->remote_port == port) && + ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && + ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { + /* linux returns EISCONN here, but ERR_USE should be OK for us */ + return ERR_USE; + } + } + } + } +#endif /* SO_REUSE */ + iss = tcp_next_iss(); + pcb->rcv_nxt = 0; + pcb->snd_nxt = iss; + pcb->lastack = iss - 1; + pcb->snd_lbb = iss - 1; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->snd_wnd = TCP_WND; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + pcb->cwnd = 1; + pcb->ssthresh = pcb->mss * 10; +#if LWIP_CALLBACK_API + pcb->connected = connected; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(connected); +#endif /* LWIP_CALLBACK_API */ + + /* Send a SYN together with the MSS option. */ + ret = tcp_enqueue_flags(pcb, TCP_SYN); + if (ret == ERR_OK) { + /* SYN segment was enqueued, changed the pcbs state now */ + pcb->state = SYN_SENT; + if (old_local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + TCP_REG_ACTIVE(pcb); + snmp_inc_tcpactiveopens(); + + tcp_output(pcb); + } + return ret; +} + +/** + * Called every 500 ms and implements the retransmission timer and the timer that + * removes PCBs that have been in TIME-WAIT for enough time. It also increments + * various timers such as the inactivity timer in each PCB. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_slowtmr(void) +{ + struct tcp_pcb *pcb, *prev; + u16_t eff_wnd; + u8_t pcb_remove; /* flag if a PCB should be removed */ + u8_t pcb_reset; /* flag if a RST should be sent when removing */ + err_t err; + + err = ERR_OK; + + ++tcp_ticks; + ++tcp_timer_ctr; + +tcp_slowtmr_start: + /* Steps through all of the active PCBs. */ + prev = NULL; + pcb = tcp_active_pcbs; + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } + while (pcb != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + if (pcb->last_timer == tcp_timer_ctr) { + /* skip this pcb, we have already processed it */ + pcb = pcb->next; + continue; + } + pcb->last_timer = tcp_timer_ctr; + + pcb_remove = 0; + pcb_reset = 0; + + if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); + } + else if (pcb->nrtx == TCP_MAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); + } else { + if (pcb->persist_backoff > 0) { + /* If snd_wnd is zero, use persist timer to send 1 byte probes + * instead of using the standard retransmission mechanism. */ + pcb->persist_cnt++; + if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { + pcb->persist_cnt = 0; + if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { + pcb->persist_backoff++; + } + tcp_zero_window_probe(pcb); + } + } else { + /* Increase the retransmission timer if it is running */ + if(pcb->rtime >= 0) { + ++pcb->rtime; + } + + if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { + /* Time for a retransmission. */ + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F + " pcb->rto %"S16_F"\n", + pcb->rtime, pcb->rto)); + + /* Double retransmission time-out unless we are trying to + * connect to somebody (i.e., we are in SYN_SENT). */ + if (pcb->state != SYN_SENT) { + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; + } + + /* Reset the retransmission timer. */ + pcb->rtime = 0; + + /* Reduce congestion window and ssthresh. */ + eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); + pcb->ssthresh = eff_wnd >> 1; + if (pcb->ssthresh < (pcb->mss << 1)) { + pcb->ssthresh = (pcb->mss << 1); + } + pcb->cwnd = pcb->mss; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F + " ssthresh %"U16_F"\n", + pcb->cwnd, pcb->ssthresh)); + + /* The following needs to be called AFTER cwnd is set to one + mss - STJ */ + tcp_rexmit_rto(pcb); + } + } + } + /* Check if this PCB has stayed too long in FIN-WAIT-2 */ + if (pcb->state == FIN_WAIT_2) { + /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ + if (pcb->flags & TF_RXCLOSED) { + /* PCB was fully closed (either through close() or SHUT_RDWR): + normal FIN-WAIT timeout handling. */ + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); + } + } + } + + /* Check if KEEPALIVE should be sent */ + if(ip_get_option(pcb, SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT))) { + if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) + { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", + ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), + ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); + + ++pcb_remove; + ++pcb_reset; + } + else if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) + / TCP_SLOW_INTERVAL) + { + tcp_keepalive(pcb); + pcb->keep_cnt_sent++; + } + } + + /* If this PCB has queued out of sequence data, but has been + inactive for too long, will drop the data (it will eventually + be retransmitted). */ +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL && + (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); + } +#endif /* TCP_QUEUE_OOSEQ */ + + /* Check if this PCB has stayed too long in SYN-RCVD */ + if (pcb->state == SYN_RCVD) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); + } + } + + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_err_fn err_fn; + void *err_arg; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_active_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); + tcp_active_pcbs = pcb->next; + } + + if (pcb_reset) { + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + } + + err_fn = pcb->errf; + err_arg = pcb->callback_arg; + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + + tcp_active_pcbs_changed = 0; + TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + } else { + /* get the 'next' element now and work with 'prev' below (in case of abort) */ + prev = pcb; + pcb = pcb->next; + + /* We check if we should poll the connection. */ + ++prev->polltmr; + if (prev->polltmr >= prev->pollinterval) { + prev->polltmr = 0; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); + tcp_active_pcbs_changed = 0; + TCP_EVENT_POLL(prev, err); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + /* if err == ERR_ABRT, 'prev' is already deallocated */ + if (err == ERR_OK) { + tcp_output(prev); + } + } + } + } + + + /* Steps through all of the TIME-WAIT PCBs. */ + prev = NULL; + pcb = tcp_tw_pcbs; + while (pcb != NULL) { + LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + pcb_remove = 0; + + /* Check if this PCB has stayed long enough in TIME-WAIT */ + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + } + + + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); + tcp_tw_pcbs = pcb->next; + } + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + } else { + prev = pcb; + pcb = pcb->next; + } + } +} + +/** + * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously + * "refused" by upper layer (application) and sends delayed ACKs. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_fasttmr(void) +{ + struct tcp_pcb *pcb; + + ++tcp_timer_ctr; + +tcp_fasttmr_start: + pcb = tcp_active_pcbs; + + while(pcb != NULL) { + if (pcb->last_timer != tcp_timer_ctr) { + struct tcp_pcb *next; + pcb->last_timer = tcp_timer_ctr; + /* send delayed ACKs */ + if (pcb->flags & TF_ACK_DELAY) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); + tcp_ack_now(pcb); + tcp_output(pcb); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + next = pcb->next; + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + tcp_active_pcbs_changed = 0; + tcp_process_refused_data(pcb); + if (tcp_active_pcbs_changed) { + /* application callback has changed the pcb list: restart the loop */ + goto tcp_fasttmr_start; + } + } + pcb = next; + } + } +} + +/** Pass pcb->refused_data to the recv callback */ +err_t +tcp_process_refused_data(struct tcp_pcb *pcb) +{ + err_t err; + u8_t refused_flags = pcb->refused_data->flags; + /* set pcb->refused_data to NULL in case the callback frees it and then + closes the pcb */ + struct pbuf *refused_data = pcb->refused_data; + pcb->refused_data = NULL; + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); + if (err == ERR_OK) { + /* did refused_data include a FIN? */ + if (refused_flags & PBUF_FLAG_TCP_FIN) { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + } + } else if (err == ERR_ABRT) { + /* if err == ERR_ABRT, 'pcb' is already deallocated */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + return ERR_ABRT; + } else { + /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ + pcb->refused_data = refused_data; + } + return ERR_OK; +} + +/** + * Deallocates a list of TCP segments (tcp_seg structures). + * + * @param seg tcp_seg list of TCP segments to free + */ +void +tcp_segs_free(struct tcp_seg *seg) +{ + while (seg != NULL) { + struct tcp_seg *next = seg->next; + tcp_seg_free(seg); + seg = next; + } +} + +/** + * Frees a TCP segment (tcp_seg structure). + * + * @param seg single tcp_seg to free + */ +void +tcp_seg_free(struct tcp_seg *seg) +{ + if (seg != NULL) { + if (seg->p != NULL) { + pbuf_free(seg->p); +#if TCP_DEBUG + seg->p = NULL; +#endif /* TCP_DEBUG */ + } + memp_free(MEMP_TCP_SEG, seg); + } +} + +/** + * Sets the priority of a connection. + * + * @param pcb the tcp_pcb to manipulate + * @param prio new priority + */ +void +tcp_setprio(struct tcp_pcb *pcb, u8_t prio) +{ + pcb->prio = prio; +} + +#if TCP_QUEUE_OOSEQ +/** + * Returns a copy of the given TCP segment. + * The pbuf and data are not copied, only the pointers + * + * @param seg the old tcp_seg + * @return a copy of seg + */ +struct tcp_seg * +tcp_seg_copy(struct tcp_seg *seg) +{ + struct tcp_seg *cseg; + + cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); + if (cseg == NULL) { + return NULL; + } + SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); + pbuf_ref(cseg->p); + return cseg; +} +#endif /* TCP_QUEUE_OOSEQ */ + +#if LWIP_CALLBACK_API +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) { + return tcp_close(pcb); + } + return ERR_OK; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Kills the oldest active connection that has the same or lower priority than + * 'prio'. + * + * @param prio minimum priority + */ +static void +tcp_kill_prio(u8_t prio) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + u8_t mprio; + + + mprio = TCP_PRIO_MAX; + + /* We kill the oldest active connection that has lower priority than prio. */ + inactivity = 0; + inactive = NULL; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->prio <= prio && + pcb->prio <= mprio && + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + mprio = pcb->prio; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Kills the oldest connection that is in TIME_WAIT state. + * Called from tcp_alloc() if no more connections are available. + */ +static void +tcp_kill_timewait(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Allocate a new tcp_pcb structure. + * + * @param prio priority for the new pcb + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_alloc(u8_t prio) +{ + struct tcp_pcb *pcb; + u32_t iss; + + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in TIME-WAIT. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); + tcp_kill_timewait(); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing active connections with lower priority than the new one. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); + tcp_kill_prio(prio); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed twice before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: timewait PCB was freed above */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + memset(pcb, 0, sizeof(struct tcp_pcb)); + pcb->prio = prio; + pcb->snd_buf = TCP_SND_BUF; + pcb->snd_queuelen = 0; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->tos = 0; + pcb->ttl = TCP_TTL; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; + pcb->rto = 3000 / TCP_SLOW_INTERVAL; + pcb->sa = 0; + pcb->sv = 3000 / TCP_SLOW_INTERVAL; + pcb->rtime = -1; + pcb->cwnd = 1; + iss = tcp_next_iss(); + pcb->snd_wl2 = iss; + pcb->snd_nxt = iss; + pcb->lastack = iss; + pcb->snd_lbb = iss; + pcb->tmr = tcp_ticks; + pcb->last_timer = tcp_timer_ctr; + + pcb->polltmr = 0; + +#if LWIP_CALLBACK_API + pcb->recv = tcp_recv_null; +#endif /* LWIP_CALLBACK_API */ + + /* Init KEEPALIVE timer */ + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#if LWIP_TCP_KEEPALIVE + pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; +#endif /* LWIP_TCP_KEEPALIVE */ + + pcb->keep_cnt_sent = 0; + } + return pcb; +} + +/** + * Creates a new TCP protocol control block but doesn't place it on + * any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @internal: Maybe there should be a idle TCP PCB list where these + * PCBs are put on. Port reservation using tcp_bind() is implemented but + * allocated pcbs that are not bound can't be killed automatically if wanting + * to allocate a pcb with higher prio (@see tcp_kill_prio()) + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new(void) +{ + return tcp_alloc(TCP_PRIO_NORMAL); +} + +/** + * Used to specify the argument that should be passed callback + * functions. + * + * @param pcb tcp_pcb to set the callback argument + * @param arg void pointer argument to pass to callback functions + */ +void +tcp_arg(struct tcp_pcb *pcb, void *arg) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->callback_arg = arg; +} +#if LWIP_CALLBACK_API + +/** + * Used to specify the function that should be called when a TCP + * connection receives data. + * + * @param pcb tcp_pcb to set the recv callback + * @param recv callback function to call for this pcb when data is received + */ +void +tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) +{ + LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); + pcb->recv = recv; +} + +/** + * Used to specify the function that should be called when TCP data + * has been successfully delivered to the remote host. + * + * @param pcb tcp_pcb to set the sent callback + * @param sent callback function to call for this pcb when data is successfully sent + */ +void +tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) +{ + LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); + pcb->sent = sent; +} + +/** + * Used to specify the function that should be called when a fatal error + * has occured on the connection. + * + * @param pcb tcp_pcb to set the err callback + * @param err callback function to call for this pcb when a fatal error + * has occured on the connection + */ +void +tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) +{ + LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); + pcb->errf = err; +} + +/** + * Used for specifying the function that should be called when a + * LISTENing connection has been connected to another host. + * + * @param pcb tcp_pcb to set the accept callback + * @param accept callback function to call for this pcb when LISTENing + * connection has been connected to another host + */ +void +tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->accept = accept; +} +#endif /* LWIP_CALLBACK_API */ + + +/** + * Used to specify the function that should be called periodically + * from TCP. The interval is specified in terms of the TCP coarse + * timer interval, which is called twice a second. + * + */ +void +tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) +{ + LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); +#if LWIP_CALLBACK_API + pcb->poll = poll; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(poll); +#endif /* LWIP_CALLBACK_API */ + pcb->pollinterval = interval; +} + +/** + * Purges a TCP PCB. Removes any buffered data and frees the buffer memory + * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). + * + * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! + */ +void +tcp_pcb_purge(struct tcp_pcb *pcb) +{ + if (pcb->state != CLOSED && + pcb->state != TIME_WAIT && + pcb->state != LISTEN) { + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); + +#if TCP_LISTEN_BACKLOG + if (pcb->state == SYN_RCVD) { + /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ + struct tcp_pcb_listen *lpcb; + LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", + tcp_listen_pcbs.listen_pcbs != NULL); + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + (ip_addr_isany(&lpcb->local_ip) || + ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) { + /* port and address of the listen pcb match the timed-out pcb */ + LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", + lpcb->accepts_pending > 0); + lpcb->accepts_pending--; + break; + } + } + } +#endif /* TCP_LISTEN_BACKLOG */ + + + if (pcb->refused_data != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + if (pcb->unsent != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); + } + if (pcb->unacked != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); + } + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; +#endif /* TCP_QUEUE_OOSEQ */ + + /* Stop the retransmission timer as it will expect data on unacked + queue if it fires */ + pcb->rtime = -1; + + tcp_segs_free(pcb->unsent); + tcp_segs_free(pcb->unacked); + pcb->unacked = pcb->unsent = NULL; +#if TCP_OVERSIZE + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + } +} + +/** + * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. + * + * @param pcblist PCB list to purge. + * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! + */ +void +tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) +{ + TCP_RMV(pcblist, pcb); + + tcp_pcb_purge(pcb); + + /* if there is an outstanding delayed ACKs, send it */ + if (pcb->state != TIME_WAIT && + pcb->state != LISTEN && + pcb->flags & TF_ACK_DELAY) { + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + + pcb->state = CLOSED; + + LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); +} + +/** + * Calculates a new initial sequence number for new connections. + * + * @return u32_t pseudo random sequence number + */ +u32_t +tcp_next_iss(void) +{ + static u32_t iss = 6510; + + iss += tcp_ticks; /* XXX */ + return iss; +} + +#if TCP_CALCULATE_EFF_SEND_MSS +/** + * Calcluates the effective send mss that can be used for a specific IP address + * by using ip_route to determin the netif used to send to the address and + * calculating the minimum of TCP_MSS and that netif's mtu (if set). + */ +u16_t +tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr) +{ + u16_t mss_s; + struct netif *outif; + + outif = ip_route(addr); + if ((outif != NULL) && (outif->mtu != 0)) { + mss_s = outif->mtu - IP_HLEN - TCP_HLEN; + /* RFC 1122, chap 4.2.2.6: + * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize + * We correct for TCP options in tcp_write(), and don't support IP options. + */ + sendmss = LWIP_MIN(sendmss, mss_s); + } + return sendmss; +} +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +const char* +tcp_debug_state_str(enum tcp_state s) +{ + return tcp_state_str[s]; +} + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +/** + * Print a tcp header for debugging purposes. + * + * @param tcphdr pointer to a struct tcp_hdr + */ +void +tcp_debug_print(struct tcp_hdr *tcphdr) +{ + LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(tcphdr->src), ntohs(tcphdr->dest))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", + ntohl(tcphdr->seqno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", + ntohl(tcphdr->ackno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", + TCPH_HDRLEN(tcphdr), + TCPH_FLAGS(tcphdr) >> 5 & 1, + TCPH_FLAGS(tcphdr) >> 4 & 1, + TCPH_FLAGS(tcphdr) >> 3 & 1, + TCPH_FLAGS(tcphdr) >> 2 & 1, + TCPH_FLAGS(tcphdr) >> 1 & 1, + TCPH_FLAGS(tcphdr) & 1, + ntohs(tcphdr->wnd))); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", + ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); +} + +/** + * Print a tcp state for debugging purposes. + * + * @param s enum tcp_state to print + */ +void +tcp_debug_print_state(enum tcp_state s) +{ + LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); +} + +/** + * Print tcp flags for debugging purposes. + * + * @param flags tcp flags, all active flags are printed + */ +void +tcp_debug_print_flags(u8_t flags) +{ + if (flags & TCP_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); + } + if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); + } + if (flags & TCP_RST) { + LWIP_DEBUGF(TCP_DEBUG, ("RST ")); + } + if (flags & TCP_PSH) { + LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); + } + if (flags & TCP_ACK) { + LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); + } + if (flags & TCP_URG) { + LWIP_DEBUGF(TCP_DEBUG, ("URG ")); + } + if (flags & TCP_ECE) { + LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); + } + if (flags & TCP_CWR) { + LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); + } + LWIP_DEBUGF(TCP_DEBUG, ("\n")); +} + +/** + * Print all tcp_pcbs in every list for debugging purposes. + */ +void +tcp_debug_print_pcbs(void) +{ + struct tcp_pcb *pcb; + LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); + for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } +} + +/** + * Check state consistency of the tcp_pcb lists. + */ +s16_t +tcp_pcbs_sane(void) +{ + struct tcp_pcb *pcb; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + } + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + } + return 1; +} +#endif /* TCP_DEBUG */ + +#endif /* LWIP_TCP */ diff --git a/ext/lwip/src/core/tcp_in.c b/ext/lwip/src/core/tcp_in.c new file mode 100644 index 000000000..051869ff9 --- /dev/null +++ b/ext/lwip/src/core/tcp_in.c @@ -0,0 +1,1619 @@ +/** + * @file + * Transmission Control Protocol, incoming traffic + * + * The input processing functions of the TCP layer. + * + * These functions are generally called in the order (ip_input() ->) + * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp_impl.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" + +/* These variables are global to all functions involved in the input + processing of TCP segments. They are set by the tcp_input() + function. */ +static struct tcp_seg inseg; +static struct tcp_hdr *tcphdr; +static struct ip_hdr *iphdr; +static u32_t seqno, ackno; +static u8_t flags; +static u16_t tcplen; + +static u8_t recv_flags; +static struct pbuf *recv_data; + +struct tcp_pcb *tcp_input_pcb; + +/* Forward declarations. */ +static err_t tcp_process(struct tcp_pcb *pcb); +static void tcp_receive(struct tcp_pcb *pcb); +static void tcp_parseopt(struct tcp_pcb *pcb); + +static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); +static err_t tcp_timewait_input(struct tcp_pcb *pcb); + +/** + * The initial input processing of TCP. It verifies the TCP header, demultiplexes + * the segment between the PCBs and passes it on to tcp_process(), which implements + * the TCP finite state machine. This function is called by the IP layer (in + * ip_input()). + * + * @param p received TCP segment to process (p->payload pointing to the IP header) + * @param inp network interface on which this segment was received + */ +void +tcp_input(struct pbuf *p, struct netif *inp) +{ + struct tcp_pcb *pcb, *prev; + struct tcp_pcb_listen *lpcb; +#if SO_REUSE + struct tcp_pcb *lpcb_prev = NULL; + struct tcp_pcb_listen *lpcb_any = NULL; +#endif /* SO_REUSE */ + u8_t hdrlen; + err_t err; + + PERF_START; + + TCP_STATS_INC(tcp.recv); + snmp_inc_tcpinsegs(); + + iphdr = (struct ip_hdr *)p->payload; + tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); + +#if TCP_INPUT_DEBUG + tcp_debug_print(tcphdr); +#endif + + /* remove header from payload */ + if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Don't even process incoming broadcasts/multicasts. */ + if (ip_addr_isbroadcast(¤t_iphdr_dest, inp) || + ip_addr_ismulticast(¤t_iphdr_dest)) { + TCP_STATS_INC(tcp.proterr); + goto dropped; + } + +#if CHECKSUM_CHECK_TCP + /* Verify TCP checksum. */ + if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(), + IP_PROTO_TCP, p->tot_len) != 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", + inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(), + IP_PROTO_TCP, p->tot_len))); +#if TCP_DEBUG + tcp_debug_print(tcphdr); +#endif /* TCP_DEBUG */ + TCP_STATS_INC(tcp.chkerr); + goto dropped; + } +#endif + + /* Move the payload pointer in the pbuf so that it points to the + TCP data instead of the TCP header. */ + hdrlen = TCPH_HDRLEN(tcphdr); + if(pbuf_header(p, -(hdrlen * 4))){ + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Convert fields in TCP header to host byte order. */ + tcphdr->src = ntohs(tcphdr->src); + tcphdr->dest = ntohs(tcphdr->dest); + seqno = tcphdr->seqno = ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = ntohl(tcphdr->ackno); + tcphdr->wnd = ntohs(tcphdr->wnd); + + flags = TCPH_FLAGS(tcphdr); + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); + + /* Demultiplex an incoming segment. First, we check if it is destined + for an active connection. */ + prev = NULL; + + + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) && + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) { + + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); + if (prev != NULL) { + prev->next = pcb->next; + pcb->next = tcp_active_pcbs; + tcp_active_pcbs = pcb; + } + LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); + break; + } + prev = pcb; + } + + if (pcb == NULL) { + /* If it did not go to an active connection, we check the connections + in the TIME-WAIT state. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) && + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) { + /* We don't really care enough to move this PCB to the front + of the list since we are not very likely to receive that + many segments for connections in TIME-WAIT. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); + tcp_timewait_input(pcb); + pbuf_free(p); + return; + } + } + + /* Finally, if we still did not get a match, we check all PCBs that + are LISTENing for incoming connections. */ + prev = NULL; + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == tcphdr->dest) { +#if SO_REUSE + if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest)) { + /* found an exact match */ + break; + } else if(ip_addr_isany(&(lpcb->local_ip))) { + /* found an ANY-match */ + lpcb_any = lpcb; + lpcb_prev = prev; + } +#else /* SO_REUSE */ + if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest) || + ip_addr_isany(&(lpcb->local_ip))) { + /* found a match */ + break; + } +#endif /* SO_REUSE */ + } + prev = (struct tcp_pcb *)lpcb; + } +#if SO_REUSE + /* first try specific local IP */ + if (lpcb == NULL) { + /* only pass to ANY if no specific local IP has been found */ + lpcb = lpcb_any; + prev = lpcb_prev; + } +#endif /* SO_REUSE */ + if (lpcb != NULL) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + if (prev != NULL) { + ((struct tcp_pcb_listen *)prev)->next = lpcb->next; + /* our successor is the remainder of the listening list */ + lpcb->next = tcp_listen_pcbs.listen_pcbs; + /* put this listening pcb at the head of the listening list */ + tcp_listen_pcbs.listen_pcbs = lpcb; + } + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); + tcp_listen_input(lpcb); + pbuf_free(p); + return; + } + } + +#if TCP_INPUT_DEBUG + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); +#endif /* TCP_INPUT_DEBUG */ + + + if (pcb != NULL) { + /* The incoming segment belongs to a connection. */ +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + + /* Set up a tcp_seg structure. */ + inseg.next = NULL; + inseg.len = p->tot_len; + inseg.p = p; + inseg.tcphdr = tcphdr; + + recv_data = NULL; + recv_flags = 0; + + if (flags & TCP_PSH) { + p->flags |= PBUF_FLAG_PUSH; + } + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + if ((tcp_process_refused_data(pcb) == ERR_ABRT) || + ((pcb->refused_data != NULL) && (tcplen > 0))) { + /* pcb has been aborted or refused data is still refused and the new + segment contains data */ + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + goto aborted; + } + } + tcp_input_pcb = pcb; + err = tcp_process(pcb); + /* A return value of ERR_ABRT means that tcp_abort() was called + and that the pcb has been freed. If so, we don't do anything. */ + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { + /* TF_RESET means that the connection was reset by the other + end. We then call the error callback to inform the + application that the connection is dead before we + deallocate the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + if (!(pcb->flags & TF_RXCLOSED)) { + /* Connection closed although the application has only shut down the + tx side: call the PCB's err callback and indicate the closure to + ensure the application doesn't continue using the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD); + } + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + err = ERR_OK; + /* If the application has registered a "sent" function to be + called when new send buffer space is available, we call it + now. */ + if (pcb->acked > 0) { + TCP_EVENT_SENT(pcb, pcb->acked, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + + if (recv_data != NULL) { + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); + if (pcb->flags & TF_RXCLOSED) { + /* received data although already closed -> abort (send RST) to + notify the remote host that not all data has been processed */ + pbuf_free(recv_data); + tcp_abort(pcb); + goto aborted; + } + + /* Notify application that data has been received. */ + TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); + if (err == ERR_ABRT) { + goto aborted; + } + + /* If the upper layer can't receive this data, store it */ + if (err != ERR_OK) { + pcb->refused_data = recv_data; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); + } + } + + /* If a FIN segment was received, we call the callback + function with a NULL buffer to indicate EOF. */ + if (recv_flags & TF_GOT_FIN) { + if (pcb->refused_data != NULL) { + /* Delay this if we have refused data. */ + pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; + } else { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + + tcp_input_pcb = NULL; + /* Try to send something out. */ + tcp_output(pcb); +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + } + } + /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). + Below this line, 'pcb' may not be dereferenced! */ +aborted: + tcp_input_pcb = NULL; + recv_data = NULL; + + /* give up our reference to inseg.p */ + if (inseg.p != NULL) + { + pbuf_free(inseg.p); + inseg.p = NULL; + } + } else { + + /* If no matching PCB was found, send a TCP RST (reset) to the + sender. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); + if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + tcp_rst(ackno, seqno + tcplen, + ip_current_dest_addr(), ip_current_src_addr(), + tcphdr->dest, tcphdr->src); + } + pbuf_free(p); + } + + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); + PERF_STOP("tcp_input"); + return; +dropped: + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); +} + +/** + * Called by tcp_input() when a segment arrives for a listening + * connection (from tcp_input()). + * + * @param pcb the tcp_pcb_listen for which a segment arrived + * @return ERR_OK if the segment was processed + * another err_t on error + * + * @note the return value is not (yet?) used in tcp_input() + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_listen_input(struct tcp_pcb_listen *pcb) +{ + struct tcp_pcb *npcb; + err_t rc; + + if (flags & TCP_RST) { + /* An incoming RST should be ignored. Return. */ + return ERR_OK; + } + + /* In the LISTEN state, we check for incoming SYN segments, + creates a new PCB, and responds with a SYN|ACK. */ + if (flags & TCP_ACK) { + /* For incoming segments with the ACK flag set, respond with a + RST. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } else if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); +#if TCP_LISTEN_BACKLOG + if (pcb->accepts_pending >= pcb->backlog) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); + return ERR_ABRT; + } +#endif /* TCP_LISTEN_BACKLOG */ + npcb = tcp_alloc(pcb->prio); + /* If a new PCB could not be created (probably due to lack of memory), + we don't do anything, but rely on the sender will retransmit the + SYN at a time when we have more memory available. */ + if (npcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } +#if TCP_LISTEN_BACKLOG + pcb->accepts_pending++; +#endif /* TCP_LISTEN_BACKLOG */ + /* Set up the new PCB. */ + ip_addr_copy(npcb->local_ip, current_iphdr_dest); + npcb->local_port = pcb->local_port; + ip_addr_copy(npcb->remote_ip, current_iphdr_src); + npcb->remote_port = tcphdr->src; + npcb->state = SYN_RCVD; + npcb->rcv_nxt = seqno + 1; + npcb->rcv_ann_right_edge = npcb->rcv_nxt; + npcb->snd_wnd = tcphdr->wnd; + npcb->snd_wnd_max = tcphdr->wnd; + npcb->ssthresh = npcb->snd_wnd; + npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ + npcb->callback_arg = pcb->callback_arg; +#if LWIP_CALLBACK_API + npcb->accept = pcb->accept; +#endif /* LWIP_CALLBACK_API */ + /* inherit socket options */ + npcb->so_options = pcb->so_options & SOF_INHERITED; + /* Register the new PCB so that we can begin receiving segments + for it. */ + TCP_REG_ACTIVE(npcb); + + /* Parse any options in the SYN. */ + tcp_parseopt(npcb); +#if TCP_CALCULATE_EFF_SEND_MSS + npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + snmp_inc_tcppassiveopens(); + + /* Send a SYN|ACK together with the MSS option. */ + rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return rc; + } + return tcp_output(npcb); + } + return ERR_OK; +} + +/** + * Called by tcp_input() when a segment arrives for a connection in + * TIME_WAIT. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_timewait_input(struct tcp_pcb *pcb) +{ + /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ + /* RFC 793 3.9 Event Processing - Segment Arrives: + * - first check sequence number - we skip that one in TIME_WAIT (always + * acceptable since we only send ACKs) + * - second check the RST bit (... return) */ + if (flags & TCP_RST) { + return ERR_OK; + } + /* - fourth, check the SYN bit, */ + if (flags & TCP_SYN) { + /* If an incoming segment is not acceptable, an acknowledgment + should be sent in reply */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { + /* If the SYN is in the window it is an error, send a reset */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), + tcphdr->dest, tcphdr->src); + return ERR_OK; + } + } else if (flags & TCP_FIN) { + /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. + Restart the 2 MSL time-wait timeout.*/ + pcb->tmr = tcp_ticks; + } + + if ((tcplen > 0)) { + /* Acknowledge data, FIN or out-of-window SYN */ + pcb->flags |= TF_ACK_NOW; + return tcp_output(pcb); + } + return ERR_OK; +} + +/** + * Implements the TCP state machine. Called by tcp_input. In some + * states tcp_receive() is called to receive data. The tcp_seg + * argument will be freed by the caller (tcp_input()) unless the + * recv_data pointer in the pcb is set. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_process(struct tcp_pcb *pcb) +{ + struct tcp_seg *rseg; + u8_t acceptable = 0; + err_t err; + + err = ERR_OK; + + /* Process incoming RST segments. */ + if (flags & TCP_RST) { + /* First, determine if the reset is acceptable. */ + if (pcb->state == SYN_SENT) { + if (ackno == pcb->snd_nxt) { + acceptable = 1; + } + } else { + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt+pcb->rcv_wnd)) { + acceptable = 1; + } + } + + if (acceptable) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); + LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); + recv_flags |= TF_RESET; + pcb->flags &= ~TF_ACK_DELAY; + return ERR_RST; + } else { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + return ERR_OK; + } + } + + if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + /* Cope with new connection attempt after remote end crashed */ + tcp_ack_now(pcb); + return ERR_OK; + } + + if ((pcb->flags & TF_RXCLOSED) == 0) { + /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ + pcb->tmr = tcp_ticks; + } + pcb->keep_cnt_sent = 0; + + tcp_parseopt(pcb); + + /* Do different things depending on the TCP state. */ + switch (pcb->state) { + case SYN_SENT: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, + pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ + if ((flags & TCP_ACK) && (flags & TCP_SYN) + && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { + pcb->snd_buf++; + pcb->rcv_nxt = seqno + 1; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->lastack = ackno; + pcb->snd_wnd = tcphdr->wnd; + pcb->snd_wnd_max = tcphdr->wnd; + pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ + pcb->state = ESTABLISHED; + +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + /* Set ssthresh again after changing pcb->mss (already set in tcp_connect + * but for the default value of pcb->mss) */ + pcb->ssthresh = pcb->mss * 10; + + pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); + --pcb->snd_queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + rseg = pcb->unacked; + pcb->unacked = rseg->next; + tcp_seg_free(rseg); + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else { + pcb->rtime = 0; + pcb->nrtx = 0; + } + + /* Call the user specified function to call when sucessfully + * connected. */ + TCP_EVENT_CONNECTED(pcb, ERR_OK, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + tcp_ack_now(pcb); + } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), + tcphdr->dest, tcphdr->src); + } + break; + case SYN_RCVD: + if (flags & TCP_ACK) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + u16_t old_cwnd; + pcb->state = ESTABLISHED; + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API + LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); +#endif + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb, ERR_OK, err); + if (err != ERR_OK) { + /* If the accept function returns with an error, we abort + * the connection. */ + /* Already aborted? */ + if (err != ERR_ABRT) { + tcp_abort(pcb); + } + return ERR_ABRT; + } + old_cwnd = pcb->cwnd; + /* If there was any data contained within this ACK, + * we'd better pass it on to the application as well. */ + tcp_receive(pcb); + + /* Prevent ACK for SYN to generate a sent event */ + if (pcb->acked != 0) { + pcb->acked--; + } + + pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); + + if (recv_flags & TF_GOT_FIN) { + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + } else { + /* incorrect ACK number, send RST */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), + tcphdr->dest, tcphdr->src); + } + } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + break; + case CLOSE_WAIT: + /* FALLTHROUGH */ + case ESTABLISHED: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + break; + case FIN_WAIT_1: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_DEBUG, + ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + tcp_ack_now(pcb); + pcb->state = CLOSING; + } + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + pcb->state = FIN_WAIT_2; + } + break; + case FIN_WAIT_2: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case CLOSING: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case LAST_ACK: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ + recv_flags |= TF_CLOSED; + } + break; + default: + break; + } + return ERR_OK; +} + +#if TCP_QUEUE_OOSEQ +/** + * Insert segment into the list (segments covered with new one will be deleted) + * + * Called from tcp_receive() + */ +static void +tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) +{ + struct tcp_seg *old_seg; + + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + /* received segment overlaps all following segments */ + tcp_segs_free(next); + next = NULL; + } + else { + /* delete some following segments + oos queue may have segments with FIN flag */ + while (next && + TCP_SEQ_GEQ((seqno + cseg->len), + (next->tcphdr->seqno + next->len))) { + /* cseg with FIN already processed */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + if (next && + TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + cseg->len = (u16_t)(next->tcphdr->seqno - seqno); + pbuf_realloc(cseg->p, cseg->len); + } + } + cseg->next = next; +} +#endif /* TCP_QUEUE_OOSEQ */ + +/** + * Called by tcp_process. Checks if the given segment is an ACK for outstanding + * data, and if so frees the memory of the buffered data. Next, is places the + * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment + * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until + * it has been removed from the buffer. + * + * If the incoming segment constitutes an ACK for a segment that was used for RTT + * estimation, the RTT is estimated here as well. + * + * Called from tcp_process(). + */ +static void +tcp_receive(struct tcp_pcb *pcb) +{ + struct tcp_seg *next; +#if TCP_QUEUE_OOSEQ + struct tcp_seg *prev, *cseg; +#endif /* TCP_QUEUE_OOSEQ */ + struct pbuf *p; + s32_t off; + s16_t m; + u32_t right_wnd_edge; + u16_t new_tot_len; + int found_dupack = 0; +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + u32_t ooseq_blen; + u16_t ooseq_qlen; +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ + + LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); + + if (flags & TCP_ACK) { + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; + + /* Update window. */ + if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || + (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || + (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { + pcb->snd_wnd = tcphdr->wnd; + /* keep track of the biggest window announced by the remote host to calculate + the maximum segment size */ + if (pcb->snd_wnd_max < tcphdr->wnd) { + pcb->snd_wnd_max = tcphdr->wnd; + } + pcb->snd_wl1 = seqno; + pcb->snd_wl2 = ackno; + if (pcb->snd_wnd == 0) { + if (pcb->persist_backoff == 0) { + /* start persist timer */ + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + } else if (pcb->persist_backoff > 0) { + /* stop persist timer */ + pcb->persist_backoff = 0; + } + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); +#if TCP_WND_DEBUG + } else { + if (pcb->snd_wnd != tcphdr->wnd) { + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + } +#endif /* TCP_WND_DEBUG */ + } + + /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a + * duplicate ack if: + * 1) It doesn't ACK new data + * 2) length of received packet is zero (i.e. no payload) + * 3) the advertised window hasn't changed + * 4) There is outstanding unacknowledged data (retransmission timer running) + * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) + * + * If it passes all five, should process as a dupack: + * a) dupacks < 3: do nothing + * b) dupacks == 3: fast retransmit + * c) dupacks > 3: increase cwnd + * + * If it only passes 1-3, should reset dupack counter (and add to + * stats, which we don't do in lwIP) + * + * If it only passes 1, should reset dupack counter + * + */ + + /* Clause 1 */ + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { + pcb->acked = 0; + /* Clause 2 */ + if (tcplen == 0) { + /* Clause 3 */ + if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ + /* Clause 4 */ + if (pcb->rtime >= 0) { + /* Clause 5 */ + if (pcb->lastack == ackno) { + found_dupack = 1; + if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { + ++pcb->dupacks; + } + if (pcb->dupacks > 3) { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } else if (pcb->dupacks == 3) { + /* Do fast retransmit */ + tcp_rexmit_fast(pcb); + } + } + } + } + } + /* If Clause (1) or more is true, but not a duplicate ack, reset + * count of consecutive duplicate acks */ + if (!found_dupack) { + pcb->dupacks = 0; + } + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ + /* We come here when the ACK acknowledges new data. */ + + /* Reset the "IN Fast Retransmit" flag, since we are no longer + in fast retransmit. Also reset the congestion window to the + slow start threshold. */ + if (pcb->flags & TF_INFR) { + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; + } + + /* Reset the number of retransmissions. */ + pcb->nrtx = 0; + + /* Reset the retransmission time-out. */ + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + /* Update the send buffer space. Diff between the two can never exceed 64K? */ + pcb->acked = (u16_t)(ackno - pcb->lastack); + + pcb->snd_buf += pcb->acked; + + /* Reset the fast retransmit variables. */ + pcb->dupacks = 0; + pcb->lastack = ackno; + + /* Update the congestion control variables (cwnd and + ssthresh). */ + if (pcb->state >= ESTABLISHED) { + if (pcb->cwnd < pcb->ssthresh) { + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); + } else { + u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); + } + } + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + + /* Remove segment from the unacknowledged list if the incoming + ACK acknowlegdes them. */ + while (pcb->unacked != NULL && + TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + ntohl(pcb->unacked->tcphdr->seqno), + ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); + + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + } + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else + pcb->rtime = 0; + + pcb->polltmr = 0; + } else { + /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ + pcb->acked = 0; + } + + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); + + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + } + /* End of ACK for new data processing. */ + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); + + /* RTT estimation calculations. This is done by checking if the + incoming segment acknowledges the segment we use to take a + round-trip time measurement. */ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { + /* diff between this shouldn't exceed 32K since this are tcp timer ticks + and a round-trip shouldn't be that long... */ + m = (s16_t)(tcp_ticks - pcb->rttest); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, m * TCP_SLOW_INTERVAL)); + + /* This is taken directly from VJs original code in his paper */ + m = m - (pcb->sa >> 3); + pcb->sa += m; + if (m < 0) { + m = -m; + } + m = m - (pcb->sv >> 2); + pcb->sv += m; + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", + pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); + + pcb->rttest = 0; + } + } + + /* If the incoming segment contains data, we must process it + further unless the pcb already received a FIN. + (RFC 793, chapeter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, + LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ + if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { + /* This code basically does three things: + + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. + + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. + + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. + */ + + /* First, we check if we must trim the first edge. We have to do + this if the sequence number of the incoming segment is less + than rcv_nxt, and the sequence number plus the length of the + segment is larger than rcv_nxt. */ + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + off = pcb->rcv_nxt - seqno; + p = inseg.p; + LWIP_ASSERT("inseg.p != NULL", inseg.p); + LWIP_ASSERT("insane offset!", (off < 0x7fff)); + if (inseg.p->len < off) { + LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); + new_tot_len = (u16_t)(inseg.p->tot_len - off); + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + if(pbuf_header(p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } else { + if(pbuf_header(inseg.p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } + inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; + } + else { + if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); + } + } + + /* The sequence number must be within the window (above rcv_nxt + and below rcv_nxt + rcv_wnd) in order to be further + processed. */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd - 1)){ + if (pcb->rcv_nxt == seqno) { + /* The incoming segment is the next in sequence. We check if + we have to trim the end of the segment and update rcv_nxt + and pass the data to the application. */ + tcplen = TCP_TCPLEN(&inseg); + + if (tcplen > pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + inseg.len = pcb->rcv_wnd; + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } +#if TCP_QUEUE_OOSEQ + /* Received in-sequence data, adjust ooseq data if: + - FIN has been received or + - inseq overlaps with ooseq */ + if (pcb->ooseq != NULL) { + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: received in-order FIN, binning ooseq queue\n")); + /* Received in-order FIN means anything that was received + * out of order must now have been received in-order, so + * bin the ooseq queue */ + while (pcb->ooseq != NULL) { + struct tcp_seg *old_ooseq = pcb->ooseq; + pcb->ooseq = pcb->ooseq->next; + tcp_seg_free(old_ooseq); + } + } else { + next = pcb->ooseq; + /* Remove all segments on ooseq that are covered by inseg already. + * FIN is copied from ooseq to inseg if present. */ + while (next && + TCP_SEQ_GEQ(seqno + tcplen, + next->tcphdr->seqno + next->len)) { + /* inseg cannot have FIN here (already processed above) */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && + (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { + TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); + tcplen = TCP_TCPLEN(&inseg); + } + prev = next; + next = next->next; + tcp_seg_free(prev); + } + /* Now trim right side of inseg if it overlaps with the first + * segment on ooseq */ + if (next && + TCP_SEQ_GT(seqno + tcplen, + next->tcphdr->seqno)) { + /* inseg cannot have FIN here (already processed above) */ + inseg.len = (u16_t)(next->tcphdr->seqno - seqno); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + (seqno + tcplen) == next->tcphdr->seqno); + } + pcb->ooseq = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + pcb->rcv_nxt = seqno + tcplen; + + /* Update the receiver's (our) window. */ + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + pcb->rcv_wnd -= tcplen; + + tcp_update_rcv_ann_wnd(pcb); + + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. + + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags |= TF_GOT_FIN; + } + +#if TCP_QUEUE_OOSEQ + /* We now check if we have segments on the ->ooseq queue that + are now in sequence. */ + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; + + pcb->rcv_nxt += TCP_TCPLEN(cseg); + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + pcb->rcv_wnd >= TCP_TCPLEN(cseg)); + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + + tcp_update_rcv_ann_wnd(pcb); + + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + if (recv_data) { + pbuf_cat(recv_data, cseg->p); + } else { + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags |= TF_GOT_FIN; + if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ + pcb->state = CLOSE_WAIT; + } + } + + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } +#endif /* TCP_QUEUE_OOSEQ */ + + + /* Acknowledge the segment(s). */ + tcp_ack(pcb); + + } else { + /* We get here if the incoming segment is out-of-sequence. */ + tcp_send_empty_ack(pcb); +#if TCP_QUEUE_OOSEQ + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. + + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ + + prev = NULL; + for(next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the + same as the sequence number of the segment on + ->ooseq. We check the lengths to see which one to + discard. */ + if (inseg.len > next->len) { + /* The incoming segment is larger than the old + segment. We replace some segments with the new + one. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + tcp_oos_insert_segment(cseg, next); + } + break; + } else { + /* Either the lenghts are the same or the incoming + segment was smaller than the old one; in either + case, we ditch the incoming segment. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + pcb->ooseq = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } else { + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { + /* The sequence number of the incoming segment is in + between the sequence numbers of the previous and + the next segment on ->ooseq. We trim trim the previous + segment, delete next segments that included in received segment + and trim received, if needed. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = (u16_t)(seqno - prev->tcphdr->seqno); + pbuf_realloc(prev->p, prev->len); + } + prev->next = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } + /* If the "next" segment is the last segment on the + ooseq queue, we add the incoming segment to the end + of the list. */ + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + /* segment "next" already contains all data */ + break; + } + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = (u16_t)(seqno - next->tcphdr->seqno); + pbuf_realloc(next->p, next->len); + } + /* check if the remote side overruns our receive window */ + if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno; + pbuf_realloc(next->next->p, next->next->len); + tcplen = TCP_TCPLEN(next->next); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } + } + break; + } + } + prev = next; + } + } +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + /* Check that the data on ooseq doesn't exceed one of the limits + and throw away everything above that limit. */ + ooseq_blen = 0; + ooseq_qlen = 0; + prev = NULL; + for(next = pcb->ooseq; next != NULL; prev = next, next = next->next) { + struct pbuf *p = next->p; + ooseq_blen += p->tot_len; + ooseq_qlen += pbuf_clen(p); + if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || + (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { + /* too much ooseq data, dump this and everything after it */ + tcp_segs_free(next); + if (prev == NULL) { + /* first ooseq segment is too much, dump the whole queue */ + pcb->ooseq = NULL; + } else { + /* just dump 'next' and everything after it */ + prev->next = NULL; + } + break; + } + } +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ +#endif /* TCP_QUEUE_OOSEQ */ + } + } else { + /* The incoming segment is not withing the window. */ + tcp_send_empty_ack(pcb); + } + } else { + /* Segments with length 0 is taken care of here. Segments that + fall out of the window are ACKed. */ + /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || + TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ + if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ + tcp_ack_now(pcb); + } + } +} + +/** + * Parses the options contained in the incoming segment. + * + * Called from tcp_listen_input() and tcp_process(). + * Currently, only the MSS option is supported! + * + * @param pcb the tcp_pcb for which a segment arrived + */ +static void +tcp_parseopt(struct tcp_pcb *pcb) +{ + u16_t c, max_c; + u16_t mss; + u8_t *opts, opt; +#if LWIP_TCP_TIMESTAMPS + u32_t tsval; +#endif + + opts = (u8_t *)tcphdr + TCP_HLEN; + + /* Parse the TCP MSS option, if present. */ + if(TCPH_HDRLEN(tcphdr) > 0x5) { + max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; + for (c = 0; c < max_c; ) { + opt = opts[c]; + switch (opt) { + case 0x00: + /* End of options. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); + return; + case 0x01: + /* NOP option. */ + ++c; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); + break; + case 0x02: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); + if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An MSS option with the right option length. */ + mss = (opts[c + 2] << 8) | opts[c + 3]; + /* Limit the mss to the configured TCP_MSS and prevent division by zero */ + pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; + /* Advance to next option */ + c += 0x04; + break; +#if LWIP_TCP_TIMESTAMPS + case 0x08: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); + if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* TCP timestamp option with valid length */ + tsval = (opts[c+2]) | (opts[c+3] << 8) | + (opts[c+4] << 16) | (opts[c+5] << 24); + if (flags & TCP_SYN) { + pcb->ts_recent = ntohl(tsval); + pcb->flags |= TF_TIMESTAMP; + } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { + pcb->ts_recent = ntohl(tsval); + } + /* Advance to next option */ + c += 0x0A; + break; +#endif + default: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); + if (opts[c + 1] == 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + /* If the length field is zero, the options are malformed + and we don't process them further. */ + return; + } + /* All other options have a length field, so that we easily + can skip past them. */ + c += opts[c + 1]; + } + } + } +} + +#endif /* LWIP_TCP */ diff --git a/ext/lwip/src/core/tcp_out.c b/ext/lwip/src/core/tcp_out.c new file mode 100644 index 000000000..94395e25d --- /dev/null +++ b/ext/lwip/src/core/tcp_out.c @@ -0,0 +1,1485 @@ +/** + * @file + * Transmission Control Protocol, outgoing traffic + * + * The output functions of TCP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp_impl.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#if LWIP_TCP_TIMESTAMPS +#include "lwip/sys.h" +#endif + +#include + +/* Define some copy-macros for checksum-on-copy so that the code looks + nicer by preventing too many ifdef's. */ +#if TCP_CHECKSUM_ON_COPY +#define TCP_DATA_COPY(dst, src, len, seg) do { \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ + len, &seg->chksum, &seg->chksum_swapped); \ + seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); +#else /* TCP_CHECKSUM_ON_COPY*/ +#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) +#endif /* TCP_CHECKSUM_ON_COPY*/ + +/** Define this to 1 for an extra check that the output checksum is valid + * (usefule when the checksum is generated by the application, not the stack) */ +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 +#endif + +/* Forward declarations.*/ +static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); + +/** Allocate a pbuf and create a tcphdr at p->payload, used for output + * functions other than the default tcp_output -> tcp_output_segment + * (e.g. tcp_send_empty_ack, etc.) + * + * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) + * @param optlen length of header-options + * @param datalen length of tcp data to reserve in pbuf + * @param seqno_be seqno in network byte order (big-endian) + * @return pbuf with p->payload being the tcp_hdr + */ +static struct pbuf * +tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, + u32_t seqno_be /* already in network byte order */) +{ + struct tcp_hdr *tcphdr; + struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= TCP_HLEN + optlen)); + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(pcb->local_port); + tcphdr->dest = htons(pcb->remote_port); + tcphdr->seqno = seqno_be; + tcphdr->ackno = htonl(pcb->rcv_nxt); + TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); + tcphdr->wnd = htons(pcb->rcv_ann_wnd); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + /* If we're sending a packet, update the announced right window edge */ + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + } + return p; +} + +/** + * Called by tcp_close() to send a segment including FIN flag but not data. + * + * @param pcb the tcp_pcb over which to send a segment + * @return ERR_OK if sent, another err_t otherwise + */ +err_t +tcp_send_fin(struct tcp_pcb *pcb) +{ + /* first, try to add the fin to the last unsent segment */ + if (pcb->unsent != NULL) { + struct tcp_seg *last_unsent; + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { + /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ + TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); + pcb->flags |= TF_FIN; + return ERR_OK; + } + } + /* no data, no length, flags, copy=1, no optdata */ + return tcp_enqueue_flags(pcb, TCP_FIN); +} + +/** + * Create a TCP segment with prefilled header. + * + * Called by tcp_write and tcp_enqueue_flags. + * + * @param pcb Protocol control block for the TCP connection. + * @param p pbuf that is used to hold the TCP header. + * @param flags TCP flags for header. + * @param seqno TCP sequence number of this packet + * @param optflags options to include in TCP header + * @return a new tcp_seg pointing to p, or NULL. + * The TCP header is filled in except ackno and wnd. + * p is freed on failure. + */ +static struct tcp_seg * +tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) +{ + struct tcp_seg *seg; + u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); + + if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no memory.\n")); + pbuf_free(p); + return NULL; + } + seg->flags = optflags; + seg->next = NULL; + seg->p = p; + seg->len = p->tot_len - optlen; +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = 0; + seg->chksum_swapped = 0; + /* check optflags */ + LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", + (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* build TCP header */ + if (pbuf_header(p, TCP_HLEN)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no room for TCP header in pbuf.\n")); + TCP_STATS_INC(tcp.err); + tcp_seg_free(seg); + return NULL; + } + seg->tcphdr = (struct tcp_hdr *)seg->p->payload; + seg->tcphdr->src = htons(pcb->local_port); + seg->tcphdr->dest = htons(pcb->remote_port); + seg->tcphdr->seqno = htonl(seqno); + /* ackno is set in tcp_output */ + TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); + /* wnd and chksum are set in tcp_output */ + seg->tcphdr->urgp = 0; + return seg; +} + +/** + * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. + * + * This function is like pbuf_alloc(layer, length, PBUF_RAM) except + * there may be extra bytes available at the end. + * + * @param layer flag to define header size. + * @param length size of the pbuf's payload. + * @param max_length maximum usable size of payload+oversize. + * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. + * @param pcb The TCP connection that willo enqueue the pbuf. + * @param apiflags API flags given to tcp_write. + * @param first_seg true when this pbuf will be used in the first enqueued segment. + * @param + */ +#if TCP_OVERSIZE +static struct pbuf * +tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, + u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, + u8_t first_seg) +{ + struct pbuf *p; + u16_t alloc = length; + +#if LWIP_NETIF_TX_SINGLE_PBUF + LWIP_UNUSED_ARG(max_length); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(apiflags); + LWIP_UNUSED_ARG(first_seg); + /* always create MSS-sized pbufs */ + alloc = max_length; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (length < max_length) { + /* Should we allocate an oversized pbuf, or just the minimum + * length required? If tcp_write is going to be called again + * before this segment is transmitted, we want the oversized + * buffer. If the segment will be transmitted immediately, we can + * save memory by allocating only length. We use a simple + * heuristic based on the following information: + * + * Did the user set TCP_WRITE_FLAG_MORE? + * + * Will the Nagle algorithm defer transmission of this segment? + */ + if ((apiflags & TCP_WRITE_FLAG_MORE) || + (!(pcb->flags & TF_NODELAY) && + (!first_seg || + pcb->unsent != NULL || + pcb->unacked != NULL))) { + alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(length + TCP_OVERSIZE)); + } + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(layer, alloc, PBUF_RAM); + if (p == NULL) { + return NULL; + } + LWIP_ASSERT("need unchained pbuf", p->next == NULL); + *oversize = p->len - length; + /* trim p->len to the currently used size */ + p->len = p->tot_len = length; + return p; +} +#else /* TCP_OVERSIZE */ +#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) +#endif /* TCP_OVERSIZE */ + +#if TCP_CHECKSUM_ON_COPY +/** Add a checksum of newly added data to the segment */ +static void +tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, + u8_t *seg_chksum_swapped) +{ + u32_t helper; + /* add chksum to old chksum and fold to u16_t */ + helper = chksum + *seg_chksum; + chksum = FOLD_U32T(helper); + if ((len & 1) != 0) { + *seg_chksum_swapped = 1 - *seg_chksum_swapped; + chksum = SWAP_BYTES_IN_WORD(chksum); + } + *seg_chksum = chksum; +} +#endif /* TCP_CHECKSUM_ON_COPY */ + +/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). + * + * @param pcb the tcp pcb to check for + * @param len length of data to send (checked agains snd_buf) + * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise + */ +static err_t +tcp_write_checks(struct tcp_pcb *pcb, u16_t len) +{ + /* connection is in invalid state for data transmission? */ + if ((pcb->state != ESTABLISHED) && + (pcb->state != CLOSE_WAIT) && + (pcb->state != SYN_SENT) && + (pcb->state != SYN_RCVD)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } else if (len == 0) { + return ERR_OK; + } + + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", + len, pcb->snd_buf)); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + return ERR_OK; +} + +/** + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @param pcb Protocol control block for the TCP connection to enqueue data for. + * @param arg Pointer to the data to be enqueued for sending. + * @param len Data length in bytes + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent, + * @return ERR_OK if enqueued, another err_t on error + */ +err_t +tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) +{ + struct pbuf *concat_p = NULL; + struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; + u16_t pos = 0; /* position in 'arg' data */ + u16_t queuelen; + u8_t optlen = 0; + u8_t optflags = 0; +#if TCP_OVERSIZE + u16_t oversize = 0; + u16_t oversize_used = 0; +#endif /* TCP_OVERSIZE */ +#if TCP_CHECKSUM_ON_COPY + u16_t concat_chksum = 0; + u8_t concat_chksum_swapped = 0; + u16_t concat_chksummed = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + err_t err; + /* don't allocate segments bigger than half the maximum window we ever received */ + u16_t mss_local = LWIP_MIN(pcb->mss, pcb->snd_wnd_max/2); + +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Always copy to try to create single pbufs for TX */ + apiflags |= TCP_WRITE_FLAG_COPY; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)apiflags)); + LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", + arg != NULL, return ERR_ARG;); + + err = tcp_write_checks(pcb, len); + if (err != ERR_OK) { + return err; + } + queuelen = pcb->snd_queuelen; + +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + optflags = TF_SEG_OPTS_TS; + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif /* LWIP_TCP_TIMESTAMPS */ + + + /* + * TCP segmentation is done in three phases with increasing complexity: + * + * 1. Copy data directly into an oversized pbuf. + * 2. Chain a new pbuf to the end of pcb->unsent. + * 3. Create new segments. + * + * We may run out of memory at any point. In that case we must + * return ERR_MEM and not change anything in pcb. Therefore, all + * changes are recorded in local variables and committed at the end + * of the function. Some pcb fields are maintained in local copies: + * + * queuelen = pcb->snd_queuelen + * oversize = pcb->unsent_oversize + * + * These variables are set consistently by the phases: + * + * seg points to the last segment tampered with. + * + * pos records progress as data is segmented. + */ + + /* Find the tail of the unsent queue. */ + if (pcb->unsent != NULL) { + u16_t space; + u16_t unsent_optlen; + + /* @todo: this could be sped up by keeping last_unsent in the pcb */ + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + /* Usable space at the end of the last unsent segment */ + unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); + space = mss_local - (last_unsent->len + unsent_optlen); + + /* + * Phase 1: Copy data directly into an oversized pbuf. + * + * The number of bytes copied is recorded in the oversize_used + * variable. The actual copying is done at the bottom of the + * function. + */ +#if TCP_OVERSIZE +#if TCP_OVERSIZE_DBGCHECK + /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */ + LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", + pcb->unsent_oversize == last_unsent->oversize_left); +#endif /* TCP_OVERSIZE_DBGCHECK */ + oversize = pcb->unsent_oversize; + if (oversize > 0) { + LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space); + seg = last_unsent; + oversize_used = oversize < len ? oversize : len; + pos += oversize_used; + oversize -= oversize_used; + space -= oversize_used; + } + /* now we are either finished or oversize is zero */ + LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len)); +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: Chain a new pbuf to the end of pcb->unsent. + * + * We don't extend segments containing SYN/FIN flags or options + * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at + * the end. + */ + if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { + u16_t seglen = space < len - pos ? space : len - pos; + seg = last_unsent; + + /* Create a pbuf with a copy or reference to seglen bytes. We + * can use PBUF_RAW here since the data appears in the middle of + * a segment. A header will never be prepended. */ + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* Data is copied */ + if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, + ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", + seglen)); + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + last_unsent->oversize_left += oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ + TCP_DATA_COPY2(concat_p->payload, (u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); +#if TCP_CHECKSUM_ON_COPY + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + } else { + /* Data is not copied */ + if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, + ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + tcp_seg_add_chksum(~inet_chksum((u8_t*)arg + pos, seglen), seglen, + &concat_chksum, &concat_chksum_swapped); + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + concat_p->payload = (u8_t*)arg + pos; + } + + pos += seglen; + queuelen += pbuf_clen(concat_p); + } + } else { +#if TCP_OVERSIZE + LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", + pcb->unsent_oversize == 0); +#endif /* TCP_OVERSIZE */ + } + + /* + * Phase 3: Create new segments. + * + * The new segments are chained together in the local 'queue' + * variable, ready to be appended to pcb->unsent. + */ + while (pos < len) { + struct pbuf *p; + u16_t left = len - pos; + u16_t max_len = mss_local - optlen; + u16_t seglen = left > max_len ? max_len : left; +#if TCP_CHECKSUM_ON_COPY + u16_t chksum = 0; + u8_t chksum_swapped = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* If copy is set, memory should be allocated and data copied + * into pbuf */ + if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); + goto memerr; + } + LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", + (p->len >= seglen)); + TCP_DATA_COPY2((char *)p->payload + optlen, (u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); + } else { + /* Copy is not set: First allocate a pbuf for holding the data. + * Since the referenced data is available at least until it is + * sent out on the link (as it has to be ACKed by the remote + * party) we can safely use PBUF_ROM instead of PBUF_REF here. + */ + struct pbuf *p2; +#if TCP_OVERSIZE + LWIP_ASSERT("oversize == 0", oversize == 0); +#endif /* TCP_OVERSIZE */ + if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + chksum = ~inet_chksum((u8_t*)arg + pos, seglen); +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + p2->payload = (u8_t*)arg + pos; + + /* Second, allocate a pbuf for the headers. */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + /* If allocation fails, we have to deallocate the data pbuf as + * well. */ + pbuf_free(p2); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for header pbuf\n")); + goto memerr; + } + /* Concatenate the headers and data pbufs together. */ + pbuf_cat(p/*header*/, p2/*data*/); + } + + queuelen += pbuf_clen(p); + + /* Now that there are more segments queued, we check again if the + * length of the queue exceeds the configured maximum or + * overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); + pbuf_free(p); + goto memerr; + } + + if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = chksum; + seg->chksum_swapped = chksum_swapped; + seg->flags |= TF_SEG_DATA_CHECKSUMMED; +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* first segment of to-be-queued data? */ + if (queue == NULL) { + queue = seg; + } else { + /* Attach the segment to the end of the queued segments */ + LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); + prev_seg->next = seg; + } + /* remember last segment of to-be-queued data for next iteration */ + prev_seg = seg; + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); + + pos += seglen; + } + + /* + * All three segmentation phases were successful. We can commit the + * transaction. + */ + + /* + * Phase 1: If data has been added to the preallocated tail of + * last_unsent, we update the length fields of the pbuf chain. + */ +#if TCP_OVERSIZE + if (oversize_used > 0) { + struct pbuf *p; + /* Bump tot_len of whole chain, len of tail */ + for (p = last_unsent->p; p; p = p->next) { + p->tot_len += oversize_used; + if (p->next == NULL) { + TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); + p->len += oversize_used; + } + } + last_unsent->len += oversize_used; +#if TCP_OVERSIZE_DBGCHECK + LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", + last_unsent->oversize_left >= oversize_used); + last_unsent->oversize_left -= oversize_used; +#endif /* TCP_OVERSIZE_DBGCHECK */ + } + pcb->unsent_oversize = oversize; +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: concat_p can be concatenated onto last_unsent->p + */ + if (concat_p != NULL) { + LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", + (last_unsent != NULL)); + pbuf_cat(last_unsent->p, concat_p); + last_unsent->len += concat_p->tot_len; +#if TCP_CHECKSUM_ON_COPY + if (concat_chksummed) { + tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, + &last_unsent->chksum_swapped); + last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; + } +#endif /* TCP_CHECKSUM_ON_COPY */ + } + + /* + * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that + * is harmless + */ + if (last_unsent == NULL) { + pcb->unsent = queue; + } else { + last_unsent->next = queue; + } + + /* + * Finally update the pcb state. + */ + pcb->snd_lbb += len; + pcb->snd_buf -= len; + pcb->snd_queuelen = queuelen; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", + pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + /* Set the PSH flag in the last segment that we enqueued. */ + if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { + TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); + } + + return ERR_OK; +memerr: + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + + if (concat_p != NULL) { + pbuf_free(concat_p); + } + if (queue != NULL) { + tcp_segs_free(queue); + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); + return ERR_MEM; +} + +/** + * Enqueue TCP options for transmission. + * + * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). + * + * @param pcb Protocol control block for the TCP connection. + * @param flags TCP header flags to set in the outgoing segment. + * @param optdata pointer to TCP options, or NULL. + * @param optlen length of TCP options in bytes. + */ +err_t +tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) +{ + struct pbuf *p; + struct tcp_seg *seg; + u8_t optflags = 0; + u8_t optlen = 0; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", + (flags & (TCP_SYN | TCP_FIN)) != 0); + + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + if (flags & TCP_SYN) { + optflags = TF_SEG_OPTS_MSS; + } +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + optflags |= TF_SEG_OPTS_TS; + } +#endif /* LWIP_TCP_TIMESTAMPS */ + optlen = LWIP_TCP_OPT_LENGTH(optflags); + + /* tcp_enqueue_flags is always called with either SYN or FIN in flags. + * We need one available snd_buf byte to do that. + * This means we can't send FIN while snd_buf==0. A better fix would be to + * not include SYN and FIN sequence numbers in the snd_buf count. */ + if (pcb->snd_buf == 0) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: no send buffer available\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + + /* Allocate pbuf with room for TCP header + options */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", + (p->len >= optlen)); + + /* Allocate memory for tcp_seg, and fill in fields. */ + if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, + ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + (u16_t)flags)); + + /* Now append seg to pcb->unsent queue */ + if (pcb->unsent == NULL) { + pcb->unsent = seg; + } else { + struct tcp_seg *useg; + for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); + useg->next = seg; + } +#if TCP_OVERSIZE + /* The new unsent tail has no space */ + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + + /* SYN and FIN bump the sequence number */ + if ((flags & TCP_SYN) || (flags & TCP_FIN)) { + pcb->snd_lbb++; + /* optlen does not influence snd_buf */ + pcb->snd_buf--; + } + if (flags & TCP_FIN) { + pcb->flags |= TF_FIN; + } + + /* update number of segments on the queues */ + pcb->snd_queuelen += pbuf_clen(seg->p); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + return ERR_OK; +} + +#if LWIP_TCP_TIMESTAMPS +/* Build a timestamp option (12 bytes long) at the specified options pointer) + * + * @param pcb tcp_pcb + * @param opts option pointer where to store the timestamp option + */ +static void +tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) +{ + /* Pad with two NOP options to make everything nicely aligned */ + opts[0] = PP_HTONL(0x0101080A); + opts[1] = htonl(sys_now()); + opts[2] = htonl(pcb->ts_recent); +} +#endif + +/** Send an ACK without data. + * + * @param pcb Protocol control block for the TCP connection to send the ACK + */ +err_t +tcp_send_empty_ack(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + u8_t optlen = 0; + +#if LWIP_TCP_TIMESTAMPS + if (pcb->flags & TF_TIMESTAMP) { + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif + + p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt)); + if (p == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); + return ERR_BUF; + } + tcphdr = (struct tcp_hdr *)p->payload; + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + /* remove ACK flags from the PCB, as we send an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + + /* NB. MSS option is only sent on SYNs, so ignore it here */ +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (pcb->flags & TF_TIMESTAMP) { + tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); + } +#endif + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip), + IP_PROTO_TCP, p->tot_len); +#endif +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP, &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + pbuf_free(p); + + return ERR_OK; +} + +/** + * Find out what we can send and send it + * + * @param pcb Protocol control block for the TCP connection to send data + * @return ERR_OK if data has been sent or nothing to send + * another err_t on error + */ +err_t +tcp_output(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg, *useg; + u32_t wnd, snd_nxt; +#if TCP_CWND_DEBUG + s16_t i = 0; +#endif /* TCP_CWND_DEBUG */ + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_output for listen-pcbs", + pcb->state != LISTEN); + + /* First, check if we are invoked by the TCP input processing + code. If so, we do not output anything. Instead, we rely on the + input processing code to call us when input processing is done + with. */ + if (tcp_input_pcb == pcb) { + return ERR_OK; + } + + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); + + seg = pcb->unsent; + + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ + if (pcb->flags & TF_ACK_NOW && + (seg == NULL || + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + return tcp_send_empty_ack(pcb); + } + + /* useg should point to last segment on unacked queue */ + useg = pcb->unacked; + if (useg != NULL) { + for (; useg->next != NULL; useg = useg->next); + } + +#if TCP_OUTPUT_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", + (void*)pcb->unsent)); + } +#endif /* TCP_OUTPUT_DEBUG */ +#if TCP_CWND_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F + ", cwnd %"U16_F", wnd %"U32_F + ", seg == NULL, ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); + } else { + LWIP_DEBUGF(TCP_CWND_DEBUG, + ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F + ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + ntohl(seg->tcphdr->seqno), pcb->lastack)); + } +#endif /* TCP_CWND_DEBUG */ + /* data available and window allows it to be sent? */ + while (seg != NULL && + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + LWIP_ASSERT("RST not expected here!", + (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); + /* Stop sending if the nagle algorithm would prevent it + * Don't stop: + * - if tcp_write had a memory error before (prevent delayed ACK timeout) or + * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - + * either seg->next != NULL or pcb->unacked == NULL; + * RST is no sent using tcp_write/tcp_output. + */ + if((tcp_do_output_nagle(pcb) == 0) && + ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){ + break; + } +#if TCP_CWND_DEBUG + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) + seg->len - + pcb->lastack, + ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + ++i; +#endif /* TCP_CWND_DEBUG */ + + pcb->unsent = seg->next; + + if (pcb->state != SYN_SENT) { + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + tcp_output_segment(seg, pcb); + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + /* put segment on unacknowledged list if length > 0 */ + if (TCP_TCPLEN(seg) > 0) { + seg->next = NULL; + /* unacked list is empty? */ + if (pcb->unacked == NULL) { + pcb->unacked = seg; + useg = seg; + /* unacked list is not empty? */ + } else { + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather somewhere before it. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { + /* add segment to before tail of unacked list, keeping the list sorted */ + struct tcp_seg **cur_seg = &(pcb->unacked); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = (*cur_seg); + (*cur_seg) = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } + } + /* do not queue empty segments on the unacked list */ + } else { + tcp_seg_free(seg); + } + seg = pcb->unsent; + } +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + /* last unsent has been removed, reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + pcb->flags &= ~TF_NAGLEMEMERR; + return ERR_OK; +} + +/** + * Called by tcp_output() to actually send a TCP segment over IP. + * + * @param seg the tcp_seg to send + * @param pcb the tcp_pcb for the TCP connection used to send the segment + */ +static void +tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) +{ + u16_t len; + struct netif *netif; + u32_t *opts; + + /** @bug Exclude retransmitted segments from this count. */ + snmp_inc_tcpoutsegs(); + + /* The TCP header has already been constructed, but the ackno and + wnd fields remain. */ + seg->tcphdr->ackno = htonl(pcb->rcv_nxt); + + /* advertise our receive window size in this TCP segment */ + seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd); + + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + /* Add any requested options. NB MSS option is only set on SYN + packets, so ignore it here */ + opts = (u32_t *)(void *)(seg->tcphdr + 1); + if (seg->flags & TF_SEG_OPTS_MSS) { + u16_t mss; +#if TCP_CALCULATE_EFF_SEND_MSS + mss = tcp_eff_send_mss(TCP_MSS, &pcb->remote_ip); +#else /* TCP_CALCULATE_EFF_SEND_MSS */ + mss = TCP_MSS; +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + *opts = TCP_BUILD_MSS_OPTION(mss); + opts += 1; + } +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (seg->flags & TF_SEG_OPTS_TS) { + tcp_build_timestamp_option(pcb, opts); + opts += 3; + } +#endif + + /* Set retransmission timer running if it is not currently enabled + This must be set before checking the route. */ + if (pcb->rtime == -1) { + pcb->rtime = 0; + } + + /* If we don't have a local IP address, we get one by + calling ip_route(). */ + if (ip_addr_isany(&(pcb->local_ip))) { + netif = ip_route(&(pcb->remote_ip)); + if (netif == NULL) { + return; + } + ip_addr_copy(pcb->local_ip, netif->ip_addr); + } + + if (pcb->rttest == 0) { + pcb->rttest = tcp_ticks; + pcb->rtseq = ntohl(seg->tcphdr->seqno); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", + htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + + seg->len)); + + len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + + seg->p->len -= len; + seg->p->tot_len -= len; + + seg->p->payload = seg->tcphdr; + + seg->tcphdr->chksum = 0; +#if CHECKSUM_GEN_TCP +#if TCP_CHECKSUM_ON_COPY + { + u32_t acc; +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip), + &(pcb->remote_ip), + IP_PROTO_TCP, seg->p->tot_len); +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { + LWIP_ASSERT("data included but not checksummed", + seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); + } + + /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ + acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip), + &(pcb->remote_ip), + IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4); + /* add payload checksum */ + if (seg->chksum_swapped) { + seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); + seg->chksum_swapped = 0; + } + acc += (u16_t)~(seg->chksum); + seg->tcphdr->chksum = FOLD_U32T(acc); +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + if (chksum_slow != seg->tcphdr->chksum) { + LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", + seg->tcphdr->chksum, chksum_slow)); + seg->tcphdr->chksum = chksum_slow; + } +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + } +#else /* TCP_CHECKSUM_ON_COPY */ + seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip), + &(pcb->remote_ip), + IP_PROTO_TCP, seg->p->tot_len); +#endif /* TCP_CHECKSUM_ON_COPY */ +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP, &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) either to + * abort a connection or to show that there is no matching local connection + * for a received segment. + * + * Called by tcp_abort() (to abort a local connection), tcp_input() (if no + * matching local pcb was found), tcp_listen_input() (if incoming segment + * has ACK flag set) and tcp_process() (received segment in the wrong state) + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst(u32_t seqno, u32_t ackno, + ip_addr_t *local_ip, ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(local_port); + tcphdr->dest = htons(remote_port); + tcphdr->seqno = htonl(seqno); + tcphdr->ackno = htonl(ackno); + TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); + tcphdr->wnd = PP_HTONS(TCP_WND); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + snmp_inc_tcpoutrsts(); + /* Send output with hardcoded TTL since we have no access to the pcb */ + ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); + pbuf_free(p); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/** + * Requeue all unacked segments for retransmission + * + * Called by tcp_slowtmr() for slow retransmission. + * + * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + /* last unsent hasn't changed, no need to reset unsent_oversize */ + + /* increment number of retransmissions */ + ++pcb->nrtx; + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); +} + +/** + * Requeue the first unacked segment for retransmission + * + * Called by tcp_receive() for fast retramsmit. + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + struct tcp_seg **cur_seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move the first unacked segment to the unsent queue */ + /* Keep the unsent queue sorted. */ + seg = pcb->unacked; + pcb->unacked = seg->next; + + cur_seg = &(pcb->unsent); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = *cur_seg; + *cur_seg = seg; +#if TCP_OVERSIZE + if (seg->next == NULL) { + /* the retransmitted segment is last in unsent, so reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + ++pcb->nrtx; + + /* Don't take any rtt measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission. */ + snmp_inc_tcpretranssegs(); + /* No need to call tcp_output: we are always called from tcp_input() + and thus tcp_output directly returns. */ +} + + +/** + * Handle retransmission after three dupacks received + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit_fast(struct tcp_pcb *pcb) +{ + if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: dupacks %"U16_F" (%"U32_F + "), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + + /* Set ssthresh to half of the minimum of the current + * cwnd and the advertised window */ + if (pcb->cwnd > pcb->snd_wnd) { + pcb->ssthresh = pcb->snd_wnd / 2; + } else { + pcb->ssthresh = pcb->cwnd / 2; + } + + /* The minimum value for ssthresh should be 2 MSS */ + if (pcb->ssthresh < 2*pcb->mss) { + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: The minimum value for ssthresh %"U16_F + " should be min 2 mss %"U16_F"...\n", + pcb->ssthresh, 2*pcb->mss)); + pcb->ssthresh = 2*pcb->mss; + } + + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + } +} + + +/** + * Send keepalive packets to keep a connection active although + * no data is sent over it. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a keepalive packet + */ +void +tcp_keepalive(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), + ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_keepalive: could not allocate memory for pbuf\n")); + return; + } + tcphdr = (struct tcp_hdr *)p->payload; + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, + &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} + + +/** + * Send persist timer zero-window probes to keep a connection active + * when a window update is lost. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a zero-window probe packet + */ +void +tcp_zero_window_probe(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct tcp_seg *seg; + u16_t len; + u8_t is_fin; + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: sending ZERO WINDOW probe to %" + U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), + ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: tcp_ticks %"U32_F + " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + seg = pcb->unacked; + + if(seg == NULL) { + seg = pcb->unsent; + } + if(seg == NULL) { + return; + } + + is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); + /* we want to send one seqno: either FIN or data (no options) */ + len = is_fin ? 0 : 1; + + p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); + return; + } + tcphdr = (struct tcp_hdr *)p->payload; + + if (is_fin) { + /* FIN segment, no data */ + TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); + } else { + /* Data segment, copy in one byte from the head of the unacked queue */ + char *d = ((char *)p->payload + TCP_HLEN); + /* Depending on whether the segment has already been sent (unacked) or not + (unsent), seg->p->payload points to the IP header or TCP header. + Ensure we copy the first TCP data byte: */ + pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); + } + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, + &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F + " ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} +#endif /* LWIP_TCP */ diff --git a/ext/lwip/src/core/timers.c b/ext/lwip/src/core/timers.c new file mode 100644 index 000000000..e30846660 --- /dev/null +++ b/ext/lwip/src/core/timers.c @@ -0,0 +1,487 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/timers.h" +#include "lwip/tcp_impl.h" + +#if LWIP_TIMERS + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/tcpip.h" + +#include "lwip/ip_frag.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" + + +/** The one and only timeout list */ +static struct sys_timeo *next_timeout; +#if NO_SYS +static u32_t timeouts_last_time; +#endif /* NO_SYS */ + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +/** + * Timer callback function that calls ip_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n")); + ip_reass_tmr(); + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +} +#endif /* IP_REASSEMBLY */ + +#if LWIP_ARP +/** + * Timer callback function that calls etharp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +arp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n")); + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} +#endif /* LWIP_ARP */ + +#if LWIP_DHCP +/** + * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_coarse(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); + dhcp_coarse_tmr(); + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); +} + +/** + * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_fine(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); + dhcp_fine_tmr(); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +} +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP +/** + * Timer callback function that calls autoip_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +autoip_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n")); + autoip_tmr(); + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +} +#endif /* LWIP_AUTOIP */ + +#if LWIP_IGMP +/** + * Timer callback function that calls igmp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +igmp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n")); + igmp_tmr(); + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Timer callback function that calls dns_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dns_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n")); + dns_tmr(); + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +} +#endif /* LWIP_DNS */ + +/** Initialize this module */ +void sys_timeouts_init(void) +{ +#if IP_REASSEMBLY + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +#endif /* LWIP_ARP */ +#if LWIP_DHCP + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +#endif /* LWIP_DNS */ + +#if NO_SYS + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now(); +#endif +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ +void +sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; + + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); + return; + } + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + timeout->time = msecs; +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", + (void *)timeout, msecs, handler_name, (void *)arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (next_timeout == NULL) { + next_timeout = timeout; + return; + } + + if (next_timeout->time > msecs) { + next_timeout->time -= msecs; + timeout->next = next_timeout; + next_timeout = timeout; + } else { + for(t = next_timeout; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry, even though the timeout has not triggered yet. + * + * @note This function only works as expected if there is only one timeout + * calling 'handler' in the list of timeouts. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout(sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + + if (next_timeout == NULL) { + return; + } + + for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + next_timeout = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +#if NO_SYS + +/** Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +void +sys_check_timeouts(void) +{ + if (next_timeout) { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now(); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do + { +#if PBUF_POOL_FREE_OOSEQ + PBUF_CHECK_FREE_OOSEQ(); +#endif /* PBUF_POOL_FREE_OOSEQ */ + had_one = 0; + tmptimeout = next_timeout; + if (tmptimeout && (tmptimeout->time <= diff)) { + /* timeout has expired */ + had_one = 1; + timeouts_last_time = now; + diff -= tmptimeout->time; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + handler(arg); + } + } + /* repeat until all expired timers have been called */ + }while(had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts(void) +{ + timeouts_last_time = sys_now(); +} + +#else /* NO_SYS */ + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) +{ + u32_t time_needed; + struct sys_timeo *tmptimeout; + sys_timeout_handler handler; + void *arg; + + again: + if (!next_timeout) { + time_needed = sys_arch_mbox_fetch(mbox, msg, 0); + } else { + if (next_timeout->time > 0) { + time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = next_timeout; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE(); + handler(arg); + UNLOCK_TCPIP_CORE(); + } + LWIP_TCPIP_THREAD_ALIVE(); + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < next_timeout->time) { + next_timeout->time -= time_needed; + } else { + next_timeout->time = 0; + } + } + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS */ +/* Satisfy the TCP code which calls this function */ +void +tcp_timer_needed(void) +{ +} +#endif /* LWIP_TIMERS */ diff --git a/ext/lwip/src/core/udp.c b/ext/lwip/src/core/udp.c new file mode 100644 index 000000000..32c7d3840 --- /dev/null +++ b/ext/lwip/src/core/udp.c @@ -0,0 +1,1013 @@ +/** + * @file + * User Datagram Protocol module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +/* udp.c + * + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). + * + */ + +/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! + */ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" +#include "lwip/dhcp.h" + +#include + +#ifndef UDP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff +#define UDP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START) +#endif + +/* last local UDP port */ +static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; + +/* The list of UDP PCBs */ +/* exported in udp.h (was static) */ +struct udp_pcb *udp_pcbs; + +/** + * Initialize this module. + */ +void +udp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Allocate a new local UDP port. + * + * @return a new (free) local UDP port number + */ +static u16_t +udp_new_port(void) +{ + u16_t n = 0; + struct udp_pcb *pcb; + +again: + if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { + udp_port = UDP_LOCAL_PORT_RANGE_START; + } + /* Check all PCBs. */ + for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == udp_port) { + if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + return udp_port; +#if 0 + struct udp_pcb *ipcb = udp_pcbs; + while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) { + if (ipcb->local_port == udp_port) { + /* port is already used by another udp_pcb */ + udp_port++; + /* restart scanning all udp pcbs */ + ipcb = udp_pcbs; + } else { + /* go on with next udp pcb */ + ipcb = ipcb->next; + } + } + if (ipcb != NULL) { + return 0; + } + return udp_port; +#endif +} + +/** + * Process an incoming UDP datagram. + * + * Given an incoming UDP datagram (as a chain of pbufs) this function + * finds a corresponding UDP PCB and hands over the pbuf to the pcbs + * recv function. If no pcb is found or the datagram is incorrect, the + * pbuf is freed. + * + * @param p pbuf to be demultiplexed to a UDP PCB. + * @param inp network interface on which the datagram was received. + * + */ +void +udp_input(struct pbuf *p, struct netif *inp) +{ + struct udp_hdr *udphdr; + struct udp_pcb *pcb, *prev; + struct udp_pcb *uncon_pcb; + struct ip_hdr *iphdr; + u16_t src, dest; + u8_t local_match; + u8_t broadcast; + + PERF_START; + + UDP_STATS_INC(udp.recv); + + iphdr = (struct ip_hdr *)p->payload; + + /* Check minimum length (IP header + UDP header) + * and move payload pointer to UDP header */ + if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) { + /* drop short packets */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); + UDP_STATS_INC(udp.lenerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + + udphdr = (struct udp_hdr *)p->payload; + + /* is broadcast packet ? */ + broadcast = ip_addr_isbroadcast(¤t_iphdr_dest, inp); + + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); + + /* convert src and dest ports to host byte order */ + src = ntohs(udphdr->src); + dest = ntohs(udphdr->dest); + + udp_debug_print(udphdr); + + /* print the UDP source and destination */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- " + "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", + ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest), + ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src))); + +#if LWIP_DHCP + pcb = NULL; + /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by + the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */ + if (dest == DHCP_CLIENT_PORT) { + /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */ + if (src == DHCP_SERVER_PORT) { + if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) { + /* accept the packe if + (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY! + - inp->dhcp->pcb->remote == ANY or iphdr->src */ + if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) || + ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), ¤t_iphdr_src))) { + pcb = inp->dhcp->pcb; + } + } + } + } else +#endif /* LWIP_DHCP */ + { + prev = NULL; + local_match = 0; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb. + * 'Perfect match' pcbs (connected to the remote port & ip address) are + * preferred. If no perfect match is found, the first unconnected pcb that + * matches the local port and ip address gets the datagram. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + local_match = 0; + /* print the PCB local and remote address */ + LWIP_DEBUGF(UDP_DEBUG, + ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- " + "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", + ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip), + ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port, + ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), + ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port)); + + /* compare PCB local addr+port to UDP destination addr+port */ + if (pcb->local_port == dest) { + if ( + (!broadcast && ip_addr_isany(&pcb->local_ip)) || + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest) || +#if LWIP_IGMP + ip_addr_ismulticast(¤t_iphdr_dest) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && ip_get_option(pcb, SOF_BROADCAST) && + (ip_addr_isany(&pcb->local_ip) || + ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast && + (ip_addr_isany(&pcb->local_ip) || + ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) { +#endif /* IP_SOF_BROADCAST_RECV */ + local_match = 1; + if ((uncon_pcb == NULL) && + ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + } + } + /* compare PCB remote addr+port to UDP source addr+port */ + if ((local_match != 0) && + (pcb->remote_port == src) && + (ip_addr_isany(&pcb->remote_ip) || + ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src))) { + /* the first fully matching PCB */ + if (prev != NULL) { + /* move the pcb to the front of udp_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } else { + UDP_STATS_INC(udp.cachehit); + } + break; + } + prev = pcb; + } + /* no fully matching pcb found? then look for an unconnected pcb */ + if (pcb == NULL) { + pcb = uncon_pcb; + } + } + + /* Check checksum if this is a match or if it was directed at us. */ + if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, ¤t_iphdr_dest)) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); +#if LWIP_UDPLITE + if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) { + /* Do the UDP Lite checksum */ +#if CHECKSUM_CHECK_UDP + u16_t chklen = ntohs(udphdr->len); + if (chklen < sizeof(struct udp_hdr)) { + if (chklen == 0) { + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet (See RFC 3828 chap. 3.1) */ + chklen = p->tot_len; + } else { + /* At least the UDP-Lite header must be covered by the + checksum! (Again, see RFC 3828 chap. 3.1) */ + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + } + if (inet_chksum_pseudo_partial(p, ¤t_iphdr_src, ¤t_iphdr_dest, + IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP Lite datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } +#endif /* CHECKSUM_CHECK_UDP */ + } else +#endif /* LWIP_UDPLITE */ + { +#if CHECKSUM_CHECK_UDP + if (udphdr->chksum != 0) { + if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(), + IP_PROTO_UDP, p->tot_len) != 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + } +#endif /* CHECKSUM_CHECK_UDP */ + } + if(pbuf_header(p, -UDP_HLEN)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + if (pcb != NULL) { + snmp_inc_udpindatagrams(); +#if SO_REUSE && SO_REUSE_RXTOALL + if ((broadcast || ip_addr_ismulticast(¤t_iphdr_dest)) && + ip_get_option(pcb, SOF_REUSEADDR)) { + /* pass broadcast- or multicast packets to all multicast pcbs + if SOF_REUSEADDR is set on the first match */ + struct udp_pcb *mpcb; + u8_t p_header_changed = 0; + for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { + if (mpcb != pcb) { + /* compare PCB local addr+port to UDP destination addr+port */ + if ((mpcb->local_port == dest) && + ((!broadcast && ip_addr_isany(&mpcb->local_ip)) || + ip_addr_cmp(&(mpcb->local_ip), ¤t_iphdr_dest) || +#if LWIP_IGMP + ip_addr_ismulticast(¤t_iphdr_dest) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast))) { +#endif /* IP_SOF_BROADCAST_RECV */ + /* pass a copy of the packet to all local matches */ + if (mpcb->recv != NULL) { + struct pbuf *q; + /* for that, move payload to IP header again */ + if (p_header_changed == 0) { + pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); + p_header_changed = 1; + } + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + err_t err = pbuf_copy(q, p); + if (err == ERR_OK) { + /* move payload to UDP data */ + pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); + mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); + } + } + } + } + } + } + if (p_header_changed) { + /* and move payload to UDP data again */ + pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); + } + } +#endif /* SO_REUSE && SO_REUSE_RXTOALL */ + /* callback */ + if (pcb->recv != NULL) { + /* now the recv function is responsible for freeing p */ + pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); + } else { + /* no recv function registered? then we have to free the pbuf! */ + pbuf_free(p); + goto end; + } + } else { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); + +#if LWIP_ICMP + /* No match was found, send ICMP destination port unreachable unless + destination address was broadcast/multicast. */ + if (!broadcast && + !ip_addr_ismulticast(¤t_iphdr_dest)) { + /* move payload pointer back to ip header */ + pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN); + LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr)); + icmp_dest_unreach(p, ICMP_DUR_PORT); + } +#endif /* LWIP_ICMP */ + UDP_STATS_INC(udp.proterr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpnoports(); + pbuf_free(p); + } + } else { + pbuf_free(p); + } +end: + PERF_STOP("udp_input"); +} + +/** + * Send data using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * + * The datagram will be sent to the current remote_ip & remote_port + * stored in pcb. If the pcb is not bound to a port, it will + * automatically be bound to a random port. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_MEM. Out of memory. + * - ERR_RTE. Could not find route to destination address. + * - More errors could be returned by lower protocol layers. + * + * @see udp_disconnect() udp_sendto() + */ +err_t +udp_send(struct udp_pcb *pcb, struct pbuf *p) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); +} + +#if LWIP_CHECKSUM_ON_COPY +/** Same as udp_send() but with checksum + */ +err_t +udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port, + have_chksum, chksum); +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + +/** + * Send data to a specified address using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * If the PCB already has a remote address association, it will + * be restored after the data is sent. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port) +{ +#if LWIP_CHECKSUM_ON_COPY + return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); +} + +/** Same as udp_sendto(), but with checksum */ +err_t +udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, u8_t have_chksum, u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY */ + struct netif *netif; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); + + /* find the outgoing network interface for this packet */ +#if LWIP_IGMP + netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip)); +#else + netif = ip_route(dst_ip); +#endif /* LWIP_IGMP */ + + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip))); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } +#if LWIP_CHECKSUM_ON_COPY + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); +#else /* LWIP_CHECKSUM_ON_COPY */ + return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); +#endif /* LWIP_CHECKSUM_ON_COPY */ +} + +/** + * Send data to a specified address using UDP. + * The netif used for sending can be specified. + * + * This function exists mainly for DHCP, to be able to send UDP packets + * on a netif that is still down. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * @param netif the netif used for sending. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) +{ +#if LWIP_CHECKSUM_ON_COPY + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); +} + +/** Same as udp_sendto_if(), but with checksum */ +err_t +udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY */ + struct udp_hdr *udphdr; + ip_addr_t *src_ip; + err_t err; + struct pbuf *q; /* q will be sent down the stack */ + +#if IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(dst_ip, netif)) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + return ERR_VAL; + } +#endif /* IP_SOF_BROADCAST */ + + /* if the PCB is not yet bound to a port, bind it here */ + if (pcb->local_port == 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); + err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); + return err; + } + } + + /* not enough space to add an UDP header to first pbuf in given p chain? */ + if (pbuf_header(p, UDP_HLEN)) { + /* allocate header in a separate new pbuf */ + q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p (only if p contains data) */ + pbuf_chain(q, p); + } + /* first pbuf q points to header pbuf */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* adding space for header within p succeeded */ + /* first pbuf q equals given pbuf */ + q = p; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); + } + LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", + (q->len >= sizeof(struct udp_hdr))); + /* q now represents the packet to be sent */ + udphdr = (struct udp_hdr *)q->payload; + udphdr->src = htons(pcb->local_port); + udphdr->dest = htons(dst_port); + /* in UDP, 0 checksum means 'no checksum' */ + udphdr->chksum = 0x0000; + + /* Multicast Loop? */ +#if LWIP_IGMP + if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) { + q->flags |= PBUF_FLAG_MCASTLOOP; + } +#endif /* LWIP_IGMP */ + + + /* PCB local address is IP_ANY_ADDR? */ + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) { + /* local_ip doesn't match, drop the packet */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + return ERR_VAL; + } + /* use UDP PCB local IP address as source address */ + src_ip = &(pcb->local_ip); + } + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); + +#if LWIP_UDPLITE + /* UDP Lite protocol? */ + if (pcb->flags & UDP_FLAGS_UDPLITE) { + u16_t chklen, chklen_hdr; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); + /* set UDP message length in UDP header */ + chklen_hdr = chklen = pcb->chksum_len_tx; + if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { + if (chklen != 0) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); + } + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet. (See RFC 3828 chap. 3.1) + At least the UDP-Lite header must be covered by the + checksum, therefore, if chksum_len has an illegal + value, we generate the checksum over the complete + packet to be safe. */ + chklen_hdr = 0; + chklen = q->tot_len; + } + udphdr->len = htons(chklen_hdr); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, + IP_PROTO_UDPLITE, q->tot_len, +#if !LWIP_CHECKSUM_ON_COPY + chklen); +#else /* !LWIP_CHECKSUM_ON_COPY */ + (have_chksum ? UDP_HLEN : chklen)); + if (have_chksum) { + u32_t acc; + acc = udphdr->chksum + (u16_t)~(chksum); + udphdr->chksum = FOLD_U32T(acc); + } +#endif /* !LWIP_CHECKSUM_ON_COPY */ + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) { + udphdr->chksum = 0xffff; + } +#endif /* CHECKSUM_GEN_UDP */ + /* output to IP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n")); + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } else +#endif /* LWIP_UDPLITE */ + { /* UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); + udphdr->len = htons(q->tot_len); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { + u16_t udpchksum; +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP, + q->tot_len, UDP_HLEN); + acc = udpchksum + (u16_t)~(chksum); + udpchksum = FOLD_U32T(acc); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len); + } + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udpchksum == 0x0000) { + udpchksum = 0xffff; + } + udphdr->chksum = udpchksum; + } +#endif /* CHECKSUM_GEN_UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n")); + /* output to IP */ + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + /* TODO: must this be increased even if error occured? */ + snmp_inc_udpoutdatagrams(); + + /* did we chain a separate header pbuf earlier? */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + + UDP_STATS_INC(udp.xmit); + return err; +} + +/** + * Bind an UDP PCB. + * + * @param pcb UDP PCB to be bound with a local address ipaddr and port. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * @param port local UDP port to bind with. Use 0 to automatically bind + * to a random port between UDP_LOCAL_PORT_RANGE_START and + * UDP_LOCAL_PORT_RANGE_END. + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_USE. The specified ipaddr and port are already bound to by + * another UDP PCB. + * + * @see udp_disconnect() + */ +err_t +udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + u8_t rebind; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); + ip_addr_debug_print(UDP_DEBUG, ipaddr); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); + + rebind = 0; + /* Check for double bind and rebind of the same pcb */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + /* is this UDP PCB already on active list? */ + if (pcb == ipcb) { + /* pcb may occur at most once in active list */ + LWIP_ASSERT("rebind == 0", rebind == 0); + /* pcb already in list, just rebind */ + rebind = 1; + } + + /* By default, we don't allow to bind to a port that any other udp + PCB is alread bound to, unless *all* PCBs with that port have tha + REUSEADDR flag set. */ +#if SO_REUSE + else if (!ip_get_option(pcb, SOF_REUSEADDR) && + !ip_get_option(ipcb, SOF_REUSEADDR)) { +#else /* SO_REUSE */ + /* port matches that of PCB in list and REUSEADDR not set -> reject */ + else { +#endif /* SO_REUSE */ + if ((ipcb->local_port == port) && + /* IP address matches, or one is IP_ADDR_ANY? */ + (ip_addr_isany(&(ipcb->local_ip)) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&(ipcb->local_ip), ipaddr))) { + /* other PCB already binds to this local IP and port */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); + return ERR_USE; + } + } + } + + ip_addr_set(&pcb->local_ip, ipaddr); + + /* no port specified? */ + if (port == 0) { + port = udp_new_port(); + if (port == 0) { + /* no more ports available in local range */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); + return ERR_USE; + } + } + pcb->local_port = port; + snmp_insert_udpidx_tree(pcb); + /* pcb not active yet? */ + if (rebind == 0) { + /* place the PCB on the active list if not already there */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n", + ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip), + ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), + pcb->local_port)); + return ERR_OK; +} +/** + * Connect an UDP PCB. + * + * This will associate the UDP PCB with the remote address. + * + * @param pcb UDP PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * @param port remote UDP port to connect with. + * + * @return lwIP error code + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * The udp pcb is bound to a random local port if not already bound. + * + * @see udp_disconnect() + */ +err_t +udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + + if (pcb->local_port == 0) { + err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + return err; + } + } + + ip_addr_set(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; +/** TODO: this functionality belongs in upper layers */ +#ifdef LWIP_UDP_TODO + /* Nail down local IP for netconn_addr()/getsockname() */ + if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) { + struct netif *netif; + + if ((netif = ip_route(&(pcb->remote_ip))) == NULL) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr)); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } + /** TODO: this will bind the udp pcb locally, to the interface which + is used to route output packets to the remote address. However, we + might want to accept incoming packets on any interface! */ + pcb->local_ip = netif->ip_addr; + } else if (ip_addr_isany(&pcb->remote_ip)) { + pcb->local_ip.addr = 0; + } +#endif + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n", + ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip), + ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), + pcb->local_port)); + + /* Insert UDP PCB into the list of active UDP PCBs. */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb == ipcb) { + /* already on the list, just return */ + return ERR_OK; + } + } + /* PCB not yet on the list, add PCB now */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + return ERR_OK; +} + +/** + * Disconnect a UDP PCB + * + * @param pcb the udp pcb to disconnect. + */ +void +udp_disconnect(struct udp_pcb *pcb) +{ + /* reset remote address association */ + ip_addr_set_any(&pcb->remote_ip); + pcb->remote_port = 0; + /* mark PCB as unconnected */ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} + +/** + * Set a receive callback for a UDP PCB + * + * This callback will be called when receiving a datagram for the pcb. + * + * @param pcb the pcb for wich to set the recv callback + * @param recv function pointer of the callback function + * @param recv_arg additional argument to pass to the callback function + */ +void +udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Remove an UDP PCB. + * + * @param pcb UDP PCB to be removed. The PCB is removed from the list of + * UDP PCB's and the data structure is freed from memory. + * + * @see udp_new() + */ +void +udp_remove(struct udp_pcb *pcb) +{ + struct udp_pcb *pcb2; + + snmp_delete_udpidx_tree(pcb); + /* pcb to be removed is first in list? */ + if (udp_pcbs == pcb) { + /* make list start at 2nd pcb */ + udp_pcbs = udp_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in udp_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + } + memp_free(MEMP_UDP_PCB, pcb); +} + +/** + * Create a UDP PCB. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new(void) +{ + struct udp_pcb *pcb; + pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); + /* could allocate UDP PCB? */ + if (pcb != NULL) { + /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 + * which means checksum is generated over the whole datagram per default + * (recommended as default by RFC 3828). */ + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct udp_pcb)); + pcb->ttl = UDP_TTL; + } + return pcb; +} + +#if UDP_DEBUG +/** + * Print UDP header information for debug purposes. + * + * @param udphdr pointer to the udp header in memory. + */ +void +udp_debug_print(struct udp_hdr *udphdr) +{ + LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(udphdr->src), ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", + ntohs(udphdr->len), ntohs(udphdr->chksum))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* UDP_DEBUG */ + +#endif /* LWIP_UDP */ diff --git a/ext/lwip/src/include/arch/cc.h b/ext/lwip/src/include/arch/cc.h new file mode 100644 index 000000000..462124dac --- /dev/null +++ b/ext/lwip/src/include/arch/cc.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_CC_H__ +#define __ARCH_CC_H__ + +/* Include some files for defining library routines */ +#include +#include +#include + +#define LWIP_TIMEVAL_PRIVATE 0 + +/* Define platform endianness */ +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif /* BYTE_ORDER */ + +/* Define generic types used in lwIP */ +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned int u32_t; +typedef signed int s32_t; + +typedef unsigned long mem_ptr_t; + +/* Define (sn)printf formatters for these lwIP types */ +#define X8_F "02x" +#define U16_F "hu" +#define S16_F "hd" +#define X16_F "hx" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" + +/* If only we could use C99 and get %zu */ +#if defined(__x86_64__) +#define SZT_F "lu" +#else +#define SZT_F "u" +#endif + +/* Compiler hints for packing structures */ +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END + +/* prototypes for printf() and abort() */ +#include +#include +/* Plaform specific diagnostic output */ +#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) + +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ + x, __LINE__, __FILE__); fflush(NULL); abort();} while(0) + +#define LWIP_RAND() ((u32_t)rand()) + +#endif /* __ARCH_CC_H__ */ diff --git a/ext/lwip/src/include/arch/perf.h b/ext/lwip/src/include/arch/perf.h new file mode 100644 index 000000000..9fbcf600e --- /dev/null +++ b/ext/lwip/src/include/arch/perf.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_PERF_H__ +#define __ARCH_PERF_H__ + +#include + +#ifdef PERF +#define PERF_START { \ + unsigned long __c1l, __c1h, __c2l, __c2h; \ + __asm__(".byte 0x0f, 0x31" : "=a" (__c1l), "=d" (__c1h)) +#define PERF_STOP(x) __asm__(".byte 0x0f, 0x31" : "=a" (__c2l), "=d" (__c2h)); \ + perf_print(__c1l, __c1h, __c2l, __c2h, x);} + +/*#define PERF_START do { \ + struct tms __perf_start, __perf_end; \ + times(&__perf_start) +#define PERF_STOP(x) times(&__perf_end); \ + perf_print_times(&__perf_start, &__perf_end, x);\ + } while(0)*/ +#else /* PERF */ +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ +#endif /* PERF */ + +void perf_print(unsigned long c1l, unsigned long c1h, + unsigned long c2l, unsigned long c2h, + char *key); + +void perf_print_times(struct tms *start, struct tms *end, char *key); + +void perf_init(char *fname); + +#endif /* __ARCH_PERF_H__ */ diff --git a/ext/lwip/src/include/arch/sys_arch.h b/ext/lwip/src/include/arch/sys_arch.h new file mode 100644 index 000000000..56d20af07 --- /dev/null +++ b/ext/lwip/src/include/arch/sys_arch.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_SYS_ARCH_H__ +#define __ARCH_SYS_ARCH_H__ + +#include + +#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL + +typedef u32_t sys_prot_t; + +struct sys_sem; +typedef struct sys_sem * sys_sem_t; +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) + +/* let sys.h use binary semaphores for mutexes */ +#define LWIP_COMPAT_MUTEX 1 + +struct sys_mbox; +typedef struct sys_mbox *sys_mbox_t; +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) +#define sys_mbox_set_invalid(mbox) do { if((mbox) != NULL) { *(mbox) = NULL; }}while(0) + +struct sys_thread; +typedef struct sys_thread * sys_thread_t; + +#endif /* __ARCH_SYS_ARCH_H__ */ + diff --git a/ext/lwip/src/include/ipv4/lwip/autoip.h b/ext/lwip/src/include/ipv4/lwip/autoip.h new file mode 100644 index 000000000..e62b72e8c --- /dev/null +++ b/ext/lwip/src/include/ipv4/lwip/autoip.h @@ -0,0 +1,118 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +#ifndef __LWIP_AUTOIP_H__ +#define __LWIP_AUTOIP_H__ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +#define AUTOIP_STATE_OFF 0 +#define AUTOIP_STATE_PROBING 1 +#define AUTOIP_STATE_ANNOUNCING 2 +#define AUTOIP_STATE_BOUND 3 + +struct autoip +{ + ip_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */ + u8_t state; /* current AutoIP state machine state */ + u8_t sent_num; /* sent number of probes or announces, dependent on state */ + u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u8_t lastconflict; /* ticks until a conflict can be solved by defending */ + u8_t tried_llipaddr; /* total number of probed/used Link Local IP-Addresses */ +}; + + +#define autoip_init() /* Compatibility define, no init needed. */ + +/** Set a struct autoip allocated by the application to work with */ +void autoip_set_struct(struct netif *netif, struct autoip *autoip); + +/** Start AutoIP client */ +err_t autoip_start(struct netif *netif); + +/** Stop AutoIP client */ +err_t autoip_stop(struct netif *netif); + +/** Handles every incoming ARP Packet, called by etharp_arp_input */ +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); + +/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ +void autoip_tmr(void); + +/** Handle a possible change in the network configuration */ +void autoip_network_changed(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_AUTOIP */ + +#endif /* __LWIP_AUTOIP_H__ */ diff --git a/ext/lwip/src/include/ipv4/lwip/icmp.h b/ext/lwip/src/include/ipv4/lwip/icmp.h new file mode 100644 index 000000000..d47a7d8a2 --- /dev/null +++ b/ext/lwip/src/include/ipv4/lwip/icmp.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is splitted to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) + +/** Combines type and code to an u16_t */ +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp); +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#endif /* LWIP_ICMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ICMP_H__ */ diff --git a/ext/lwip/src/include/ipv4/lwip/igmp.h b/ext/lwip/src/include/ipv4/lwip/igmp.h new file mode 100644 index 000000000..8aabac248 --- /dev/null +++ b/ext/lwip/src/include/ipv4/lwip/igmp.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef __LWIP_IGMP_H__ +#define __LWIP_IGMP_H__ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* MAC Filter Actions, these are passed to a netif's + * igmp_mac_filter callback function. */ +#define IGMP_DEL_MAC_FILTER 0 +#define IGMP_ADD_MAC_FILTER 1 + + +/** + * igmp group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ +struct igmp_group { + /** next link */ + struct igmp_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting, negative is OFF */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/* Prototypes */ +void igmp_init(void); +err_t igmp_start(struct netif *netif); +err_t igmp_stop(struct netif *netif); +void igmp_report_groups(struct netif *netif); +struct igmp_group *igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr); +void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest); +err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr); +err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr); +void igmp_tmr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IGMP */ + +#endif /* __LWIP_IGMP_H__ */ diff --git a/ext/lwip/src/include/ipv4/lwip/inet.h b/ext/lwip/src/include/ipv4/lwip/inet.h new file mode 100644 index 000000000..7bff49b59 --- /dev/null +++ b/ext/lwip/src/include/ipv4/lwip/inet.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** For compatibility with BSD code */ +struct in_addr { + u32_t s_addr; +}; + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IN_CLASSA(a) IP_CLASSA(a) +#define IN_CLASSA_NET IP_CLASSA_NET +#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT +#define IN_CLASSA_HOST IP_CLASSA_HOST +#define IN_CLASSA_MAX IP_CLASSA_MAX + +#define IN_CLASSB(b) IP_CLASSB(b) +#define IN_CLASSB_NET IP_CLASSB_NET +#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT +#define IN_CLASSB_HOST IP_CLASSB_HOST +#define IN_CLASSB_MAX IP_CLASSB_MAX + +#define IN_CLASSC(c) IP_CLASSC(c) +#define IN_CLASSC_NET IP_CLASSC_NET +#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT +#define IN_CLASSC_HOST IP_CLASSC_HOST +#define IN_CLASSC_MAX IP_CLASSC_MAX + +#define IN_CLASSD(d) IP_CLASSD(d) +#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ +#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ +#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ +#define IN_CLASSD_MAX IP_CLASSD_MAX + +#define IN_MULTICAST(a) IP_MULTICAST(a) + +#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) +#define IN_BADCLASS(a) IP_BADCLASS(a) + +#define IN_LOOPBACKNET IP_LOOPBACKNET + +#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) +#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */ +#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr)) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ipaddr_aton(cp, (ip_addr_t*)addr) +#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) ipaddr_ntoa_r((ip_addr_t*)&(addr), buf, buflen) + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ diff --git a/ext/lwip/src/include/ipv4/lwip/inet_chksum.h b/ext/lwip/src/include/ipv4/lwip/inet_chksum.h new file mode 100644 index 000000000..79a2d90f2 --- /dev/null +++ b/ext/lwip/src/include/ipv4/lwip/inet_chksum.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_CHKSUM_H__ +#define __LWIP_INET_CHKSUM_H__ + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +/** Swap the bytes in an u16_t: much like htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) +/* little endian and PLATFORM_BYTESWAP defined */ +#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) +#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */ +/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/ +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +#ifndef LWIP_CHKSUM_COPY +#define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +#ifndef LWIP_CHKSUM_COPY_ALGORITHM +#define LWIP_CHKSUM_COPY_ALGORITHM 1 +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +#endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +#define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len); +u16_t inet_chksum_pseudo_partial(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len, u16_t chksum_len); +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/ext/lwip/src/include/ipv4/lwip/ip.h b/ext/lwip/src/include/ipv4/lwip/ip.h new file mode 100644 index 000000000..00c83a0a1 --- /dev/null +++ b/ext/lwip/src/include/ipv4/lwip/ip.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND LWIP_IGMP + +#define IP_HLEN 20 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + /* ip addresses in network byte order */ \ + ip_addr_t local_ip; \ + ip_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX. + */ +/*#define SOF_DEBUG 0x01U Unimplemented: turn on debugging info recording */ +#define SOF_ACCEPTCONN 0x02U /* socket has had listen() */ +#define SOF_REUSEADDR 0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE 0x08U /* keep connections alive */ +/*#define SOF_DONTROUTE 0x10U Unimplemented: just use interface addresses */ +#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +/*#define SOF_USELOOPBACK 0x40U Unimplemented: bypass hardware when possible */ +#define SOF_LINGER 0x80U /* linger on close if data present */ +/*#define SOF_OOBINLINE 0x0100U Unimplemented: leave received OOB data in line */ +/*#define SOF_REUSEPORT 0x0200U Unimplemented: allow local address & port reuse */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/) + + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FIELD(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FIELD(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* dont fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FIELD(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FIELD(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FIELD(ip_addr_p_t src); + PACK_STRUCT_FIELD(ip_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl)) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + +/** The interface that provided the packet for the current callback invocation. */ +extern struct netif *current_netif; +/** Header of the input packet currently being processed. */ +extern const struct ip_hdr *current_header; +/** Source IP address of current_header */ +extern ip_addr_t current_iphdr_src; +/** Destination IP address of current_header */ +extern ip_addr_t current_iphdr_dest; + +#define ip_init() /* Compatibility define, not init needed. */ +struct netif *ip_route(ip_addr_t *dest); +err_t ip_input(struct pbuf *p, struct netif *inp); +err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, + struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (current_netif) +/** Get the IP header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_header() (current_header) +/** Source IP address of current_header */ +#define ip_current_src_addr() (¤t_iphdr_src) +/** Destination IP address of current_header */ +#define ip_current_dest_addr() (¤t_iphdr_dest) + +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#else +#define ip_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/ext/lwip/src/include/ipv4/lwip/ip_addr.h b/ext/lwip/src/include/ipv4/lwip/ip_addr.h new file mode 100644 index 000000000..77f84e02c --- /dev/null +++ b/ext/lwip/src/include/ipv4/lwip/ip_addr.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the aligned version of ip_addr_t, + used as local variable, on the stack, etc. */ +struct ip_addr { + u32_t addr; +}; + +/* This is the packed version of ip_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr_packed { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** ip_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip_addr_t as well as on ip_addr_p_t. */ +typedef struct ip_addr ip_addr_t; +typedef struct ip_addr_packed ip_addr_p_t; + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Forward declaration to not include netif.h */ +struct netif; + +extern const ip_addr_t ip_addr_any; +extern const ip_addr_t ip_addr_broadcast; + +/** IP_ADDR_ can be used as a fixed IP address + * for the wildcard and the broadcast address + */ +#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) +#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IP_CLASSA_NET 0xff000000 +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IP_CLASSB_NET 0xffff0000 +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IP_CLASSC_NET 0xffffff00 +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) + +#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IP_MULTICAST(a) IP_CLASSD(a) + +#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IP_LOOPBACKNET 127 /* official! */ + + +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IP address given by the four byte-parts. + Little-endian version that prevents the use of htonl. */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t)) +#endif + +/** Copy IP address - faster than ip_addr_set: no NULL check */ +#define ip_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for htonl()) */ +#define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY) + +#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif)) +u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif); + +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask); + +#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \ + ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0)) + +/* Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0]) +#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1]) +#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2]) +#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3]) +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +u32_t ipaddr_addr(const char *cp); +int ipaddr_aton(const char *cp, ip_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ipaddr_ntoa(const ip_addr_t *addr); +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/ext/lwip/src/include/ipv4/lwip/ip_frag.h b/ext/lwip/src/include/ipv4/lwip/ip_frag.h new file mode 100644 index 000000000..77b5eb1ee --- /dev/null +++ b/ext/lwip/src/include/ipv4/lwip/ip_frag.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef __LWIP_IP_FRAG_H__ +#define __LWIP_IP_FRAG_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_FRAG_H__ */ diff --git a/ext/lwip/src/include/ipv6/lwip/icmp.h b/ext/lwip/src/include/ipv6/lwip/icmp.h new file mode 100644 index 000000000..87e9ffd96 --- /dev/null +++ b/ext/lwip/src/include/ipv6/lwip/icmp.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP6_DUR 1 +#define ICMP6_TE 3 +#define ICMP6_ECHO 128 /* echo */ +#define ICMP6_ER 129 /* echo reply */ + + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +void icmp_input(struct pbuf *p, struct netif *inp); + +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +struct icmp_echo_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u16_t id; + u16_t seqno; +}; + +struct icmp_dur_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u32_t unused; +}; + +struct icmp_te_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u32_t unused; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ICMP */ + +#endif /* __LWIP_ICMP_H__ */ + diff --git a/ext/lwip/src/include/ipv6/lwip/inet.h b/ext/lwip/src/include/ipv6/lwip/inet.h new file mode 100644 index 000000000..de1a0b636 --- /dev/null +++ b/ext/lwip/src/include/ipv6/lwip/inet.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *data, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u32_t proto_len); + +u32_t inet_addr(const char *cp); +s8_t inet_aton(const char *cp, struct in_addr *addr); + +#ifndef _MACHINE_ENDIAN_H_ +#ifndef _NETINET_IN_H +#ifndef _LINUX_BYTEORDER_GENERIC_H +u16_t htons(u16_t n); +u16_t ntohs(u16_t n); +u32_t htonl(u32_t n); +u32_t ntohl(u32_t n); +#endif /* _LINUX_BYTEORDER_GENERIC_H */ +#endif /* _NETINET_IN_H */ +#endif /* _MACHINE_ENDIAN_H_ */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/ext/lwip/src/include/ipv6/lwip/ip.h b/ext/lwip/src/include/ipv6/lwip/ip.h new file mode 100644 index 000000000..a01cfc65b --- /dev/null +++ b/ext/lwip/src/include/ipv6/lwip/ip.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP_HLEN 40 + +#define IP_PROTO_ICMP 58 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB struct ip_addr local_ip; \ + struct ip_addr remote_ip; \ + /* Socket options */ \ + u16_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl; \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + + +/* The IPv6 header. */ +struct ip_hdr { +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t tclass1:4, v:4; + u8_t flow1:4, tclass2:4; +#else + u8_t v:4, tclass1:4; + u8_t tclass2:8, flow1:4; +#endif + u16_t flow2; + u16_t len; /* payload length */ + u8_t nexthdr; /* next header */ + u8_t hoplim; /* hop limit (TTL) */ + struct ip_addr src, dest; /* source and destination IP addresses */ +}; + +#define IPH_PROTO(hdr) (iphdr->nexthdr) + +void ip_init(void); + +#include "lwip/netif.h" + +struct netif *ip_route(struct ip_addr *dest); + +void ip_input(struct pbuf *p, struct netif *inp); + +/* source and destination addresses in network byte order, please */ +err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto); + +err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto, + struct netif *netif); + +#define ip_current_netif() NULL +#define ip_current_header() NULL + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/ext/lwip/src/include/ipv6/lwip/ip_addr.h b/ext/lwip/src/include/ipv6/lwip/ip_addr.h new file mode 100644 index 000000000..b2d8ae566 --- /dev/null +++ b/ext/lwip/src/include/ipv6/lwip/ip_addr.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP_ADDR_ANY 0 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN + struct ip_addr { + PACK_STRUCT_FIELD(u32_t addr[4]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6_ADDR(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = htonl((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \ + (ipaddr)->addr[1] = htonl(((c & 0xffff) << 16) | (d & 0xffff)); \ + (ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \ + (ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0) + +u8_t ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2, + struct ip_addr *mask); +u8_t ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2); +void ip_addr_set(struct ip_addr *dest, struct ip_addr *src); +u8_t ip_addr_isany(struct ip_addr *addr); + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F"\n", \ + (ntohl(ipaddr->addr[0]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[0]) & 0xffff, \ + (ntohl(ipaddr->addr[1]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[1]) & 0xffff, \ + (ntohl(ipaddr->addr[2]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[2]) & 0xffff, \ + (ntohl(ipaddr->addr[3]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[3]) & 0xffff)); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/ext/lwip/src/include/lwip/api.h b/ext/lwip/src/include/lwip/api.h new file mode 100644 index 000000000..7a9fa9366 --- /dev/null +++ b/ext/lwip/src/include/lwip/api.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_API_H__ +#define __LWIP_API_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write (u8_t) */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 +#define NETCONN_DONTBLOCK 0x04 + +/* Flags for struct netconn.flags (u8_t) */ +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define NETCONN_FLAG_WRITE_DELAYED 0x01 +/** Should this netconn avoid blocking? */ +#define NETCONN_FLAG_NON_BLOCKING 0x02 +/** Was the last connect action a non-blocking one? */ +#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define NETCONN_FLAG_NO_AUTO_RECVED 0x08 +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 + + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) (t&0xF0) +#define NETCONNTYPE_DATAGRAM(t) (t&0xE0) + +/** Protocol family and type of the netconn */ +enum netconn_type { + NETCONN_INVALID = 0, + /* NETCONN_TCP Group */ + NETCONN_TCP = 0x10, + /* NETCONN_UDP Group */ + NETCONN_UDP = 0x20, + NETCONN_UDPLITE = 0x21, + NETCONN_UDPNOCHKSUM= 0x22, + /* NETCONN_RAW Group */ + NETCONN_RAW = 0x40 +}; + +/** Current state of the netconn. Non-TCP netconns are always + * in state NETCONN_NONE! */ +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Use to inform the callback function about changes */ +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS, + NETCONN_EVT_ERROR +}; + +#if LWIP_IGMP +/** Used for netconn_join_leave_group() */ +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; +struct api_msg_msg; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t last_err; + /** sem that is used to synchroneously execute functions in the core context */ + sys_sem_t op_completed; + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; +#if LWIP_TCP + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; +#endif /* LWIP_TCP */ + /** only used for socket layer */ +#if LWIP_SOCKET + int socket; +#endif /* LWIP_SOCKET */ +#if LWIP_SO_SNDTIMEO + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) */ + s32_t send_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVTIMEO + /** timeout to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox + not used for TCP: adjust TCP_WND instead! */ + int recv_bufsize; + /** number of bytes currently in recvmbox to be received, + tested against recv_bufsize to limit bytes on recvmbox + for UDP and RAW, used for FIONREAD */ + s16_t recv_avail; +#endif /* LWIP_SO_RCVBUF */ + /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ + u8_t flags; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. */ + struct api_msg_msg *current_msg; +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/** Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define NETCONN_SET_SAFE_ERR(conn, err) do { \ + SYS_ARCH_DECL_PROTECT(lev); \ + SYS_ARCH_PROTECT(lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(lev); \ +} while(0); + +/* Network connection functions: */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct +netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +err_t netconn_delete(struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port); +err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port); +err_t netconn_disconnect (struct netconn *conn); +err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); +err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); +err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); +void netconn_recved(struct netconn *conn, u32_t length); +err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, + ip_addr_t *addr, u16_t port); +err_t netconn_send(struct netconn *conn, struct netbuf *buf); +err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written); +#define netconn_write(conn, dataptr, size, apiflags) \ + netconn_write_partly(conn, dataptr, size, apiflags, NULL) +err_t netconn_close(struct netconn *conn); +err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); + +#if LWIP_IGMP +err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr, + ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP */ +#if LWIP_DNS +err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); +#endif /* LWIP_DNS */ + +#define netconn_err(conn) ((conn)->last_err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_set_nonblocking(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) + +/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_set_noautorecved(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0) +/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0) + +#if LWIP_SO_SNDTIMEO +/** Set the send timeout in milliseconds */ +#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) +/** Get the send timeout in milliseconds */ +#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO +/** Set the receive timeout in milliseconds */ +#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) +/** Get the receive timeout in milliseconds */ +#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +/** Set the receive buffer in bytes */ +#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) +/** Get the receive buffer in bytes */ +#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) +#endif /* LWIP_SO_RCVBUF*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_H__ */ diff --git a/ext/lwip/src/include/lwip/api_msg.h b/ext/lwip/src/include/lwip/api_msg.h new file mode 100644 index 000000000..f9e1c7d29 --- /dev/null +++ b/ext/lwip/src/include/lwip/api_msg.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_API_MSG_H__ +#define __LWIP_API_MSG_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** The return value of the function executed in tcpip_thread. */ + err_t err; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for do_send */ + struct netbuf *b; + /** used for do_newconn */ + struct { + u8_t proto; + } n; + /** used for do_bind and do_connect */ + struct { + ip_addr_t *ipaddr; + u16_t port; + } bc; + /** used for do_getaddr */ + struct { + ip_addr_t *ipaddr; + u16_t *port; + u8_t local; + } ad; + /** used for do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; +#if LWIP_SO_SNDTIMEO + u32_t time_started; +#endif /* LWIP_SO_SNDTIMEO */ + } w; + /** used for do_recv */ + struct { + u32_t len; + } r; + /** used for do_close (/shutdown) */ + struct { + u8_t shut; + } sd; +#if LWIP_IGMP + /** used for do_join_leave_group */ + struct { + ip_addr_t *multiaddr; + ip_addr_t *netif_addr; + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +}; + +/** This struct contains a function to execute in another thread context and + a struct api_msg_msg that serves as an argument for this function. + This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */ +struct api_msg { + /** function to execute in tcpip_thread context */ + void (* function)(struct api_msg_msg *msg); + /** arguments for this function */ + struct api_msg_msg msg; +}; + +#if LWIP_DNS +/** As do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ + const char *name; + /** Rhe resolved address is stored here */ + ip_addr_t *addr; + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t *sem; + /** Errors are given back here */ + err_t *err; +}; +#endif /* LWIP_DNS */ + +void do_newconn ( struct api_msg_msg *msg); +void do_delconn ( struct api_msg_msg *msg); +void do_bind ( struct api_msg_msg *msg); +void do_connect ( struct api_msg_msg *msg); +void do_disconnect ( struct api_msg_msg *msg); +void do_listen ( struct api_msg_msg *msg); +void do_send ( struct api_msg_msg *msg); +void do_recv ( struct api_msg_msg *msg); +void do_write ( struct api_msg_msg *msg); +void do_getaddr ( struct api_msg_msg *msg); +void do_close ( struct api_msg_msg *msg); +void do_shutdown ( struct api_msg_msg *msg); +#if LWIP_IGMP +void do_join_leave_group( struct api_msg_msg *msg); +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +void do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_MSG_H__ */ diff --git a/ext/lwip/src/include/lwip/arch.h b/ext/lwip/src/include/lwip/arch.h new file mode 100644 index 000000000..4d6df773f --- /dev/null +++ b/ext/lwip/src/include/lwip/arch.h @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ARCH_H__ +#define __LWIP_ARCH_H__ + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ +/** Temporary upgrade helper: define format string for u8_t as hex if not + defined in cc.h */ +#ifndef X8_F +#define X8_F "02x" +#endif /* X8_F */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ARCH_H__ */ diff --git a/ext/lwip/src/include/lwip/debug.h b/ext/lwip/src/include/lwip/debug.h new file mode 100644 index 000000000..0fe041396 --- /dev/null +++ b/ext/lwip/src/include/lwip/debug.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEBUG_H__ +#define __LWIP_DEBUG_H__ + +#include "lwip/arch.h" +#include "lwip/opt.h" + +/** lower two bits indicate debug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define LWIP_DBG_LEVEL_ALL 0x00 +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */ +#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +#define LWIP_DBG_MASK_LEVEL 0x03 + +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U + +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ + LWIP_PLATFORM_ASSERT(message); } while(0) +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +/** if "expression" isn't true, then print "message" and execute "handler" expression */ +#ifndef LWIP_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ASSERT(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +#ifdef LWIP_DEBUG +/** print debug message only if debug message type is enabled... + * AND is of correct type AND is at least LWIP_DBG_LEVEL + */ +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG(message); \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* __LWIP_DEBUG_H__ */ + diff --git a/ext/lwip/src/include/lwip/def.h b/ext/lwip/src/include/lwip/def.h new file mode 100644 index 000000000..73a1b560b --- /dev/null +++ b/ext/lwip/src/include/lwip/def.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEF_H__ +#define __LWIP_DEF_H__ + +/* arch.h might define NULL already */ +#include "lwip/arch.h" +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* Endianess-optimized shifting of two u8_t to create one u16_t */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define LWIP_MAKE_U16(a, b) ((a << 8) | b) +#else +#define LWIP_MAKE_U16(a, b) ((b << 8) | a) +#endif + +#ifndef LWIP_PLATFORM_BYTESWAP +#define LWIP_PLATFORM_BYTESWAP 0 +#endif + +#ifndef LWIP_PREFIX_BYTEORDER_FUNCS +/* workaround for naming collisions on some platforms */ + +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ + +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */ + +#if BYTE_ORDER == BIG_ENDIAN +#define lwip_htons(x) (x) +#define lwip_ntohs(x) (x) +#define lwip_htonl(x) (x) +#define lwip_ntohl(x) (x) +#define PP_HTONS(x) (x) +#define PP_NTOHS(x) (x) +#define PP_HTONL(x) (x) +#define PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#if LWIP_PLATFORM_BYTESWAP +#define lwip_htons(x) LWIP_PLATFORM_HTONS(x) +#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x) +#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x) +#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x) +#else /* LWIP_PLATFORM_BYTESWAP */ +u16_t lwip_htons(u16_t x); +u16_t lwip_ntohs(u16_t x); +u32_t lwip_htonl(u32_t x); +u32_t lwip_ntohl(u32_t x); +#endif /* LWIP_PLATFORM_BYTESWAP */ + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_DEF_H__ */ + diff --git a/ext/lwip/src/include/lwip/dhcp.h b/ext/lwip/src/include/lwip/dhcp.h new file mode 100644 index 000000000..32d93381d --- /dev/null +++ b/ext/lwip/src/include/lwip/dhcp.h @@ -0,0 +1,242 @@ +/** @file + */ + +#ifndef __LWIP_DHCP_H__ +#define __LWIP_DHCP_H__ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_LEN 128U + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** our connection to the DHCP server */ + struct udp_pcb *pcb; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease */ + ip_addr_t offered_ip_addr; + ip_addr_t offered_sn_mask; + ip_addr_t offered_gw_addr; + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */ + /* @todo: LWIP_DHCP_BOOTP_FILE configuration option? + integrate with possible TFTP-client for booting? */ +#if LWIP_DHCP_BOOTP_FILE + ip_addr_t offered_si_addr; + char boot_file_name[DHCP_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ +}; + +/* MUST be compiled with "pack structs" or equivalent! */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FIELD(u8_t op); + PACK_STRUCT_FIELD(u8_t htype); + PACK_STRUCT_FIELD(u8_t hlen); + PACK_STRUCT_FIELD(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FIELD(ip_addr_p_t ciaddr); + PACK_STRUCT_FIELD(ip_addr_p_t yiaddr); + PACK_STRUCT_FIELD(ip_addr_p_t siaddr); + PACK_STRUCT_FIELD(ip_addr_p_t giaddr); + PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FIELD(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) +void dhcp_cleanup(struct netif *netif); +/** start DHCP configuration */ +err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); +/** stop DHCP configuration */ +void dhcp_stop(struct netif *netif); +/** inform server of our manual IP address */ +void dhcp_inform(struct netif *netif); +/** Handle a possible change in the network configuration */ +void dhcp_network_changed(struct netif *netif); + +/** if enabled, check whether the offered IP address is not in use, using ARP */ +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr); +#endif + +/** to be called every minute */ +void dhcp_coarse_tmr(void); +/** to be called every half second */ +void dhcp_fine_tmr(void); + +/** DHCP message item offsets and length */ +#define DHCP_OP_OFS 0 +#define DHCP_HTYPE_OFS 1 +#define DHCP_HLEN_OFS 2 +#define DHCP_HOPS_OFS 3 +#define DHCP_XID_OFS 4 +#define DHCP_SECS_OFS 8 +#define DHCP_FLAGS_OFS 10 +#define DHCP_CIADDR_OFS 12 +#define DHCP_YIADDR_OFS 16 +#define DHCP_SIADDR_OFS 20 +#define DHCP_GIADDR_OFS 24 +#define DHCP_CHADDR_OFS 28 +#define DHCP_SNAME_OFS 44 +#define DHCP_FILE_OFS 108 +#define DHCP_MSG_LEN 236 + +#define DHCP_COOKIE_OFS DHCP_MSG_LEN +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4) + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + +/** DHCP client states */ +#define DHCP_OFF 0 +#define DHCP_REQUESTING 1 +#define DHCP_INIT 2 +#define DHCP_REBOOTING 3 +#define DHCP_REBINDING 4 +#define DHCP_RENEWING 5 +#define DHCP_SELECTING 6 +#define DHCP_INFORMING 7 +#define DHCP_CHECKING 8 +#define DHCP_PERMANENT 9 +#define DHCP_BOUND 10 +/** not yet implemented #define DHCP_RELEASING 11 */ +#define DHCP_BACKING_OFF 12 + +/** AUTOIP cooperatation flags */ +#define DHCP_AUTOIP_COOP_STATE_OFF 0 +#define DHCP_AUTOIP_COOP_STATE_ON 1 + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/** DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/** BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_END 255 + +/** DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/** possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*__LWIP_DHCP_H__*/ diff --git a/ext/lwip/src/include/lwip/dns.h b/ext/lwip/src/include/lwip/dns.h new file mode 100644 index 000000000..6c7d9b073 --- /dev/null +++ b/ext/lwip/src/include/lwip/dns.h @@ -0,0 +1,124 @@ +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LWIP_DNS_H__ +#define __LWIP_DNS_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ + +/** DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/* The size used for the next line is rather a hack, but it prevents including socket.h in all files + that include memp.h, and that would possibly break portability (since socket.h defines some types + and constants possibly already define by the OS). + Calculation rule: + sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */ +#define NETDB_ELEM_SIZE (32 + 16 + DNS_MAX_NAME_LENGTH + 1) + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + ip_addr_t addr; + struct local_hostlist_entry *next; +}; +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN +#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH +#endif +#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg); + +void dns_init(void); +void dns_tmr(void); +void dns_setserver(u8_t numdns, ip_addr_t *dnsserver); +ip_addr_t dns_getserver(u8_t numdns); +err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg); + +#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const ip_addr_t *addr); +err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); +#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS */ + +#endif /* __LWIP_DNS_H__ */ diff --git a/ext/lwip/src/include/lwip/err.h b/ext/lwip/src/include/lwip/err.h new file mode 100644 index 000000000..ac907729f --- /dev/null +++ b/ext/lwip/src/include/lwip/err.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ERR_H__ +#define __LWIP_ERR_H__ + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ +typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/* Definitions for error constants. */ + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ +#define ERR_INPROGRESS -5 /* Operation in progress */ +#define ERR_VAL -6 /* Illegal value. */ +#define ERR_WOULDBLOCK -7 /* Operation would block. */ +#define ERR_USE -8 /* Address in use. */ +#define ERR_ISCONN -9 /* Already connected. */ + +#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN) + +#define ERR_ABRT -10 /* Connection aborted. */ +#define ERR_RST -11 /* Connection reset. */ +#define ERR_CLSD -12 /* Connection closed. */ +#define ERR_CONN -13 /* Not connected. */ + +#define ERR_ARG -14 /* Illegal argument. */ + +#define ERR_IF -15 /* Low-level netif error */ + + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ERR_H__ */ diff --git a/ext/lwip/src/include/lwip/init.h b/ext/lwip/src/include/lwip/init.h new file mode 100644 index 000000000..323853454 --- /dev/null +++ b/ext/lwip/src/include/lwip/init.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INIT_H__ +#define __LWIP_INIT_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 1U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 4U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 1U +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC 255U + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for CVS versions */ +#define LWIP_RC_DEVELOPMENT 0U + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/** Provides the version of the stack */ +#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ + LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INIT_H__ */ diff --git a/ext/lwip/src/include/lwip/ip.h b/ext/lwip/src/include/lwip/ip.h new file mode 100644 index 000000000..00c83a0a1 --- /dev/null +++ b/ext/lwip/src/include/lwip/ip.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND LWIP_IGMP + +#define IP_HLEN 20 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + /* ip addresses in network byte order */ \ + ip_addr_t local_ip; \ + ip_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX. + */ +/*#define SOF_DEBUG 0x01U Unimplemented: turn on debugging info recording */ +#define SOF_ACCEPTCONN 0x02U /* socket has had listen() */ +#define SOF_REUSEADDR 0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE 0x08U /* keep connections alive */ +/*#define SOF_DONTROUTE 0x10U Unimplemented: just use interface addresses */ +#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +/*#define SOF_USELOOPBACK 0x40U Unimplemented: bypass hardware when possible */ +#define SOF_LINGER 0x80U /* linger on close if data present */ +/*#define SOF_OOBINLINE 0x0100U Unimplemented: leave received OOB data in line */ +/*#define SOF_REUSEPORT 0x0200U Unimplemented: allow local address & port reuse */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/) + + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FIELD(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FIELD(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* dont fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FIELD(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FIELD(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FIELD(ip_addr_p_t src); + PACK_STRUCT_FIELD(ip_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl)) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + +/** The interface that provided the packet for the current callback invocation. */ +extern struct netif *current_netif; +/** Header of the input packet currently being processed. */ +extern const struct ip_hdr *current_header; +/** Source IP address of current_header */ +extern ip_addr_t current_iphdr_src; +/** Destination IP address of current_header */ +extern ip_addr_t current_iphdr_dest; + +#define ip_init() /* Compatibility define, not init needed. */ +struct netif *ip_route(ip_addr_t *dest); +err_t ip_input(struct pbuf *p, struct netif *inp); +err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, + struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (current_netif) +/** Get the IP header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_header() (current_header) +/** Source IP address of current_header */ +#define ip_current_src_addr() (¤t_iphdr_src) +/** Destination IP address of current_header */ +#define ip_current_dest_addr() (¤t_iphdr_dest) + +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#else +#define ip_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/ext/lwip/src/include/lwip/mem.h b/ext/lwip/src/include/lwip/mem.h new file mode 100644 index 000000000..5bb906b63 --- /dev/null +++ b/ext/lwip/src/include/lwip/mem.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_MEM_H__ +#define __LWIP_MEM_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include /* for size_t */ + +typedef size_t mem_size_t; +#define MEM_SIZE_F SZT_F + +/* aliases for C library malloc() */ +#define mem_init() +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_free +#define mem_free free +#endif +#ifndef mem_malloc +#define mem_malloc malloc +#endif +#ifndef mem_calloc +#define mem_calloc calloc +#endif +/* Since there is no C library allocation function to shrink memory without + moving it, define this to nothing. */ +#ifndef mem_trim +#define mem_trim(mem, size) (mem) +#endif +#else /* MEM_LIBC_MALLOC */ + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000L +typedef u32_t mem_size_t; +#define MEM_SIZE_F U32_F +#else +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F +#endif /* MEM_SIZE > 64000 */ + +#if MEM_USE_POOLS +/** mem_init is not used when using pools instead of a heap */ +#define mem_init() +/** mem_trim is not used when using pools instead of a heap: + we can't free part of a pool element and don't want to copy the rest */ +#define mem_trim(mem, size) (mem) +#else /* MEM_USE_POOLS */ +/* lwIP alternative malloc */ +void mem_init(void); +void *mem_trim(void *mem, mem_size_t size); +#endif /* MEM_USE_POOLS */ +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void mem_free(void *mem); +#endif /* MEM_LIBC_MALLOC */ + +/** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and + * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). + */ +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1)) +#endif + +/** Calculate safe memory size for an aligned buffer when using an unaligned + * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the + * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) + */ +#ifndef LWIP_MEM_ALIGN_BUFFER +#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1)) +#endif + +/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT + * so that ADDR % MEM_ALIGNMENT == 0 + */ +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEM_H__ */ diff --git a/ext/lwip/src/include/lwip/memp.h b/ext/lwip/src/include/lwip/memp.h new file mode 100644 index 000000000..f0d073994 --- /dev/null +++ b/ext/lwip/src/include/lwip/memp.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_MEMP_H__ +#define __LWIP_MEMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, +#include "lwip/memp_std.h" + MEMP_MAX +} memp_t; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC || MEM_USE_POOLS +extern const u16_t memp_sizes[MEMP_MAX]; +#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC + +#include "mem.h" + +#define memp_init() +#define memp_malloc(type) mem_malloc(memp_sizes[type]) +#define memp_free(type, mem) mem_free(mem) + +#else /* MEMP_MEM_MALLOC */ + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. */ +struct memp_malloc_helper +{ + memp_t poolnr; +}; +#endif /* MEM_USE_POOLS */ + +void memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void memp_free(memp_t type, void *mem); + +#endif /* MEMP_MEM_MALLOC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEMP_H__ */ diff --git a/ext/lwip/src/include/lwip/memp_std.h b/ext/lwip/src/include/lwip/memp_std.h new file mode 100644 index 000000000..461ed1acf --- /dev/null +++ b/ext/lwip/src/include/lwip/memp_std.h @@ -0,0 +1,122 @@ +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") +#endif /* IP_REASSEMBLY */ +#if IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") +#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +#if LWIP_NETCONN +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if !LWIP_TCPIP_CORE_LOCKING_INPUT +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ +#endif /* NO_SYS==0 */ + +#if LWIP_ARP && ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* LWIP_ARP && ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */ +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") +#endif /* LWIP_TIMERS */ + +#if LWIP_SNMP +LWIP_MEMPOOL(SNMP_ROOTNODE, MEMP_NUM_SNMP_ROOTNODE, sizeof(struct mib_list_rootnode), "SNMP_ROOTNODE") +LWIP_MEMPOOL(SNMP_NODE, MEMP_NUM_SNMP_NODE, sizeof(struct mib_list_node), "SNMP_NODE") +LWIP_MEMPOOL(SNMP_VARBIND, MEMP_NUM_SNMP_VARBIND, sizeof(struct snmp_varbind), "SNMP_VARBIND") +LWIP_MEMPOOL(SNMP_VALUE, MEMP_NUM_SNMP_VALUE, SNMP_MAX_VALUE_SIZE, "SNMP_VALUE") +#endif /* LWIP_SNMP */ +#if LWIP_DNS && LWIP_SOCKET +LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") +#endif /* LWIP_DNS && LWIP_SOCKET */ +#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") +#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#if PPP_SUPPORT && PPPOE_SUPPORT +LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/ext/lwip/src/include/lwip/netbuf.h b/ext/lwip/src/include/lwip/netbuf.h new file mode 100644 index 000000000..7d247d71b --- /dev/null +++ b/ext/lwip/src/include/lwip/netbuf.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETBUF_H__ +#define __LWIP_NETBUF_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 +/** This netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + u8_t flags; +#endif /* LWIP_CHECKSUM_ON_COPY */ + u16_t toport_chksum; +#if LWIP_NETBUF_RECVINFO + ip_addr_t toaddr; +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ +}; + +/* Network buffer functions: */ +struct netbuf * netbuf_new (void); +void netbuf_delete (struct netbuf *buf); +void * netbuf_alloc (struct netbuf *buf, u16_t size); +void netbuf_free (struct netbuf *buf); +err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +void netbuf_chain (struct netbuf *head, + struct netbuf *tail); + +err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len); +s8_t netbuf_next (struct netbuf *buf); +void netbuf_first (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) (&((buf)->addr)) +#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr), fromaddr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) (&((buf)->toaddr)) +#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->addr), destaddr) +#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) +#endif /* LWIP_NETBUF_RECVINFO */ +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ + (buf)->toport_chksum = chksum; } while(0) +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETBUF_H__ */ diff --git a/ext/lwip/src/include/lwip/netdb.h b/ext/lwip/src/include/lwip/netdb.h new file mode 100644 index 000000000..7587e2f2d --- /dev/null +++ b/ext/lwip/src/include/lwip/netdb.h @@ -0,0 +1,124 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIP_NETDB_H__ +#define __LWIP_NETDB_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include /* for size_t */ + +#include "lwip/inet.h" +#include "lwip/sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessable error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +#define gethostbyname(name) lwip_gethostbyname(name) +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS && LWIP_SOCKET */ + +#endif /* __LWIP_NETDB_H__ */ diff --git a/ext/lwip/src/include/lwip/netif.h b/ext/lwip/src/include/lwip/netif.h new file mode 100644 index 000000000..f7e493745 --- /dev/null +++ b/ext/lwip/src/include/lwip/netif.h @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETIF_H__ +#define __LWIP_NETIF_H__ + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#if LWIP_DHCP +struct dhcp; +#endif +#if LWIP_AUTOIP +struct autoip; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** must be the maximum of all used hardware address lengths + across all types of interfaces in use */ +#define NETIF_MAX_HWADDR_LEN 6U + +/** Whether the network interface is 'up'. This is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + * It is set by the startup code (for static IP configuration) or + * by dhcp/autoip when an address has been assigned. + */ +#define NETIF_FLAG_UP 0x01U +/** If set, the netif has broadcast capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_BROADCAST 0x02U +/** If set, the netif is one end of a point-to-point connection. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_POINTTOPOINT 0x04U +/** If set, the interface is configured using DHCP. + * Set by the DHCP code when starting or stopping DHCP. */ +#define NETIF_FLAG_DHCP 0x08U +/** If set, the interface has an active link + * (set by the network interface driver). + * Either set by the netif driver in its init function (if the link + * is up at that time) or at a later point once the link comes up + * (if link detection is supported by the hardware). */ +#define NETIF_FLAG_LINK_UP 0x10U +/** If set, the netif is an ethernet device using ARP. + * Set by the netif driver in its init function. + * Used to check input packet types and use of DHCP. */ +#define NETIF_FLAG_ETHARP 0x20U +/** If set, the netif is an ethernet device. It might not use + * ARP or TCP/IP if it is used for PPPoE only. + */ +#define NETIF_FLAG_ETHERNET 0x40U +/** If set, the netif has IGMP capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_IGMP 0x80U + +/** Function prototype for netif init functions. Set up flags and output/linkoutput + * callback functions in this function. + * + * @param netif The netif to initialize + */ +typedef err_t (*netif_init_fn)(struct netif *netif); +/** Function prototype for netif->input functions. This function is saved as 'input' + * callback function in the netif struct. Call it when a packet has been received. + * + * @param p The received packet, copied into a pbuf + * @param inp The netif which received the packet + */ +typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); +/** Function prototype for netif->output functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'etharp_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IP address to which the packet shall be sent + */ +typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr); +/** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (raw ethernet packet) + */ +typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); +/** Function prototype for netif status- or link-callback functions. */ +typedef void (*netif_status_callback_fn)(struct netif *netif); +/** Function prototype for netif igmp_mac_filter functions */ +typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, + ip_addr_t *group, u8_t action); + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ +struct netif { + /** pointer to next in linked list */ + struct netif *next; + + /** IP address configuration in network byte order */ + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; + + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + netif_input_fn input; + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + netif_output_fn output; + /** This function is called by the ARP module when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ + netif_linkoutput_fn linkoutput; +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + netif_status_callback_fn status_callback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + netif_status_callback_fn link_callback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK + /** This function is called when the netif has been removed */ + netif_status_callback_fn remove_callback; +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. */ + void *state; +#if LWIP_DHCP + /** the DHCP client state information for this netif */ + struct dhcp *dhcp; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /** the AutoIP client state information for this netif */ + struct autoip *autoip; +#endif +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + /** maximum transfer unit (in bytes) */ + u16_t mtu; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; + /** link level hardware address of this interface */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (see NETIF_FLAG_ above) */ + u8_t flags; + /** descriptive abbreviation */ + char name[2]; + /** number of this interface */ + u8_t num; +#if LWIP_SNMP + /** link type (from "snmp_ifType" enum from snmp.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + u32_t ifinoctets; + u32_t ifinucastpkts; + u32_t ifinnucastpkts; + u32_t ifindiscards; + u32_t ifoutoctets; + u32_t ifoutucastpkts; + u32_t ifoutnucastpkts; + u32_t ifoutdiscards; +#endif /* LWIP_SNMP */ +#if LWIP_IGMP + /** This function could be called to add or delete a entry in the multicast + filter table of the ethernet MAC.*/ + netif_igmp_mac_filter_fn igmp_mac_filter; +#endif /* LWIP_IGMP */ +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. */ + struct pbuf *loop_first; + struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_SNMP +#define NETIF_INIT_SNMP(netif, type, speed) \ + /* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \ + (netif)->link_type = (type); \ + /* your link speed here (units: bits per second) */ \ + (netif)->link_speed = (speed); \ + (netif)->ts = 0; \ + (netif)->ifinoctets = 0; \ + (netif)->ifinucastpkts = 0; \ + (netif)->ifinnucastpkts = 0; \ + (netif)->ifindiscards = 0; \ + (netif)->ifoutoctets = 0; \ + (netif)->ifoutucastpkts = 0; \ + (netif)->ifoutnucastpkts = 0; \ + (netif)->ifoutdiscards = 0 +#else /* LWIP_SNMP */ +#define NETIF_INIT_SNMP(netif, type, speed) +#endif /* LWIP_SNMP */ + + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +void netif_init(void); + +struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input); + +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw); +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(char *name); + +void netif_set_default(struct netif *netif); + +void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr); +void netif_set_netmask(struct netif *netif, ip_addr_t *netmask); +void netif_set_gw(struct netif *netif, ip_addr_t *gw); + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +/** Ask if an interface is up */ +#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_STATUS_CALLBACK +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK +void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +/** Ask if a link is up */ +#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if LWIP_NETIF_HOSTNAME +#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_IGMP +#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) +#endif /* LWIP_IGMP */ + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p, ip_addr_t *dest_ip); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_NETIF_HWADDRHINT +#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) +#else /* LWIP_NETIF_HWADDRHINT */ +#define NETIF_SET_HWADDRHINT(netif, hint) +#endif /* LWIP_NETIF_HWADDRHINT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETIF_H__ */ diff --git a/ext/lwip/src/include/lwip/netifapi.h b/ext/lwip/src/include/lwip/netifapi.h new file mode 100644 index 000000000..33318efaf --- /dev/null +++ b/ext/lwip/src/include/lwip/netifapi.h @@ -0,0 +1,108 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_NETIFAPI_H__ +#define __LWIP_NETIFAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*netifapi_void_fn)(struct netif *netif); +typedef err_t (*netifapi_errt_fn)(struct netif *netif); + +struct netifapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING + sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + err_t err; + struct netif *netif; + union { + struct { + ip_addr_t *ipaddr; + ip_addr_t *netmask; + ip_addr_t *gw; + void *state; + netif_init_fn init; + netif_input_fn input; + } add; + struct { + netifapi_void_fn voidfunc; + netifapi_errt_fn errtfunc; + } common; + } msg; +}; + +struct netifapi_msg { + void (* function)(struct netifapi_msg_msg *msg); + struct netifapi_msg_msg msg; +}; + + +/* API for application */ +err_t netifapi_netif_add ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw, + void *state, + netif_init_fn init, + netif_input_fn input); + +err_t netifapi_netif_set_addr ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw ); + +err_t netifapi_netif_common ( struct netif *netif, + netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc); + +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* __LWIP_NETIFAPI_H__ */ diff --git a/ext/lwip/src/include/lwip/opt.h b/ext/lwip/src/include/lwip/opt.h new file mode 100644 index 000000000..e00097232 --- /dev/null +++ b/ext/lwip/src/include/lwip/opt.h @@ -0,0 +1,2133 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_OPT_H__ +#define __LWIP_OPT_H__ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "../../../lwipopts.h" +#include "lwip/debug.h" + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 0 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 1 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 0 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE 1024 * 1024 * 64 +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 0 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 128 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 64 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 64 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 64 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 256 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 50 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 30 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 2 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 3 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 0 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 0 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 +#endif + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 0 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + * Does not have to be changed unless external MIBs answer request asynchronously + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + * When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 8192 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF 8192 * 7 +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN 128 +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#ifndef LWIP_NETIF_REMOVE_CALLBACK +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppInputThread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppInputThread" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 0 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppInputThread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 0 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +#else + +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 1 +#define MEM_STATS 1 +#define MEMP_STATS 0 +#define SYS_STATS 1 +#define LWIP_STATS_DISPLAY 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#ifndef CHECKSUM_GEN_ICMP +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* Hooks are undefined by default, define them to a function if you need them. */ + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_ON +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_ON +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +#endif /* __LWIP_OPT_H__ */ diff --git a/ext/lwip/src/include/lwip/pbuf.h b/ext/lwip/src/include/lwip/pbuf.h new file mode 100644 index 000000000..99d5443bf --- /dev/null +++ b/ext/lwip/src/include/lwip/pbuf.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_PBUF_H__ +#define __LWIP_PBUF_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG */ +#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) + +#define PBUF_TRANSPORT_HLEN 20 +#define PBUF_IP_HLEN 20 + +typedef enum { + PBUF_TRANSPORT, + PBUF_IP, + PBUF_LINK, + PBUF_RAW +} pbuf_layer; + +typedef enum { + PBUF_RAM, /* pbuf data is stored in RAM */ + PBUF_ROM, /* pbuf data is stored in ROM */ + PBUF_REF, /* pbuf comes from the pbuf pool */ + PBUF_POOL /* pbuf payload refers to RAM */ +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a + a pbuf differently */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U +/** indicates this pbuf was received as link-level broadcast */ +#define PBUF_FLAG_LLBCAST 0x08U +/** indicates this pbuf was received as link-level multicast */ +#define PBUF_FLAG_LLMCAST 0x10U +/** indicates this pbuf includes a TCP FIN flag */ +#define PBUF_FLAG_TCP_FIN 0x20U + +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +#if LWIP_TCP && TCP_QUEUE_OOSEQ +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ +#if NO_SYS && PBUF_POOL_FREE_OOSEQ +extern volatile u8_t pbuf_free_ooseq_pending; +void pbuf_free_ooseq(); +/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level to check if ooseq pbufs need to be + freed! */ +#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ + /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ + ooseq queued pbufs now */ \ + pbuf_free_ooseq(); }}while(0) +#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/ +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len); +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u8_t pbuf_clen(struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ + +u8_t pbuf_get_at(struct pbuf* p, u16_t offset); +u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(struct pbuf* p, const char* substr); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_PBUF_H__ */ diff --git a/ext/lwip/src/include/lwip/raw.h b/ext/lwip/src/include/lwip/raw.h new file mode 100644 index 000000000..17d0a1c54 --- /dev/null +++ b/ext/lwip/src/include/lwip/raw.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_RAW_H__ +#define __LWIP_RAW_H__ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb; + +/** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip_addr_t *addr); + +struct raw_pcb { + /* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /** receive callback function */ + raw_recv_fn recv; + /* user-supplied argument for the recv callback */ + void *recv_arg; +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto); +void raw_remove (struct raw_pcb *pcb); +err_t raw_bind (struct raw_pcb *pcb, ip_addr_t *ipaddr); +err_t raw_connect (struct raw_pcb *pcb, ip_addr_t *ipaddr); + +void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr); +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, not init needed. */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* __LWIP_RAW_H__ */ diff --git a/ext/lwip/src/include/lwip/sio.h b/ext/lwip/src/include/lwip/sio.h new file mode 100644 index 000000000..28ae2f225 --- /dev/null +++ b/ext/lwip/src/include/lwip/sio.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef __SIO_H__ +#define __SIO_H__ + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum); +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd); +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd); +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __SIO_H__ */ diff --git a/ext/lwip/src/include/lwip/snmp.h b/ext/lwip/src/include/lwip/snmp.h new file mode 100644 index 000000000..2ed043dd5 --- /dev/null +++ b/ext/lwip/src/include/lwip/snmp.h @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2001, 2002 Leon Woestenberg + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef __LWIP_SNMP_H__ +#define __LWIP_SNMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/ip_addr.h" + +struct udp_pcb; +struct netif; + +/** + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** SNMP "sysuptime" Interval */ +#define SNMP_SYSUPTIME_INTERVAL 10 + +/** fixed maximum length for object identifier type */ +#define LWIP_SNMP_OBJ_ID_LEN 32 + +/** internal object identifier representation */ +struct snmp_obj_id +{ + u8_t len; + s32_t id[LWIP_SNMP_OBJ_ID_LEN]; +}; + +/* system */ +void snmp_set_sysdesr(u8_t* str, u8_t* len); +void snmp_set_sysobjid(struct snmp_obj_id *oid); +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); +void snmp_inc_sysuptime(void); +void snmp_add_sysuptime(u32_t value); +void snmp_get_sysuptime(u32_t *value); +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen); + +/* network interface */ +void snmp_add_ifinoctets(struct netif *ni, u32_t value); +void snmp_inc_ifinucastpkts(struct netif *ni); +void snmp_inc_ifinnucastpkts(struct netif *ni); +void snmp_inc_ifindiscards(struct netif *ni); +void snmp_add_ifoutoctets(struct netif *ni, u32_t value); +void snmp_inc_ifoutucastpkts(struct netif *ni); +void snmp_inc_ifoutnucastpkts(struct netif *ni); +void snmp_inc_ifoutdiscards(struct netif *ni); +void snmp_inc_iflist(void); +void snmp_dec_iflist(void); + +/* ARP (for atTable and ipNetToMediaTable) */ +void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip); +void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip); + +/* IP */ +void snmp_inc_ipinreceives(void); +void snmp_inc_ipinhdrerrors(void); +void snmp_inc_ipinaddrerrors(void); +void snmp_inc_ipforwdatagrams(void); +void snmp_inc_ipinunknownprotos(void); +void snmp_inc_ipindiscards(void); +void snmp_inc_ipindelivers(void); +void snmp_inc_ipoutrequests(void); +void snmp_inc_ipoutdiscards(void); +void snmp_inc_ipoutnoroutes(void); +void snmp_inc_ipreasmreqds(void); +void snmp_inc_ipreasmoks(void); +void snmp_inc_ipreasmfails(void); +void snmp_inc_ipfragoks(void); +void snmp_inc_ipfragfails(void); +void snmp_inc_ipfragcreates(void); +void snmp_inc_iproutingdiscards(void); +void snmp_insert_ipaddridx_tree(struct netif *ni); +void snmp_delete_ipaddridx_tree(struct netif *ni); +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni); +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni); + +/* ICMP */ +void snmp_inc_icmpinmsgs(void); +void snmp_inc_icmpinerrors(void); +void snmp_inc_icmpindestunreachs(void); +void snmp_inc_icmpintimeexcds(void); +void snmp_inc_icmpinparmprobs(void); +void snmp_inc_icmpinsrcquenchs(void); +void snmp_inc_icmpinredirects(void); +void snmp_inc_icmpinechos(void); +void snmp_inc_icmpinechoreps(void); +void snmp_inc_icmpintimestamps(void); +void snmp_inc_icmpintimestampreps(void); +void snmp_inc_icmpinaddrmasks(void); +void snmp_inc_icmpinaddrmaskreps(void); +void snmp_inc_icmpoutmsgs(void); +void snmp_inc_icmpouterrors(void); +void snmp_inc_icmpoutdestunreachs(void); +void snmp_inc_icmpouttimeexcds(void); +void snmp_inc_icmpoutparmprobs(void); +void snmp_inc_icmpoutsrcquenchs(void); +void snmp_inc_icmpoutredirects(void); +void snmp_inc_icmpoutechos(void); +void snmp_inc_icmpoutechoreps(void); +void snmp_inc_icmpouttimestamps(void); +void snmp_inc_icmpouttimestampreps(void); +void snmp_inc_icmpoutaddrmasks(void); +void snmp_inc_icmpoutaddrmaskreps(void); + +/* TCP */ +void snmp_inc_tcpactiveopens(void); +void snmp_inc_tcppassiveopens(void); +void snmp_inc_tcpattemptfails(void); +void snmp_inc_tcpestabresets(void); +void snmp_inc_tcpinsegs(void); +void snmp_inc_tcpoutsegs(void); +void snmp_inc_tcpretranssegs(void); +void snmp_inc_tcpinerrs(void); +void snmp_inc_tcpoutrsts(void); + +/* UDP */ +void snmp_inc_udpindatagrams(void); +void snmp_inc_udpnoports(void); +void snmp_inc_udpinerrors(void); +void snmp_inc_udpoutdatagrams(void); +void snmp_insert_udpidx_tree(struct udp_pcb *pcb); +void snmp_delete_udpidx_tree(struct udp_pcb *pcb); + +/* SNMP */ +void snmp_inc_snmpinpkts(void); +void snmp_inc_snmpoutpkts(void); +void snmp_inc_snmpinbadversions(void); +void snmp_inc_snmpinbadcommunitynames(void); +void snmp_inc_snmpinbadcommunityuses(void); +void snmp_inc_snmpinasnparseerrs(void); +void snmp_inc_snmpintoobigs(void); +void snmp_inc_snmpinnosuchnames(void); +void snmp_inc_snmpinbadvalues(void); +void snmp_inc_snmpinreadonlys(void); +void snmp_inc_snmpingenerrs(void); +void snmp_add_snmpintotalreqvars(u8_t value); +void snmp_add_snmpintotalsetvars(u8_t value); +void snmp_inc_snmpingetrequests(void); +void snmp_inc_snmpingetnexts(void); +void snmp_inc_snmpinsetrequests(void); +void snmp_inc_snmpingetresponses(void); +void snmp_inc_snmpintraps(void); +void snmp_inc_snmpouttoobigs(void); +void snmp_inc_snmpoutnosuchnames(void); +void snmp_inc_snmpoutbadvalues(void); +void snmp_inc_snmpoutgenerrs(void); +void snmp_inc_snmpoutgetrequests(void); +void snmp_inc_snmpoutgetnexts(void); +void snmp_inc_snmpoutsetrequests(void); +void snmp_inc_snmpoutgetresponses(void); +void snmp_inc_snmpouttraps(void); +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid); +void snmp_set_snmpenableauthentraps(u8_t *value); +void snmp_get_snmpenableauthentraps(u8_t *value); + +/* LWIP_SNMP support not available */ +/* define everything to be empty */ +#else + +/* system */ +#define snmp_set_sysdesr(str, len) +#define snmp_set_sysobjid(oid); +#define snmp_get_sysobjid_ptr(oid) +#define snmp_inc_sysuptime() +#define snmp_add_sysuptime(value) +#define snmp_get_sysuptime(value) +#define snmp_set_syscontact(ocstr, ocstrlen); +#define snmp_set_sysname(ocstr, ocstrlen); +#define snmp_set_syslocation(ocstr, ocstrlen); + +/* network interface */ +#define snmp_add_ifinoctets(ni,value) +#define snmp_inc_ifinucastpkts(ni) +#define snmp_inc_ifinnucastpkts(ni) +#define snmp_inc_ifindiscards(ni) +#define snmp_add_ifoutoctets(ni,value) +#define snmp_inc_ifoutucastpkts(ni) +#define snmp_inc_ifoutnucastpkts(ni) +#define snmp_inc_ifoutdiscards(ni) +#define snmp_inc_iflist() +#define snmp_dec_iflist() + +/* ARP */ +#define snmp_insert_arpidx_tree(ni,ip) +#define snmp_delete_arpidx_tree(ni,ip) + +/* IP */ +#define snmp_inc_ipinreceives() +#define snmp_inc_ipinhdrerrors() +#define snmp_inc_ipinaddrerrors() +#define snmp_inc_ipforwdatagrams() +#define snmp_inc_ipinunknownprotos() +#define snmp_inc_ipindiscards() +#define snmp_inc_ipindelivers() +#define snmp_inc_ipoutrequests() +#define snmp_inc_ipoutdiscards() +#define snmp_inc_ipoutnoroutes() +#define snmp_inc_ipreasmreqds() +#define snmp_inc_ipreasmoks() +#define snmp_inc_ipreasmfails() +#define snmp_inc_ipfragoks() +#define snmp_inc_ipfragfails() +#define snmp_inc_ipfragcreates() +#define snmp_inc_iproutingdiscards() +#define snmp_insert_ipaddridx_tree(ni) +#define snmp_delete_ipaddridx_tree(ni) +#define snmp_insert_iprteidx_tree(dflt, ni) +#define snmp_delete_iprteidx_tree(dflt, ni) + +/* ICMP */ +#define snmp_inc_icmpinmsgs() +#define snmp_inc_icmpinerrors() +#define snmp_inc_icmpindestunreachs() +#define snmp_inc_icmpintimeexcds() +#define snmp_inc_icmpinparmprobs() +#define snmp_inc_icmpinsrcquenchs() +#define snmp_inc_icmpinredirects() +#define snmp_inc_icmpinechos() +#define snmp_inc_icmpinechoreps() +#define snmp_inc_icmpintimestamps() +#define snmp_inc_icmpintimestampreps() +#define snmp_inc_icmpinaddrmasks() +#define snmp_inc_icmpinaddrmaskreps() +#define snmp_inc_icmpoutmsgs() +#define snmp_inc_icmpouterrors() +#define snmp_inc_icmpoutdestunreachs() +#define snmp_inc_icmpouttimeexcds() +#define snmp_inc_icmpoutparmprobs() +#define snmp_inc_icmpoutsrcquenchs() +#define snmp_inc_icmpoutredirects() +#define snmp_inc_icmpoutechos() +#define snmp_inc_icmpoutechoreps() +#define snmp_inc_icmpouttimestamps() +#define snmp_inc_icmpouttimestampreps() +#define snmp_inc_icmpoutaddrmasks() +#define snmp_inc_icmpoutaddrmaskreps() +/* TCP */ +#define snmp_inc_tcpactiveopens() +#define snmp_inc_tcppassiveopens() +#define snmp_inc_tcpattemptfails() +#define snmp_inc_tcpestabresets() +#define snmp_inc_tcpinsegs() +#define snmp_inc_tcpoutsegs() +#define snmp_inc_tcpretranssegs() +#define snmp_inc_tcpinerrs() +#define snmp_inc_tcpoutrsts() + +/* UDP */ +#define snmp_inc_udpindatagrams() +#define snmp_inc_udpnoports() +#define snmp_inc_udpinerrors() +#define snmp_inc_udpoutdatagrams() +#define snmp_insert_udpidx_tree(pcb) +#define snmp_delete_udpidx_tree(pcb) + +/* SNMP */ +#define snmp_inc_snmpinpkts() +#define snmp_inc_snmpoutpkts() +#define snmp_inc_snmpinbadversions() +#define snmp_inc_snmpinbadcommunitynames() +#define snmp_inc_snmpinbadcommunityuses() +#define snmp_inc_snmpinasnparseerrs() +#define snmp_inc_snmpintoobigs() +#define snmp_inc_snmpinnosuchnames() +#define snmp_inc_snmpinbadvalues() +#define snmp_inc_snmpinreadonlys() +#define snmp_inc_snmpingenerrs() +#define snmp_add_snmpintotalreqvars(value) +#define snmp_add_snmpintotalsetvars(value) +#define snmp_inc_snmpingetrequests() +#define snmp_inc_snmpingetnexts() +#define snmp_inc_snmpinsetrequests() +#define snmp_inc_snmpingetresponses() +#define snmp_inc_snmpintraps() +#define snmp_inc_snmpouttoobigs() +#define snmp_inc_snmpoutnosuchnames() +#define snmp_inc_snmpoutbadvalues() +#define snmp_inc_snmpoutgenerrs() +#define snmp_inc_snmpoutgetrequests() +#define snmp_inc_snmpoutgetnexts() +#define snmp_inc_snmpoutsetrequests() +#define snmp_inc_snmpoutgetresponses() +#define snmp_inc_snmpouttraps() +#define snmp_get_snmpgrpid_ptr(oid) +#define snmp_set_snmpenableauthentraps(value) +#define snmp_get_snmpenableauthentraps(value) + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SNMP_H__ */ diff --git a/ext/lwip/src/include/lwip/snmp_asn1.h b/ext/lwip/src/include/lwip/snmp_asn1.h new file mode 100644 index 000000000..605fa3f16 --- /dev/null +++ b/ext/lwip/src/include/lwip/snmp_asn1.h @@ -0,0 +1,101 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_ASN1_H__ +#define __LWIP_SNMP_ASN1_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" + +#if LWIP_SNMP + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_UNIV (0) /* (!0x80 | !0x40) */ +#define SNMP_ASN1_APPLIC (0x40) /* (!0x80 | 0x40) */ +#define SNMP_ASN1_CONTXT (0x80) /* ( 0x80 | !0x40) */ + +#define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */ +#define SNMP_ASN1_PRIMIT (0) /* (!0x20) */ + +/* universal tags */ +#define SNMP_ASN1_INTEG 2 +#define SNMP_ASN1_OC_STR 4 +#define SNMP_ASN1_NUL 5 +#define SNMP_ASN1_OBJ_ID 6 +#define SNMP_ASN1_SEQ 16 + +/* application specific (SNMP) tags */ +#define SNMP_ASN1_IPADDR 0 /* octet string size(4) */ +#define SNMP_ASN1_COUNTER 1 /* u32_t */ +#define SNMP_ASN1_GAUGE 2 /* u32_t */ +#define SNMP_ASN1_TIMETICKS 3 /* u32_t */ +#define SNMP_ASN1_OPAQUE 4 /* octet string */ + +/* context specific (SNMP) tags */ +#define SNMP_ASN1_PDU_GET_REQ 0 +#define SNMP_ASN1_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_PDU_GET_RESP 2 +#define SNMP_ASN1_PDU_SET_REQ 3 +#define SNMP_ASN1_PDU_TRAP 4 + +err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type); +err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length); +err_t snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid); +err_t snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed); +err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type); +err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length); +err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value); +err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value); +err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident); +err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_ASN1_H__ */ diff --git a/ext/lwip/src/include/lwip/snmp_msg.h b/ext/lwip/src/include/lwip/snmp_msg.h new file mode 100644 index 000000000..1183e3a95 --- /dev/null +++ b/ext/lwip/src/include/lwip/snmp_msg.h @@ -0,0 +1,315 @@ +/** + * @file + * SNMP Agent message handling structures. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_MSG_H__ +#define __LWIP_SNMP_MSG_H__ + +#include "lwip/opt.h" +#include "lwip/snmp.h" +#include "lwip/snmp_structs.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#if LWIP_SNMP + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to + this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't + work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +#define SNMP_ES_NOERROR 0 +#define SNMP_ES_TOOBIG 1 +#define SNMP_ES_NOSUCHNAME 2 +#define SNMP_ES_BADVALUE 3 +#define SNMP_ES_READONLY 4 +#define SNMP_ES_GENERROR 5 + +#define SNMP_GENTRAP_COLDSTART 0 +#define SNMP_GENTRAP_WARMSTART 1 +#define SNMP_GENTRAP_AUTHFAIL 4 +#define SNMP_GENTRAP_ENTERPRISESPC 6 + +struct snmp_varbind +{ + /* next pointer, NULL for last in list */ + struct snmp_varbind *next; + /* previous pointer, NULL for first in list */ + struct snmp_varbind *prev; + + /* object identifier length (in s32_t) */ + u8_t ident_len; + /* object identifier array */ + s32_t *ident; + + /* object value ASN1 type */ + u8_t value_type; + /* object value length (in u8_t) */ + u8_t value_len; + /* object value */ + void *value; + + /* encoding varbind seq length length */ + u8_t seqlenlen; + /* encoding object identifier length length */ + u8_t olenlen; + /* encoding object value length length */ + u8_t vlenlen; + /* encoding varbind seq length */ + u16_t seqlen; + /* encoding object identifier length */ + u16_t olen; + /* encoding object value length */ + u16_t vlen; +}; + +struct snmp_varbind_root +{ + struct snmp_varbind *head; + struct snmp_varbind *tail; + /* number of variable bindings in list */ + u8_t count; + /* encoding varbind-list seq length length */ + u8_t seqlenlen; + /* encoding varbind-list seq length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_resp_header_lengths +{ + /* encoding error-index length length */ + u8_t erridxlenlen; + /* encoding error-status length length */ + u8_t errstatlenlen; + /* encoding request id length length */ + u8_t ridlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding error-index length */ + u16_t erridxlen; + /* encoding error-status length */ + u16_t errstatlen; + /* encoding request id length */ + u16_t ridlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_trap_header_lengths +{ + /* encoding timestamp length length */ + u8_t tslenlen; + /* encoding specific-trap length length */ + u8_t strplenlen; + /* encoding generic-trap length length */ + u8_t gtrplenlen; + /* encoding agent-addr length length */ + u8_t aaddrlenlen; + /* encoding enterprise-id length length */ + u8_t eidlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding timestamp length */ + u16_t tslen; + /* encoding specific-trap length */ + u16_t strplen; + /* encoding generic-trap length */ + u16_t gtrplen; + /* encoding agent-addr length */ + u16_t aaddrlen; + /* encoding enterprise-id length */ + u16_t eidlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/* Accepting new SNMP messages. */ +#define SNMP_MSG_EMPTY 0 +/* Search for matching object for variable binding. */ +#define SNMP_MSG_SEARCH_OBJ 1 +/* Perform SNMP operation on in-memory object. + Pass-through states, for symmetry only. */ +#define SNMP_MSG_INTERNAL_GET_OBJDEF 2 +#define SNMP_MSG_INTERNAL_GET_VALUE 3 +#define SNMP_MSG_INTERNAL_SET_TEST 4 +#define SNMP_MSG_INTERNAL_GET_OBJDEF_S 5 +#define SNMP_MSG_INTERNAL_SET_VALUE 6 +/* Perform SNMP operation on object located externally. + In theory this could be used for building a proxy agent. + Practical use is for an enterprise spc. app. gateway. */ +#define SNMP_MSG_EXTERNAL_GET_OBJDEF 7 +#define SNMP_MSG_EXTERNAL_GET_VALUE 8 +#define SNMP_MSG_EXTERNAL_SET_TEST 9 +#define SNMP_MSG_EXTERNAL_GET_OBJDEF_S 10 +#define SNMP_MSG_EXTERNAL_SET_VALUE 11 + +#define SNMP_COMMUNITY_STR_LEN 64 +struct snmp_msg_pstat +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* source IP address */ + ip_addr_t sip; + /* source UDP port */ + u16_t sp; + /* request type */ + u8_t rt; + /* request ID */ + s32_t rid; + /* error status */ + s32_t error_status; + /* error index */ + s32_t error_index; + /* community name (zero terminated) */ + u8_t community[SNMP_COMMUNITY_STR_LEN + 1]; + /* community string length (exclusive zero term) */ + u8_t com_strlen; + /* one out of MSG_EMPTY, MSG_DEMUX, MSG_INTERNAL, MSG_EXTERNAL_x */ + u8_t state; + /* saved arguments for MSG_EXTERNAL_x */ + struct mib_external_node *ext_mib_node; + struct snmp_name_ptr ext_name_ptr; + struct obj_def ext_object_def; + struct snmp_obj_id ext_oid; + /* index into input variable binding list */ + u8_t vb_idx; + /* ptr into input variable binding list */ + struct snmp_varbind *vb_ptr; + /* list of variable bindings from input */ + struct snmp_varbind_root invb; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output response lengths used in ASN encoding */ + struct snmp_resp_header_lengths rhl; +}; + +struct snmp_msg_trap +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* destination IP address in network order */ + ip_addr_t dip; + + /* source enterprise ID (sysObjectID) */ + struct snmp_obj_id *enterprise; + /* source IP address, raw network order format */ + u8_t sip_raw[4]; + /* generic trap code */ + u32_t gen_trap; + /* specific trap code */ + u32_t spc_trap; + /* timestamp */ + u32_t ts; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output trap lengths used in ASN encoding */ + struct snmp_trap_header_lengths thl; +}; + +/** Agent Version constant, 0 = v1 oddity */ +extern const s32_t snmp_version; +/** Agent default "public" community string */ +extern const char snmp_publiccommunity[7]; + +extern struct snmp_msg_trap trap_msg; + +/** Agent setup, start listening to port 161. */ +void snmp_init(void); +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst); + +/** Varbind-list functions. */ +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); +void snmp_varbind_free(struct snmp_varbind *vb); +void snmp_varbind_list_free(struct snmp_varbind_root *root); +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); + +/** Handle an internal (recv) or external (private response) event. */ +void snmp_msg_event(u8_t request_id); +err_t snmp_send_response(struct snmp_msg_pstat *m_stat); +err_t snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap); +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_MSG_H__ */ diff --git a/ext/lwip/src/include/lwip/snmp_structs.h b/ext/lwip/src/include/lwip/snmp_structs.h new file mode 100644 index 000000000..0d3b46a92 --- /dev/null +++ b/ext/lwip/src/include/lwip/snmp_structs.h @@ -0,0 +1,268 @@ +/** + * @file + * Generic MIB tree structures. + * + * @todo namespace prefixes + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_STRUCTS_H__ +#define __LWIP_SNMP_STRUCTS_H__ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MIB object instance */ +#define MIB_OBJECT_NONE 0 +#define MIB_OBJECT_SCALAR 1 +#define MIB_OBJECT_TAB 2 + +/* MIB access types */ +#define MIB_ACCESS_READ 1 +#define MIB_ACCESS_WRITE 2 + +/* MIB object access */ +#define MIB_OBJECT_READ_ONLY MIB_ACCESS_READ +#define MIB_OBJECT_READ_WRITE (MIB_ACCESS_READ | MIB_ACCESS_WRITE) +#define MIB_OBJECT_WRITE_ONLY MIB_ACCESS_WRITE +#define MIB_OBJECT_NOT_ACCESSIBLE 0 + +/** object definition returned by (get_object_def)() */ +struct obj_def +{ + /* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */ + u8_t instance; + /* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */ + u8_t access; + /* ASN type for this object */ + u8_t asn_type; + /* value length (host length) */ + u16_t v_len; + /* length of instance part of supplied object identifier */ + u8_t id_inst_len; + /* instance part of supplied object identifier */ + s32_t *id_inst_ptr; +}; + +struct snmp_name_ptr +{ + u8_t ident_len; + s32_t *ident; +}; + +/** MIB const scalar (.0) node */ +#define MIB_NODE_SC 0x01 +/** MIB const array node */ +#define MIB_NODE_AR 0x02 +/** MIB array node (mem_malloced from RAM) */ +#define MIB_NODE_RA 0x03 +/** MIB list root node (mem_malloced from RAM) */ +#define MIB_NODE_LR 0x04 +/** MIB node for external objects */ +#define MIB_NODE_EX 0x05 + +/** node "base class" layout, the mandatory fields for a node */ +struct mib_node +{ + /** returns struct obj_def for the given object identifier */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + /** returns object value for the given object identifier, + @note the caller must allocate at least len bytes for the value */ + void (*get_value)(struct obj_def *od, u16_t len, void *value); + /** tests length and/or range BEFORE setting */ + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + /** sets object value, only to be called when set_test() */ + void (*set_value)(struct obj_def *od, u16_t len, void *value); + /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */ + u8_t node_type; + /* array or max list length */ + u16_t maxlength; +}; + +/** derived node for scalars .0 index */ +typedef struct mib_node mib_scalar_node; + +/** derived node, points to a fixed size const array + of sub-identifiers plus a 'child' pointer */ +struct mib_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + const s32_t *objid; + struct mib_node* const *nptr; +}; + +/** derived node, points to a fixed size mem_malloced array + of sub-identifiers plus a 'child' pointer */ +struct mib_ram_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + s32_t *objid; + struct mib_node **nptr; +}; + +struct mib_list_node +{ + struct mib_list_node *prev; + struct mib_list_node *next; + s32_t objid; + struct mib_node *nptr; +}; + +/** derived node, points to a doubly linked list + of sub-identifiers plus a 'child' pointer */ +struct mib_list_rootnode +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + struct mib_list_node *head; + struct mib_list_node *tail; + /* counts list nodes in list */ + u16_t count; +}; + +/** derived node, has access functions for mib object in external memory or device + using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */ +struct mib_external_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + /** points to an external (in memory) record of some sort of addressing + information, passed to and interpreted by the funtions below */ + void* addr_inf; + /** tree levels under this node */ + u8_t tree_levels; + /** number of objects at this level */ + u16_t (*level_length)(void* addr_inf, u8_t level); + /** compares object sub identifier with external id + return zero when equal, nonzero when unequal */ + s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); + void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); + + /** async Questions */ + void (*get_object_def_q)(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_q)(u8_t rid, struct obj_def *od); + void (*set_test_q)(u8_t rid, struct obj_def *od); + void (*set_value_q)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Answers */ + void (*get_object_def_a)(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Panic Close (agent returns error reply, + e.g. used for external transaction cleanup) */ + void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_pc)(u8_t rid, struct obj_def *od); + void (*set_test_pc)(u8_t rid, struct obj_def *od); + void (*set_value_pc)(u8_t rid, struct obj_def *od); +}; + +/** export MIB tree from mib2.c */ +extern const struct mib_array_node internet; + +/** dummy function pointers for non-leaf MIB nodes from mib2.c */ +void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +void noleafs_get_value(struct obj_def *od, u16_t len, void *value); +u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value); +void noleafs_set_value(struct obj_def *od, u16_t len, void *value); + +void snmp_oidtoip(s32_t *ident, ip_addr_t *ip); +void snmp_iptooid(ip_addr_t *ip, s32_t *ident); +void snmp_ifindextonetif(s32_t ifindex, struct netif **netif); +void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx); + +struct mib_list_node* snmp_mib_ln_alloc(s32_t id); +void snmp_mib_ln_free(struct mib_list_node *ln); +struct mib_list_rootnode* snmp_mib_lrn_alloc(void); +void snmp_mib_lrn_free(struct mib_list_rootnode *lrn); + +s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn); +s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn); +struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n); + +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np); +struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); +u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident); +u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_STRUCTS_H__ */ diff --git a/ext/lwip/src/include/lwip/sockets.h b/ext/lwip/src/include/lwip/sockets.h new file mode 100644 index 000000000..3ea32f13f --- /dev/null +++ b/ext/lwip/src/include/lwip/sockets.h @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#ifndef __LWIP_SOCKETS_H__ +#define __LWIP_SOCKETS_H__ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + u8_t sin_family; + u16_t sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +struct sockaddr { + u8_t sa_len; + u8_t sa_family; + char sa_data[14]; +}; + +/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef u32_t socklen_t; +#endif + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ + +#define SO_DONTLINGER ((int)(~SO_LINGER)) + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* Unimplemented: send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#define PF_INET AF_INET +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_UDPLITE 136 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_IGMP +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET + #undef FD_SETSIZE + /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ + #define FD_SETSIZE MEMP_NUM_NETCONN + #define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7))) + #define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7))) + #define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7))) + #define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p))) + + typedef struct fd_set { + unsigned char fd_bits [(FD_SETSIZE+7)/8]; + } fd_set; + +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +void lwip_socket_init(void); + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); +int lwip_fcntl(int s, int cmd, int val); + +#if LWIP_COMPAT_SOCKETS +#define accept(a,b,c) lwip_accept(a,b,c) +#define bind(a,b,c) lwip_bind(a,b,c) +#define shutdown(a,b) lwip_shutdown(a,b) +#define closesocket(s) lwip_close(s) +#define connect(a,b,c) lwip_connect(a,b,c) +#define getsockname(a,b,c) lwip_getsockname(a,b,c) +#define getpeername(a,b,c) lwip_getpeername(a,b,c) +#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e) +#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e) +#define listen(a,b) lwip_listen(a,b) +#define recv(a,b,c,d) lwip_recv(a,b,c,d) +#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f) +#define send(a,b,c,d) lwip_send(a,b,c,d) +#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f) +#define socket(a,b,c) lwip_socket(a,b,c) +#define select(a,b,c,d,e) lwip_select(a,b,c,d,e) +#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(a,b,c) lwip_read(a,b,c) +#define write(a,b,c) lwip_write(a,b,c) +#define close(s) lwip_close(s) +#define fcntl(a,b,c) lwip_fcntl(a,b,c) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* __LWIP_SOCKETS_H__ */ diff --git a/ext/lwip/src/include/lwip/stats.h b/ext/lwip/src/include/lwip/stats.h new file mode 100644 index 000000000..d828980a9 --- /dev/null +++ b/ext/lwip/src/include/lwip/stats.h @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_STATS_H__ +#define __LWIP_STATS_H__ + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +struct stats_igmp { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER rx_v1; /* Received v1 frames. */ + STAT_COUNTER rx_group; /* Received group-specific queries. */ + STAT_COUNTER rx_general; /* Received general queries. */ + STAT_COUNTER rx_report; /* Received reports. */ + STAT_COUNTER tx_join; /* Sent joins. */ + STAT_COUNTER tx_leave; /* Sent leaves. */ + STAT_COUNTER tx_report; /* Sent reports. */ +}; + +struct stats_mem { +#ifdef LWIP_DEBUG + const char *name; +#endif /* LWIP_DEBUG */ + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER err; + STAT_COUNTER illegal; +}; + +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mutex; + struct stats_syselem mbox; +}; + +struct stats_ { +#if LINK_STATS + struct stats_proto link; +#endif +#if ETHARP_STATS + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + struct stats_proto ip_frag; +#endif +#if IP_STATS + struct stats_proto ip; +#endif +#if ICMP_STATS + struct stats_proto icmp; +#endif +#if IGMP_STATS + struct stats_igmp igmp; +#endif +#if UDP_STATS + struct stats_proto udp; +#endif +#if TCP_STATS + struct stats_proto tcp; +#endif +#if MEM_STATS + struct stats_mem mem; +#endif +#if MEMP_STATS + struct stats_mem memp[MEMP_MAX]; +#endif +#if SYS_STATS + struct stats_sys sys; +#endif +}; + +extern struct stats_ lwip_stats; + +void stats_init(void); + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ + if (lwip_stats.x.max < lwip_stats.x.used) { \ + lwip_stats.x.max = lwip_stats.x.used; \ + } \ + } while(0) +#else /* LWIP_STATS */ +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#define STATS_INC_USED(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp) +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) STATS_INC(mem.x) +#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y) +#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + +#if MEMP_STATS +#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y +#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x) +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) +#define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#else +#define MEMP_STATS_AVAIL(x, i, y) +#define MEMP_STATS_INC(x, i) +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_INC_USED(x, i) +#define MEMP_STATS_DISPLAY(i) +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_INC_USED(x) +#define SYS_STATS_DISPLAY() +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, const char *name); +void stats_display_igmp(struct stats_igmp *igmp); +void stats_display_mem(struct stats_mem *mem, const char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else /* LWIP_STATS_DISPLAY */ +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_STATS_H__ */ diff --git a/ext/lwip/src/include/lwip/sys.h b/ext/lwip/src/include/lwip/sys.h new file mode 100644 index 000000000..dc9351335 --- /dev/null +++ b/ext/lwip/src/include/lwip/sys.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_SYS_H__ +#define __LWIP_SYS_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mutex_t; +typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_sem_valid(s) 0 +#define sys_sem_set_invalid(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mutex_valid(mu) 0 +#define sys_mutex_set_invalid(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) +#define sys_mbox_valid(m) +#define sys_mbox_set_invalid(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ +typedef void (*lwip_thread_fn)(void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t sys_mutex_new(sys_mutex_t *mutex); +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); +/** Signals a semaphore + * @param sem the semaphore to signal */ +void sys_sem_signal(sys_sem_t *sem); +/** Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); +/** Delete a semaphore + * @param sem semaphore to delete */ +void sys_sem_free(sys_sem_t *sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif + +/* Time functions. */ +#ifndef sys_msleep +void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */ +#endif + +/* Mailbox functions. */ + +/** Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (miminum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); +/** Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg); +/** Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); +#endif +/** For now, we map straight to sys_arch implementation. */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** Delete an mbox + * @param mbox mbox to delete */ +void sys_mbox_free(sys_mbox_t *mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif + +/** The only thread function: + * Creates a new thread + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anthing else. */ +void sys_init(void); + +#ifndef sys_jiffies +/** Ticks/jiffies since power up. */ +u32_t sys_jiffies(void); +#endif + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SYS_H__ */ diff --git a/ext/lwip/src/include/lwip/tcp.h b/ext/lwip/src/include/lwip/tcp.h new file mode 100644 index 000000000..c6e61ad1f --- /dev/null +++ b/ext/lwip/src/include/lwip/tcp.h @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_H__ +#define __LWIP_TCP_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +/** Function prototype for tcp accept callback functions. Called when a new + * connection can be accepted on a listening pcb. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param newpcb The new connection pcb + * @param err An error code if there has been an error accepting. + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); + +/** Function prototype for tcp receive callback functions. Called when data has + * been received. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which received data + * @param p The received data (or NULL when the connection has been closed!) + * @param err An error code if there has been an error receiving + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err); + +/** Function prototype for tcp sent callback functions. Called when sent data has + * been acknowledged by the remote side. Use it to free corresponding resources. + * This also means that the pcb has now space available to send new data. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb for which data has been acknowledged + * @param len The amount of bytes acknowledged + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, + u16_t len); + +/** Function prototype for tcp poll callback functions. Called periodically as + * specified by @see tcp_poll. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb tcp pcb + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); + +/** Function prototype for tcp error callback functions. Called when the pcb + * receives a RST or is unexpectedly closed for any other reason. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param err Error code to indicate why the pcb has been closed + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ +typedef void (*tcp_err_fn)(void *arg, err_t err); + +/** Function prototype for tcp connected callback functions. Called when a pcb + * is connected to the remote side after initiating a connection attempt by + * calling tcp_connect(). + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which is connected + * @param err An unused error code, always ERR_OK currently ;-) TODO! + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + * + * @note When a connection attempt fails, the error callback is currently called! + */ +typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb a new tcp_pcb that now is connected + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return ERR_OK: accept the new connection, + * any other err_t abortsthe new connection + */ +#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept; +#else /* LWIP_CALLBACK_API */ +#define DEF_ACCEPT_CALLBACK +#endif /* LWIP_CALLBACK_API */ + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + void *callback_arg; \ + /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ + DEF_ACCEPT_CALLBACK \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + /* ports are in host byte order */ \ + u16_t local_port + + +/* the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + u8_t flags; +#define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */ +#define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */ +#define TF_INFR ((u8_t)0x04U) /* In fast recovery. */ +#define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */ +#define TF_RXCLOSED ((u8_t)0x10U) /* rx closed by tcp_shutdown */ +#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + + /* Timers */ + u8_t polltmr, pollinterval; + u8_t last_timer; + u32_t tmr; + + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + u16_t rcv_wnd; /* receiver window available */ + u16_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u8_t dupacks; + u32_t lastack; /* Highest acknowledged seqno. */ + + /* congestion avoidance/control variables */ + u16_t cwnd; + u16_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + u16_t snd_wnd; /* sender window */ + u16_t snd_wnd_max; /* the maximum sender window announced by the remote host */ + + u16_t acked; + + u16_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) + u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ + +#if TCP_OVERSIZE + /* Extra bytes available at the end of the last pbuf in unsent. */ + u16_t unsent_oversize; +#endif /* TCP_OVERSIZE */ + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. */ + tcp_sent_fn sent; + /* Function to be called when (in-sequence) data has arrived. */ + tcp_recv_fn recv; + /* Function to be called when a connection has been set up. */ + tcp_connected_fn connected; + /* Function which is called periodically. */ + tcp_poll_fn poll; + /* Function to be called whenever a fatal error occurs. */ + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u8_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; +}; + +struct tcp_pcb_listen { +/* Common members of all PCB types */ + IP_PCB; +/* Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#endif /* LWIP_EVENT_API */ + +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void); + +void tcp_arg (struct tcp_pcb *pcb, void *arg); +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); +void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); +void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); + +#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) +#define tcp_sndbuf(pcb) ((pcb)->snd_buf) +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY) +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_accepted(pcb) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \ + (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0) +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \ + (pcb)->state == LISTEN) +#endif /* TCP_LISTEN_BACKLOG */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len); +err_t tcp_bind (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +err_t tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, tcp_connected_fn connected); + +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abort (struct tcp_pcb *pcb); +err_t tcp_close (struct tcp_pcb *pcb); +err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); + +/* Flags for "apiflags" parameter in tcp_write */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags); + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +err_t tcp_output (struct tcp_pcb *pcb); + + +const char* tcp_debug_state_str(enum tcp_state s); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/ext/lwip/src/include/lwip/tcp_impl.h b/ext/lwip/src/include/lwip/tcp_impl.h new file mode 100644 index 000000000..623f4e33c --- /dev/null +++ b/ext/lwip/src/include/lwip/tcp_impl.h @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_IMPL_H__ +#define __LWIP_TCP_IMPL_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +void tcp_init (void); /* Initialize this module. */ +void tcp_tmr (void); /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void); +void tcp_fasttmr (void); + + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +struct tcp_pcb * tcp_alloc (u8_t prio); +void tcp_abandon (struct tcp_pcb *pcb, int reset); +err_t tcp_send_empty_ack(struct tcp_pcb *pcb); +void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); +void tcp_rexmit_fast (struct tcp_pcb *pcb); +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); +err_t tcp_process_refused_data(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) || \ + ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U + +#define TCP_FLAGS 0x3fU + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 1 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) +#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) + +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags)) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) ) + +#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0)) + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_EVENT_API + +#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_POLL, NULL, 0, ERR_OK) +#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ + LWIP_EVENT_ERR, NULL, 0, (err)) + +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(pcb,err,ret) \ + do { \ + if((pcb)->accept != NULL) \ + (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_ARG; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(errf,arg,err) \ + do { \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ +#if TCP_OVERSIZE && defined(LWIP_DEBUG) +#define TCP_OVERSIZE_DBGCHECK 1 +#else +#define TCP_OVERSIZE_DBGCHECK 0 +#endif + +/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ +#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) + +/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segements on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + u16_t len; /* the TCP length of this segment */ +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_left; /* Extra bytes available at the end of the last + pbuf in unsent (used for asserting vs. + tcp_pcb.unsent_oversized only) */ +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + u16_t chksum; + u8_t chksum_swapped; +#endif /* TCP_CHECKSUM_ON_COPY */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is + checksummed into 'chksum' */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \ + (flags & TF_SEG_OPTS_TS ? 12 : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF)) + +/* Global variables: */ +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; +extern u8_t tcp_active_pcbs_changed; + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */ + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#ifndef TCP_DEBUG_PCB_LISTS +#define TCP_DEBUG_PCB_LISTS 0 +#endif +#if TCP_DEBUG_PCB_LISTS +#define TCP_REG(pcbs, npcb) do {\ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ + for(tcp_tmp_pcb = *(pcbs); \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ + (npcb)->next = *(pcbs); \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ + *(pcbs) = (npcb); \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ + if(*(pcbs) == (npcb)) { \ + *(pcbs) = (*pcbs)->next; \ + } else for(tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + (npcb)->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + (npcb)->next = *pcbs; \ + *(pcbs) = (npcb); \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == (npcb)) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + for(tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + } \ + (npcb)->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + +#define TCP_REG_ACTIVE(npcb) \ + do { \ + TCP_REG(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_RMV_ACTIVE(npcb) \ + do { \ + TCP_RMV(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_PCB_REMOVE_ACTIVE(pcb) \ + do { \ + tcp_pcb_remove(&tcp_active_pcbs, pcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + + +/* Internal functions: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +void tcp_segs_free(struct tcp_seg *seg); +void tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) + +err_t tcp_send_fin(struct tcp_pcb *pcb); +err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst(u32_t seqno, u32_t ackno, + ip_addr_t *local_ip, ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port); + +u32_t tcp_next_iss(void); + +void tcp_keepalive(struct tcp_pcb *pcb); +void tcp_zero_window_probe(struct tcp_pcb *pcb); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +/** External function (implemented in timers.c), called when TCP detects + * that a timer is needed (i.e. active- or time-wait-pcb found). */ +void tcp_timer_needed(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/ext/lwip/src/include/lwip/tcpip.h b/ext/lwip/src/include/lwip/tcpip.h new file mode 100644 index 000000000..637476e1a --- /dev/null +++ b/ext/lwip/src/include/lwip/tcpip.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCPIP_H__ +#define __LWIP_TCPIP_H__ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" +#include "lwip/netifapi.h" +#include "lwip/pbuf.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/timers.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. */ +#ifndef LWIP_TCPIP_THREAD_ALIVE +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_mutex_t lock_tcpip_core; +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) +#define TCPIP_APIMSG(m) tcpip_apimsg_lock(m) +#define TCPIP_APIMSG_ACK(m) +#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m) +#define TCPIP_NETIFAPI_ACK(m) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#define TCPIP_APIMSG(m) tcpip_apimsg(m) +#define TCPIP_APIMSG_ACK(m) sys_sem_signal(&m->conn->op_completed) +#define TCPIP_NETIFAPI(m) tcpip_netifapi(m) +#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn)(void *arg); +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn)(void *ctx); + +/* Forward declarations */ +struct tcpip_callback_msg; + +void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); + +#if LWIP_NETCONN +err_t tcpip_apimsg(struct api_msg *apimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_apimsg_lock(struct api_msg *apimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETCONN */ + +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +#if LWIP_NETIF_API +err_t tcpip_netifapi(struct netifapi_msg *netifapimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); +err_t tcpip_trycallback(struct tcpip_callback_msg* msg); + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +#if LWIP_TCPIP_TIMEOUT +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); +#endif /* LWIP_TCPIP_TIMEOUT */ + +enum tcpip_msg_type { +#if LWIP_NETCONN + TCPIP_MSG_API, +#endif /* LWIP_NETCONN */ + TCPIP_MSG_INPKT, +#if LWIP_NETIF_API + TCPIP_MSG_NETIFAPI, +#endif /* LWIP_NETIF_API */ +#if LWIP_TCPIP_TIMEOUT + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT, +#endif /* LWIP_TCPIP_TIMEOUT */ + TCPIP_MSG_CALLBACK, + TCPIP_MSG_CALLBACK_STATIC +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + sys_sem_t *sem; + union { +#if LWIP_NETCONN + struct api_msg *apimsg; +#endif /* LWIP_NETCONN */ +#if LWIP_NETIF_API + struct netifapi_msg *netifapimsg; +#endif /* LWIP_NETIF_API */ + struct { + struct pbuf *p; + struct netif *netif; + } inp; + struct { + tcpip_callback_fn function; + void *ctx; + } cb; +#if LWIP_TCPIP_TIMEOUT + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; +#endif /* LWIP_TCPIP_TIMEOUT */ + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* __LWIP_TCPIP_H__ */ diff --git a/ext/lwip/src/include/lwip/timers.h b/ext/lwip/src/include/lwip/timers.h new file mode 100644 index 000000000..04e78e0fe --- /dev/null +++ b/ext/lwip/src/include/lwip/timers.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef __LWIP_TIMERS_H__ +#define __LWIP_TIMERS_H__ + +#include "lwip/opt.h" + +/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */ +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) + +#if LWIP_TIMERS + +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void); + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout(sys_timeout_handler handler, void *arg); +#if NO_SYS +void sys_check_timeouts(void); +void sys_restart_timeouts(void); +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); +#endif /* NO_SYS */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TIMERS */ +#endif /* __LWIP_TIMERS_H__ */ diff --git a/ext/lwip/src/include/lwip/udp.h b/ext/lwip/src/include/lwip/udp.h new file mode 100644 index 000000000..f1e6d3f1e --- /dev/null +++ b/ext/lwip/src/include/lwip/udp.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_UDP_H__ +#define __LWIP_UDP_H__ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U +#define UDP_FLAGS_MULTICAST_LOOP 0x08U + +struct udp_pcb; + +/** Function prototype for udp pcb receive callback functions + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf + * makes 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port); + + +struct udp_pcb { +/* Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /** ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_IGMP + /** outgoing network interface for multicast packets */ + ip_addr_t multicast_ip; +#endif /* LWIP_IGMP */ + +#if LWIP_UDPLITE + /** used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /** receive callback function */ + udp_recv_fn recv; + /** user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for exernal reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void); +void udp_remove (struct udp_pcb *pcb); +err_t udp_bind (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +err_t udp_connect (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +void udp_disconnect (struct udp_pcb *pcb); +void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, + void *recv_arg); +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif); +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port); +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); + +#if LWIP_CHECKSUM_ON_COPY +err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, u8_t have_chksum, + u16_t chksum); +err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + u8_t have_chksum, u16_t chksum); +err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp); + +void udp_init (void); + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* __LWIP_UDP_H__ */ diff --git a/ext/lwip/src/include/netif/etharp.h b/ext/lwip/src/include/netif/etharp.h new file mode 100644 index 000000000..859608df9 --- /dev/null +++ b/ext/lwip/src/include/netif/etharp.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __NETIF_ETHARP_H__ +#define __NETIF_ETHARP_H__ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN 6 +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FIELD(u8_t addr[ETHARP_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** Ethernet header */ +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FIELD(struct eth_addr dest); + PACK_STRUCT_FIELD(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#if ETHARP_SUPPORT_VLAN + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** VLAN header inserted between ethernet header and payload + * if 'type' in ethernet header is ETHTYPE_VLAN. + * See IEEE802.Q */ +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF) + +#endif /* ETHARP_SUPPORT_VLAN */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message, see RFC 826 ("Packet format") */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FIELD(u8_t hwlen); + PACK_STRUCT_FIELD(u8_t protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FIELD(struct eth_addr shwaddr); + PACK_STRUCT_FIELD(struct ip_addr2 sipaddr); + PACK_STRUCT_FIELD(struct eth_addr dhwaddr); + PACK_STRUCT_FIELD(struct ip_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 +#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) + +/** 5 seconds period */ +#define ARP_TMR_INTERVAL 5000 + +#define ETHTYPE_ARP 0x0806U +#define ETHTYPE_IP 0x0800U +#define ETHTYPE_VLAN 0x8100U +#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */ +#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */ + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables + * or known to be 32-bit aligned within the protocol header. */ +#ifndef ETHADDR32_COPY +#define ETHADDR32_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN) +#endif + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local + * variables and known to be 16-bit aligned within the protocol header. */ +#ifndef ETHADDR16_COPY +#define ETHADDR16_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN) +#endif + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** ARP message types (opcodes) */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) + * to a filter function that returns the correct netif when using multiple + * netifs on one hardware interface where the netif's low-level receive + * routine cannot decide for the correct netif (e.g. when mapping multiple + * IP addresses to one hardware interface). + */ +#ifndef LWIP_ARP_FILTER_NETIF +#define LWIP_ARP_FILTER_NETIF 0 +#endif + +#if ARP_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct etharp_q_entry { + struct etharp_q_entry *next; + struct pbuf *p; +}; +#endif /* ARP_QUEUEING */ + +#define etharp_init() /* Compatibility define, not init needed. */ +void etharp_tmr(void); +s8_t etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, + struct eth_addr **eth_ret, ip_addr_t **ip_ret); +err_t etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr); +err_t etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q); +err_t etharp_request(struct netif *netif, ip_addr_t *ipaddr); +/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; + * this is an ARP packet sent by a node in order to spontaneously cause other + * nodes to update an entry in their ARP cache. + * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ +#define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr) +void etharp_cleanup_netif(struct netif *netif); + +#if ETHARP_SUPPORT_STATIC_ENTRIES +err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr); +err_t etharp_remove_static_entry(ip_addr_t *ipaddr); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_AUTOIP +err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, + const u16_t opcode); +#endif /* LWIP_AUTOIP */ + +#endif /* LWIP_ARP */ + +err_t ethernet_input(struct pbuf *p, struct netif *netif); + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETHARP_HWADDR_LEN) == 0) + +extern const struct eth_addr ethbroadcast, ethzero; + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NETIF_ARP_H__ */ diff --git a/ext/lwip/src/include/netif/ppp_oe.h b/ext/lwip/src/include/netif/ppp_oe.h new file mode 100644 index 000000000..e1cdfa519 --- /dev/null +++ b/ext/lwip/src/include/netif/ppp_oe.h @@ -0,0 +1,190 @@ +/***************************************************************************** +* ppp_oe.h - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PPP_OE_H +#define PPP_OE_H + +#include "lwip/opt.h" + +#if PPPOE_SUPPORT > 0 + +#include "netif/etharp.h" + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoehdr { + PACK_STRUCT_FIELD(u8_t vertype); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t session); + PACK_STRUCT_FIELD(u16_t plen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoetag { + PACK_STRUCT_FIELD(u16_t tag); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +#define PPPOE_STATE_CLOSING 4 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +#define PPPOE_HEADERLEN sizeof(struct pppoehdr) +#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ + +#define PPPOE_TAG_EOL 0x0000 /* end of list */ +#define PPPOE_TAG_SNAME 0x0101 /* service name */ +#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ +#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ +#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ +#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ +#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ +#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ +#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ + +#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ +#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ +#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ +#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ +#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ + +#ifndef ETHERMTU +#define ETHERMTU 1500 +#endif + +/* two byte PPP protocol discriminator, then IP data */ +#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2) + +#ifndef PPPOE_MAX_AC_COOKIE_LEN +#define PPPOE_MAX_AC_COOKIE_LEN 64 +#endif + +struct pppoe_softc { + struct pppoe_softc *next; + struct netif *sc_ethif; /* ethernet interface we are using */ + int sc_pd; /* ppp unit number */ + void (*sc_linkStatusCB)(int pd, int up); + + int sc_state; /* discovery phase or session connected */ + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + +#ifdef PPPOE_TODO + char *sc_service_name; /* if != NULL: requested name of service */ + char *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_TODO */ + u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ + size_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + size_t sc_hunique_len; /* length of host unique */ +#endif + int sc_padi_retried; /* number of PADI retries already done */ + int sc_padr_retried; /* number of PADR retries already done */ +}; + + +#define pppoe_init() /* compatibility define, no initialization needed */ + +err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr); +err_t pppoe_destroy(struct netif *ifp); + +int pppoe_connect(struct pppoe_softc *sc); +void pppoe_disconnect(struct pppoe_softc *sc); + +void pppoe_disc_input(struct netif *netif, struct pbuf *p); +void pppoe_data_input(struct netif *netif, struct pbuf *p); + +err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); + +/** used in ppp.c */ +#define PPPOE_HDRLEN (sizeof(struct eth_hdr) + PPPOE_HEADERLEN) + +#endif /* PPPOE_SUPPORT */ + +#endif /* PPP_OE_H */ diff --git a/ext/lwip/src/include/netif/slipif.h b/ext/lwip/src/include/netif/slipif.h new file mode 100644 index 000000000..7b6ce5e28 --- /dev/null +++ b/ext/lwip/src/include/netif/slipif.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __NETIF_SLIPIF_H__ +#define __NETIF_SLIPIF_H__ + +#include "lwip/opt.h" +#include "lwip/netif.h" + +/** Set this to 1 to start a thread that blocks reading on the serial line + * (using sio_read()). + */ +#ifndef SLIP_USE_RX_THREAD +#define SLIP_USE_RX_THREAD !NO_SYS +#endif + +/** Set this to 1 to enable functions to pass in RX bytes from ISR context. + * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled + * packets on a queue, which is fed into lwIP from slipif_poll(). + * If disabled, slipif_poll() polls the serila line (using sio_tryread()). + */ +#ifndef SLIP_RX_FROM_ISR +#define SLIP_RX_FROM_ISR 0 +#endif + +/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets + * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. + * If disabled, packets will be dropped if more than one packet is received. + */ +#ifndef SLIP_RX_QUEUE +#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); +#if SLIP_RX_FROM_ISR +void slipif_process_rxqueue(struct netif *netif); +void slipif_received_byte(struct netif *netif, u8_t data); +void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); +#endif /* SLIP_RX_FROM_ISR */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/lwip/src/include/posix/netdb.h b/ext/lwip/src/include/posix/netdb.h new file mode 100644 index 000000000..7134032d2 --- /dev/null +++ b/ext/lwip/src/include/posix/netdb.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/netdb.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/netdb.h" diff --git a/ext/lwip/src/include/posix/sys/socket.h b/ext/lwip/src/include/posix/sys/socket.h new file mode 100644 index 000000000..f7c7066e6 --- /dev/null +++ b/ext/lwip/src/include/posix/sys/socket.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/sockets.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/sockets.h" diff --git a/ext/lwip/src/netif/FILES b/ext/lwip/src/netif/FILES new file mode 100644 index 000000000..099dbf3ec --- /dev/null +++ b/ext/lwip/src/netif/FILES @@ -0,0 +1,29 @@ +This directory contains generic network interface device drivers that +do not contain any hardware or architecture specific code. The files +are: + +etharp.c + Implements the ARP (Address Resolution Protocol) over + Ethernet. The code in this file should be used together with + Ethernet device drivers. Note that this module has been + largely made Ethernet independent so you should be able to + adapt this for other link layers (such as Firewire). + +ethernetif.c + An example of how an Ethernet device driver could look. This + file can be used as a "skeleton" for developing new Ethernet + network device drivers. It uses the etharp.c ARP code. + +loopif.c + A "loopback" network interface driver. It requires configuration + through the define LWIP_LOOPIF_MULTITHREADING (see opt.h). + +slipif.c + A generic implementation of the SLIP (Serial Line IP) + protocol. It requires a sio (serial I/O) module to work. + +ppp/ Point-to-Point Protocol stack + The PPP stack has been ported from ucip (http://ucip.sourceforge.net). + It matches quite well to pppd 2.3.1 (http://ppp.samba.org), although + compared to that, it has some modifications for embedded systems and + the source code has been reordered a bit. \ No newline at end of file diff --git a/ext/lwip/src/netif/etharp.c b/ext/lwip/src/netif/etharp.c new file mode 100644 index 000000000..5e382d1d6 --- /dev/null +++ b/ext/lwip/src/netif/etharp.c @@ -0,0 +1,1399 @@ +/** + * @file + * Address Resolution Protocol module for IP over Ethernet + * + * Functionally, ARP is divided into two parts. The first maps an IP address + * to a physical address when sending a packet, and the second part answers + * requests from other machines for our physical address. + * + * This implementation complies with RFC 826 (Ethernet ARP). It supports + * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 + * if an interface calls etharp_gratuitous(our_netif) upon address change. + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "lwip/ip_addr.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" + +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#endif /* PPPOE_SUPPORT */ + +#include + +const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +const struct eth_addr ethzero = {{0,0,0,0,0,0}}; + +/** The 24-bit IANA multicast OUI is 01-00-5e: */ +#define LL_MULTICAST_ADDR_0 0x01 +#define LL_MULTICAST_ADDR_1 0x00 +#define LL_MULTICAST_ADDR_2 0x5e + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 5000, this is + * (240 * 5) seconds = 20 minutes. + */ +#define ARP_MAXAGE 240 +/** Re-request a used ARP entry 1 minute before it would expire to prevent + * breaking a steadily used connection because the ARP entry timed out. */ +#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 12) + +/** the time an ARP entry stays pending after first request, + * for ARP_TMR_INTERVAL = 5000, this is + * (2 * 5) seconds = 10 seconds. + * + * @internal Keep this number at least 2, otherwise it might + * run out instantly if the timeout occurs directly after a request. + */ +#define ARP_MAXPENDING 2 + +#define HWTYPE_ETHERNET 1 + +enum etharp_state { + ETHARP_STATE_EMPTY = 0, + ETHARP_STATE_PENDING, + ETHARP_STATE_STABLE, + ETHARP_STATE_STABLE_REREQUESTING +#if ETHARP_SUPPORT_STATIC_ENTRIES + ,ETHARP_STATE_STATIC +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ +}; + +struct etharp_entry { +#if ARP_QUEUEING + /** Pointer to queue of pending outgoing packets on this ARP entry. */ + struct etharp_q_entry *q; +#else /* ARP_QUEUEING */ + /** Pointer to a single pending outgoing packet on this ARP entry. */ + struct pbuf *q; +#endif /* ARP_QUEUEING */ + ip_addr_t ipaddr; + struct netif *netif; + struct eth_addr ethaddr; + u8_t state; + u8_t ctime; +}; + +static struct etharp_entry arp_table[ARP_TABLE_SIZE]; + +#if !LWIP_NETIF_HWADDRHINT +static u8_t etharp_cached_entry; +#endif /* !LWIP_NETIF_HWADDRHINT */ + +/** Try hard to create a new entry - we want the IP address to appear in + the cache (even if this means removing an active entry or so). */ +#define ETHARP_FLAG_TRY_HARD 1 +#define ETHARP_FLAG_FIND_ONLY 2 +#if ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_FLAG_STATIC_ENTRY 4 +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_NETIF_HWADDRHINT +#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ + *((netif)->addr_hint) = (hint); +#else /* LWIP_NETIF_HWADDRHINT */ +#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) +#endif /* LWIP_NETIF_HWADDRHINT */ + + +/* Some checks, instead of etharp_init(): */ +#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) + #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" +#endif + + +#if ARP_QUEUEING +/** + * Free a complete queue of etharp entries + * + * @param q a qeueue of etharp_q_entry's to free + */ +static void +free_etharp_q(struct etharp_q_entry *q) +{ + struct etharp_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ARP_QUEUE, r); + } +} +#else /* ARP_QUEUEING */ + +/** Compatibility define: free the queued pbuf */ +#define free_etharp_q(q) pbuf_free(q) + +#endif /* ARP_QUEUEING */ + +/** Clean up ARP table entries */ +static void +etharp_free_entry(int i) +{ + /* remove from SNMP ARP index tree */ + snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; +#ifdef LWIP_DEBUG + /* for debugging, clean out the complete entry */ + arp_table[i].ctime = 0; + arp_table[i].netif = NULL; + ip_addr_set_zero(&arp_table[i].ipaddr); + arp_table[i].ethaddr = ethzero; +#endif /* LWIP_DEBUG */ +} + +/** + * Clears expired entries in the ARP table. + * + * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds), + * in order to expire entries in the ARP table. + */ +void +etharp_tmr(void) +{ + u8_t i; + + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); + /* remove expired entries from the ARP table */ + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if (state != ETHARP_STATE_EMPTY +#if ETHARP_SUPPORT_STATIC_ENTRIES + && (state != ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + ) { + arp_table[i].ctime++; + if ((arp_table[i].ctime >= ARP_MAXAGE) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + etharp_free_entry(i); + } + else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING) { + /* Reset state to stable, so that the next transmitted packet will + re-send an ARP request. */ + arp_table[i].state = ETHARP_STATE_STABLE; + } +#if ARP_QUEUEING + /* still pending entry? (not expired) */ + if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* resend an ARP query here? */ + } +#endif /* ARP_QUEUEING */ + } + } +} + +/** + * Search the ARP table for a matching or new entry. + * + * If an IP address is given, return a pending or stable ARP entry that matches + * the address. If no match is found, create a new entry with this address set, + * but in state ETHARP_EMPTY. The caller must check and possibly change the + * state of the returned entry. + * + * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. + * + * In all cases, attempt to create new entries from an empty entry. If no + * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle + * old entries. Heuristic choose the least important entry for recycling. + * + * @param ipaddr IP address to find in ARP cache, or to add if not found. + * @param flags @see definition of ETHARP_FLAG_* + * @param netif netif related to this address (used for NETIF_HWADDRHINT) + * + * @return The ARP entry index that matched or is created, ERR_MEM if no + * entry is found or could be recycled. + */ +static s8_t +etharp_find_entry(ip_addr_t *ipaddr, u8_t flags) +{ + s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; + s8_t empty = ARP_TABLE_SIZE; + u8_t i = 0, age_pending = 0, age_stable = 0; + /* oldest entry with packets on queue */ + s8_t old_queue = ARP_TABLE_SIZE; + /* its age */ + u8_t age_queue = 0; + + /** + * a) do a search through the cache, remember candidates + * b) select candidate entry + * c) create new entry + */ + + /* a) in a single search sweep, do all of this + * 1) remember the first empty entry (if any) + * 2) remember the oldest stable entry (if any) + * 3) remember the oldest pending entry without queued packets (if any) + * 4) remember the oldest pending entry with queued packets (if any) + * 5) search for a matching IP entry, either pending or stable + * until 5 matches, or all entries are searched for. + */ + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + /* no empty entry found yet and now we do find one? */ + if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); + /* remember first empty entry */ + empty = i; + } else if (state != ETHARP_STATE_EMPTY) { + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); + /* if given, does IP address match IP address in ARP entry? */ + if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); + /* found exact IP address match, simply bail out */ + return i; + } + /* pending entry? */ + if (state == ETHARP_STATE_PENDING) { + /* pending with queued packets? */ + if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } + } else + /* pending without queued packets? */ + { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } + } + /* stable entry? */ + } else if (state >= ETHARP_STATE_STABLE) { +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* don't record old_stable for static entries since they never expire */ + if (state < ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } + } + } + } + } + /* { we have no match } => try to create a new entry */ + + /* don't create new entry, only search? */ + if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || + /* or no empty entry found and not allowed to recycle? */ + ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); + return (s8_t)ERR_MEM; + } + + /* b) choose the least destructive entry to recycle: + * 1) empty entry + * 2) oldest stable entry + * 3) oldest pending entry without queued packets + * 4) oldest pending entry with queued packets + * + * { ETHARP_FLAG_TRY_HARD is set at this point } + */ + + /* 1) empty entry available? */ + if (empty < ARP_TABLE_SIZE) { + i = empty; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); + } else { + /* 2) found recyclable stable entry? */ + if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending (queued packets are free in etharp_free_entry) */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + /* no empty or recyclable entries found */ + } else { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + etharp_free_entry(i); + } + + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", + arp_table[i].state == ETHARP_STATE_EMPTY); + + /* IP address given? */ + if (ipaddr != NULL) { + /* set IP address */ + ip_addr_copy(arp_table[i].ipaddr, *ipaddr); + } + arp_table[i].ctime = 0; + return (err_t)i; +} + +/** + * Send an IP packet on the network using netif->linkoutput + * The ethernet header is filled in before sending. + * + * @params netif the lwIP network interface on which to send the packet + * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header + * @params src the source MAC address to be copied into the ethernet header + * @params dst the destination MAC address to be copied into the ethernet header + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +static err_t +etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) +{ + struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); + ETHADDR32_COPY(ðhdr->dest, dst); + ETHADDR16_COPY(ðhdr->src, src); + ethhdr->type = PP_HTONS(ETHTYPE_IP); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); + /* send the packet */ + return netif->linkoutput(netif, p); +} + +/** + * Update (or insert) a IP/MAC address pair in the ARP cache. + * + * If a pending entry is resolved, any queued packets will be sent + * at this point. + * + * @param netif netif related to this entry (used for NETIF_ADDRHINT) + * @param ipaddr IP address of the inserted ARP entry. + * @param ethaddr Ethernet address of the inserted ARP entry. + * @param flags @see definition of ETHARP_FLAG_* + * + * @return + * - ERR_OK Succesfully updated ARP cache. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + * @see pbuf_free() + */ +static err_t +etharp_update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) +{ + s8_t i; + LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + /* non-unicast address? */ + if (ip_addr_isany(ipaddr) || + ip_addr_isbroadcast(ipaddr, netif) || + ip_addr_ismulticast(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, flags); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + +#if ETHARP_SUPPORT_STATIC_ENTRIES + if (flags & ETHARP_FLAG_STATIC_ENTRY) { + /* record static type */ + arp_table[i].state = ETHARP_STATE_STATIC; + } else +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* mark it stable */ + arp_table[i].state = ETHARP_STATE_STABLE; + } + + /* record network interface */ + arp_table[i].netif = netif; + /* insert in SNMP ARP index tree */ + snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); + /* update address */ + ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); + /* reset time stamp */ + arp_table[i].ctime = 0; + /* this is where we will send out queued packets! */ +#if ARP_QUEUEING + while (arp_table[i].q != NULL) { + struct pbuf *p; + /* remember remainder of queue */ + struct etharp_q_entry *q = arp_table[i].q; + /* pop first item off the queue */ + arp_table[i].q = q->next; + /* get the packet pointer */ + p = q->p; + /* now queue entry can be freed */ + memp_free(MEMP_ARP_QUEUE, q); +#else /* ARP_QUEUEING */ + if (arp_table[i].q != NULL) { + struct pbuf *p = arp_table[i].q; + arp_table[i].q = NULL; +#endif /* ARP_QUEUEING */ + /* send the queued IP packet */ + etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); + /* free the queued IP packet */ + pbuf_free(p); + } + return ERR_OK; +} + +#if ETHARP_SUPPORT_STATIC_ENTRIES +/** Add a new static entry to the ARP table. If an entry exists for the + * specified IP address, this entry is overwritten. + * If packets are queued for the specified IP address, they are sent out. + * + * @param ipaddr IP address for the new static entry + * @param ethaddr ethernet address for the new static entry + * @return @see return values of etharp_add_static_entry + */ +err_t +etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) +{ + struct netif *netif; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + + netif = ip_route(ipaddr); + if (netif == NULL) { + return ERR_RTE; + } + + return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); +} + +/** Remove a static entry from the ARP table previously added with a call to + * etharp_add_static_entry. + * + * @param ipaddr IP address of the static entry to remove + * @return ERR_OK: entry removed + * ERR_MEM: entry wasn't found + * ERR_ARG: entry wasn't a static entry but a dynamic one + */ +err_t +etharp_remove_static_entry(ip_addr_t *ipaddr) +{ + s8_t i; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + + if (arp_table[i].state != ETHARP_STATE_STATIC) { + /* entry wasn't a static entry, cannot remove it */ + return ERR_ARG; + } + /* entry found, free it */ + etharp_free_entry(i); + return ERR_OK; +} +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +/** + * Remove all ARP table entries of the specified netif. + * + * @param netif points to a network interface + */ +void etharp_cleanup_netif(struct netif *netif) +{ + u8_t i; + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { + etharp_free_entry(i); + } + } +} + +/** + * Finds (stable) ethernet/IP address pair from ARP table + * using interface and IP address index. + * @note the addresses in the ARP table are in network order! + * + * @param netif points to interface index + * @param ipaddr points to the (network order) IP address index + * @param eth_ret points to return pointer + * @param ip_ret points to return pointer + * @return table index if found, -1 otherwise + */ +s8_t +etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, + struct eth_addr **eth_ret, ip_addr_t **ip_ret) +{ + s8_t i; + + LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", + eth_ret != NULL && ip_ret != NULL); + + LWIP_UNUSED_ARG(netif); + + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); + if((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *eth_ret = &arp_table[i].ethaddr; + *ip_ret = &arp_table[i].ipaddr; + return i; + } + return -1; +} + +#if ETHARP_TRUST_IP_MAC +/** + * Updates the ARP table using the given IP packet. + * + * Uses the incoming IP packet's source address to update the + * ARP cache for the local network. The function does not alter + * or free the packet. This function must be called before the + * packet p is passed to the IP layer. + * + * @param netif The lwIP network interface on which the IP packet pbuf arrived. + * @param p The IP packet that arrived on netif. + * + * @return NULL + * + * @see pbuf_free() + */ +static void +etharp_ip_input(struct netif *netif, struct pbuf *p) +{ + struct eth_hdr *ethhdr; + struct ip_hdr *iphdr; + ip_addr_t iphdr_src; + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* Only insert an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + ethhdr = (struct eth_hdr *)p->payload; + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + ip_addr_copy(iphdr_src, iphdr->src); + + /* source is not on the local network? */ + if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) { + /* do nothing */ + return; + } + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); + /* update the source IP address in the cache, if present */ + /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk + * back soon (for example, if the destination IP address is ours. */ + etharp_update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY); +} +#endif /* ETHARP_TRUST_IP_MAC */ + +/** + * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache + * send out queued IP packets. Updates cache with snooped address pairs. + * + * Should be called for incoming ARP packets. The pbuf in the argument + * is freed by this function. + * + * @param netif The lwIP network interface on which the ARP packet pbuf arrived. + * @param ethaddr Ethernet address of netif. + * @param p The ARP packet that arrived on netif. Is freed by this function. + * + * @return NULL + * + * @see pbuf_free() + */ +static void +etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) +{ + struct etharp_hdr *hdr; + struct eth_hdr *ethhdr; + /* these are aligned properly, whereas the ARP header fields might not be */ + ip_addr_t sipaddr, dipaddr; + u8_t for_us; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* drop short ARP packets: we have to check for p->len instead of p->tot_len here + since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ + if (p->len < SIZEOF_ETHARP_PACKET) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, + (s16_t)SIZEOF_ETHARP_PACKET)); + ETHARP_STATS_INC(etharp.lenerr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + + ethhdr = (struct eth_hdr *)p->payload; + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { + hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + /* RFC 826 "Packet Reception": */ + if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || + (hdr->hwlen != ETHARP_HWADDR_LEN) || + (hdr->protolen != sizeof(ip_addr_t)) || + (hdr->proto != PP_HTONS(ETHTYPE_IP))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen)); + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + ETHARP_STATS_INC(etharp.recv); + +#if LWIP_AUTOIP + /* We have to check if a host already has configured our random + * created link local address and continously check if there is + * a host with this IP-address so we can detect collisions */ + autoip_arp_reply(netif, hdr); +#endif /* LWIP_AUTOIP */ + + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + /* this interface is not configured? */ + if (ip_addr_isany(&netif->ip_addr)) { + for_us = 0; + } else { + /* ARP packet directed to us? */ + for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr)); + } + + /* ARP message directed to us? + -> add IP address in ARP cache; assume requester wants to talk to us, + can result in directly sending the queued packets for this host. + ARP message not directed to us? + -> update the source IP address in the cache, if present */ + etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), + for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); + + /* now act on the message itself */ + switch (hdr->opcode) { + /* ARP request? */ + case PP_HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + * reply. In any case, we time-stamp any existing ARP entry, + * and possiby send out an IP packet that was queued on it. */ + + LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); + /* ARP request for our address? */ + if (for_us) { + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); + /* Re-use pbuf to send ARP reply. + Since we are re-using an existing pbuf, we can't call etharp_raw since + that would allocate a new pbuf. */ + hdr->opcode = htons(ARP_REPLY); + + IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr); + IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; +#endif /* LWIP_AUTOIP */ + + ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr); +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, &hdr->shwaddr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(&hdr->shwaddr, ethaddr); + ETHADDR16_COPY(ðhdr->src, ethaddr); + + /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header + are already correct, we tested that before */ + + /* return ARP reply */ + netif->linkoutput(netif, p); + /* we are not configured? */ + } else if (ip_addr_isany(&netif->ip_addr)) { + /* { for_us == 0 and netif->ip_addr.addr == 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); + /* request was not directed to us */ + } else { + /* { for_us == 0 and netif->ip_addr.addr != 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n")); + } + break; + case PP_HTONS(ARP_REPLY): + /* ARP reply. We already updated the ARP cache earlier. */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); +#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) + /* DHCP wants to know about ARP replies from any host with an + * IP address also offered to us by the DHCP server. We do not + * want to take a duplicate IP address on a single network. + * @todo How should we handle redundant (fail-over) interfaces? */ + dhcp_arp_reply(netif, &sipaddr); +#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ + break; + default: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); + ETHARP_STATS_INC(etharp.err); + break; + } + /* free ARP packet */ + pbuf_free(p); +} + +/** Just a small helper function that sends a pbuf to an ethernet address + * in the arp_table specified by the index 'arp_idx'. + */ +static err_t +etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) +{ + LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", + arp_table[arp_idx].state >= ETHARP_STATE_STABLE); + /* if arp table entry is about to expire: re-request it, + but only if its state is ETHARP_STATE_STABLE to prevent flooding the + network with ARP requests if this address is used frequently. */ + if ((arp_table[arp_idx].state == ETHARP_STATE_STABLE) && + (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED)) { + if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING; + } + } + + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), + &arp_table[arp_idx].ethaddr); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IP packet. + * + * For IP multicast and broadcast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, the packet is submitted to etharp_query(). In + * case the IP address is outside the local network, the IP address of + * the gateway is used. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ipaddr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or etharp_send_ip(). + */ +err_t +etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) +{ + struct eth_addr *dest; + struct eth_addr mcastaddr; + ip_addr_t *dst_addr = ipaddr; + + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { + /* bail out */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_output: could not allocate room for header.\n")); + LINK_STATS_INC(link.lenerr); + return ERR_BUF; + } + + /* Determine on destination hardware address. Broadcasts and multicasts + * are special, other IP addresses are looked up in the ARP table. */ + + /* broadcast destination IP address? */ + if (ip_addr_isbroadcast(ipaddr, netif)) { + /* broadcast on Ethernet also */ + dest = (struct eth_addr *)ðbroadcast; + /* multicast destination IP address? */ + } else if (ip_addr_ismulticast(ipaddr)) { + /* Hash IP multicast address to MAC address.*/ + mcastaddr.addr[0] = LL_MULTICAST_ADDR_0; + mcastaddr.addr[1] = LL_MULTICAST_ADDR_1; + mcastaddr.addr[2] = LL_MULTICAST_ADDR_2; + mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; + mcastaddr.addr[4] = ip4_addr3(ipaddr); + mcastaddr.addr[5] = ip4_addr4(ipaddr); + /* destination Ethernet address is multicast */ + dest = &mcastaddr; + /* unicast destination IP address? */ + } else { + s8_t i; + /* outside local network? if so, this can neither be a global broadcast nor + a subnet broadcast. */ + if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) && + !ip_addr_islinklocal(ipaddr)) { +#if LWIP_AUTOIP + struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload + + sizeof(struct eth_hdr)); + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!ip_addr_islinklocal(&iphdr->src)) +#endif /* LWIP_AUTOIP */ + { + /* interface has default gateway? */ + if (!ip_addr_isany(&netif->gw)) { + /* send to hardware address of default gateway IP address */ + dst_addr = &(netif->gw); + /* no default gateway available */ + } else { + /* no route to destination error (default gateway missing) */ + return ERR_RTE; + } + } + } +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t etharp_cached_entry = *(netif->addr_hint); + if (etharp_cached_entry < ARP_TABLE_SIZE) { +#endif /* LWIP_NETIF_HWADDRHINT */ + if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && + (ip_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { + /* the per-pcb-cached entry is stable and the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return etharp_output_to_arp_index(netif, q, etharp_cached_entry); + } +#if LWIP_NETIF_HWADDRHINT + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* find stable entry: do this here since this is a critical path for + throughput and etharp_find_entry() is kind of slow */ + for (i = 0; i < ARP_TABLE_SIZE; i++) { + if ((arp_table[i].state >= ETHARP_STATE_STABLE) && + (ip_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { + /* found an existing, stable entry */ + ETHARP_SET_HINT(netif, i); + return etharp_output_to_arp_index(netif, q, i); + } + } + /* no stable entry found, use the (slower) query function: + queue on destination Ethernet address belonging to ipaddr */ + return etharp_query(netif, dst_addr, q); + } + + /* continuation for multicast/broadcast destinations */ + /* obtain source Ethernet address of the given interface */ + /* send packet directly on the link */ + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest); +} + +/** + * Send an ARP request for the given IP address and/or queue a packet. + * + * If the IP address was not yet in the cache, a pending ARP cache entry + * is added and an ARP request is sent for the given address. The packet + * is queued on this entry. + * + * If the IP address was already pending in the cache, a new ARP request + * is sent for the given address. The packet is queued on this entry. + * + * If the IP address was already stable in the cache, and a packet is + * given, it is directly sent and no ARP request is sent out. + * + * If the IP address was already stable in the cache, and no packet is + * given, an ARP request is sent out. + * + * @param netif The lwIP network interface on which ipaddr + * must be queried for. + * @param ipaddr The IP address to be resolved. + * @param q If non-NULL, a pbuf that must be delivered to the IP address. + * q is not freed by this function. + * + * @note q must only be ONE packet, not a packet queue! + * + * @return + * - ERR_BUF Could not make room for Ethernet header. + * - ERR_MEM Hardware address unknown, and no more ARP entries available + * to query for address or queue the packet. + * - ERR_MEM Could not queue packet due to memory shortage. + * - ERR_RTE No route to destination (no gateway to external networks). + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + */ +err_t +etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) +{ + struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; + err_t result = ERR_MEM; + s8_t i; /* ARP entry index */ + + /* non-unicast address? */ + if (ip_addr_isbroadcast(ipaddr, netif) || + ip_addr_ismulticast(ipaddr) || + ip_addr_isany(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + + /* find entry in ARP cache, ask to create entry if queueing packet */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD); + + /* could not find or create entry? */ + if (i < 0) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); + if (q) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); + ETHARP_STATS_INC(etharp.memerr); + } + return (err_t)i; + } + + /* mark a fresh entry as pending (we just sent a request) */ + if (arp_table[i].state == ETHARP_STATE_EMPTY) { + arp_table[i].state = ETHARP_STATE_PENDING; + } + + /* { i is either a STABLE or (new or existing) PENDING entry } */ + LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", + ((arp_table[i].state == ETHARP_STATE_PENDING) || + (arp_table[i].state >= ETHARP_STATE_STABLE))); + + /* do we have a pending entry? or an implicit query request? */ + if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { + /* try to resolve it; send out ARP request */ + result = etharp_request(netif, ipaddr); + if (result != ERR_OK) { + /* ARP request couldn't be sent */ + /* We don't re-send arp request in etharp_tmr, but we still queue packets, + since this failure could be temporary, and the next packet calling + etharp_query again could lead to sending the queued packets. */ + } + if (q == NULL) { + return result; + } + } + + /* packet given? */ + LWIP_ASSERT("q != NULL", q != NULL); + /* stable entry? */ + if (arp_table[i].state >= ETHARP_STATE_STABLE) { + /* we have a valid IP->Ethernet address mapping */ + ETHARP_SET_HINT(netif, i); + /* send the packet */ + result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); + /* pending entry? (either just created or already pending */ + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* entry is still pending, queue the given packet 'q' */ + struct pbuf *p; + int copy_needed = 0; + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + if(p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if(copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet could be taken over? */ + if (p != NULL) { + /* queue packet ... */ +#if ARP_QUEUEING + struct etharp_q_entry *new_entry; + /* allocate a new arp queue entry */ + new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); + if (new_entry != NULL) { + new_entry->next = 0; + new_entry->p = p; + if(arp_table[i].q != NULL) { + /* queue was already existent, append the new entry to the end */ + struct etharp_q_entry *r; + r = arp_table[i].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + arp_table[i].q = new_entry; + } + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + result = ERR_OK; + } else { + /* the pool MEMP_ARP_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } +#else /* ARP_QUEUEING */ + /* always queue one packet per ARP request only, freeing a previously queued packet */ + if (arp_table[i].q != NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + pbuf_free(arp_table[i].q); + } + arp_table[i].q = p; + result = ERR_OK; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); +#endif /* ARP_QUEUEING */ + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } + } + return result; +} + +/** + * Send a raw ARP packet (opcode and all addresses can be modified) + * + * @param netif the lwip network interface on which to send the ARP packet + * @param ethsrc_addr the source MAC address for the ethernet header + * @param ethdst_addr the destination MAC address for the ethernet header + * @param hwsrc_addr the source MAC address for the ARP protocol header + * @param ipsrc_addr the source IP address for the ARP protocol header + * @param hwdst_addr the destination MAC address for the ARP protocol header + * @param ipdst_addr the destination IP address for the ARP protocol header + * @param opcode the type of the ARP packet + * @return ERR_OK if the ARP packet has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +#if !LWIP_AUTOIP +static +#endif /* LWIP_AUTOIP */ +err_t +etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, + const u16_t opcode) +{ + struct pbuf *p; + err_t result = ERR_OK; + struct eth_hdr *ethhdr; + struct etharp_hdr *hdr; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ASSERT("netif != NULL", netif != NULL); + + /* allocate a pbuf for the outgoing ARP request packet */ + p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM); + /* could allocate a pbuf for an ARP request? */ + if (p == NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_raw: could not allocate pbuf for ARP request.\n")); + ETHARP_STATS_INC(etharp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", + (p->len >= SIZEOF_ETHARP_PACKET)); + + ethhdr = (struct eth_hdr *)p->payload; + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); + hdr->opcode = htons(opcode); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; +#endif /* LWIP_AUTOIP */ + /* Write the ARP MAC-Addresses */ + ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); + ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); + /* Write the Ethernet MAC-Addresses */ +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, ethdst_addr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->src, ethsrc_addr); + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing. */ + IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); + IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); + + hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); + hdr->proto = PP_HTONS(ETHTYPE_IP); + /* set hwlen and protolen */ + hdr->hwlen = ETHARP_HWADDR_LEN; + hdr->protolen = sizeof(ip_addr_t); + + ethhdr->type = PP_HTONS(ETHTYPE_ARP); + /* send ARP query */ + result = netif->linkoutput(netif, p); + ETHARP_STATS_INC(etharp.xmit); + /* free ARP query packet */ + pbuf_free(p); + p = NULL; + /* could not allocate pbuf for ARP request */ + + return result; +} + +/** + * Send an ARP request packet asking for ipaddr. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +err_t +etharp_request(struct netif *netif, ip_addr_t *ipaddr) +{ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero, + ipaddr, ARP_REQUEST); +} +#endif /* LWIP_ARP */ + +/** + * Process received ethernet frames. Using this function instead of directly + * calling ip_input and passing ARP frames through etharp in ethernetif_input, + * the ARP cache is protected from concurrent access. + * + * @param p the recevied packet, p->payload pointing to the ethernet header + * @param netif the network interface on which the packet was received + */ +err_t +ethernet_input(struct pbuf *p, struct netif *netif) +{ + struct eth_hdr* ethhdr; + u16_t type; +#if LWIP_ARP || ETHARP_SUPPORT_VLAN + s16_t ip_hdr_offset = SIZEOF_ETH_HDR; +#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ + + if (p->len <= SIZEOF_ETH_HDR) { + /* a packet with only an ethernet header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = (struct eth_hdr *)p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", + (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], + (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], + (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], + (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], + (unsigned)htons(ethhdr->type))); + + type = ethhdr->type; +#if ETHARP_SUPPORT_VLAN + if (type == PP_HTONS(ETHTYPE_VLAN)) { + struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); + if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { + /* a packet with only an ethernet/vlan header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } +#if defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ +#ifdef ETHARP_VLAN_CHECK_FN + if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK) + if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { +#endif + /* silently ignore this packet: not for our VLAN */ + pbuf_free(p); + return ERR_OK; + } +#endif /* defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ + type = vlan->tpid; + ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; + } +#endif /* ETHARP_SUPPORT_VLAN */ + +#if LWIP_ARP_FILTER_NETIF + netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); +#endif /* LWIP_ARP_FILTER_NETIF*/ + + if (ethhdr->dest.addr[0] & 1) { + /* this might be a multicast or broadcast packet */ + if (ethhdr->dest.addr[0] == LL_MULTICAST_ADDR_0) { + if ((ethhdr->dest.addr[1] == LL_MULTICAST_ADDR_1) && + (ethhdr->dest.addr[2] == LL_MULTICAST_ADDR_2)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } + } else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { + /* mark the pbuf as link-layer broadcast */ + p->flags |= PBUF_FLAG_LLBCAST; + } + } + + switch (type) { +#if LWIP_ARP + /* IP packet? */ + case PP_HTONS(ETHTYPE_IP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } +#if ETHARP_TRUST_IP_MAC + /* update ARP table */ + etharp_ip_input(netif, p); +#endif /* ETHARP_TRUST_IP_MAC */ + /* skip Ethernet header */ + if(pbuf_header(p, -ip_hdr_offset)) { + LWIP_ASSERT("Can't move over header in packet", 0); + goto free_and_return; + } else { + /* pass to IP layer */ + ip_input(p, netif); + } + break; + + case PP_HTONS(ETHTYPE_ARP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } + /* pass p to ARP module */ + etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); + break; +#endif /* LWIP_ARP */ +#if PPPOE_SUPPORT + case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ + pppoe_disc_input(netif, p); + break; + + case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ + pppoe_data_input(netif, p); + break; +#endif /* PPPOE_SUPPORT */ + + default: + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } + + /* This means the pbuf is freed or consumed, + so the caller doesn't have to free it again */ + return ERR_OK; + +free_and_return: + pbuf_free(p); + return ERR_OK; +} +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/ext/lwip/src/netif/ethernetif.c b/ext/lwip/src/netif/ethernetif.c new file mode 100644 index 000000000..27060e39b --- /dev/null +++ b/ext/lwip/src/netif/ethernetif.c @@ -0,0 +1,317 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include "lwip/opt.h" + +#if 0 /* don't build, this is only a skeleton, see previous comment */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include +#include +#include "netif/etharp.h" +#include "netif/ppp_oe.h" + +/* Define those to better describe your network interface. */ +#define IFNAME0 'e' +#define IFNAME1 'n' + +/** + * Helper struct to hold private data used to operate your ethernet interface. + * Keeping the ethernet address of the MAC in this struct is not necessary + * as it is already kept in the struct netif. + * But this is only an example, anyway... + */ +struct ethernetif { + struct eth_addr *ethaddr; + /* Add whatever per-interface state that is needed here. */ +}; + +/* Forward declarations. */ +static void ethernetif_input(struct netif *netif); + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void +low_level_init(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = ; + ... + netif->hwaddr[5] = ; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + /* Do whatever else is needed to initialize interface. */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t +low_level_output(struct netif *netif, struct pbuf *p) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *q; + + initiate transfer(); + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + for(q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + send data from(q->payload, q->len); + } + + signal that packet should be sent(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * +low_level_input(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *p, *q; + u16_t len; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + len = ; + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) { + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for(q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + read data into(q->payload, q->len); + } + acknowledge that packet has been read(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } else { + drop packet(); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +static void +ethernetif_input(struct netif *netif) +{ + struct ethernetif *ethernetif; + struct eth_hdr *ethhdr; + struct pbuf *p; + + ethernetif = netif->state; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + /* no packet could be read, silently ignore this */ + if (p == NULL) return; + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: +#if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif)!=ERR_OK) + { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + break; + + default: + pbuf_free(p); + p = NULL; + break; + } +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t +ethernetif_init(struct netif *netif) +{ + struct ethernetif *ethernetif; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + ethernetif = mem_malloc(sizeof(struct ethernetif)); + if (ethernetif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); + return ERR_MEM; + } + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + netif->state = ethernetif; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +#endif /* 0 */ diff --git a/ext/lwip/src/netif/ppp/auth.c b/ext/lwip/src/netif/ppp/auth.c new file mode 100644 index 000000000..0fd87a379 --- /dev/null +++ b/ext/lwip/src/netif/ppp/auth.c @@ -0,0 +1,1334 @@ +/***************************************************************************** +* auth.c - Network Authentication and Phase Control program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Ported from public pppd code. +*****************************************************************************/ +/* + * auth.c - PPP authentication and phase control. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "fsm.h" +#include "lcp.h" +#include "pap.h" +#include "chap.h" +#include "auth.h" +#include "ipcp.h" + +#if CBCP_SUPPORT +#include "cbcp.h" +#endif /* CBCP_SUPPORT */ + +#include "lwip/inet.h" + +#include + +#if 0 /* UNUSED */ +/* Bits in scan_authfile return value */ +#define NONWILD_SERVER 1 +#define NONWILD_CLIENT 2 + +#define ISWILD(word) (word[0] == '*' && word[1] == 0) +#endif /* UNUSED */ + +#if PAP_SUPPORT || CHAP_SUPPORT +/* The name by which the peer authenticated itself to us. */ +static char peer_authname[MAXNAMELEN]; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + +/* Records which authentication operations haven't completed yet. */ +static int auth_pending[NUM_PPP]; + +/* Set if we have successfully called plogin() */ +static int logged_in; + +/* Set if we have run the /etc/ppp/auth-up script. */ +static int did_authup; /* @todo, we don't need this in lwip*/ + +/* List of addresses which the peer may use. */ +static struct wordlist *addresses[NUM_PPP]; + +#if 0 /* UNUSED */ +/* Wordlist giving addresses which the peer may use + without authenticating itself. */ +static struct wordlist *noauth_addrs; + +/* Extra options to apply, from the secrets file entry for the peer. */ +static struct wordlist *extra_options; +#endif /* UNUSED */ + +/* Number of network protocols which we have opened. */ +static int num_np_open; + +/* Number of network protocols which have come up. */ +static int num_np_up; + +#if PAP_SUPPORT || CHAP_SUPPORT +/* Set if we got the contents of passwd[] from the pap-secrets file. */ +static int passwd_from_file; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* Set if we require authentication only because we have a default route. */ +static bool default_auth; + +/* Hook to enable a plugin to control the idle time limit */ +int (*idle_time_hook) __P((struct ppp_idle *)) = NULL; + +/* Hook for a plugin to say whether we can possibly authenticate any peer */ +int (*pap_check_hook) __P((void)) = NULL; + +/* Hook for a plugin to check the PAP user and password */ +int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts)) = NULL; + +/* Hook for a plugin to know about the PAP user logout */ +void (*pap_logout_hook) __P((void)) = NULL; + +/* Hook for a plugin to get the PAP password for authenticating us */ +int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; + +/* + * This is used to ensure that we don't start an auth-up/down + * script while one is already running. + */ +enum script_state { + s_down, + s_up +}; + +static enum script_state auth_state = s_down; +static enum script_state auth_script_state = s_down; +static pid_t auth_script_pid = 0; + +/* + * Option variables. + * lwip: some of these are present in the ppp_settings structure + */ +bool uselogin = 0; /* Use /etc/passwd for checking PAP */ +bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ +bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ +bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +bool usehostname = 0; /* Use hostname for our_name */ +bool auth_required = 0; /* Always require authentication from peer */ +bool allow_any_ip = 0; /* Allow peer to use any IP address */ +bool explicit_remote = 0; /* User specified explicit remote name */ +char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ + +#endif /* UNUSED */ + +/* Bits in auth_pending[] */ +#define PAP_WITHPEER 1 +#define PAP_PEER 2 +#define CHAP_WITHPEER 4 +#define CHAP_PEER 8 + +/* @todo, move this somewhere */ +/* Used for storing a sequence of words. Usually malloced. */ +struct wordlist { + struct wordlist *next; + char word[1]; +}; + + +extern char *crypt (const char *, const char *); + +/* Prototypes for procedures local to this file. */ + +static void network_phase (int); +static void check_idle (void *); +static void connect_time_expired (void *); +#if 0 +static int plogin (char *, char *, char **, int *); +#endif +static void plogout (void); +static int null_login (int); +static int get_pap_passwd (int, char *, char *); +static int have_pap_secret (void); +static int have_chap_secret (char *, char *, u32_t); +static int ip_addr_check (u32_t, struct wordlist *); + +#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +static int scan_authfile (FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, + char *); +static void free_wordlist (struct wordlist *); +static void auth_script (char *); +static void auth_script_done (void *); +static void set_allowed_addrs (int unit, struct wordlist *addrs); +static int some_ip_ok (struct wordlist *); +static int setupapfile (char **); +static int privgroup (char **); +static int set_noauth_addr (char **); +static void check_access (FILE *, char *); +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * Authentication-related options. + */ +option_t auth_options[] = { + { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", 1, &auth_required }, + { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", 1, &auth_required }, + { "refuse-pap", o_bool, &refuse_pap, + "Don't agree to auth to peer with PAP", 1 }, + { "-pap", o_bool, &refuse_pap, + "Don't allow PAP authentication with peer", 1 }, + { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", 1, &auth_required }, + { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", 1, &auth_required }, + { "refuse-chap", o_bool, &refuse_chap, + "Don't agree to auth to peer with CHAP", 1 }, + { "-chap", o_bool, &refuse_chap, + "Don't allow CHAP authentication with peer", 1 }, + { "name", o_string, our_name, + "Set local name for authentication", + OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN }, + { "user", o_string, user, + "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN }, + { "usehostname", o_bool, &usehostname, + "Must use hostname for authentication", 1 }, + { "remotename", o_string, remote_name, + "Set remote name for authentication", OPT_STATIC, + &explicit_remote, MAXNAMELEN }, + { "auth", o_bool, &auth_required, + "Require authentication from peer", 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip }, + { "login", o_bool, &uselogin, + "Use system password database for PAP", 1 }, + { "papcrypt", o_bool, &cryptpap, + "PAP passwords are encrypted", 1 }, + { "+ua", o_special, (void *)setupapfile, + "Get PAP user and password from file" }, + { "password", o_string, passwd, + "Password for authenticating us to the peer", OPT_STATIC, + NULL, MAXSECRETLEN }, + { "privgroup", o_special, (void *)privgroup, + "Allow group members to use privileged options", OPT_PRIV }, + { "allow-ip", o_special, (void *)set_noauth_addr, + "Set IP address(es) which can be used without authentication", + OPT_PRIV }, + { NULL } +}; +#endif /* UNUSED */ +#if 0 /* UNUSED */ +/* + * setupapfile - specifies UPAP info for authenticating with peer. + */ +static int +setupapfile(char **argv) +{ + FILE * ufile; + int l; + + lcp_allowoptions[0].neg_upap = 1; + + /* open user info file */ + seteuid(getuid()); + ufile = fopen(*argv, "r"); + seteuid(0); + if (ufile == NULL) { + option_error("unable to open user login data file %s", *argv); + return 0; + } + check_access(ufile, *argv); + + /* get username */ + if (fgets(user, MAXNAMELEN - 1, ufile) == NULL + || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ + option_error("unable to read user login data file %s", *argv); + return 0; + } + fclose(ufile); + + /* get rid of newlines */ + l = strlen(user); + if (l > 0 && user[l-1] == '\n') + user[l-1] = 0; + l = strlen(passwd); + if (l > 0 && passwd[l-1] == '\n') + passwd[l-1] = 0; + + return (1); +} +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* + * privgroup - allow members of the group to have privileged access. + */ +static int +privgroup(char **argv) +{ + struct group *g; + int i; + + g = getgrnam(*argv); + if (g == 0) { + option_error("group %s is unknown", *argv); + return 0; + } + for (i = 0; i < ngroups; ++i) { + if (groups[i] == g->gr_gid) { + privileged = 1; + break; + } + } + return 1; +} +#endif + +#if 0 /* UNUSED */ +/* + * set_noauth_addr - set address(es) that can be used without authentication. + * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. + */ +static int +set_noauth_addr(char **argv) +{ + char *addr = *argv; + int l = strlen(addr); + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l + 1); + if (wp == NULL) + novm("allow-ip argument"); + wp->word = (char *) (wp + 1); + wp->next = noauth_addrs; + BCOPY(addr, wp->word, l); + noauth_addrs = wp; + return 1; +} +#endif /* UNUSED */ + +/* + * An Open on LCP has requested a change from Dead to Establish phase. + * Do what's necessary to bring the physical layer up. + */ +void +link_required(int unit) +{ + LWIP_UNUSED_ARG(unit); + + AUTHDEBUG(LOG_INFO, ("link_required: %d\n", unit)); +} + +/* + * LCP has terminated the link; go to the Dead phase and take the + * physical layer down. + */ +void +link_terminated(int unit) +{ + AUTHDEBUG(LOG_INFO, ("link_terminated: %d\n", unit)); + if (lcp_phase[unit] == PHASE_DEAD) { + return; + } + if (logged_in) { + plogout(); + } + lcp_phase[unit] = PHASE_DEAD; + AUTHDEBUG(LOG_NOTICE, ("Connection terminated.\n")); + pppLinkTerminated(unit); +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void +link_down(int unit) +{ + int i; + struct protent *protp; + + AUTHDEBUG(LOG_INFO, ("link_down: %d\n", unit)); + + if (did_authup) { + /* XXX Do link down processing. */ + did_authup = 0; + } + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (!protp->enabled_flag) { + continue; + } + if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) { + (*protp->lowerdown)(unit); + } + if (protp->protocol < 0xC000 && protp->close != NULL) { + (*protp->close)(unit, "LCP down"); + } + } + num_np_open = 0; /* number of network protocols we have opened */ + num_np_up = 0; /* Number of network protocols which have come up */ + + if (lcp_phase[unit] != PHASE_DEAD) { + lcp_phase[unit] = PHASE_TERMINATE; + } + pppLinkDown(unit); +} + +/* + * The link is established. + * Proceed to the Dead, Authenticate or Network phase as appropriate. + */ +void +link_established(int unit) +{ + int auth; + int i; + struct protent *protp; + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *go = &lcp_gotoptions[unit]; +#if PAP_SUPPORT || CHAP_SUPPORT + lcp_options *ho = &lcp_hisoptions[unit]; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + + AUTHDEBUG(LOG_INFO, ("link_established: unit %d; Lowering up all protocols...\n", unit)); + /* + * Tell higher-level protocols that LCP is up. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol != PPP_LCP && protp->enabled_flag && protp->lowerup != NULL) { + (*protp->lowerup)(unit); + } + } + if (ppp_settings.auth_required && !(go->neg_chap || go->neg_upap)) { + /* + * We wanted the peer to authenticate itself, and it refused: + * treat it as though it authenticated with PAP using a username + * of "" and a password of "". If that's not OK, boot it out. + */ + if (!wo->neg_upap || !null_login(unit)) { + AUTHDEBUG(LOG_WARNING, ("peer refused to authenticate\n")); + lcp_close(unit, "peer refused to authenticate"); + return; + } + } + + lcp_phase[unit] = PHASE_AUTHENTICATE; + auth = 0; +#if CHAP_SUPPORT + if (go->neg_chap) { + ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype); + auth |= CHAP_PEER; + } +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT && CHAP_SUPPORT + else +#endif /* PAP_SUPPORT && CHAP_SUPPORT */ +#if PAP_SUPPORT + if (go->neg_upap) { + upap_authpeer(unit); + auth |= PAP_PEER; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (ho->neg_chap) { + ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype); + auth |= CHAP_WITHPEER; + } +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT && CHAP_SUPPORT + else +#endif /* PAP_SUPPORT && CHAP_SUPPORT */ +#if PAP_SUPPORT + if (ho->neg_upap) { + if (ppp_settings.passwd[0] == 0) { + passwd_from_file = 1; + if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) { + AUTHDEBUG(LOG_ERR, ("No secret found for PAP login\n")); + } + } + upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd); + auth |= PAP_WITHPEER; + } +#endif /* PAP_SUPPORT */ + auth_pending[unit] = auth; + + if (!auth) { + network_phase(unit); + } +} + +/* + * Proceed to the network phase. + */ +static void +network_phase(int unit) +{ + int i; + struct protent *protp; + lcp_options *go = &lcp_gotoptions[unit]; + + /* + * If the peer had to authenticate, run the auth-up script now. + */ + if ((go->neg_chap || go->neg_upap) && !did_authup) { + /* XXX Do setup for peer authentication. */ + did_authup = 1; + } + +#if CBCP_SUPPORT + /* + * If we negotiated callback, do it now. + */ + if (go->neg_cbcp) { + lcp_phase[unit] = PHASE_CALLBACK; + (*cbcp_protent.open)(unit); + return; + } +#endif /* CBCP_SUPPORT */ + + lcp_phase[unit] = PHASE_NETWORK; + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { + (*protp->open)(unit); + if (protp->protocol != PPP_CCP) { + ++num_np_open; + } + } + } + + if (num_np_open == 0) { + /* nothing to do */ + lcp_close(0, "No network protocols running"); + } +} +/* @todo: add void start_networks(void) here (pppd 2.3.11) */ + +/* + * The peer has failed to authenticate himself using `protocol'. + */ +void +auth_peer_fail(int unit, u16_t protocol) +{ + LWIP_UNUSED_ARG(protocol); + + AUTHDEBUG(LOG_INFO, ("auth_peer_fail: %d proto=%X\n", unit, protocol)); + /* + * Authentication failure: take the link down + */ + lcp_close(unit, "Authentication failed"); +} + + +#if PAP_SUPPORT || CHAP_SUPPORT +/* + * The peer has been successfully authenticated using `protocol'. + */ +void +auth_peer_success(int unit, u16_t protocol, char *name, int namelen) +{ + int pbit; + + AUTHDEBUG(LOG_INFO, ("auth_peer_success: %d proto=%X\n", unit, protocol)); + switch (protocol) { + case PPP_CHAP: + pbit = CHAP_PEER; + break; + case PPP_PAP: + pbit = PAP_PEER; + break; + default: + AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); + return; + } + + /* + * Save the authenticated name of the peer for later. + */ + if (namelen > (int)sizeof(peer_authname) - 1) { + namelen = sizeof(peer_authname) - 1; + } + BCOPY(name, peer_authname, namelen); + peer_authname[namelen] = 0; + + /* + * If there is no more authentication still to be done, + * proceed to the network (or callback) phase. + */ + if ((auth_pending[unit] &= ~pbit) == 0) { + network_phase(unit); + } +} + +/* + * We have failed to authenticate ourselves to the peer using `protocol'. + */ +void +auth_withpeer_fail(int unit, u16_t protocol) +{ + int errCode = PPPERR_AUTHFAIL; + + LWIP_UNUSED_ARG(protocol); + + AUTHDEBUG(LOG_INFO, ("auth_withpeer_fail: %d proto=%X\n", unit, protocol)); + if (passwd_from_file) { + BZERO(ppp_settings.passwd, MAXSECRETLEN); + } + + /* + * We've failed to authenticate ourselves to our peer. + * He'll probably take the link down, and there's not much + * we can do except wait for that. + */ + pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode); + lcp_close(unit, "Failed to authenticate ourselves to peer"); +} + +/* + * We have successfully authenticated ourselves with the peer using `protocol'. + */ +void +auth_withpeer_success(int unit, u16_t protocol) +{ + int pbit; + + AUTHDEBUG(LOG_INFO, ("auth_withpeer_success: %d proto=%X\n", unit, protocol)); + switch (protocol) { + case PPP_CHAP: + pbit = CHAP_WITHPEER; + break; + case PPP_PAP: + if (passwd_from_file) { + BZERO(ppp_settings.passwd, MAXSECRETLEN); + } + pbit = PAP_WITHPEER; + break; + default: + AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); + pbit = 0; + } + + /* + * If there is no more authentication still being done, + * proceed to the network (or callback) phase. + */ + if ((auth_pending[unit] &= ~pbit) == 0) { + network_phase(unit); + } +} +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + + +/* + * np_up - a network protocol has come up. + */ +void +np_up(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG(LOG_INFO, ("np_up: %d proto=%X\n", unit, proto)); + if (num_np_up == 0) { + AUTHDEBUG(LOG_INFO, ("np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit)); + /* + * At this point we consider that the link has come up successfully. + */ + if (ppp_settings.idle_time_limit > 0) { + TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit); + } + + /* + * Set a timeout to close the connection once the maximum + * connect time has expired. + */ + if (ppp_settings.maxconnect > 0) { + TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect); + } + } + ++num_np_up; +} + +/* + * np_down - a network protocol has gone down. + */ +void +np_down(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG(LOG_INFO, ("np_down: %d proto=%X\n", unit, proto)); + if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) { + UNTIMEOUT(check_idle, NULL); + } +} + +/* + * np_finished - a network protocol has finished using the link. + */ +void +np_finished(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG(LOG_INFO, ("np_finished: %d proto=%X\n", unit, proto)); + if (--num_np_open <= 0) { + /* no further use for the link: shut up shop. */ + lcp_close(0, "No network protocols running"); + } +} + +/* + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. + */ +static void +check_idle(void *arg) +{ + struct ppp_idle idle; + u_short itime; + + LWIP_UNUSED_ARG(arg); + if (!get_idle_time(0, &idle)) { + return; + } + itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); + if (itime >= ppp_settings.idle_time_limit) { + /* link is idle: shut it down. */ + AUTHDEBUG(LOG_INFO, ("Terminating connection due to lack of activity.\n")); + lcp_close(0, "Link inactive"); + } else { + TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); + } +} + +/* + * connect_time_expired - log a message and close the connection. + */ +static void +connect_time_expired(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + AUTHDEBUG(LOG_INFO, ("Connect time expired\n")); + lcp_close(0, "Connect time expired"); /* Close connection */ +} + +#if 0 /* UNUSED */ +/* + * auth_check_options - called to check authentication options. + */ +void +auth_check_options(void) +{ + lcp_options *wo = &lcp_wantoptions[0]; + int can_auth; + ipcp_options *ipwo = &ipcp_wantoptions[0]; + u32_t remote; + + /* Default our_name to hostname, and user to our_name */ + if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) { + strcpy(ppp_settings.our_name, ppp_settings.hostname); + } + + if (ppp_settings.user[0] == 0) { + strcpy(ppp_settings.user, ppp_settings.our_name); + } + + /* If authentication is required, ask peer for CHAP or PAP. */ + if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) { + wo->neg_chap = 1; + wo->neg_upap = 1; + } + + /* + * Check whether we have appropriate secrets to use + * to authenticate the peer. + */ + can_auth = wo->neg_upap && have_pap_secret(); + if (!can_auth && wo->neg_chap) { + remote = ipwo->accept_remote? 0: ipwo->hisaddr; + can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote); + } + + if (ppp_settings.auth_required && !can_auth) { + ppp_panic("No auth secret"); + } +} +#endif /* UNUSED */ + +/* + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. + */ +void +auth_reset(int unit) +{ + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ao = &lcp_allowoptions[0]; + ipcp_options *ipwo = &ipcp_wantoptions[0]; + u32_t remote; + + AUTHDEBUG(LOG_INFO, ("auth_reset: %d\n", unit)); + ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL)); + ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/; + + if (go->neg_upap && !have_pap_secret()) { + go->neg_upap = 0; + } + if (go->neg_chap) { + remote = ipwo->accept_remote? 0: ipwo->hisaddr; + if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) { + go->neg_chap = 0; + } + } +} + +#if PAP_SUPPORT +/* + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. + * UPAP_AUTHACK: Authentication succeeded. + * In either case, msg points to an appropriate message. + */ +u_char +check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen) +{ +#if 1 /* XXX Assume all entries OK. */ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(auser); + LWIP_UNUSED_ARG(userlen); + LWIP_UNUSED_ARG(apasswd); + LWIP_UNUSED_ARG(passwdlen); + LWIP_UNUSED_ARG(msglen); + *msg = (char *) 0; + return UPAP_AUTHACK; /* XXX Assume all entries OK. */ +#else + u_char ret = 0; + struct wordlist *addrs = NULL; + char passwd[256], user[256]; + char secret[MAXWORDLEN]; + static u_short attempts = 0; + + /* + * Make copies of apasswd and auser, then null-terminate them. + */ + BCOPY(apasswd, passwd, passwdlen); + passwd[passwdlen] = '\0'; + BCOPY(auser, user, userlen); + user[userlen] = '\0'; + *msg = (char *) 0; + + /* XXX Validate user name and password. */ + ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */ + + if (ret == UPAP_AUTHNAK) { + if (*msg == (char *) 0) { + *msg = "Login incorrect"; + } + *msglen = strlen(*msg); + /* + * Frustrate passwd stealer programs. + * Allow 10 tries, but start backing off after 3 (stolen from login). + * On 10'th, drop the connection. + */ + if (attempts++ >= 10) { + AUTHDEBUG(LOG_WARNING, ("%d LOGIN FAILURES BY %s\n", attempts, user)); + /*ppp_panic("Excess Bad Logins");*/ + } + if (attempts > 3) { + /* @todo: this was sleep(), i.e. seconds, not milliseconds + * I don't think we really need this in lwIP - we would block tcpip_thread! + */ + /*sys_msleep((attempts - 3) * 5);*/ + } + if (addrs != NULL) { + free_wordlist(addrs); + } + } else { + attempts = 0; /* Reset count */ + if (*msg == (char *) 0) { + *msg = "Login ok"; + } + *msglen = strlen(*msg); + set_allowed_addrs(unit, addrs); + } + + BZERO(passwd, sizeof(passwd)); + BZERO(secret, sizeof(secret)); + + return ret; +#endif +} +#endif /* PAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * This function is needed for PAM. + */ + +#ifdef USE_PAM + +/* lwip does not support PAM*/ + +#endif /* USE_PAM */ + +#endif /* UNUSED */ + + +#if 0 /* UNUSED */ +/* + * plogin - Check the user name and password against the system + * password database, and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Login failed. + * UPAP_AUTHACK: Login succeeded. + * In either case, msg points to an appropriate message. + */ +static int +plogin(char *user, char *passwd, char **msg, int *msglen) +{ + + LWIP_UNUSED_ARG(user); + LWIP_UNUSED_ARG(passwd); + LWIP_UNUSED_ARG(msg); + LWIP_UNUSED_ARG(msglen); + + + /* The new lines are here align the file when + * compared against the pppd 2.3.11 code */ + + + + + + + + + + + + + + + + + /* XXX Fail until we decide that we want to support logins. */ + return (UPAP_AUTHNAK); +} +#endif + + + +/* + * plogout - Logout the user. + */ +static void +plogout(void) +{ + logged_in = 0; +} + +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(int unit) +{ + LWIP_UNUSED_ARG(unit); + /* XXX Fail until we decide that we want to support logins. */ + return 0; +} + + +/* + * get_pap_passwd - get a password for authenticating ourselves with + * our peer using PAP. Returns 1 on success, 0 if no suitable password + * could be found. + */ +static int +get_pap_passwd(int unit, char *user, char *passwd) +{ + LWIP_UNUSED_ARG(unit); +/* normally we would reject PAP if no password is provided, + but this causes problems with some providers (like CHT in Taiwan) + who incorrectly request PAP and expect a bogus/empty password, so + always provide a default user/passwd of "none"/"none" + + @todo: This should be configured by the user, instead of being hardcoded here! +*/ + if(user) { + strcpy(user, "none"); + } + if(passwd) { + strcpy(passwd, "none"); + } + return 1; +} + +/* + * have_pap_secret - check whether we have a PAP file with any + * secrets that we could possibly use for authenticating the peer. + */ +static int +have_pap_secret(void) +{ + /* XXX Fail until we set up our passwords. */ + return 0; +} + +/* + * have_chap_secret - check whether we have a CHAP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_chap_secret(char *client, char *server, u32_t remote) +{ + LWIP_UNUSED_ARG(client); + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(remote); + + /* XXX Fail until we set up our passwords. */ + return 0; +} +#if CHAP_SUPPORT + +/* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int +get_secret(int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs) +{ +#if 1 + int len; + struct wordlist *addrs; + + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(save_addrs); + + addrs = NULL; + + if(!client || !client[0] || strcmp(client, ppp_settings.user)) { + return 0; + } + + len = (int)strlen(ppp_settings.passwd); + if (len > MAXSECRETLEN) { + AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); + len = MAXSECRETLEN; + } + + BCOPY(ppp_settings.passwd, secret, len); + *secret_len = len; + + return 1; +#else + int ret = 0, len; + struct wordlist *addrs; + char secbuf[MAXWORDLEN]; + + addrs = NULL; + secbuf[0] = 0; + + /* XXX Find secret. */ + if (ret < 0) { + return 0; + } + + if (save_addrs) { + set_allowed_addrs(unit, addrs); + } + + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); + len = MAXSECRETLEN; + } + + BCOPY(secbuf, secret, len); + BZERO(secbuf, sizeof(secbuf)); + *secret_len = len; + + return 1; +#endif +} +#endif /* CHAP_SUPPORT */ + + +#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * set_allowed_addrs() - set the list of allowed addresses. + */ +static void +set_allowed_addrs(int unit, struct wordlist *addrs) +{ + if (addresses[unit] != NULL) { + free_wordlist(addresses[unit]); + } + addresses[unit] = addrs; + +#if 0 + /* + * If there's only one authorized address we might as well + * ask our peer for that one right away + */ + if (addrs != NULL && addrs->next == NULL) { + char *p = addrs->word; + struct ipcp_options *wo = &ipcp_wantoptions[unit]; + u32_t a; + struct hostent *hp; + + if (wo->hisaddr == 0 && *p != '!' && *p != '-' && strchr(p, '/') == NULL) { + hp = gethostbyname(p); + if (hp != NULL && hp->h_addrtype == AF_INET) { + a = *(u32_t *)hp->h_addr; + } else { + a = inet_addr(p); + } + if (a != (u32_t) -1) { + wo->hisaddr = a; + } + } + } +#endif +} +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ + +/* + * auth_ip_addr - check whether the peer is authorized to use + * a given IP address. Returns 1 if authorized, 0 otherwise. + */ +int +auth_ip_addr(int unit, u32_t addr) +{ + return ip_addr_check(addr, addresses[unit]); +} + +static int /* @todo: integrate this funtion into auth_ip_addr()*/ +ip_addr_check(u32_t addr, struct wordlist *addrs) +{ + /* don't allow loopback or multicast address */ + if (bad_ip_adrs(addr)) { + return 0; + } + + if (addrs == NULL) { + return !ppp_settings.auth_required; /* no addresses authorized */ + } + + /* XXX All other addresses allowed. */ + return 1; +} + +/* + * bad_ip_adrs - return 1 if the IP address is one we don't want + * to use, such as an address in the loopback net or a multicast address. + * addr is in network byte order. + */ +int +bad_ip_adrs(u32_t addr) +{ + addr = ntohl(addr); + return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET + || IN_MULTICAST(addr) || IN_BADCLASS(addr); +} + +#if 0 /* UNUSED */ /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * some_ip_ok - check a wordlist to see if it authorizes any + * IP address(es). + */ +static int +some_ip_ok(struct wordlist *addrs) +{ + for (; addrs != 0; addrs = addrs->next) { + if (addrs->word[0] == '-') + break; + if (addrs->word[0] != '!') + return 1; /* some IP address is allowed */ + } + return 0; +} + +/* + * check_access - complain if a secret file has too-liberal permissions. + */ +static void +check_access(FILE *f, char *filename) +{ + struct stat sbuf; + + if (fstat(fileno(f), &sbuf) < 0) { + warn("cannot stat secret file %s: %m", filename); + } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + warn("Warning - secret file %s has world and/or group access", + filename); + } +} + + +/* + * scan_authfile - Scan an authorization file for a secret suitable + * for authenticating `client' on `server'. The return value is -1 + * if no secret is found, otherwise >= 0. The return value has + * NONWILD_CLIENT set if the secret didn't have "*" for the client, and + * NONWILD_SERVER set if the secret didn't have "*" for the server. + * Any following words on the line up to a "--" (i.e. address authorization + * info) are placed in a wordlist and returned in *addrs. Any + * following words (extra options) are placed in a wordlist and + * returned in *opts. + * We assume secret is NULL or points to MAXWORDLEN bytes of space. + */ +static int +scan_authfile(FILE *f, char *client, char *server, char *secret, struct wordlist **addrs, struct wordlist **opts, char *filename) +{ + /* We do not (currently) need this in lwip */ + return 0; /* dummy */ +} +/* + * free_wordlist - release memory allocated for a wordlist. + */ +static void +free_wordlist(struct wordlist *wp) +{ + struct wordlist *next; + + while (wp != NULL) { + next = wp->next; + free(wp); + wp = next; + } +} + +/* + * auth_script_done - called when the auth-up or auth-down script + * has finished. + */ +static void +auth_script_done(void *arg) +{ + auth_script_pid = 0; + switch (auth_script_state) { + case s_up: + if (auth_state == s_down) { + auth_script_state = s_down; + auth_script(_PATH_AUTHDOWN); + } + break; + case s_down: + if (auth_state == s_up) { + auth_script_state = s_up; + auth_script(_PATH_AUTHUP); + } + break; + } +} + +/* + * auth_script - execute a script with arguments + * interface-name peer-name real-user tty speed + */ +static void +auth_script(char *script) +{ + char strspeed[32]; + struct passwd *pw; + char struid[32]; + char *user_name; + char *argv[8]; + + if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) + user_name = pw->pw_name; + else { + slprintf(struid, sizeof(struid), "%d", getuid()); + user_name = struid; + } + slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); + + argv[0] = script; + argv[1] = ifname; + argv[2] = peer_authname; + argv[3] = user_name; + argv[4] = devnam; + argv[5] = strspeed; + argv[6] = NULL; + + auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL); +} +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/auth.h b/ext/lwip/src/netif/ppp/auth.h new file mode 100644 index 000000000..a8069ec46 --- /dev/null +++ b/ext/lwip/src/netif/ppp/auth.h @@ -0,0 +1,111 @@ +/***************************************************************************** +* auth.h - PPP Authentication and phase control header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD pppd.h. +*****************************************************************************/ +/* + * pppd.h - PPP daemon global declarations. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef AUTH_H +#define AUTH_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* we are starting to use the link */ +void link_required (int); + +/* we are finished with the link */ +void link_terminated (int); + +/* the LCP layer has left the Opened state */ +void link_down (int); + +/* the link is up; authenticate now */ +void link_established (int); + +/* a network protocol has come up */ +void np_up (int, u16_t); + +/* a network protocol has gone down */ +void np_down (int, u16_t); + +/* a network protocol no longer needs link */ +void np_finished (int, u16_t); + +/* peer failed to authenticate itself */ +void auth_peer_fail (int, u16_t); + +/* peer successfully authenticated itself */ +void auth_peer_success (int, u16_t, char *, int); + +/* we failed to authenticate ourselves */ +void auth_withpeer_fail (int, u16_t); + +/* we successfully authenticated ourselves */ +void auth_withpeer_success (int, u16_t); + +/* check authentication options supplied */ +void auth_check_options (void); + +/* check what secrets we have */ +void auth_reset (int); + +/* Check peer-supplied username/password */ +u_char check_passwd (int, char *, int, char *, int, char **, int *); + +/* get "secret" for chap */ +int get_secret (int, char *, char *, char *, int *, int); + +/* check if IP address is authorized */ +int auth_ip_addr (int, u32_t); + +/* check if IP address is unreasonable */ +int bad_ip_adrs (u32_t); + +#endif /* AUTH_H */ diff --git a/ext/lwip/src/netif/ppp/chap.c b/ext/lwip/src/netif/ppp/chap.c new file mode 100644 index 000000000..f10e27d2e --- /dev/null +++ b/ext/lwip/src/netif/ppp/chap.c @@ -0,0 +1,908 @@ +/*** WARNING - THIS HAS NEVER BEEN FINISHED ***/ +/***************************************************************************** +* chap.c - Network Challenge Handshake Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD chap.c. +*****************************************************************************/ +/* + * chap.c - Challenge Handshake Authentication Protocol. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1991 Gregory M. Christy. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Gregory M. Christy. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "magic.h" +#include "randm.h" +#include "auth.h" +#include "md5.h" +#include "chap.h" +#include "chpms.h" + +#include + +#if 0 /* UNUSED */ +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap[0].timeouttime, + "Set timeout for CHAP" }, + { "chap-max-challenge", o_int, &chap[0].max_transmits, + "Set max #xmits for challenge" }, + { "chap-interval", o_int, &chap[0].chal_interval, + "Set interval for rechallenge" }, +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif + { NULL } +}; +#endif /* UNUSED */ + +/* + * Protocol entry points. + */ +static void ChapInit (int); +static void ChapLowerUp (int); +static void ChapLowerDown (int); +static void ChapInput (int, u_char *, int); +static void ChapProtocolReject (int); +#if PPP_ADDITIONAL_CALLBACKS +static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *); +#endif + +struct protent chap_protent = { + PPP_CHAP, + ChapInit, + ChapInput, + ChapProtocolReject, + ChapLowerUp, + ChapLowerDown, + NULL, + NULL, +#if PPP_ADDITIONAL_CALLBACKS + ChapPrintPkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "CHAP", +#if PPP_ADDITIONAL_CALLBACKS + NULL, + NULL, + NULL +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ + +static void ChapChallengeTimeout (void *); +static void ChapResponseTimeout (void *); +static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int); +static void ChapRechallenge (void *); +static void ChapReceiveResponse (chap_state *, u_char *, int, int); +static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len); +static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len); +static void ChapSendStatus (chap_state *, int); +static void ChapSendChallenge (chap_state *); +static void ChapSendResponse (chap_state *); +static void ChapGenChallenge (chap_state *); + +/* + * ChapInit - Initialize a CHAP unit. + */ +static void +ChapInit(int unit) +{ + chap_state *cstate = &chap[unit]; + + BZERO(cstate, sizeof(*cstate)); + cstate->unit = unit; + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; + cstate->timeouttime = CHAP_DEFTIMEOUT; + cstate->max_transmits = CHAP_DEFTRANSMITS; + /* random number generator is initialized in magic_init */ +} + + +/* + * ChapAuthWithPeer - Authenticate us with our peer (start client). + * + */ +void +ChapAuthWithPeer(int unit, char *our_name, u_char digest) +{ + chap_state *cstate = &chap[unit]; + + cstate->resp_name = our_name; + cstate->resp_type = digest; + + if (cstate->clientstate == CHAPCS_INITIAL || + cstate->clientstate == CHAPCS_PENDING) { + /* lower layer isn't up - wait until later */ + cstate->clientstate = CHAPCS_PENDING; + return; + } + + /* + * We get here as a result of LCP coming up. + * So even if CHAP was open before, we will + * have to re-authenticate ourselves. + */ + cstate->clientstate = CHAPCS_LISTEN; +} + + +/* + * ChapAuthPeer - Authenticate our peer (start server). + */ +void +ChapAuthPeer(int unit, char *our_name, u_char digest) +{ + chap_state *cstate = &chap[unit]; + + cstate->chal_name = our_name; + cstate->chal_type = digest; + + if (cstate->serverstate == CHAPSS_INITIAL || + cstate->serverstate == CHAPSS_PENDING) { + /* lower layer isn't up - wait until later */ + cstate->serverstate = CHAPSS_PENDING; + return; + } + + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); /* crank it up dude! */ + cstate->serverstate = CHAPSS_INITIAL_CHAL; +} + + +/* + * ChapChallengeTimeout - Timeout expired on sending challenge. + */ +static void +ChapChallengeTimeout(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending challenges, don't worry. then again we */ + /* probably shouldn't be here either */ + if (cstate->serverstate != CHAPSS_INITIAL_CHAL && + cstate->serverstate != CHAPSS_RECHALLENGE) { + return; + } + + if (cstate->chal_transmits >= cstate->max_transmits) { + /* give up on peer */ + CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n")); + cstate->serverstate = CHAPSS_BADAUTH; + auth_peer_fail(cstate->unit, PPP_CHAP); + return; + } + + ChapSendChallenge(cstate); /* Re-send challenge */ +} + + +/* + * ChapResponseTimeout - Timeout expired on sending response. + */ +static void +ChapResponseTimeout(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending a response, don't worry. */ + if (cstate->clientstate != CHAPCS_RESPONSE) { + return; + } + + ChapSendResponse(cstate); /* re-send response */ +} + + +/* + * ChapRechallenge - Time to challenge the peer again. + */ +static void +ChapRechallenge(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending a response, don't worry. */ + if (cstate->serverstate != CHAPSS_OPEN) { + return; + } + + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); + cstate->serverstate = CHAPSS_RECHALLENGE; +} + + +/* + * ChapLowerUp - The lower layer is up. + * + * Start up if we have pending requests. + */ +static void +ChapLowerUp(int unit) +{ + chap_state *cstate = &chap[unit]; + + if (cstate->clientstate == CHAPCS_INITIAL) { + cstate->clientstate = CHAPCS_CLOSED; + } else if (cstate->clientstate == CHAPCS_PENDING) { + cstate->clientstate = CHAPCS_LISTEN; + } + + if (cstate->serverstate == CHAPSS_INITIAL) { + cstate->serverstate = CHAPSS_CLOSED; + } else if (cstate->serverstate == CHAPSS_PENDING) { + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); + cstate->serverstate = CHAPSS_INITIAL_CHAL; + } +} + + +/* + * ChapLowerDown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void +ChapLowerDown(int unit) +{ + chap_state *cstate = &chap[unit]; + + /* Timeout(s) pending? Cancel if so. */ + if (cstate->serverstate == CHAPSS_INITIAL_CHAL || + cstate->serverstate == CHAPSS_RECHALLENGE) { + UNTIMEOUT(ChapChallengeTimeout, cstate); + } else if (cstate->serverstate == CHAPSS_OPEN + && cstate->chal_interval != 0) { + UNTIMEOUT(ChapRechallenge, cstate); + } + if (cstate->clientstate == CHAPCS_RESPONSE) { + UNTIMEOUT(ChapResponseTimeout, cstate); + } + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; +} + + +/* + * ChapProtocolReject - Peer doesn't grok CHAP. + */ +static void +ChapProtocolReject(int unit) +{ + chap_state *cstate = &chap[unit]; + + if (cstate->serverstate != CHAPSS_INITIAL && + cstate->serverstate != CHAPSS_CLOSED) { + auth_peer_fail(unit, PPP_CHAP); + } + if (cstate->clientstate != CHAPCS_INITIAL && + cstate->clientstate != CHAPCS_CLOSED) { + auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ + } + ChapLowerDown(unit); /* shutdown chap */ +} + + +/* + * ChapInput - Input CHAP packet. + */ +static void +ChapInput(int unit, u_char *inpacket, int packet_len) +{ + chap_state *cstate = &chap[unit]; + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (packet_len < CHAP_HEADERLEN) { + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < CHAP_HEADERLEN) { + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n")); + return; + } + if (len > packet_len) { + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n")); + return; + } + len -= CHAP_HEADERLEN; + + /* + * Action depends on code (as in fact it usually does :-). + */ + switch (code) { + case CHAP_CHALLENGE: + ChapReceiveChallenge(cstate, inp, id, len); + break; + + case CHAP_RESPONSE: + ChapReceiveResponse(cstate, inp, id, len); + break; + + case CHAP_FAILURE: + ChapReceiveFailure(cstate, inp, id, len); + break; + + case CHAP_SUCCESS: + ChapReceiveSuccess(cstate, inp, id, len); + break; + + default: /* Need code reject? */ + CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code)); + break; + } +} + + +/* + * ChapReceiveChallenge - Receive Challenge and send Response. + */ +static void +ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len) +{ + int rchallenge_len; + u_char *rchallenge; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[256]; + MD5_CTX mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; + + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id)); + if (cstate->clientstate == CHAPCS_CLOSED || + cstate->clientstate == CHAPCS_PENDING) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n", + cstate->clientstate)); + return; + } + + if (len < 2) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n")); + return; + } + + GETCHAR(rchallenge_len, inp); + len -= sizeof (u_char) + rchallenge_len; /* now name field length */ + if (len < 0) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n")); + return; + } + rchallenge = inp; + INCPTR(rchallenge_len, inp); + + if (len >= (int)sizeof(rhostname)) { + len = sizeof(rhostname) - 1; + } + BCOPY(inp, rhostname, len); + rhostname[len] = '\000'; + + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n", + rhostname)); + + /* Microsoft doesn't send their name back in the PPP packet */ + if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) { + strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname)); + rhostname[sizeof(rhostname) - 1] = 0; + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n", + rhostname)); + } + + /* get secret for authenticating ourselves with the specified host */ + if (!get_secret(cstate->unit, cstate->resp_name, rhostname, + secret, &secret_len, 0)) { + secret_len = 0; /* assume null secret if can't find one */ + CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n", + rhostname)); + } + + /* cancel response send timeout if necessary */ + if (cstate->clientstate == CHAPCS_RESPONSE) { + UNTIMEOUT(ChapResponseTimeout, cstate); + } + + cstate->resp_id = id; + cstate->resp_transmits = 0; + + /* generate MD based on negotiated type */ + switch (cstate->resp_type) { + + case CHAP_DIGEST_MD5: + MD5Init(&mdContext); + MD5Update(&mdContext, &cstate->resp_id, 1); + MD5Update(&mdContext, (u_char*)secret, secret_len); + MD5Update(&mdContext, rchallenge, rchallenge_len); + MD5Final(hash, &mdContext); + BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE); + cstate->resp_length = MD5_SIGNATURE_SIZE; + break; + +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); + break; +#endif + + default: + CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type)); + return; + } + + BZERO(secret, sizeof(secret)); + ChapSendResponse(cstate); +} + + +/* + * ChapReceiveResponse - Receive and process response. + */ +static void +ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) +{ + u_char *remmd, remmd_len; + int secret_len, old_state; + int code; + char rhostname[256]; + MD5_CTX mdContext; + char secret[MAXSECRETLEN]; + u_char hash[MD5_SIGNATURE_SIZE]; + + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id)); + + if (cstate->serverstate == CHAPSS_CLOSED || + cstate->serverstate == CHAPSS_PENDING) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n", + cstate->serverstate)); + return; + } + + if (id != cstate->chal_id) { + return; /* doesn't match ID of last challenge */ + } + + /* + * If we have received a duplicate or bogus Response, + * we have to send the same answer (Success/Failure) + * as we did for the first Response we saw. + */ + if (cstate->serverstate == CHAPSS_OPEN) { + ChapSendStatus(cstate, CHAP_SUCCESS); + return; + } + if (cstate->serverstate == CHAPSS_BADAUTH) { + ChapSendStatus(cstate, CHAP_FAILURE); + return; + } + + if (len < 2) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n")); + return; + } + GETCHAR(remmd_len, inp); /* get length of MD */ + remmd = inp; /* get pointer to MD */ + INCPTR(remmd_len, inp); + + len -= sizeof (u_char) + remmd_len; + if (len < 0) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n")); + return; + } + + UNTIMEOUT(ChapChallengeTimeout, cstate); + + if (len >= (int)sizeof(rhostname)) { + len = sizeof(rhostname) - 1; + } + BCOPY(inp, rhostname, len); + rhostname[len] = '\000'; + + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n", + rhostname)); + + /* + * Get secret for authenticating them with us, + * do the hash ourselves, and compare the result. + */ + code = CHAP_FAILURE; + if (!get_secret(cstate->unit, rhostname, cstate->chal_name, + secret, &secret_len, 1)) { + CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n", + rhostname)); + } else { + /* generate MD based on negotiated type */ + switch (cstate->chal_type) { + + case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ + if (remmd_len != MD5_SIGNATURE_SIZE) { + break; /* it's not even the right length */ + } + MD5Init(&mdContext); + MD5Update(&mdContext, &cstate->chal_id, 1); + MD5Update(&mdContext, (u_char*)secret, secret_len); + MD5Update(&mdContext, cstate->challenge, cstate->chal_len); + MD5Final(hash, &mdContext); + + /* compare local and remote MDs and send the appropriate status */ + if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) { + code = CHAP_SUCCESS; /* they are the same! */ + } + break; + + default: + CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type)); + } + } + + BZERO(secret, sizeof(secret)); + ChapSendStatus(cstate, code); + + if (code == CHAP_SUCCESS) { + old_state = cstate->serverstate; + cstate->serverstate = CHAPSS_OPEN; + if (old_state == CHAPSS_INITIAL_CHAL) { + auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len); + } + if (cstate->chal_interval != 0) { + TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); + } + } else { + CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n")); + cstate->serverstate = CHAPSS_BADAUTH; + auth_peer_fail(cstate->unit, PPP_CHAP); + } +} + +/* + * ChapReceiveSuccess - Receive Success + */ +static void +ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len) +{ + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(inp); + + CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id)); + + if (cstate->clientstate == CHAPCS_OPEN) { + /* presumably an answer to a duplicate response */ + return; + } + + if (cstate->clientstate != CHAPCS_RESPONSE) { + /* don't know what this is */ + CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n", + cstate->clientstate)); + return; + } + + UNTIMEOUT(ChapResponseTimeout, cstate); + + /* + * Print message. + */ + if (len > 0) { + PRINTMSG(inp, len); + } + + cstate->clientstate = CHAPCS_OPEN; + + auth_withpeer_success(cstate->unit, PPP_CHAP); +} + + +/* + * ChapReceiveFailure - Receive failure. + */ +static void +ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len) +{ + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(inp); + + CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id)); + + if (cstate->clientstate != CHAPCS_RESPONSE) { + /* don't know what this is */ + CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n", + cstate->clientstate)); + return; + } + + UNTIMEOUT(ChapResponseTimeout, cstate); + + /* + * Print message. + */ + if (len > 0) { + PRINTMSG(inp, len); + } + + CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n")); + auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ +} + + +/* + * ChapSendChallenge - Send an Authenticate challenge. + */ +static void +ChapSendChallenge(chap_state *cstate) +{ + u_char *outp; + int chal_len, name_len; + int outlen; + + chal_len = cstate->chal_len; + name_len = (int)strlen(cstate->chal_name); + outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */ + + PUTCHAR(CHAP_CHALLENGE, outp); + PUTCHAR(cstate->chal_id, outp); + PUTSHORT(outlen, outp); + + PUTCHAR(chal_len, outp); /* put length of challenge */ + BCOPY(cstate->challenge, outp, chal_len); + INCPTR(chal_len, outp); + + BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ + + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id)); + + TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime); + ++cstate->chal_transmits; +} + + +/* + * ChapSendStatus - Send a status response (ack or nak). + */ +static void +ChapSendStatus(chap_state *cstate, int code) +{ + u_char *outp; + int outlen, msglen; + char msg[256]; /* @todo: this can be a char*, no strcpy needed */ + + if (code == CHAP_SUCCESS) { + strcpy(msg, "Welcome!"); + } else { + strcpy(msg, "I don't like you. Go 'way."); + } + msglen = (int)strlen(msg); + + outlen = CHAP_HEADERLEN + msglen; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ + + PUTCHAR(code, outp); + PUTCHAR(cstate->chal_id, outp); + PUTSHORT(outlen, outp); + BCOPY(msg, outp, msglen); + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code, + cstate->chal_id)); +} + +/* + * ChapGenChallenge is used to generate a pseudo-random challenge string of + * a pseudo-random length between min_len and max_len. The challenge + * string and its length are stored in *cstate, and various other fields of + * *cstate are initialized. + */ + +static void +ChapGenChallenge(chap_state *cstate) +{ + int chal_len; + u_char *ptr = cstate->challenge; + int i; + + /* pick a random challenge length between MIN_CHALLENGE_LENGTH and + MAX_CHALLENGE_LENGTH */ + chal_len = (unsigned) + ((((magic() >> 16) * + (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16) + + MIN_CHALLENGE_LENGTH); + LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff); + cstate->chal_len = (u_char)chal_len; + cstate->chal_id = ++cstate->id; + cstate->chal_transmits = 0; + + /* generate a random string */ + for (i = 0; i < chal_len; i++ ) { + *ptr++ = (char) (magic() & 0xff); + } +} + +/* + * ChapSendResponse - send a response packet with values as specified + * in *cstate. + */ +/* ARGSUSED */ +static void +ChapSendResponse(chap_state *cstate) +{ + u_char *outp; + int outlen, md_len, name_len; + + md_len = cstate->resp_length; + name_len = (int)strlen(cstate->resp_name); + outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); + + PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */ + PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */ + PUTSHORT(outlen, outp); /* packet length */ + + PUTCHAR(md_len, outp); /* length of MD */ + BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */ + INCPTR(md_len, outp); + + BCOPY(cstate->resp_name, outp, name_len); /* append our name */ + + /* send the packet */ + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + cstate->clientstate = CHAPCS_RESPONSE; + TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime); + ++cstate->resp_transmits; +} + +#if PPP_ADDITIONAL_CALLBACKS +static char *ChapCodenames[] = { + "Challenge", "Response", "Success", "Failure" +}; +/* + * ChapPrintPkt - print the contents of a CHAP packet. + */ +static int +ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + int code, id, len; + int clen, nlen; + u_char x; + + if (plen < CHAP_HEADERLEN) { + return 0; + } + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HEADERLEN || len > plen) { + return 0; + } + + if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) { + printer(arg, " %s", ChapCodenames[code-1]); + } else { + printer(arg, " code=0x%x", code); + } + printer(arg, " id=0x%x", id); + len -= CHAP_HEADERLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) { + break; + } + clen = p[0]; + if (len < clen + 1) { + break; + } + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = %.*Z", nlen, p); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " %.*Z", len, p); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + } + + return len + CHAP_HEADERLEN; +} +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +#endif /* CHAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/chap.h b/ext/lwip/src/netif/ppp/chap.h new file mode 100644 index 000000000..fedcab8da --- /dev/null +++ b/ext/lwip/src/netif/ppp/chap.h @@ -0,0 +1,150 @@ +/***************************************************************************** +* chap.h - Network Challenge Handshake Authentication Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-03 Guy Lancaster , Global Election Systems Inc. +* Original built from BSD network code. +******************************************************************************/ +/* + * chap.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1991 Gregory M. Christy + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the author. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: chap.h,v 1.6 2010/01/24 13:19:34 goldsimon Exp $ + */ + +#ifndef CHAP_H +#define CHAP_H + +/* Code + ID + length */ +#define CHAP_HEADERLEN 4 + +/* + * CHAP codes. + */ + +#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */ +#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */ +#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */ +#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ + +#define CHAP_CHALLENGE 1 +#define CHAP_RESPONSE 2 +#define CHAP_SUCCESS 3 +#define CHAP_FAILURE 4 + +/* + * Challenge lengths (for challenges we send) and other limits. + */ +#define MIN_CHALLENGE_LENGTH 32 +#define MAX_CHALLENGE_LENGTH 64 +#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */ + +/* + * Each interface is described by a chap structure. + */ + +typedef struct chap_state { + int unit; /* Interface unit number */ + int clientstate; /* Client state */ + int serverstate; /* Server state */ + u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */ + u_char chal_len; /* challenge length */ + u_char chal_id; /* ID of last challenge */ + u_char chal_type; /* hash algorithm for challenges */ + u_char id; /* Current id */ + char *chal_name; /* Our name to use with challenge */ + int chal_interval; /* Time until we challenge peer again */ + int timeouttime; /* Timeout time in seconds */ + int max_transmits; /* Maximum # of challenge transmissions */ + int chal_transmits; /* Number of transmissions of challenge */ + int resp_transmits; /* Number of transmissions of response */ + u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */ + u_char resp_length; /* length of response */ + u_char resp_id; /* ID for response messages */ + u_char resp_type; /* hash algorithm for responses */ + char *resp_name; /* Our name to send with response */ +} chap_state; + + +/* + * Client (peer) states. + */ +#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */ +#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */ +#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */ +#define CHAPCS_LISTEN 3 /* Listening for a challenge */ +#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */ +#define CHAPCS_OPEN 5 /* We've received Success */ + +/* + * Server (authenticator) states. + */ +#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */ +#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */ +#define CHAPSS_PENDING 2 /* Auth peer when lower up */ +#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */ +#define CHAPSS_OPEN 4 /* We've sent a Success msg */ +#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */ +#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */ + +extern chap_state chap[]; + +void ChapAuthWithPeer (int, char *, u_char); +void ChapAuthPeer (int, char *, u_char); + +extern struct protent chap_protent; + +#endif /* CHAP_H */ diff --git a/ext/lwip/src/netif/ppp/chpms.c b/ext/lwip/src/netif/ppp/chpms.c new file mode 100644 index 000000000..81a887b83 --- /dev/null +++ b/ext/lwip/src/netif/ppp/chpms.c @@ -0,0 +1,396 @@ +/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/ +/*** The original PPPD code is written in a way to require either the UNIX DES + encryption functions encrypt(3) and setkey(3) or the DES library libdes. + Since both is not included in lwIP, MSCHAP currently does not work! */ +/***************************************************************************** +* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD chap_ms.c. +*****************************************************************************/ +/* + * chap_ms.c - Microsoft MS-CHAP compatible implementation. + * + * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. + * http://www.strataware.com/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Eric Rosenquist. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 + * + * Implemented LANManager type password response to MS-CHAP challenges. + * Now pppd provides both NT style and LANMan style blocks, and the + * prefered is set by option "ms-lanman". Default is to use NT. + * The hash text (StdText) was taken from Win95 RASAPI32.DLL. + * + * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 + */ + +#define USE_CRYPT + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "md4.h" +#ifndef USE_CRYPT +#include "des.h" +#endif +#include "chap.h" +#include "chpms.h" + +#include + + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ +typedef struct { + u_char LANManResp[24]; + u_char NTResp[24]; + u_char UseNT; /* If 1, ignore the LANMan response field */ +} MS_ChapResponse; +/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), + in case this struct gets padded. */ + + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ + +/* XXX Don't know what to do with these. */ +extern void setkey(const char *); +extern void encrypt(char *, int); + +static void DesEncrypt (u_char *, u_char *, u_char *); +static void MakeKey (u_char *, u_char *); + +#ifdef USE_CRYPT +static void Expand (u_char *, u_char *); +static void Collapse (u_char *, u_char *); +#endif + +static void ChallengeResponse( + u_char *challenge, /* IN 8 octets */ + u_char *pwHash, /* IN 16 octets */ + u_char *response /* OUT 24 octets */ +); +static void ChapMS_NT( + char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response +); +static u_char Get7Bits( + u_char *input, + int startBit +); + +static void +ChallengeResponse( u_char *challenge, /* IN 8 octets */ + u_char *pwHash, /* IN 16 octets */ + u_char *response /* OUT 24 octets */) +{ + u_char ZPasswordHash[21]; + + BZERO(ZPasswordHash, sizeof(ZPasswordHash)); + BCOPY(pwHash, ZPasswordHash, 16); + +#if 0 + log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG); +#endif + + DesEncrypt(challenge, ZPasswordHash + 0, response + 0); + DesEncrypt(challenge, ZPasswordHash + 7, response + 8); + DesEncrypt(challenge, ZPasswordHash + 14, response + 16); + +#if 0 + log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG); +#endif +} + + +#ifdef USE_CRYPT +static void +DesEncrypt( u_char *clear, /* IN 8 octets */ + u_char *key, /* IN 7 octets */ + u_char *cipher /* OUT 8 octets */) +{ + u_char des_key[8]; + u_char crypt_key[66]; + u_char des_input[66]; + + MakeKey(key, des_key); + + Expand(des_key, crypt_key); + setkey((char*)crypt_key); + +#if 0 + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", + clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); +#endif + + Expand(clear, des_input); + encrypt((char*)des_input, 0); + Collapse(des_input, cipher); + +#if 0 + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); +#endif +} + +#else /* USE_CRYPT */ + +static void +DesEncrypt( u_char *clear, /* IN 8 octets */ + u_char *key, /* IN 7 octets */ + u_char *cipher /* OUT 8 octets */) +{ + des_cblock des_key; + des_key_schedule key_schedule; + + MakeKey(key, des_key); + + des_set_key(&des_key, key_schedule); + +#if 0 + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", + clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); +#endif + + des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); + +#if 0 + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); +#endif +} + +#endif /* USE_CRYPT */ + + +static u_char +Get7Bits( u_char *input, int startBit) +{ + register unsigned int word; + + word = (unsigned)input[startBit / 8] << 8; + word |= (unsigned)input[startBit / 8 + 1]; + + word >>= 15 - (startBit % 8 + 7); + + return word & 0xFE; +} + +#ifdef USE_CRYPT + +/* in == 8-byte string (expanded version of the 56-bit key) + * out == 64-byte string where each byte is either 1 or 0 + * Note that the low-order "bit" is always ignored by by setkey() + */ +static void +Expand(u_char *in, u_char *out) +{ + int j, c; + int i; + + for(i = 0; i < 64; in++){ + c = *in; + for(j = 7; j >= 0; j--) { + *out++ = (c >> j) & 01; + } + i += 8; + } +} + +/* The inverse of Expand + */ +static void +Collapse(u_char *in, u_char *out) +{ + int j; + int i; + unsigned int c; + + for (i = 0; i < 64; i += 8, out++) { + c = 0; + for (j = 7; j >= 0; j--, in++) { + c |= *in << j; + } + *out = c & 0xff; + } +} +#endif + +static void +MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */ + u_char *des_key /* OUT 64 bit DES key with parity bits added */) +{ + des_key[0] = Get7Bits(key, 0); + des_key[1] = Get7Bits(key, 7); + des_key[2] = Get7Bits(key, 14); + des_key[3] = Get7Bits(key, 21); + des_key[4] = Get7Bits(key, 28); + des_key[5] = Get7Bits(key, 35); + des_key[6] = Get7Bits(key, 42); + des_key[7] = Get7Bits(key, 49); + +#ifndef USE_CRYPT + des_set_odd_parity((des_cblock *)des_key); +#endif + +#if 0 + CHAPDEBUG(LOG_INFO, ("MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n", + key[0], key[1], key[2], key[3], key[4], key[5], key[6])); + CHAPDEBUG(LOG_INFO, ("MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7])); +#endif +} + +static void +ChapMS_NT( char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response) +{ + int i; + MDstruct md4Context; + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + static int low_byte_first = -1; + + LWIP_UNUSED_ARG(rchallenge_len); + + /* Initialize the Unicode version of the secret (== password). */ + /* This implicitly supports 8-bit ISO8859/1 characters. */ + BZERO(unicodePassword, sizeof(unicodePassword)); + for (i = 0; i < secret_len; i++) { + unicodePassword[i * 2] = (u_char)secret[i]; + } + MDbegin(&md4Context); + MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */ + + if (low_byte_first == -1) { + low_byte_first = (PP_HTONS((unsigned short int)1) != 1); + } + if (low_byte_first == 0) { + /* @todo: arg type - u_long* or u_int* ? */ + MDreverse((unsigned int*)&md4Context); /* sfb 961105 */ + } + + MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */ + + ChallengeResponse((u_char*)rchallenge, (u_char*)md4Context.buffer, response->NTResp); +} + +#ifdef MSLANMAN +static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +static void +ChapMS_LANMan( char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response) +{ + int i; + u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ + u_char PasswordHash[16]; + + /* LANMan password is case insensitive */ + BZERO(UcasePassword, sizeof(UcasePassword)); + for (i = 0; i < secret_len; i++) { + UcasePassword[i] = (u_char)toupper(secret[i]); + } + DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 ); + DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 ); + ChallengeResponse(rchallenge, PasswordHash, response->LANManResp); +} +#endif + +void +ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len) +{ + MS_ChapResponse response; +#ifdef MSLANMAN + extern int ms_lanman; +#endif + +#if 0 + CHAPDEBUG(LOG_INFO, ("ChapMS: secret is '%.*s'\n", secret_len, secret)); +#endif + BZERO(&response, sizeof(response)); + + /* Calculate both always */ + ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response); + +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response); + + /* prefered method is set by option */ + response.UseNT = !ms_lanman; +#else + response.UseNT = 1; +#endif + + BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); + cstate->resp_length = MS_CHAP_RESPONSE_LEN; +} + +#endif /* MSCHAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/chpms.h b/ext/lwip/src/netif/ppp/chpms.h new file mode 100644 index 000000000..df070fb35 --- /dev/null +++ b/ext/lwip/src/netif/ppp/chpms.h @@ -0,0 +1,64 @@ +/***************************************************************************** +* chpms.h - Network Microsoft Challenge Handshake Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-01-30 Guy Lancaster , Global Election Systems Inc. +* Original built from BSD network code. +******************************************************************************/ +/* + * chap.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. + * http://www.strataware.com/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Eric Rosenquist. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: chpms.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $ + */ + +#ifndef CHPMS_H +#define CHPMS_H + +#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */ + +void ChapMS (chap_state *, char *, int, char *, int); + +#endif /* CHPMS_H */ diff --git a/ext/lwip/src/netif/ppp/fsm.c b/ext/lwip/src/netif/ppp/fsm.c new file mode 100644 index 000000000..e8a254ede --- /dev/null +++ b/ext/lwip/src/netif/ppp/fsm.c @@ -0,0 +1,890 @@ +/***************************************************************************** +* fsm.c - Network Control Protocol Finite State Machine program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-01 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD fsm.c. +*****************************************************************************/ +/* + * fsm.c - {Link, IP} Control Protocol Finite State Machine. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * TODO: + * Randomize fsm id on link/init. + * Deal with variable outgoing MTU. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "fsm.h" + +#include + +#if PPP_DEBUG +static const char *ppperr_strerr[] = { + "LS_INITIAL", /* LS_INITIAL 0 */ + "LS_STARTING", /* LS_STARTING 1 */ + "LS_CLOSED", /* LS_CLOSED 2 */ + "LS_STOPPED", /* LS_STOPPED 3 */ + "LS_CLOSING", /* LS_CLOSING 4 */ + "LS_STOPPING", /* LS_STOPPING 5 */ + "LS_REQSENT", /* LS_REQSENT 6 */ + "LS_ACKRCVD", /* LS_ACKRCVD 7 */ + "LS_ACKSENT", /* LS_ACKSENT 8 */ + "LS_OPENED" /* LS_OPENED 9 */ +}; +#endif /* PPP_DEBUG */ + +static void fsm_timeout (void *); +static void fsm_rconfreq (fsm *, u_char, u_char *, int); +static void fsm_rconfack (fsm *, int, u_char *, int); +static void fsm_rconfnakrej (fsm *, int, int, u_char *, int); +static void fsm_rtermreq (fsm *, int, u_char *, int); +static void fsm_rtermack (fsm *); +static void fsm_rcoderej (fsm *, u_char *, int); +static void fsm_sconfreq (fsm *, int); + +#define PROTO_NAME(f) ((f)->callbacks->proto_name) + +int peer_mru[NUM_PPP]; + + +/* + * fsm_init - Initialize fsm. + * + * Initialize fsm state. + */ +void +fsm_init(fsm *f) +{ + f->state = LS_INITIAL; + f->flags = 0; + f->id = 0; /* XXX Start with random id? */ + f->timeouttime = FSM_DEFTIMEOUT; + f->maxconfreqtransmits = FSM_DEFMAXCONFREQS; + f->maxtermtransmits = FSM_DEFMAXTERMREQS; + f->maxnakloops = FSM_DEFMAXNAKLOOPS; + f->term_reason_len = 0; +} + + +/* + * fsm_lowerup - The lower layer is up. + */ +void +fsm_lowerup(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_INITIAL: + f->state = LS_CLOSED; + break; + + case LS_STARTING: + if( f->flags & OPT_SILENT ) { + f->state = LS_STOPPED; + } else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + } + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } + + FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_lowerdown - The lower layer is down. + * + * Cancel all timeouts and inform upper layers. + */ +void +fsm_lowerdown(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_CLOSED: + f->state = LS_INITIAL; + break; + + case LS_STOPPED: + f->state = LS_STARTING; + if( f->callbacks->starting ) { + (*f->callbacks->starting)(f); + } + break; + + case LS_CLOSING: + f->state = LS_INITIAL; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case LS_STOPPING: + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + f->state = LS_STARTING; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case LS_OPENED: + if( f->callbacks->down ) { + (*f->callbacks->down)(f); + } + f->state = LS_STARTING; + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } + + FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_open - Link is allowed to come up. + */ +void +fsm_open(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_INITIAL: + f->state = LS_STARTING; + if( f->callbacks->starting ) { + (*f->callbacks->starting)(f); + } + break; + + case LS_CLOSED: + if( f->flags & OPT_SILENT ) { + f->state = LS_STOPPED; + } else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + } + break; + + case LS_CLOSING: + f->state = LS_STOPPING; + /* fall through */ + case LS_STOPPED: + case LS_OPENED: + if( f->flags & OPT_RESTART ) { + fsm_lowerdown(f); + fsm_lowerup(f); + } + break; + } + + FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + +#if 0 /* backport pppd 2.4.4b1; */ +/* + * terminate_layer - Start process of shutting down the FSM + * + * Cancel any timeout running, notify upper layers we're done, and + * send a terminate-request message as configured. + */ +static void +terminate_layer(fsm *f, int nextstate) +{ + /* @todo */ +} +#endif + +/* + * fsm_close - Start closing connection. + * + * Cancel timeouts and either initiate close or possibly go directly to + * the LS_CLOSED state. + */ +void +fsm_close(fsm *f, char *reason) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + f->term_reason = reason; + f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason)); + switch( f->state ) { + case LS_STARTING: + f->state = LS_INITIAL; + break; + case LS_STOPPED: + f->state = LS_CLOSED; + break; + case LS_STOPPING: + f->state = LS_CLOSING; + break; + + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + case LS_OPENED: + if( f->state != LS_OPENED ) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + } else if( f->callbacks->down ) { + (*f->callbacks->down)(f); /* Inform upper layers we're down */ + } + /* Init restart counter, send Terminate-Request */ + f->retransmits = f->maxtermtransmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + + f->state = LS_CLOSING; + break; + } + + FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_timeout - Timeout expired. + */ +static void +fsm_timeout(void *arg) +{ + fsm *f = (fsm *) arg; + + switch (f->state) { + case LS_CLOSING: + case LS_STOPPING: + if( f->retransmits <= 0 ) { + FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* + * We've waited for an ack long enough. Peer probably heard us. + */ + f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + } else { + FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* Send Terminate-Request */ + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + } + break; + + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + if (f->retransmits <= 0) { + FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + f->state = LS_STOPPED; + if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + } else { + FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* Retransmit the configure-request */ + if (f->callbacks->retransmit) { + (*f->callbacks->retransmit)(f); + } + fsm_sconfreq(f, 1); /* Re-send Configure-Request */ + if( f->state == LS_ACKRCVD ) { + f->state = LS_REQSENT; + } + } + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + +/* + * fsm_input - Input packet. + */ +void +fsm_input(fsm *f, u_char *inpacket, int l) +{ + u_char *inp = inpacket; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + if (l < HEADERLEN) { + FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n", + f->protocol)); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < HEADERLEN) { + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n", + f->protocol)); + return; + } + if (len > l) { + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n", + f->protocol)); + return; + } + len -= HEADERLEN; /* subtract header length */ + + if( f->state == LS_INITIAL || f->state == LS_STARTING ) { + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n", + f->protocol, f->state, ppperr_strerr[f->state])); + return; + } + FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); + /* + * Action depends on code. + */ + switch (code) { + case CONFREQ: + fsm_rconfreq(f, id, inp, len); + break; + + case CONFACK: + fsm_rconfack(f, id, inp, len); + break; + + case CONFNAK: + case CONFREJ: + fsm_rconfnakrej(f, code, id, inp, len); + break; + + case TERMREQ: + fsm_rtermreq(f, id, inp, len); + break; + + case TERMACK: + fsm_rtermack(f); + break; + + case CODEREJ: + fsm_rcoderej(f, inp, len); + break; + + default: + FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f))); + if( !f->callbacks->extcode || + !(*f->callbacks->extcode)(f, code, id, inp, len) ) { + fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); + } + break; + } +} + + +/* + * fsm_rconfreq - Receive Configure-Request. + */ +static void +fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) +{ + int code, reject_if_disagree; + + FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + switch( f->state ) { + case LS_CLOSED: + /* Go away, we're closed */ + fsm_sdata(f, TERMACK, id, NULL, 0); + return; + case LS_CLOSING: + case LS_STOPPING: + return; + + case LS_OPENED: + /* Go down and restart negotiation */ + if( f->callbacks->down ) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + break; + + case LS_STOPPED: + /* Negotiation started by our peer */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } + + /* + * Pass the requested configuration options + * to protocol-specific code for checking. + */ + if (f->callbacks->reqci) { /* Check CI */ + reject_if_disagree = (f->nakloops >= f->maxnakloops); + code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); + } else if (len) { + code = CONFREJ; /* Reject all CI */ + } else { + code = CONFACK; + } + + /* send the Ack, Nak or Rej to the peer */ + fsm_sdata(f, (u_char)code, id, inp, len); + + if (code == CONFACK) { + if (f->state == LS_ACKRCVD) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = LS_OPENED; + if (f->callbacks->up) { + (*f->callbacks->up)(f); /* Inform upper layers */ + } + } else { + f->state = LS_ACKSENT; + } + f->nakloops = 0; + } else { + /* we sent CONFACK or CONFREJ */ + if (f->state != LS_ACKRCVD) { + f->state = LS_REQSENT; + } + if( code == CONFNAK ) { + ++f->nakloops; + } + } +} + + +/* + * fsm_rconfack - Receive Configure-Ack. + */ +static void +fsm_rconfack(fsm *f, int id, u_char *inp, int len) +{ + FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + if (id != f->reqid || f->seen_ack) { /* Expected id? */ + return; /* Nope, toss... */ + } + if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) { + /* Ack is bad - ignore it */ + FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n", + PROTO_NAME(f), len)); + return; + } + f->seen_ack = 1; + + switch (f->state) { + case LS_CLOSED: + case LS_STOPPED: + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); + break; + + case LS_REQSENT: + f->state = LS_ACKRCVD; + f->retransmits = f->maxconfreqtransmits; + break; + + case LS_ACKRCVD: + /* Huh? an extra valid Ack? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + break; + + case LS_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = LS_OPENED; + f->retransmits = f->maxconfreqtransmits; + if (f->callbacks->up) { + (*f->callbacks->up)(f); /* Inform upper layers */ + } + break; + + case LS_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } +} + + +/* + * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + */ +static void +fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) +{ + int (*proc) (fsm *, u_char *, int); + int ret; + + FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + if (id != f->reqid || f->seen_ack) { /* Expected id? */ + return; /* Nope, toss... */ + } + proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; + if (!proc || !((ret = proc(f, inp, len)))) { + /* Nak/reject is bad - ignore it */ + FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n", + PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); + return; + } + f->seen_ack = 1; + + switch (f->state) { + case LS_CLOSED: + case LS_STOPPED: + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); + break; + + case LS_REQSENT: + case LS_ACKSENT: + /* They didn't agree to what we wanted - try another request */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + if (ret < 0) { + f->state = LS_STOPPED; /* kludge for stopping CCP */ + } else { + fsm_sconfreq(f, 0); /* Send Configure-Request */ + } + break; + + case LS_ACKRCVD: + /* Got a Nak/reject when we had already had an Ack?? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + break; + + case LS_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } +} + + +/* + * fsm_rtermreq - Receive Terminate-Req. + */ +static void +fsm_rtermreq(fsm *f, int id, u_char *p, int len) +{ + LWIP_UNUSED_ARG(p); + + FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + switch (f->state) { + case LS_ACKRCVD: + case LS_ACKSENT: + f->state = LS_REQSENT; /* Start over but keep trying */ + break; + + case LS_OPENED: + if (len > 0) { + FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p)); + } else { + FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f))); + } + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + f->retransmits = 0; + f->state = LS_STOPPING; + TIMEOUT(fsm_timeout, f, f->timeouttime); + break; + } + + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); +} + + +/* + * fsm_rtermack - Receive Terminate-Ack. + */ +static void +fsm_rtermack(fsm *f) +{ + FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + + switch (f->state) { + case LS_CLOSING: + UNTIMEOUT(fsm_timeout, f); + f->state = LS_CLOSED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_STOPPING: + UNTIMEOUT(fsm_timeout, f); + f->state = LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_ACKRCVD: + f->state = LS_REQSENT; + break; + + case LS_OPENED: + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); + break; + default: + FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + +/* + * fsm_rcoderej - Receive an Code-Reject. + */ +static void +fsm_rcoderej(fsm *f, u_char *inp, int len) +{ + u_char code, id; + + FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + + if (len < HEADERLEN) { + FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n", + PROTO_NAME(f), code, id)); + + if( f->state == LS_ACKRCVD ) { + f->state = LS_REQSENT; + } +} + + +/* + * fsm_protreject - Peer doesn't speak this protocol. + * + * Treat this as a catastrophic error (RXJ-). + */ +void +fsm_protreject(fsm *f) +{ + switch( f->state ) { + case LS_CLOSING: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + case LS_CLOSED: + f->state = LS_CLOSED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_STOPPING: + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + case LS_STOPPED: + f->state = LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_OPENED: + if( f->callbacks->down ) { + (*f->callbacks->down)(f); + } + /* Init restart counter, send Terminate-Request */ + f->retransmits = f->maxtermtransmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + + f->state = LS_STOPPING; + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + +/* + * fsm_sconfreq - Send a Configure-Request. + */ +static void +fsm_sconfreq(fsm *f, int retransmit) +{ + u_char *outp; + int cilen; + + if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) { + /* Not currently negotiating - reset options */ + if( f->callbacks->resetci ) { + (*f->callbacks->resetci)(f); + } + f->nakloops = 0; + } + + if( !retransmit ) { + /* New request - reset retransmission counter, use new ID */ + f->retransmits = f->maxconfreqtransmits; + f->reqid = ++f->id; + } + + f->seen_ack = 0; + + /* + * Make up the request packet + */ + outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN; + if( f->callbacks->cilen && f->callbacks->addci ) { + cilen = (*f->callbacks->cilen)(f); + if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) { + cilen = peer_mru[f->unit] - HEADERLEN; + } + if (f->callbacks->addci) { + (*f->callbacks->addci)(f, outp, &cilen); + } + } else { + cilen = 0; + } + + /* send the request to our peer */ + fsm_sdata(f, CONFREQ, f->reqid, outp, cilen); + + /* start the retransmit timer */ + --f->retransmits; + TIMEOUT(fsm_timeout, f, f->timeouttime); + + FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n", + PROTO_NAME(f), f->reqid)); +} + + +/* + * fsm_sdata - Send some data. + * + * Used for all packets sent to our peer by this module. + */ +void +fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) +{ + u_char *outp; + int outlen; + + /* Adjust length to be smaller than MTU */ + outp = outpacket_buf[f->unit]; + if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { + datalen = peer_mru[f->unit] - HEADERLEN; + } + if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { + BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); + } + outlen = datalen + HEADERLEN; + MAKEHEADER(outp, f->protocol); + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); + FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n", + PROTO_NAME(f), code, id, outlen)); +} + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/fsm.h b/ext/lwip/src/netif/ppp/fsm.h new file mode 100644 index 000000000..8d41b5f51 --- /dev/null +++ b/ext/lwip/src/netif/ppp/fsm.h @@ -0,0 +1,157 @@ +/***************************************************************************** +* fsm.h - Network Control Protocol Finite State Machine header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD code. +*****************************************************************************/ +/* + * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: fsm.h,v 1.5 2009/12/31 17:08:08 goldsimon Exp $ + */ + +#ifndef FSM_H +#define FSM_H + +/* + * LCP Packet header = Code, id, length. + */ +#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) + + +/* + * CP (LCP, IPCP, etc.) codes. + */ +#define CONFREQ 1 /* Configuration Request */ +#define CONFACK 2 /* Configuration Ack */ +#define CONFNAK 3 /* Configuration Nak */ +#define CONFREJ 4 /* Configuration Reject */ +#define TERMREQ 5 /* Termination Request */ +#define TERMACK 6 /* Termination Ack */ +#define CODEREJ 7 /* Code Reject */ + + +/* + * Each FSM is described by an fsm structure and fsm callbacks. + */ +typedef struct fsm { + int unit; /* Interface unit number */ + u_short protocol; /* Data Link Layer Protocol field value */ + int state; /* State */ + int flags; /* Contains option bits */ + u_char id; /* Current id */ + u_char reqid; /* Current request id */ + u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */ + int timeouttime; /* Timeout time in milliseconds */ + int maxconfreqtransmits; /* Maximum Configure-Request transmissions */ + int retransmits; /* Number of retransmissions left */ + int maxtermtransmits; /* Maximum Terminate-Request transmissions */ + int nakloops; /* Number of nak loops since last ack */ + int maxnakloops; /* Maximum number of nak loops tolerated */ + struct fsm_callbacks* callbacks; /* Callback routines */ + char* term_reason; /* Reason for closing protocol */ + int term_reason_len; /* Length of term_reason */ +} fsm; + + +typedef struct fsm_callbacks { + void (*resetci)(fsm*); /* Reset our Configuration Information */ + int (*cilen)(fsm*); /* Length of our Configuration Information */ + void (*addci)(fsm*, u_char*, int*); /* Add our Configuration Information */ + int (*ackci)(fsm*, u_char*, int); /* ACK our Configuration Information */ + int (*nakci)(fsm*, u_char*, int); /* NAK our Configuration Information */ + int (*rejci)(fsm*, u_char*, int); /* Reject our Configuration Information */ + int (*reqci)(fsm*, u_char*, int*, int); /* Request peer's Configuration Information */ + void (*up)(fsm*); /* Called when fsm reaches LS_OPENED state */ + void (*down)(fsm*); /* Called when fsm leaves LS_OPENED state */ + void (*starting)(fsm*); /* Called when we want the lower layer */ + void (*finished)(fsm*); /* Called when we don't want the lower layer */ + void (*protreject)(int); /* Called when Protocol-Reject received */ + void (*retransmit)(fsm*); /* Retransmission is necessary */ + int (*extcode)(fsm*, int, u_char, u_char*, int); /* Called when unknown code received */ + char *proto_name; /* String name for protocol (for messages) */ +} fsm_callbacks; + + +/* + * Link states. + */ +#define LS_INITIAL 0 /* Down, hasn't been opened */ +#define LS_STARTING 1 /* Down, been opened */ +#define LS_CLOSED 2 /* Up, hasn't been opened */ +#define LS_STOPPED 3 /* Open, waiting for down event */ +#define LS_CLOSING 4 /* Terminating the connection, not open */ +#define LS_STOPPING 5 /* Terminating, but open */ +#define LS_REQSENT 6 /* We've sent a Config Request */ +#define LS_ACKRCVD 7 /* We've received a Config Ack */ +#define LS_ACKSENT 8 /* We've sent a Config Ack */ +#define LS_OPENED 9 /* Connection available */ + +/* + * Flags - indicate options controlling FSM operation + */ +#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ +#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ +#define OPT_SILENT 4 /* Wait for peer to speak first */ + + +/* + * Prototypes + */ +void fsm_init (fsm*); +void fsm_lowerup (fsm*); +void fsm_lowerdown (fsm*); +void fsm_open (fsm*); +void fsm_close (fsm*, char*); +void fsm_input (fsm*, u_char*, int); +void fsm_protreject (fsm*); +void fsm_sdata (fsm*, u_char, u_char, u_char*, int); + + +/* + * Variables + */ +extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */ + +#endif /* FSM_H */ diff --git a/ext/lwip/src/netif/ppp/ipcp.c b/ext/lwip/src/netif/ppp/ipcp.c new file mode 100644 index 000000000..f0ab2e0e1 --- /dev/null +++ b/ext/lwip/src/netif/ppp/ipcp.c @@ -0,0 +1,1411 @@ +/** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and + dial-on-demand has been stripped. */ +/***************************************************************************** +* ipcp.c - Network PPP IP Control Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ +/* + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "auth.h" +#include "fsm.h" +#include "vj.h" +#include "ipcp.h" + +#include "lwip/inet.h" + +#include + +/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */ + +/* global vars */ +ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ + +/* local vars */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ +static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ + + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipcp_resetci (fsm *); /* Reset our CI */ +static int ipcp_cilen (fsm *); /* Return length of our CI */ +static void ipcp_addci (fsm *, u_char *, int *); /* Add our CI */ +static int ipcp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */ +static int ipcp_nakci (fsm *, u_char *, int); /* Peer nak'd our CI */ +static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */ +static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */ +static void ipcp_up (fsm *); /* We're UP */ +static void ipcp_down (fsm *); /* We're DOWN */ +#if PPP_ADDITIONAL_CALLBACKS +static void ipcp_script (fsm *, char *); /* Run an up/down script */ +#endif +static void ipcp_finished (fsm *); /* Don't need lower layer */ + + +fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ + + +static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ + ipcp_resetci, /* Reset our Configuration Information */ + ipcp_cilen, /* Length of our Configuration Information */ + ipcp_addci, /* Add our Configuration Information */ + ipcp_ackci, /* ACK our Configuration Information */ + ipcp_nakci, /* NAK our Configuration Information */ + ipcp_rejci, /* Reject our Configuration Information */ + ipcp_reqci, /* Request peer's Configuration Information */ + ipcp_up, /* Called when fsm reaches LS_OPENED state */ + ipcp_down, /* Called when fsm leaves LS_OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPCP" /* String name of protocol */ +}; + +/* + * Protocol entry points from main code. + */ +static void ipcp_init (int); +static void ipcp_open (int); +static void ipcp_close (int, char *); +static void ipcp_lowerup (int); +static void ipcp_lowerdown (int); +static void ipcp_input (int, u_char *, int); +static void ipcp_protrej (int); + + +struct protent ipcp_protent = { + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, +#if PPP_ADDITIONAL_CALLBACKS + ipcp_printpkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "IPCP", +#if PPP_ADDITIONAL_CALLBACKS + ip_check_options, + NULL, + ip_active_pkt +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +static void ipcp_clear_addrs (int); + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ +#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ +#define CILEN_ADDR 6 /* new-style single address option */ +#define CILEN_ADDRS 10 /* old-style dual address option */ + + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + + +/* + * ipcp_init - Initialize IPCP. + */ +static void +ipcp_init(int unit) +{ + fsm *f = &ipcp_fsm[unit]; + ipcp_options *wo = &ipcp_wantoptions[unit]; + ipcp_options *ao = &ipcp_allowoptions[unit]; + + f->unit = unit; + f->protocol = PPP_IPCP; + f->callbacks = &ipcp_callbacks; + fsm_init(&ipcp_fsm[unit]); + + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); + + wo->neg_addr = 1; + wo->ouraddr = 0; +#if VJ_SUPPORT + wo->neg_vj = 1; +#else /* VJ_SUPPORT */ + wo->neg_vj = 0; +#endif /* VJ_SUPPORT */ + wo->vj_protocol = IPCP_VJ_COMP; + wo->maxslotindex = MAX_SLOTS - 1; + wo->cflag = 0; + wo->default_route = 1; + + ao->neg_addr = 1; +#if VJ_SUPPORT + ao->neg_vj = 1; +#else /* VJ_SUPPORT */ + ao->neg_vj = 0; +#endif /* VJ_SUPPORT */ + ao->maxslotindex = MAX_SLOTS - 1; + ao->cflag = 1; + ao->default_route = 1; +} + + +/* + * ipcp_open - IPCP is allowed to come up. + */ +static void +ipcp_open(int unit) +{ + fsm_open(&ipcp_fsm[unit]); +} + + +/* + * ipcp_close - Take IPCP down. + */ +static void +ipcp_close(int unit, char *reason) +{ + fsm_close(&ipcp_fsm[unit], reason); +} + + +/* + * ipcp_lowerup - The lower layer is up. + */ +static void +ipcp_lowerup(int unit) +{ + fsm_lowerup(&ipcp_fsm[unit]); +} + + +/* + * ipcp_lowerdown - The lower layer is down. + */ +static void +ipcp_lowerdown(int unit) +{ + fsm_lowerdown(&ipcp_fsm[unit]); +} + + +/* + * ipcp_input - Input IPCP packet. + */ +static void +ipcp_input(int unit, u_char *p, int len) +{ + fsm_input(&ipcp_fsm[unit], p, len); +} + + +/* + * ipcp_protrej - A Protocol-Reject was received for IPCP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void +ipcp_protrej(int unit) +{ + fsm_lowerdown(&ipcp_fsm[unit]); +} + + +/* + * ipcp_resetci - Reset our CI. + */ +static void +ipcp_resetci(fsm *f) +{ + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + + wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; + if (wo->ouraddr == 0) { + wo->accept_local = 1; + } + if (wo->hisaddr == 0) { + wo->accept_remote = 1; + } + /* Request DNS addresses from the peer */ + wo->req_dns1 = ppp_settings.usepeerdns; + wo->req_dns2 = ppp_settings.usepeerdns; + ipcp_gotoptions[f->unit] = *wo; + cis_received[f->unit] = 0; +} + + +/* + * ipcp_cilen - Return length of our CI. + */ +static int +ipcp_cilen(fsm *f) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + +#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) +#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) +#define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) + + /* + * First see if we want to change our options to the old + * forms because we have received old forms from the peer. + */ + if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { + /* use the old style of address negotiation */ + go->neg_addr = 1; + go->old_addrs = 1; + } + if (wo->neg_vj && !go->neg_vj && !go->old_vj) { + /* try an older style of VJ negotiation */ + if (cis_received[f->unit] == 0) { + /* keep trying the new style until we see some CI from the peer */ + go->neg_vj = 1; + } else { + /* use the old style only if the peer did */ + if (ho->neg_vj && ho->old_vj) { + go->neg_vj = 1; + go->old_vj = 1; + go->vj_protocol = ho->vj_protocol; + } + } + } + + return (LENCIADDR(go->neg_addr, go->old_addrs) + + LENCIVJ(go->neg_vj, go->old_vj) + + LENCIDNS(go->req_dns1) + + LENCIDNS(go->req_dns2)); +} + + +/* + * ipcp_addci - Add our desired CIs to a packet. + */ +static void +ipcp_addci(fsm *f, u_char *ucp, int *lenp) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + int len = *lenp; + +#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + if (!old) { \ + PUTCHAR(maxslotindex, ucp); \ + PUTCHAR(cflag, ucp); \ + } \ + len -= vjlen; \ + } else { \ + neg = 0; \ + } \ + } + +#define ADDCIADDR(opt, neg, old, val1, val2) \ + if (neg) { \ + int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ + if (len >= addrlen) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(addrlen, ucp); \ + l = ntohl(val1); \ + PUTLONG(l, ucp); \ + if (old) { \ + l = ntohl(val2); \ + PUTLONG(l, ucp); \ + } \ + len -= addrlen; \ + } else { \ + neg = 0; \ + } \ + } + +#define ADDCIDNS(opt, neg, addr) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else { \ + neg = 0; \ + } \ + } + + ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + + *lenp -= len; +} + + +/* + * ipcp_ackci - Ack our CIs. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int +ipcp_ackci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_short cilen, citype, cishort; + u32_t cilong; + u_char cimaxslotindex, cicflag; + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if ((len -= vjlen) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) { \ + goto bad; \ + } \ + GETSHORT(cishort, p); \ + if (cishort != val) { \ + goto bad; \ + } \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslotindex) { \ + goto bad; \ + } \ + GETCHAR(cicflag, p); \ + if (cicflag != cflag) { \ + goto bad; \ + } \ + } \ + } + +#define ACKCIADDR(opt, neg, old, val1, val2) \ + if (neg) { \ + int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ + u32_t l; \ + if ((len -= addrlen) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != addrlen || \ + citype != opt) { \ + goto bad; \ + } \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val1 != cilong) { \ + goto bad; \ + } \ + if (old) { \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val2 != cilong) { \ + goto bad; \ + } \ + } \ + } + +#define ACKCIDNS(opt, neg, addr) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || \ + citype != opt) { \ + goto bad; \ + } \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != cilong) { \ + goto bad; \ + } \ + } + + ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + return (1); + +bad: + IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n")); + return (0); +} + +/* + * ipcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPCP is in the LS_OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int +ipcp_nakci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_char cimaxslotindex, cicflag; + u_char citype, cilen, *next; + u_short cishort; + u32_t ciaddr1, ciaddr2, l, cidnsaddr; + ipcp_options no; /* options we've seen Naks for */ + ipcp_options try; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIADDR(opt, neg, old, code) \ + if (go->neg && \ + len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = htonl(l); \ + if (old) { \ + GETLONG(l, p); \ + ciaddr2 = htonl(l); \ + no.old_addrs = 1; \ + } else { \ + ciaddr2 = 0; \ + } \ + no.neg = 1; \ + code \ + } + +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } + +#define NAKCIDNS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cidnsaddr = htonl(l); \ + no.neg = 1; \ + code \ + } + + /* + * Accept the peer's idea of {our,his} address, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, + if (go->accept_local && ciaddr1) { /* Do we know our address? */ + try.ouraddr = ciaddr1; + IPCPDEBUG(LOG_INFO, ("local IP address %s\n", + inet_ntoa(ciaddr1))); + } + if (go->accept_remote && ciaddr2) { /* Does he know his? */ + try.hisaddr = ciaddr2; + IPCPDEBUG(LOG_INFO, ("remote IP address %s\n", + inet_ntoa(ciaddr2))); + } + ); + + /* + * Accept the peer's value of maxslotindex provided that it + * is less than what we asked for. Turn off slot-ID compression + * if the peer wants. Send old-style compress-type option if + * the peer wants. + */ + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + if (cilen == CILEN_VJ) { + GETCHAR(cimaxslotindex, p); + GETCHAR(cicflag, p); + if (cishort == IPCP_VJ_COMP) { + try.old_vj = 0; + if (cimaxslotindex < go->maxslotindex) { + try.maxslotindex = cimaxslotindex; + } + if (!cicflag) { + try.cflag = 0; + } + } else { + try.neg_vj = 0; + } + } else { + if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { + try.old_vj = 1; + try.vj_protocol = cishort; + } else { + try.neg_vj = 0; + } + } + ); + + NAKCIDNS(CI_MS_DNS1, req_dns1, + try.dnsaddr[0] = cidnsaddr; + IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr))); + ); + + NAKCIDNS(CI_MS_DNS2, req_dns2, + try.dnsaddr[1] = cidnsaddr; + IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr))); + ); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about IP addresses, we comply. + * If they want us to ask for compression, we refuse. + */ + while (len > CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if( (len -= cilen) < 0 ) { + goto bad; + } + next = p + cilen - 2; + + switch (citype) { + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { + goto bad; + } + no.neg_vj = 1; + break; + case CI_ADDRS: + if ((go->neg_addr && go->old_addrs) || no.old_addrs + || cilen != CILEN_ADDRS) { + goto bad; + } + try.neg_addr = 1; + try.old_addrs = 1; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) { + try.ouraddr = ciaddr1; + } + GETLONG(l, p); + ciaddr2 = htonl(l); + if (ciaddr2 && go->accept_remote) { + try.hisaddr = ciaddr2; + } + no.old_addrs = 1; + break; + case CI_ADDR: + if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) { + goto bad; + } + try.old_addrs = 0; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) { + try.ouraddr = ciaddr1; + } + if (try.ouraddr != 0) { + try.neg_addr = 1; + } + no.neg_addr = 1; + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) { + goto bad; + } + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + + return 1; + +bad: + IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n")); + return 0; +} + + +/* + * ipcp_rejci - Reject some of our CIs. + */ +static int +ipcp_rejci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_char cimaxslotindex, ciflag, cilen; + u_short cishort; + u32_t cilong; + ipcp_options try; /* options to request next time */ + + try = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIADDR(opt, neg, old, val1, val2) \ + if (go->neg && \ + len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ + p[1] == cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val1) { \ + goto bad; \ + } \ + if (old) { \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val2) { \ + goto bad; \ + } \ + } \ + try.neg = 0; \ + } + +#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ + if (go->neg && \ + p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) { \ + goto bad; \ + } \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslot) { \ + goto bad; \ + } \ + GETCHAR(ciflag, p); \ + if (ciflag != cflag) { \ + goto bad; \ + } \ + } \ + try.neg = 0; \ + } + +#define REJCIDNS(opt, neg, dnsaddr) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != dnsaddr) { \ + goto bad; \ + } \ + try.neg = 0; \ + } + + REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); + + REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + /* + * Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + return 1; + +bad: + IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n")); + return 0; +} + + +/* + * ipcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + */ +static int +ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree) +{ + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + ipcp_options *ao = &ipcp_allowoptions[f->unit]; +#ifdef OLD_CI_ADDRS + ipcp_options *go = &ipcp_gotoptions[f->unit]; +#endif + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ + u_short cishort; /* Parsed short value */ + u32_t tl, ciaddr1; /* Parsed address values */ +#ifdef OLD_CI_ADDRS + u32_t ciaddr2; /* Parsed address values */ +#endif + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + u_char maxslotindex, cflag; + int d; + + cis_received[f->unit] = 1; + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n")); + orc = CONFREJ; /* Reject bad CI */ + cilen = (u_short)l;/* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ +#ifdef OLD_CI_ADDRS /* Need to save space... */ + case CI_ADDRS: + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n")); + if (!ao->neg_addr || + cilen != CILEN_ADDRS) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1))); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * If neither we nor he knows his address, reject the option. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + /* + * If he doesn't know our address, or if we both have our address + * but disagree about it, then NAK it with our idea. + */ + GETLONG(tl, p); /* Parse desination address (ours) */ + ciaddr2 = htonl(tl); + IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2))); + if (ciaddr2 != wo->ouraddr) { + if (ciaddr2 == 0 || !wo->accept_local) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->ouraddr); + PUTLONG(tl, p); + } + } else { + go->ouraddr = ciaddr2; /* accept peer's idea */ + } + } + + ho->neg_addr = 1; + ho->old_addrs = 1; + ho->hisaddr = ciaddr1; + ho->ouraddr = ciaddr2; + break; +#endif + + case CI_ADDR: + if (!ao->neg_addr) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n")); + orc = CONFREJ; /* Reject CI */ + break; + } else if (cilen != CILEN_ADDR) { /* Check CI length */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n")); + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1))); + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * Don't ACK an address of 0.0.0.0 - reject it instead. + */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1))); + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + ho->neg_addr = 1; + ho->hisaddr = ciaddr1; + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1))); + break; + + case CI_MS_DNS1: + case CI_MS_DNS2: + /* Microsoft primary or secondary DNS request */ + d = citype == CI_MS_DNS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1)); + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->dnsaddr[d]) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n", + d+1, inet_ntoa(tl))); + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->dnsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1)); + break; + + case CI_MS_WINS1: + case CI_MS_WINS2: + /* Microsoft primary or secondary WINS request */ + d = citype == CI_MS_WINS2; + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1)); + + /* If we do not have a DNS address then we cannot send it */ + if (ao->winsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->winsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->winsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; + + case CI_COMPRESSTYPE: + if (!ao->neg_vj) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen)); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + if (!(cishort == IPCP_VJ_COMP || + (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort)); + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + if (cilen == CILEN_VJ) { + GETCHAR(maxslotindex, p); + if (maxslotindex > ao->maxslotindex) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex)); + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(1, p); + PUTCHAR(ao->maxslotindex, p); + } + } + GETCHAR(cflag, p); + if (cflag && !ao->cflag) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag)); + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(1, p); + PUTCHAR(wo->cflag, p); + } + } + ho->maxslotindex = maxslotindex; + ho->cflag = cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_SLOTS - 1; + ho->cflag = 1; + } + IPCPDEBUG(LOG_INFO, ( + "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n", + ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag)); + break; + + default: + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype)); + orc = CONFREJ; + break; + } + +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) { /* but prior CI wasnt? */ + continue; /* Don't send this one */ + } + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) { /* Getting fed up with sending NAKs? */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n")); + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) { /* Rejecting prior CI? */ + continue; /* Don't send this one */ + } + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) { + BCOPY(cip, ucp, cilen); /* Move it */ + } + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their address, and they didn't send their address, then we + * send a NAK with a CI_ADDR option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_addr && + wo->req_addr && !reject_if_disagree) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n")); + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_addr = 0; /* don't ask again */ + } + PUTCHAR(CI_ADDR, ucp); + PUTCHAR(CILEN_ADDR, ucp); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, ucp); + } + + *len = (int)(ucp - inp); /* Compute output length */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +#if 0 +/* + * ip_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void +ip_check_options(u_long localAddr) +{ + ipcp_options *wo = &ipcp_wantoptions[0]; + + /* + * Load our default IP address but allow the remote host to give us + * a new address. + */ + if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) { + wo->accept_local = 1; /* don't insist on this default value */ + wo->ouraddr = htonl(localAddr); + } +} +#endif + + +/* + * ipcp_up - IPCP has come UP. + * + * Configure the IP network interface appropriately and bring it up. + */ +static void +ipcp_up(fsm *f) +{ + u32_t mask; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + ipcp_options *go = &ipcp_gotoptions[f->unit]; + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + + np_up(f->unit, PPP_IP); + IPCPDEBUG(LOG_INFO, ("ipcp: up\n")); + + /* + * We must have a non-zero IP address for both ends of the link. + */ + if (!ho->neg_addr) { + ho->hisaddr = wo->hisaddr; + } + + if (ho->hisaddr == 0) { + IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n")); + ipcp_close(f->unit, "Could not determine remote IP address"); + return; + } + if (go->ouraddr == 0) { + IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n")); + ipcp_close(f->unit, "Could not determine local IP address"); + return; + } + + if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { + /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/ + } + + /* + * Check that the peer is allowed to use the IP address it wants. + */ + if (!auth_ip_addr(f->unit, ho->hisaddr)) { + IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n", + inet_ntoa(ho->hisaddr))); + ipcp_close(f->unit, "Unauthorized remote IP address"); + return; + } + + /* set tcp compression */ + sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); + + /* + * Set IP addresses and (if specified) netmask. + */ + mask = GetMask(go->ouraddr); + + if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) { + IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n")); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + /* bring the interface up for IP */ + if (!sifup(f->unit)) { + IPCPDEBUG(LOG_WARNING, ("sifup failed\n")); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + sifnpmode(f->unit, PPP_IP, NPMODE_PASS); + + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) { + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) { + default_route_set[f->unit] = 1; + } + } + + IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr))); + IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr))); + if (go->dnsaddr[0]) { + IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); + } + if (go->dnsaddr[1]) { + IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); + } +} + + +/* + * ipcp_down - IPCP has gone DOWN. + * + * Take the IP network interface down, clear its addresses + * and delete routes through it. + */ +static void +ipcp_down(fsm *f) +{ + IPCPDEBUG(LOG_INFO, ("ipcp: down\n")); + np_down(f->unit, PPP_IP); + sifvjcomp(f->unit, 0, 0, 0); + + sifdown(f->unit); + ipcp_clear_addrs(f->unit); +} + + +/* + * ipcp_clear_addrs() - clear the interface addresses, routes, etc. + */ +static void +ipcp_clear_addrs(int unit) +{ + u32_t ouraddr, hisaddr; + + ouraddr = ipcp_gotoptions[unit].ouraddr; + hisaddr = ipcp_hisoptions[unit].hisaddr; + if (default_route_set[unit]) { + cifdefaultroute(unit, ouraddr, hisaddr); + default_route_set[unit] = 0; + } + cifaddr(unit, ouraddr, hisaddr); +} + + +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void +ipcp_finished(fsm *f) +{ + np_finished(f->unit, PPP_IP); +} + +#if PPP_ADDITIONAL_CALLBACKS +static int +ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(plen); + LWIP_UNUSED_ARG(printer); + LWIP_UNUSED_ARG(arg); + return 0; +} + +/* + * ip_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP_HDRLEN 20 /* bytes */ +#define IP_OFFMASK 0x1fff +#define IPPROTO_TCP 6 +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define net_short(x) (((x)[0] << 8) + (x)[1]) +#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) +#define get_ipoff(x) net_short((unsigned char *)(x) + 6) +#define get_ipproto(x) (((unsigned char *)(x))[9]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int +ip_active_pkt(u_char *pkt, int len) +{ + u_char *tcp; + int hlen; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP_HDRLEN) { + return 0; + } + if ((get_ipoff(pkt) & IP_OFFMASK) != 0) { + return 0; + } + if (get_ipproto(pkt) != IPPROTO_TCP) { + return 1; + } + hlen = get_iphl(pkt) * 4; + if (len < hlen + TCP_HDRLEN) { + return 0; + } + tcp = pkt + hlen; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) { + return 0; + } + return 1; +} +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/ipcp.h b/ext/lwip/src/netif/ppp/ipcp.h new file mode 100644 index 000000000..de03f460e --- /dev/null +++ b/ext/lwip/src/netif/ppp/ipcp.h @@ -0,0 +1,106 @@ +/***************************************************************************** +* ipcp.h - PPP IP NCP: Internet Protocol Network Control Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: ipcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $ + */ + +#ifndef IPCP_H +#define IPCP_H + +/* + * Options. + */ +#define CI_ADDRS 1 /* IP Addresses */ +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#define CI_ADDR 3 + +#define CI_MS_DNS1 129 /* Primary DNS value */ +#define CI_MS_WINS1 128 /* Primary WINS value */ +#define CI_MS_DNS2 131 /* Secondary DNS value */ +#define CI_MS_WINS2 130 /* Secondary WINS value */ + +#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ +#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ +#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ + /* maxslot and slot number compression) */ + +#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option */ +#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ + /* compression option */ + +typedef struct ipcp_options { + u_int neg_addr : 1; /* Negotiate IP Address? */ + u_int old_addrs : 1; /* Use old (IP-Addresses) option? */ + u_int req_addr : 1; /* Ask peer to send IP address? */ + u_int default_route : 1; /* Assign default route through interface? */ + u_int proxy_arp : 1; /* Make proxy ARP entry for peer? */ + u_int neg_vj : 1; /* Van Jacobson Compression? */ + u_int old_vj : 1; /* use old (short) form of VJ option? */ + u_int accept_local : 1; /* accept peer's value for ouraddr */ + u_int accept_remote : 1; /* accept peer's value for hisaddr */ + u_int req_dns1 : 1; /* Ask peer to send primary DNS address? */ + u_int req_dns2 : 1; /* Ask peer to send secondary DNS address? */ + u_short vj_protocol; /* protocol value to use in VJ option */ + u_char maxslotindex; /* VJ slots - 1. */ + u_char cflag; /* VJ slot compression flag. */ + u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ + u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ + u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ +} ipcp_options; + +extern fsm ipcp_fsm[]; +extern ipcp_options ipcp_wantoptions[]; +extern ipcp_options ipcp_gotoptions[]; +extern ipcp_options ipcp_allowoptions[]; +extern ipcp_options ipcp_hisoptions[]; + +extern struct protent ipcp_protent; + +#endif /* IPCP_H */ diff --git a/ext/lwip/src/netif/ppp/lcp.c b/ext/lwip/src/netif/ppp/lcp.c new file mode 100644 index 000000000..54f758aa6 --- /dev/null +++ b/ext/lwip/src/netif/ppp/lcp.c @@ -0,0 +1,2066 @@ +/***************************************************************************** +* lcp.c - Network Link Control Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-01 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * lcp.c - PPP Link Control Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "fsm.h" +#include "chap.h" +#include "magic.h" +#include "auth.h" +#include "lcp.h" + +#include + +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#else +#define PPPOE_MAXMTU PPP_MAXMRU +#endif + +#if 0 /* UNUSED */ +/* + * LCP-related command-line options. + */ +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +bool lax_recv = 0; /* accept control chars in asyncmap */ + +static int setescape (char **); + +static option_t lcp_option_list[] = { + /* LCP options */ + /* list stripped for simplicity */ + {NULL} +}; +#endif /* UNUSED */ + +/* options */ +LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ +static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ +static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ + +/* global vars */ +static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ +lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ +ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */ + +static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ +static u32_t lcp_echo_number = 0; /* ID number of next echo frame */ +static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ + +/* @todo: do we really need such a large buffer? The typical 1500 bytes seem too much. */ +static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void lcp_resetci (fsm*); /* Reset our CI */ +static int lcp_cilen (fsm*); /* Return length of our CI */ +static void lcp_addci (fsm*, u_char*, int*); /* Add our CI to pkt */ +static int lcp_ackci (fsm*, u_char*, int); /* Peer ack'd our CI */ +static int lcp_nakci (fsm*, u_char*, int); /* Peer nak'd our CI */ +static int lcp_rejci (fsm*, u_char*, int); /* Peer rej'd our CI */ +static int lcp_reqci (fsm*, u_char*, int*, int); /* Rcv peer CI */ +static void lcp_up (fsm*); /* We're UP */ +static void lcp_down (fsm*); /* We're DOWN */ +static void lcp_starting (fsm*); /* We need lower layer up */ +static void lcp_finished (fsm*); /* We need lower layer down */ +static int lcp_extcode (fsm*, int, u_char, u_char*, int); +static void lcp_rprotrej (fsm*, u_char*, int); + +/* + * routines to send LCP echos to peer + */ + +static void lcp_echo_lowerup (int); +static void lcp_echo_lowerdown (int); +static void LcpEchoTimeout (void*); +static void lcp_received_echo_reply (fsm*, int, u_char*, int); +static void LcpSendEchoRequest (fsm*); +static void LcpLinkFailure (fsm*); +static void LcpEchoCheck (fsm*); + +static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ + lcp_resetci, /* Reset our Configuration Information */ + lcp_cilen, /* Length of our Configuration Information */ + lcp_addci, /* Add our Configuration Information */ + lcp_ackci, /* ACK our Configuration Information */ + lcp_nakci, /* NAK our Configuration Information */ + lcp_rejci, /* Reject our Configuration Information */ + lcp_reqci, /* Request peer's Configuration Information */ + lcp_up, /* Called when fsm reaches LS_OPENED state */ + lcp_down, /* Called when fsm leaves LS_OPENED state */ + lcp_starting, /* Called when we want the lower layer up */ + lcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + lcp_extcode, /* Called to handle LCP-specific codes */ + "LCP" /* String name of protocol */ +}; + +/* + * Protocol entry points. + * Some of these are called directly. + */ + +static void lcp_input (int, u_char *, int); +static void lcp_protrej (int); + +struct protent lcp_protent = { + PPP_LCP, + lcp_init, + lcp_input, + lcp_protrej, + lcp_lowerup, + lcp_lowerdown, + lcp_open, + lcp_close, +#if PPP_ADDITIONAL_CALLBACKS + lcp_printpkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "LCP", +#if PPP_ADDITIONAL_CALLBACKS + NULL, + NULL, + NULL +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +int lcp_loopbackfail = DEFLOOPBACKFAIL; + +/* + * Length of each type of configuration option (in octets) + */ +#define CILEN_VOID 2 +#define CILEN_CHAR 3 +#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ +#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ +#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ +#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ +#define CILEN_CBCP 3 + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED */ +/* + * setescape - add chars to the set we escape on transmission. + */ +static int +setescape(argv) + char **argv; +{ + int n, ret; + char *p, *endp; + + p = *argv; + ret = 1; + while (*p) { + n = strtol(p, &endp, 16); + if (p == endp) { + option_error("escape parameter contains invalid hex number '%s'", p); + return 0; + } + p = endp; + if (n < 0 || n == 0x5E || n > 0xFF) { + option_error("can't escape character 0x%x", n); + ret = 0; + } else + xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); + while (*p == ',' || *p == ' ') + ++p; + } + return ret; +} +#endif /* UNUSED */ + +/* + * lcp_init - Initialize LCP. + */ +void +lcp_init(int unit) +{ + fsm *f = &lcp_fsm[unit]; + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *ao = &lcp_allowoptions[unit]; + + f->unit = unit; + f->protocol = PPP_LCP; + f->callbacks = &lcp_callbacks; + + fsm_init(f); + + wo->passive = 0; + wo->silent = 0; + wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */ + wo->neg_mru = 1; + wo->mru = PPP_DEFMRU; + wo->neg_asyncmap = 1; + wo->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ + wo->neg_chap = 0; /* Set to 1 on server */ + wo->neg_upap = 0; /* Set to 1 on server */ + wo->chap_mdtype = CHAP_DIGEST_MD5; + wo->neg_magicnumber = 1; + wo->neg_pcompression = 1; + wo->neg_accompression = 1; + wo->neg_lqr = 0; /* no LQR implementation yet */ + wo->neg_cbcp = 0; + + ao->neg_mru = 1; + ao->mru = PPP_MAXMRU; + ao->neg_asyncmap = 1; + ao->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ + ao->neg_chap = (CHAP_SUPPORT != 0); + ao->chap_mdtype = CHAP_DIGEST_MD5; + ao->neg_upap = (PAP_SUPPORT != 0); + ao->neg_magicnumber = 1; + ao->neg_pcompression = 1; + ao->neg_accompression = 1; + ao->neg_lqr = 0; /* no LQR implementation yet */ + ao->neg_cbcp = (CBCP_SUPPORT != 0); + + /* + * Set transmit escape for the flag and escape characters plus anything + * set for the allowable options. + */ + memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); + xmit_accm[unit][15] = 0x60; + xmit_accm[unit][0] = (u_char)((ao->asyncmap & 0xFF)); + xmit_accm[unit][1] = (u_char)((ao->asyncmap >> 8) & 0xFF); + xmit_accm[unit][2] = (u_char)((ao->asyncmap >> 16) & 0xFF); + xmit_accm[unit][3] = (u_char)((ao->asyncmap >> 24) & 0xFF); + LCPDEBUG(LOG_INFO, ("lcp_init: xmit_accm=%X %X %X %X\n", + xmit_accm[unit][0], + xmit_accm[unit][1], + xmit_accm[unit][2], + xmit_accm[unit][3])); + + lcp_phase[unit] = PHASE_INITIALIZE; +} + + +/* + * lcp_open - LCP is allowed to come up. + */ +void +lcp_open(int unit) +{ + fsm *f = &lcp_fsm[unit]; + lcp_options *wo = &lcp_wantoptions[unit]; + + f->flags = 0; + if (wo->passive) { + f->flags |= OPT_PASSIVE; + } + if (wo->silent) { + f->flags |= OPT_SILENT; + } + fsm_open(f); + + lcp_phase[unit] = PHASE_ESTABLISH; +} + + +/* + * lcp_close - Take LCP down. + */ +void +lcp_close(int unit, char *reason) +{ + fsm *f = &lcp_fsm[unit]; + + if (lcp_phase[unit] != PHASE_DEAD) { + lcp_phase[unit] = PHASE_TERMINATE; + } + if (f->state == LS_STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { + /* + * This action is not strictly according to the FSM in RFC1548, + * but it does mean that the program terminates if you do an + * lcp_close() in passive/silent mode when a connection hasn't + * been established. + */ + f->state = LS_CLOSED; + lcp_finished(f); + } else { + fsm_close(f, reason); + } +} + + +/* + * lcp_lowerup - The lower layer is up. + */ +void +lcp_lowerup(int unit) +{ + lcp_options *wo = &lcp_wantoptions[unit]; + + /* + * Don't use A/C or protocol compression on transmission, + * but accept A/C and protocol compressed packets + * if we are going to ask for A/C and protocol compression. + */ + ppp_set_xaccm(unit, &xmit_accm[unit]); + ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0); + ppp_recv_config(unit, PPP_MRU, 0x00000000l, + wo->neg_pcompression, wo->neg_accompression); + peer_mru[unit] = PPP_MRU; + lcp_allowoptions[unit].asyncmap = (u_long)xmit_accm[unit][0] + | ((u_long)xmit_accm[unit][1] << 8) + | ((u_long)xmit_accm[unit][2] << 16) + | ((u_long)xmit_accm[unit][3] << 24); + LCPDEBUG(LOG_INFO, ("lcp_lowerup: asyncmap=%X %X %X %X\n", + xmit_accm[unit][3], + xmit_accm[unit][2], + xmit_accm[unit][1], + xmit_accm[unit][0])); + + fsm_lowerup(&lcp_fsm[unit]); +} + + +/* + * lcp_lowerdown - The lower layer is down. + */ +void +lcp_lowerdown(int unit) +{ + fsm_lowerdown(&lcp_fsm[unit]); +} + + +/* + * lcp_input - Input LCP packet. + */ +static void +lcp_input(int unit, u_char *p, int len) +{ + fsm *f = &lcp_fsm[unit]; + + fsm_input(f, p, len); +} + + +/* + * lcp_extcode - Handle a LCP-specific code. + */ +static int +lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len) +{ + u_char *magp; + + switch( code ){ + case PROTREJ: + lcp_rprotrej(f, inp, len); + break; + + case ECHOREQ: + if (f->state != LS_OPENED) { + break; + } + LCPDEBUG(LOG_INFO, ("lcp: Echo-Request, Rcvd id %d\n", id)); + magp = inp; + PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp); + fsm_sdata(f, ECHOREP, id, inp, len); + break; + + case ECHOREP: + lcp_received_echo_reply(f, id, inp, len); + break; + + case DISCREQ: + break; + + default: + return 0; + } + return 1; +} + + +/* + * lcp_rprotrej - Receive an Protocol-Reject. + * + * Figure out which protocol is rejected and inform it. + */ +static void +lcp_rprotrej(fsm *f, u_char *inp, int len) +{ + int i; + struct protent *protp; + u_short prot; + + if (len < (int)sizeof (u_short)) { + LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd short Protocol-Reject packet!\n")); + return; + } + + GETSHORT(prot, inp); + + LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot)); + + /* + * Protocol-Reject packets received in any state other than the LCP + * LS_OPENED state SHOULD be silently discarded. + */ + if( f->state != LS_OPENED ) { + LCPDEBUG(LOG_INFO, ("Protocol-Reject discarded: LCP in state %d\n", f->state)); + return; + } + + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol == prot && protp->enabled_flag) { + (*protp->protrej)(f->unit); + return; + } + } + + LCPDEBUG(LOG_WARNING, ("Protocol-Reject for unsupported protocol 0x%x\n", prot)); +} + + +/* + * lcp_protrej - A Protocol-Reject was received. + */ +static void +lcp_protrej(int unit) +{ + LWIP_UNUSED_ARG(unit); + /* + * Can't reject LCP! + */ + LCPDEBUG(LOG_WARNING, ("lcp_protrej: Received Protocol-Reject for LCP!\n")); + fsm_protreject(&lcp_fsm[unit]); +} + + +/* + * lcp_sprotrej - Send a Protocol-Reject for some protocol. + */ +void +lcp_sprotrej(int unit, u_char *p, int len) +{ + /* + * Send back the protocol and the information field of the + * rejected packet. We only get here if LCP is in the LS_OPENED state. + */ + + fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len); +} + + +/* + * lcp_resetci - Reset our CI. + */ +static void +lcp_resetci(fsm *f) +{ + lcp_wantoptions[f->unit].magicnumber = magic(); + lcp_wantoptions[f->unit].numloops = 0; + lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit]; + peer_mru[f->unit] = PPP_MRU; + auth_reset(f->unit); +} + + +/* + * lcp_cilen - Return length of our CI. + */ +static int +lcp_cilen(fsm *f) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + +#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) +#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) +#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) +#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) +#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) +#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) + /* + * NB: we only ask for one of CHAP and UPAP, even if we will + * accept either. + */ + return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + + LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) + + LENCICHAP(go->neg_chap) + + LENCISHORT(!go->neg_chap && go->neg_upap) + + LENCILQR(go->neg_lqr) + + LENCICBCP(go->neg_cbcp) + + LENCILONG(go->neg_magicnumber) + + LENCIVOID(go->neg_pcompression) + + LENCIVOID(go->neg_accompression)); +} + + +/* + * lcp_addci - Add our desired CIs to a packet. + */ +static void +lcp_addci(fsm *f, u_char *ucp, int *lenp) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char *start_ucp = ucp; + +#define ADDCIVOID(opt, neg) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: opt=%d\n", opt)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_VOID, ucp); \ + } +#define ADDCISHORT(opt, neg, val) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: INT opt=%d %X\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_SHORT, ucp); \ + PUTSHORT(val, ucp); \ + } +#define ADDCICHAP(opt, neg, val, digest) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: CHAP opt=%d %X\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAP, ucp); \ + PUTSHORT(val, ucp); \ + PUTCHAR(digest, ucp); \ + } +#define ADDCILONG(opt, neg, val) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: L opt=%d %lX\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LONG, ucp); \ + PUTLONG(val, ucp); \ + } +#define ADDCILQR(opt, neg, val) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: LQR opt=%d %lX\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ + PUTLONG(val, ucp); \ + } +#define ADDCICHAR(opt, neg, val) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR, ucp); \ + PUTCHAR(val, ucp); \ + } + + ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); + ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); + ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); + + if (ucp - start_ucp != *lenp) { + /* this should never happen, because peer_mtu should be 1500 */ + LCPDEBUG(LOG_ERR, ("Bug in lcp_addci: wrong length\n")); + } +} + + +/* + * lcp_ackci - Ack our CIs. + * This should not modify any state if the Ack is bad. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int +lcp_ackci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char cilen, citype, cichar; + u_short cishort; + u32_t cilong; + + /* + * CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define ACKCIVOID(opt, neg) \ + if (neg) { \ + if ((len -= CILEN_VOID) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || citype != opt) \ + goto bad; \ + } +#define ACKCISHORT(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_SHORT) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_SHORT || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#define ACKCICHAR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR || citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != val) \ + goto bad; \ + } +#define ACKCICHAP(opt, neg, val, digest) \ + if (neg) { \ + if ((len -= CILEN_CHAP) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAP || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != digest) \ + goto bad; \ + } +#define ACKCILONG(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LONG) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LONG || citype != opt) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#define ACKCILQR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LQR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LQR || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_LQR) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } + + ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); + ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); + ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + LCPDEBUG(LOG_INFO, ("lcp_acki: Ack\n")); + return (1); +bad: + LCPDEBUG(LOG_WARNING, ("lcp_acki: received bad Ack!\n")); + return (0); +} + + +/* + * lcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if LCP is in the LS_OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int +lcp_nakci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *wo = &lcp_wantoptions[f->unit]; + u_char citype, cichar, *next; + u_short cishort; + u32_t cilong; + lcp_options no; /* options we've seen Naks for */ + lcp_options try; /* options to request next time */ + int looped_back = 0; + int cilen; + + BZERO(&no, sizeof(no)); + try = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIVOID(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + no.neg = 1; \ + code \ + } +#define NAKCICHAP(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCICHAR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[1] == CILEN_CHAR && \ + p[0] == opt) { \ + len -= CILEN_CHAR; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCISHORT(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILONG(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILQR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } + + /* + * We don't care if they want to send us smaller packets than + * we want. Therefore, accept any MRU less than what we asked for, + * but then ignore the new value when setting the MRU in the kernel. + * If they send us a bigger MRU than what we asked, accept it, up to + * the limit of the default MRU we'd get if we didn't negotiate. + */ + if (go->neg_mru && go->mru != PPP_DEFMRU) { + NAKCISHORT(CI_MRU, neg_mru, + if (cishort <= wo->mru || cishort < PPP_DEFMRU) { + try.mru = cishort; + } + ); + } + + /* + * Add any characters they want to our (receive-side) asyncmap. + */ + if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) { + NAKCILONG(CI_ASYNCMAP, neg_asyncmap, + try.asyncmap = go->asyncmap | cilong; + ); + } + + /* + * If they've nak'd our authentication-protocol, check whether + * they are proposing a different protocol, or a different + * hash algorithm for CHAP. + */ + if ((go->neg_chap || go->neg_upap) + && len >= CILEN_SHORT + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { + cilen = p[1]; + len -= cilen; + no.neg_chap = go->neg_chap; + no.neg_upap = go->neg_upap; + INCPTR(2, p); + GETSHORT(cishort, p); + if (cishort == PPP_PAP && cilen == CILEN_SHORT) { + /* + * If we were asking for CHAP, they obviously don't want to do it. + * If we weren't asking for CHAP, then we were asking for PAP, + * in which case this Nak is bad. + */ + if (!go->neg_chap) { + goto bad; + } + try.neg_chap = 0; + + } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { + GETCHAR(cichar, p); + if (go->neg_chap) { + /* + * We were asking for CHAP/MD5; they must want a different + * algorithm. If they can't do MD5, we'll have to stop + * asking for CHAP. + */ + if (cichar != go->chap_mdtype) { + try.neg_chap = 0; + } + } else { + /* + * Stop asking for PAP if we were asking for it. + */ + try.neg_upap = 0; + } + + } else { + /* + * We don't recognize what they're suggesting. + * Stop asking for what we were asking for. + */ + if (go->neg_chap) { + try.neg_chap = 0; + } else { + try.neg_upap = 0; + } + p += cilen - CILEN_SHORT; + } + } + + /* + * If they can't cope with our link quality protocol, we'll have + * to stop asking for LQR. We haven't got any other protocol. + * If they Nak the reporting period, take their value XXX ? + */ + NAKCILQR(CI_QUALITY, neg_lqr, + if (cishort != PPP_LQR) { + try.neg_lqr = 0; + } else { + try.lqr_period = cilong; + } + ); + + /* + * Only implementing CBCP...not the rest of the callback options + */ + NAKCICHAR(CI_CALLBACK, neg_cbcp, + try.neg_cbcp = 0; + ); + + /* + * Check for a looped-back line. + */ + NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + try.magicnumber = magic(); + looped_back = 1; + ); + + /* + * Peer shouldn't send Nak for protocol compression or + * address/control compression requests; they should send + * a Reject instead. If they send a Nak, treat it as a Reject. + */ + NAKCIVOID(CI_PCOMPRESSION, neg_pcompression, + try.neg_pcompression = 0; + ); + NAKCIVOID(CI_ACCOMPRESSION, neg_accompression, + try.neg_accompression = 0; + ); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If we see an option that we requested, or one we've already seen + * in this packet, then this packet is bad. + * If we wanted to respond by starting to negotiate on the requested + * option(s), we could, but we don't, because except for the + * authentication type and quality protocol, if we are not negotiating + * an option, it is because we were told not to. + * For the authentication type, the Nak from the peer means + * `let me authenticate myself with you' which is a bit pointless. + * For the quality protocol, the Nak means `ask me to send you quality + * reports', but if we didn't ask for them, we don't want them. + * An option we don't recognize represents the peer asking to + * negotiate some option we don't support, so ignore it. + */ + while (len > CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if (cilen < CILEN_VOID || (len -= cilen) < 0) { + goto bad; + } + next = p + cilen - 2; + + switch (citype) { + case CI_MRU: + if ((go->neg_mru && go->mru != PPP_DEFMRU) + || no.neg_mru || cilen != CILEN_SHORT) { + goto bad; + } + GETSHORT(cishort, p); + if (cishort < PPP_DEFMRU) { + try.mru = cishort; + } + break; + case CI_ASYNCMAP: + if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) + || no.neg_asyncmap || cilen != CILEN_LONG) { + goto bad; + } + break; + case CI_AUTHTYPE: + if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap) { + goto bad; + } + break; + case CI_MAGICNUMBER: + if (go->neg_magicnumber || no.neg_magicnumber || + cilen != CILEN_LONG) { + goto bad; + } + break; + case CI_PCOMPRESSION: + if (go->neg_pcompression || no.neg_pcompression + || cilen != CILEN_VOID) { + goto bad; + } + break; + case CI_ACCOMPRESSION: + if (go->neg_accompression || no.neg_accompression + || cilen != CILEN_VOID) { + goto bad; + } + break; + case CI_QUALITY: + if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) { + goto bad; + } + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) { + goto bad; + } + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != LS_OPENED) { + if (looped_back) { + if (++try.numloops >= lcp_loopbackfail) { + LCPDEBUG(LOG_NOTICE, ("Serial line is looped back.\n")); + lcp_close(f->unit, "Loopback detected"); + } + } else { + try.numloops = 0; + } + *go = try; + } + + return 1; + +bad: + LCPDEBUG(LOG_WARNING, ("lcp_nakci: received bad Nak!\n")); + return 0; +} + + +/* + * lcp_rejci - Peer has Rejected some of our CIs. + * This should not modify any state if the Reject is bad + * or if LCP is in the LS_OPENED state. + * + * Returns: + * 0 - Reject was bad. + * 1 - Reject was good. + */ +static int +lcp_rejci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char cichar; + u_short cishort; + u32_t cilong; + lcp_options try; /* options to request next time */ + + try = *go; + + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: void opt %d rejected\n", opt)); \ + } +#define REJCISHORT(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: short opt %d rejected\n", opt)); \ + } +#define REJCICHAP(opt, neg, val, digest) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cishort != val || cichar != digest) { \ + goto bad; \ + } \ + try.neg = 0; \ + try.neg_upap = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: chap opt %d rejected\n", opt)); \ + } +#define REJCILONG(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cilong != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: long opt %d rejected\n", opt)); \ + } +#define REJCILQR(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cishort != PPP_LQR || cilong != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: LQR opt %d rejected\n", opt)); \ + } +#define REJCICBCP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CBCP && \ + p[1] == CILEN_CBCP && \ + p[0] == opt) { \ + len -= CILEN_CBCP; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cichar != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: Callback opt %d rejected\n", opt)); \ + } + + REJCISHORT(CI_MRU, neg_mru, go->mru); + REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); + REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype); + if (!go->neg_chap) { + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); + } + REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); + REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); + REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); + REJCIVOID(CI_PCOMPRESSION, neg_pcompression); + REJCIVOID(CI_ACCOMPRESSION, neg_accompression); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + /* + * Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + return 1; + +bad: + LCPDEBUG(LOG_WARNING, ("lcp_rejci: received bad Reject!\n")); + return 0; +} + + +/* + * lcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + */ +static int +lcp_reqci(fsm *f, + u_char *inp, /* Requested CIs */ + int *lenp, /* Length of requested CIs */ + int reject_if_disagree) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *ho = &lcp_hisoptions[f->unit]; + lcp_options *ao = &lcp_allowoptions[f->unit]; + u_char *cip, *next; /* Pointer to current and next CIs */ + int cilen, citype; /* Parsed len, type */ + u_char cichar; /* Parsed char value */ + u_short cishort; /* Parsed short value */ + u32_t cilong; /* Parse long value */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *rejp; /* Pointer to next char in reject frame */ + u_char *nakp; /* Pointer to next char in Nak frame */ + int l = *lenp; /* Length left */ +#if TRACELCP > 0 + char traceBuf[80]; + size_t traceNdx = 0; +#endif + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + nakp = nak_buffer; + rejp = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: bad CI length!\n")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + citype = 0; + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_MRU: + if (!ao->neg_mru) { /* Allow option? */ + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - not allowed\n")); + orc = CONFREJ; /* Reject CI */ + break; + } else if (cilen != CILEN_SHORT) { /* Check CI length */ + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - bad length\n")); + orc = CONFREJ; /* Reject CI */ + break; + } + GETSHORT(cishort, p); /* Parse MRU */ + + /* + * He must be able to receive at least our minimum. + * No need to check a maximum. If he sends a large number, + * we'll just ignore it. + */ + if (cishort < PPP_MINMRU) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak - MRU too small\n")); + orc = CONFNAK; /* Nak CI */ + PUTCHAR(CI_MRU, nakp); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_MINMRU, nakp); /* Give him a hint */ + break; + } + ho->neg_mru = 1; /* Remember he sent MRU */ + ho->mru = cishort; /* And remember value */ +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort); + traceNdx = strlen(traceBuf); +#endif + break; + + case CI_ASYNCMAP: + if (!ao->neg_asyncmap) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP not allowed\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_LONG) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP bad length\n")); + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * Asyncmap must have set at least the bits + * which are set in lcp_allowoptions[unit].asyncmap. + */ + if ((ao->asyncmap & ~cilong) != 0) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak ASYNCMAP %lX missing %lX\n", + cilong, ao->asyncmap)); + orc = CONFNAK; + PUTCHAR(CI_ASYNCMAP, nakp); + PUTCHAR(CILEN_LONG, nakp); + PUTLONG(ao->asyncmap | cilong, nakp); + break; + } + ho->neg_asyncmap = 1; + ho->asyncmap = cilong; +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong); + traceNdx = strlen(traceBuf); +#endif + break; + + case CI_AUTHTYPE: + if (cilen < CILEN_SHORT) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE missing arg\n")); + orc = CONFREJ; + break; + } else if (!(ao->neg_upap || ao->neg_chap)) { + /* + * Reject the option if we're not willing to authenticate. + */ + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE not allowed\n")); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + /* + * Authtype must be UPAP or CHAP. + * + * Note: if both ao->neg_upap and ao->neg_chap are set, + * and the peer sends a Configure-Request with two + * authenticate-protocol requests, one for CHAP and one + * for UPAP, then we will reject the second request. + * Whether we end up doing CHAP or UPAP depends then on + * the ordering of the CIs in the peer's Configure-Request. + */ + + if (cishort == PPP_PAP) { + if (ho->neg_chap) { /* we've already accepted CHAP */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP already accepted\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_SHORT) { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP bad len\n")); + orc = CONFREJ; + break; + } + if (!ao->neg_upap) { /* we don't want to do PAP */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE PAP not allowed\n")); + orc = CONFNAK; /* NAK it and suggest CHAP */ + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + break; + } + ho->neg_upap = 1; +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort); + traceNdx = strlen(traceBuf); +#endif + break; + } + if (cishort == PPP_CHAP) { + if (ho->neg_upap) { /* we've already accepted PAP */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_CHAP) { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP bad len\n")); + orc = CONFREJ; + break; + } + if (!ao->neg_chap) { /* we don't want to do CHAP */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP not allowed\n")); + orc = CONFNAK; /* NAK it and suggest PAP */ + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_PAP, nakp); + break; + } + GETCHAR(cichar, p); /* get digest type*/ + if (cichar != CHAP_DIGEST_MD5 +#if MSCHAP_SUPPORT + && cichar != CHAP_MICROSOFT +#endif + ) { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", (int)cichar)); + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + break; + } +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, (int)cichar); + traceNdx = strlen(traceBuf); +#endif + ho->chap_mdtype = cichar; /* save md type */ + ho->neg_chap = 1; + break; + } + + /* + * We don't recognize the protocol they're asking for. + * Nak it with something we're willing to do. + * (At this point we know ao->neg_upap || ao->neg_chap.) + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakp); + if (ao->neg_chap) { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort)); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + } else { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort)); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_PAP, nakp); + } + break; + + case CI_QUALITY: + GETSHORT(cishort, p); + GETLONG(cilong, p); +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong); + traceNdx = strlen(traceBuf); +#endif + + if (!ao->neg_lqr || + cilen != CILEN_LQR) { + orc = CONFREJ; + break; + } + + /* + * Check the protocol and the reporting period. + * XXX When should we Nak this, and what with? + */ + if (cishort != PPP_LQR) { + orc = CONFNAK; + PUTCHAR(CI_QUALITY, nakp); + PUTCHAR(CILEN_LQR, nakp); + PUTSHORT(PPP_LQR, nakp); + PUTLONG(ao->lqr_period, nakp); + break; + } + break; + + case CI_MAGICNUMBER: + if (!(ao->neg_magicnumber || go->neg_magicnumber) || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong); + traceNdx = strlen(traceBuf); +#endif + + /* + * He must have a different magic number. + */ + if (go->neg_magicnumber && + cilong == go->magicnumber) { + cilong = magic(); /* Don't put magic() inside macro! */ + orc = CONFNAK; + PUTCHAR(CI_MAGICNUMBER, nakp); + PUTCHAR(CILEN_LONG, nakp); + PUTLONG(cilong, nakp); + break; + } + ho->neg_magicnumber = 1; + ho->magicnumber = cilong; + break; + + + case CI_PCOMPRESSION: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION"); + traceNdx = strlen(traceBuf); +#endif + if (!ao->neg_pcompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_pcompression = 1; + break; + + case CI_ACCOMPRESSION: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION"); + traceNdx = strlen(traceBuf); +#endif + if (!ao->neg_accompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_accompression = 1; + break; + + case CI_MRRU: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + case CI_SSNHF: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + case CI_EPDISC: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + default: +#if TRACELCP + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + } + + endswitch: +#if TRACELCP + if (traceNdx >= 80 - 32) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: rcvd%s\n", traceBuf)); + traceNdx = 0; + } +#endif + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) { /* but prior CI wasnt? */ + continue; /* Don't send this one */ + } + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree /* Getting fed up with sending NAKs? */ + && citype != CI_MAGICNUMBER) { + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) { /* Rejecting prior CI? */ + continue; /* Don't send this one */ + } + rc = CONFNAK; + } + } + if (orc == CONFREJ) { /* Reject this CI */ + rc = CONFREJ; + if (cip != rejp) { /* Need to move rejected CI? */ + BCOPY(cip, rejp, cilen); /* Move it */ + } + INCPTR(cilen, rejp); /* Update output pointer */ + } + } + + /* + * If we wanted to send additional NAKs (for unsent CIs), the + * code would go here. The extra NAKs would go at *nakp. + * At present there are no cases where we want to ask the + * peer to negotiate an option. + */ + + switch (rc) { + case CONFACK: + *lenp = (int)(next - inp); + break; + case CONFNAK: + /* + * Copy the Nak'd options from the nak_buffer to the caller's buffer. + */ + *lenp = (int)(nakp - nak_buffer); + BCOPY(nak_buffer, inp, *lenp); + break; + case CONFREJ: + *lenp = (int)(rejp - inp); + break; + } + +#if TRACELCP > 0 + if (traceNdx > 0) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: %s\n", traceBuf)); + } +#endif + LCPDEBUG(LOG_INFO, ("lcp_reqci: returning CONF%s.\n", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +/* + * lcp_up - LCP has come UP. + */ +static void +lcp_up(fsm *f) +{ + lcp_options *wo = &lcp_wantoptions[f->unit]; + lcp_options *ho = &lcp_hisoptions[f->unit]; + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *ao = &lcp_allowoptions[f->unit]; + + if (!go->neg_magicnumber) { + go->magicnumber = 0; + } + if (!ho->neg_magicnumber) { + ho->magicnumber = 0; + } + + /* + * Set our MTU to the smaller of the MTU we wanted and + * the MRU our peer wanted. If we negotiated an MRU, + * set our MRU to the larger of value we wanted and + * the value we got in the negotiation. + */ + ppp_send_config(f->unit, LWIP_MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)), + (ho->neg_asyncmap? ho->asyncmap: 0xffffffffl), + ho->neg_pcompression, ho->neg_accompression); + /* + * If the asyncmap hasn't been negotiated, we really should + * set the receive asyncmap to ffffffff, but we set it to 0 + * for backwards contemptibility. + */ + ppp_recv_config(f->unit, (go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU), + (go->neg_asyncmap? go->asyncmap: 0x00000000), + go->neg_pcompression, go->neg_accompression); + + if (ho->neg_mru) { + peer_mru[f->unit] = ho->mru; + } + + lcp_echo_lowerup(f->unit); /* Enable echo messages */ + + link_established(f->unit); /* The link is up; authenticate now */ +} + + +/* + * lcp_down - LCP has gone DOWN. + * + * Alert other protocols. + */ +static void +lcp_down(fsm *f) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + + lcp_echo_lowerdown(f->unit); + + link_down(f->unit); + + ppp_send_config(f->unit, PPP_MRU, 0xffffffffl, 0, 0); + ppp_recv_config(f->unit, PPP_MRU, + (go->neg_asyncmap? go->asyncmap: 0x00000000), + go->neg_pcompression, go->neg_accompression); + peer_mru[f->unit] = PPP_MRU; +} + + +/* + * lcp_starting - LCP needs the lower layer up. + */ +static void +lcp_starting(fsm *f) +{ + link_required(f->unit); /* lwip: currently does nothing */ +} + + +/* + * lcp_finished - LCP has finished with the lower layer. + */ +static void +lcp_finished(fsm *f) +{ + link_terminated(f->unit); /* we are finished with the link */ +} + + +#if PPP_ADDITIONAL_CALLBACKS +/* + * print_string - print a readable representation of a string using + * printer. + */ +static void +print_string( char *p, int len, void (*printer) (void *, char *, ...), void *arg) +{ + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') { + if (c == '\\' || c == '"') { + printer(arg, "\\"); + } + printer(arg, "%c", c); + } else { + switch (c) { + case '\n': + printer(arg, "\\n"); + break; + case '\r': + printer(arg, "\\r"); + break; + case '\t': + printer(arg, "\\t"); + break; + default: + printer(arg, "\\%.3o", c); + } + } + } + printer(arg, "\""); +} + + +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +static char *lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq" +}; + +static int +lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u32_t cilong; + + if (plen < HEADERLEN) { + return 0; + } + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) { + return 0; + } + + if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) { + printer(arg, " %s", lcp_codenames[code-1]); + } else { + printer(arg, " code=0x%x", code); + } + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%lx", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_PAP: + printer(arg, "pap"); + break; + case PPP_CHAP: + printer(arg, "chap"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_CALLBACK: + if (olen >= CILEN_CHAR) { + p += 2; + printer(arg, "callback "); + GETSHORT(cishort, p); + switch (cishort) { + case CBCP_OPT: + printer(arg, "CBCP"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + print_string((char*)p, len, printer, arg); + p += len; + len = 0; + } + break; + + case ECHOREQ: + case ECHOREP: + case DISCREQ: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + p += 4; + len -= 4; + } + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return (int)(p - pstart); +} +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +/* + * Time to shut down the link because there is nothing out there. + */ +static void +LcpLinkFailure (fsm *f) +{ + if (f->state == LS_OPENED) { + LCPDEBUG(LOG_INFO, ("No response to %d echo-requests\n", lcp_echos_pending)); + LCPDEBUG(LOG_NOTICE, ("Serial link appears to be disconnected.\n")); + lcp_close(f->unit, "Peer not responding"); + } +} + +/* + * Timer expired for the LCP echo requests from this process. + */ +static void +LcpEchoCheck (fsm *f) +{ + LcpSendEchoRequest (f); + + /* + * Start the timer for the next interval. + */ + LWIP_ASSERT("lcp_echo_timer_running == 0", lcp_echo_timer_running == 0); + + TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval); + lcp_echo_timer_running = 1; +} + +/* + * LcpEchoTimeout - Timer expired on the LCP echo + */ +static void +LcpEchoTimeout (void *arg) +{ + if (lcp_echo_timer_running != 0) { + lcp_echo_timer_running = 0; + LcpEchoCheck ((fsm *) arg); + } +} + +/* + * LcpEchoReply - LCP has received a reply to the echo + */ +static void +lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len) +{ + u32_t magic; + + LWIP_UNUSED_ARG(id); + + /* Check the magic number - don't count replies from ourselves. */ + if (len < 4) { + LCPDEBUG(LOG_WARNING, ("lcp: received short Echo-Reply, length %d\n", len)); + return; + } + GETLONG(magic, inp); + if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) { + LCPDEBUG(LOG_WARNING, ("appear to have received our own echo-reply!\n")); + return; + } + + /* Reset the number of outstanding echo frames */ + lcp_echos_pending = 0; +} + +/* + * LcpSendEchoRequest - Send an echo request frame to the peer + */ +static void +LcpSendEchoRequest (fsm *f) +{ + u32_t lcp_magic; + u_char pkt[4], *pktp; + + /* + * Detect the failure of the peer at this point. + */ + if (lcp_echo_fails != 0) { + if (lcp_echos_pending >= lcp_echo_fails) { + LcpLinkFailure(f); + lcp_echos_pending = 0; + } + } + + /* + * Make and send the echo request frame. + */ + if (f->state == LS_OPENED) { + lcp_magic = lcp_gotoptions[f->unit].magicnumber; + pktp = pkt; + PUTLONG(lcp_magic, pktp); + fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt)); + ++lcp_echos_pending; + } +} + +/* + * lcp_echo_lowerup - Start the timer for the LCP frame + */ + +static void +lcp_echo_lowerup (int unit) +{ + fsm *f = &lcp_fsm[unit]; + + /* Clear the parameters for generating echo frames */ + lcp_echos_pending = 0; + lcp_echo_number = 0; + lcp_echo_timer_running = 0; + + /* If a timeout interval is specified then start the timer */ + if (lcp_echo_interval != 0) { + LcpEchoCheck (f); + } +} + +/* + * lcp_echo_lowerdown - Stop the timer for the LCP frame + */ + +static void +lcp_echo_lowerdown (int unit) +{ + fsm *f = &lcp_fsm[unit]; + + if (lcp_echo_timer_running != 0) { + UNTIMEOUT (LcpEchoTimeout, f); + lcp_echo_timer_running = 0; + } +} + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/lcp.h b/ext/lwip/src/netif/ppp/lcp.h new file mode 100644 index 000000000..b9201eeb5 --- /dev/null +++ b/ext/lwip/src/netif/ppp/lcp.h @@ -0,0 +1,151 @@ +/***************************************************************************** +* lcp.h - Network Link Control Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * lcp.h - Link Control Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: lcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $ + */ + +#ifndef LCP_H +#define LCP_H +/* + * Options. + */ +#define CI_MRU 1 /* Maximum Receive Unit */ +#define CI_ASYNCMAP 2 /* Async Control Character Map */ +#define CI_AUTHTYPE 3 /* Authentication Type */ +#define CI_QUALITY 4 /* Quality Protocol */ +#define CI_MAGICNUMBER 5 /* Magic Number */ +#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ +#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +#define CI_CALLBACK 13 /* callback */ +#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ +#define CI_SSNHF 18 /* short sequence numbers for multilink */ +#define CI_EPDISC 19 /* endpoint discriminator */ + +/* + * LCP-specific packet types (code numbers). + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ +#define CBCP_OPT 6 /* Use callback control protocol */ + +/* + * The state of options is described by an lcp_options structure. + */ +typedef struct lcp_options { + u_int passive : 1; /* Don't die if we don't get a response */ + u_int silent : 1; /* Wait for the other end to start first */ + u_int restart : 1; /* Restart vs. exit after close */ + u_int neg_mru : 1; /* Negotiate the MRU? */ + u_int neg_asyncmap : 1; /* Negotiate the async map? */ + u_int neg_upap : 1; /* Ask for UPAP authentication? */ + u_int neg_chap : 1; /* Ask for CHAP authentication? */ + u_int neg_magicnumber : 1; /* Ask for magic number? */ + u_int neg_pcompression : 1; /* HDLC Protocol Field Compression? */ + u_int neg_accompression : 1; /* HDLC Address/Control Field Compression? */ + u_int neg_lqr : 1; /* Negotiate use of Link Quality Reports */ + u_int neg_cbcp : 1; /* Negotiate use of CBCP */ +#ifdef PPP_MULTILINK + u_int neg_mrru : 1; /* Negotiate multilink MRRU */ + u_int neg_ssnhf : 1; /* Negotiate short sequence numbers */ + u_int neg_endpoint : 1; /* Negotiate endpoint discriminator */ +#endif + u_short mru; /* Value of MRU */ +#ifdef PPP_MULTILINK + u_short mrru; /* Value of MRRU, and multilink enable */ +#endif + u_char chap_mdtype; /* which MD type (hashing algorithm) */ + u32_t asyncmap; /* Value of async map */ + u32_t magicnumber; + int numloops; /* Number of loops during magic number neg. */ + u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ +#ifdef PPP_MULTILINK + struct epdisc endpoint; /* endpoint discriminator */ +#endif +} lcp_options; + +/* + * Values for phase from BSD pppd.h based on RFC 1661. + */ +typedef enum { + PHASE_DEAD = 0, + PHASE_INITIALIZE, + PHASE_ESTABLISH, + PHASE_AUTHENTICATE, + PHASE_CALLBACK, + PHASE_NETWORK, + PHASE_TERMINATE +} LinkPhase; + + + +extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ +extern lcp_options lcp_wantoptions[]; +extern lcp_options lcp_gotoptions[]; +extern lcp_options lcp_allowoptions[]; +extern lcp_options lcp_hisoptions[]; +extern ext_accm xmit_accm[]; + + +void lcp_init (int); +void lcp_open (int); +void lcp_close (int, char *); +void lcp_lowerup (int); +void lcp_lowerdown(int); +void lcp_sprotrej (int, u_char *, int); /* send protocol reject */ + +extern struct protent lcp_protent; + +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#define DEFLOOPBACKFAIL 10 + +#endif /* LCP_H */ diff --git a/ext/lwip/src/netif/ppp/magic.c b/ext/lwip/src/netif/ppp/magic.c new file mode 100644 index 000000000..3732a4241 --- /dev/null +++ b/ext/lwip/src/netif/ppp/magic.c @@ -0,0 +1,80 @@ +/***************************************************************************** +* magic.c - Network Random Number Generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD magic.c. +*****************************************************************************/ +/* + * magic.c - PPP Magic Number routines. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT + +#include "ppp_impl.h" +#include "randm.h" +#include "magic.h" + + +/* + * magicInit - Initialize the magic number generator. + * + * Since we use another random number generator that has its own + * initialization, we do nothing here. + */ +void magicInit() +{ + return; +} + +/* + * magic - Returns the next magic number. + */ +u32_t magic() +{ + return avRandom(); +} + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/magic.h b/ext/lwip/src/netif/ppp/magic.h new file mode 100644 index 000000000..eba70d20b --- /dev/null +++ b/ext/lwip/src/netif/ppp/magic.h @@ -0,0 +1,63 @@ +/***************************************************************************** +* magic.h - Network Random Number Generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * magic.h - PPP Magic Number definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: magic.h,v 1.3 2010/01/18 20:49:43 goldsimon Exp $ + */ + +#ifndef MAGIC_H +#define MAGIC_H + +/* Initialize the magic number generator */ +void magicInit(void); + +/* Returns the next magic number */ +u32_t magic(void); + +#endif /* MAGIC_H */ diff --git a/ext/lwip/src/netif/ppp/md5.c b/ext/lwip/src/netif/ppp/md5.c new file mode 100644 index 000000000..dc3cc751b --- /dev/null +++ b/ext/lwip/src/netif/ppp/md5.c @@ -0,0 +1,320 @@ +/* + *********************************************************************** + ** md5.c -- the source code for MD5 routines ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if CHAP_SUPPORT || MD5_SUPPORT + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "md5.h" + +#include + +/* + *********************************************************************** + ** Message-digest routines: ** + ** To form the message digest for a message M ** + ** (1) Initialize a context buffer mdContext using MD5Init ** + ** (2) Call MD5Update on mdContext and M ** + ** (3) Call MD5Final on mdContext ** + ** The message digest is now in mdContext->digest[0...15] ** + *********************************************************************** + */ + +/* forward declaration */ +static void Transform (u32_t *buf, u32_t *in); + +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#ifdef __STDC__ +#define UL(x) x##UL +#else +#ifdef WIN32 +#define UL(x) x##UL +#else +#define UL(x) x +#endif +#endif + +/* The routine MD5Init initializes the message-digest context + mdContext. All fields are set to zero. + */ +void +MD5Init (MD5_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (u32_t)0; + + /* Load magic initialization constants. */ + mdContext->buf[0] = (u32_t)0x67452301UL; + mdContext->buf[1] = (u32_t)0xefcdab89UL; + mdContext->buf[2] = (u32_t)0x98badcfeUL; + mdContext->buf[3] = (u32_t)0x10325476UL; +} + +/* The routine MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. + */ +void +MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) +{ + u32_t in[16]; + int mdi; + unsigned int i, ii; + +#if 0 + PPPDEBUG(LOG_INFO, ("MD5Update: %u:%.*H\n", inLen, LWIP_MIN(inLen, 20) * 2, inBuf)); + PPPDEBUG(LOG_INFO, ("MD5Update: %u:%s\n", inLen, inBuf)); +#endif + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((u32_t)inLen << 3)) < mdContext->i[0]) { + mdContext->i[1]++; + } + mdContext->i[0] += ((u32_t)inLen << 3); + mdContext->i[1] += ((u32_t)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) { + in[i] = (((u32_t)mdContext->in[ii+3]) << 24) | + (((u32_t)mdContext->in[ii+2]) << 16) | + (((u32_t)mdContext->in[ii+1]) << 8) | + ((u32_t)mdContext->in[ii]); + } + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. + */ +void +MD5Final (unsigned char hash[], MD5_CTX *mdContext) +{ + u32_t in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) { + in[i] = (((u32_t)mdContext->in[ii+3]) << 24) | + (((u32_t)mdContext->in[ii+2]) << 16) | + (((u32_t)mdContext->in[ii+1]) << 8) | + ((u32_t)mdContext->in[ii]); + } + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } + SMEMCPY(hash, mdContext->digest, 16); +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void +Transform (u32_t *buf, u32_t *in) +{ + u32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ + FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ + FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ + FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ + FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ + FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ + FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ + GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ + GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ + GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ + GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ + GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ + GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ + HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ + HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ + HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ + HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ + HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ + HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ + II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ + II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ + II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ + II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ + II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ + II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ + II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ + II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ + II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ + II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ + II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ + II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ + II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ + II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ + II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif /* CHAP_SUPPORT || MD5_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/md5.h b/ext/lwip/src/netif/ppp/md5.h new file mode 100644 index 000000000..e129533f3 --- /dev/null +++ b/ext/lwip/src/netif/ppp/md5.h @@ -0,0 +1,55 @@ +/* + *********************************************************************** + ** md5.h -- header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#ifndef MD5_H +#define MD5_H + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + u32_t i[2]; /* number of _bits_ handled mod 2^64 */ + u32_t buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5Init ( MD5_CTX *mdContext); +void MD5Update( MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen); +void MD5Final ( unsigned char hash[], MD5_CTX *mdContext); + +#endif /* MD5_H */ diff --git a/ext/lwip/src/netif/ppp/pap.c b/ext/lwip/src/netif/ppp/pap.c new file mode 100644 index 000000000..5fb9f886c --- /dev/null +++ b/ext/lwip/src/netif/ppp/pap.c @@ -0,0 +1,628 @@ +/***************************************************************************** +* pap.c - Network Password Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-12 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ +/* + * upap.c - User/Password Authentication Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "auth.h" +#include "pap.h" + +#include + +#if 0 /* UNUSED */ +static bool hide_password = 1; + +/* + * Command-line options. + */ +static option_t pap_option_list[] = { + { "hide-password", o_bool, &hide_password, + "Don't output passwords to log", 1 }, + { "show-password", o_bool, &hide_password, + "Show password string in debug log messages", 0 }, + { "pap-restart", o_int, &upap[0].us_timeouttime, + "Set retransmit timeout for PAP" }, + { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, + "Set max number of transmissions for auth-reqs" }, + { "pap-timeout", o_int, &upap[0].us_reqtimeout, + "Set time limit for peer PAP authentication" }, + { NULL } +}; +#endif + +/* + * Protocol entry points. + */ +static void upap_init (int); +static void upap_lowerup (int); +static void upap_lowerdown (int); +static void upap_input (int, u_char *, int); +static void upap_protrej (int); +#if PPP_ADDITIONAL_CALLBACKS +static int upap_printpkt (u_char *, int, void (*)(void *, char *, ...), void *); +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +struct protent pap_protent = { + PPP_PAP, + upap_init, + upap_input, + upap_protrej, + upap_lowerup, + upap_lowerdown, + NULL, + NULL, +#if PPP_ADDITIONAL_CALLBACKS + upap_printpkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "PAP", +#if PPP_ADDITIONAL_CALLBACKS + NULL, + NULL, + NULL +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ + +static void upap_timeout (void *); +static void upap_reqtimeout(void *); +static void upap_rauthreq (upap_state *, u_char *, u_char, int); +static void upap_rauthack (upap_state *, u_char *, int, int); +static void upap_rauthnak (upap_state *, u_char *, int, int); +static void upap_sauthreq (upap_state *); +static void upap_sresp (upap_state *, u_char, u_char, char *, int); + + +/* + * upap_init - Initialize a UPAP unit. + */ +static void +upap_init(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG(LOG_INFO, ("upap_init: %d\n", unit)); + u->us_unit = unit; + u->us_user = NULL; + u->us_userlen = 0; + u->us_passwd = NULL; + u->us_passwdlen = 0; + u->us_clientstate = UPAPCS_INITIAL; + u->us_serverstate = UPAPSS_INITIAL; + u->us_id = 0; + u->us_timeouttime = UPAP_DEFTIMEOUT; + u->us_maxtransmits = 10; + u->us_reqtimeout = UPAP_DEFREQTIME; +} + +/* + * upap_authwithpeer - Authenticate us with our peer (start client). + * + * Set new state and send authenticate's. + */ +void +upap_authwithpeer(int unit, char *user, char *password) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG(LOG_INFO, ("upap_authwithpeer: %d user=%s password=%s s=%d\n", + unit, user, password, u->us_clientstate)); + + /* Save the username and password we're given */ + u->us_user = user; + u->us_userlen = (int)strlen(user); + u->us_passwd = password; + u->us_passwdlen = (int)strlen(password); + + u->us_transmits = 0; + + /* Lower layer up yet? */ + if (u->us_clientstate == UPAPCS_INITIAL || + u->us_clientstate == UPAPCS_PENDING) { + u->us_clientstate = UPAPCS_PENDING; + return; + } + + upap_sauthreq(u); /* Start protocol */ +} + + +/* + * upap_authpeer - Authenticate our peer (start server). + * + * Set new state. + */ +void +upap_authpeer(int unit) +{ + upap_state *u = &upap[unit]; + + /* Lower layer up yet? */ + if (u->us_serverstate == UPAPSS_INITIAL || + u->us_serverstate == UPAPSS_PENDING) { + u->us_serverstate = UPAPSS_PENDING; + return; + } + + u->us_serverstate = UPAPSS_LISTEN; + if (u->us_reqtimeout > 0) { + TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); + } +} + +/* + * upap_timeout - Retransmission timer for sending auth-reqs expired. + */ +static void +upap_timeout(void *arg) +{ + upap_state *u = (upap_state *) arg; + + UPAPDEBUG(LOG_INFO, ("upap_timeout: %d timeout %d expired s=%d\n", + u->us_unit, u->us_timeouttime, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { + UPAPDEBUG(LOG_INFO, ("upap_timeout: not in AUTHREQ state!\n")); + return; + } + + if (u->us_transmits >= u->us_maxtransmits) { + /* give up in disgust */ + UPAPDEBUG(LOG_ERR, ("No response to PAP authenticate-requests\n")); + u->us_clientstate = UPAPCS_BADAUTH; + auth_withpeer_fail(u->us_unit, PPP_PAP); + return; + } + + upap_sauthreq(u); /* Send Authenticate-Request and set upap timeout*/ +} + + +/* + * upap_reqtimeout - Give up waiting for the peer to send an auth-req. + */ +static void +upap_reqtimeout(void *arg) +{ + upap_state *u = (upap_state *) arg; + + if (u->us_serverstate != UPAPSS_LISTEN) { + return; /* huh?? */ + } + + auth_peer_fail(u->us_unit, PPP_PAP); + u->us_serverstate = UPAPSS_BADAUTH; +} + + +/* + * upap_lowerup - The lower layer is up. + * + * Start authenticating if pending. + */ +static void +upap_lowerup(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG(LOG_INFO, ("upap_lowerup: init %d clientstate s=%d\n", unit, u->us_clientstate)); + + if (u->us_clientstate == UPAPCS_INITIAL) { + u->us_clientstate = UPAPCS_CLOSED; + } else if (u->us_clientstate == UPAPCS_PENDING) { + upap_sauthreq(u); /* send an auth-request */ + /* now client state is UPAPCS__AUTHREQ */ + } + + if (u->us_serverstate == UPAPSS_INITIAL) { + u->us_serverstate = UPAPSS_CLOSED; + } else if (u->us_serverstate == UPAPSS_PENDING) { + u->us_serverstate = UPAPSS_LISTEN; + if (u->us_reqtimeout > 0) { + TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); + } + } +} + + +/* + * upap_lowerdown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void +upap_lowerdown(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG(LOG_INFO, ("upap_lowerdown: %d s=%d\n", unit, u->us_clientstate)); + + if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */ + UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ + } + if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) { + UNTIMEOUT(upap_reqtimeout, u); + } + + u->us_clientstate = UPAPCS_INITIAL; + u->us_serverstate = UPAPSS_INITIAL; +} + + +/* + * upap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. In any case, pretend lower layer went down. + */ +static void +upap_protrej(int unit) +{ + upap_state *u = &upap[unit]; + + if (u->us_clientstate == UPAPCS_AUTHREQ) { + UPAPDEBUG(LOG_ERR, ("PAP authentication failed due to protocol-reject\n")); + auth_withpeer_fail(unit, PPP_PAP); + } + if (u->us_serverstate == UPAPSS_LISTEN) { + UPAPDEBUG(LOG_ERR, ("PAP authentication of peer failed (protocol-reject)\n")); + auth_peer_fail(unit, PPP_PAP); + } + upap_lowerdown(unit); +} + + +/* + * upap_input - Input UPAP packet. + */ +static void +upap_input(int unit, u_char *inpacket, int l) +{ + upap_state *u = &upap[unit]; + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < (int)UPAP_HEADERLEN) { + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short header.\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < (int)UPAP_HEADERLEN) { + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd illegal length.\n")); + return; + } + if (len > l) { + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short packet.\n")); + return; + } + len -= UPAP_HEADERLEN; + + /* + * Action depends on code. + */ + switch (code) { + case UPAP_AUTHREQ: + upap_rauthreq(u, inp, id, len); + break; + + case UPAP_AUTHACK: + upap_rauthack(u, inp, id, len); + break; + + case UPAP_AUTHNAK: + upap_rauthnak(u, inp, id, len); + break; + + default: /* XXX Need code reject */ + UPAPDEBUG(LOG_INFO, ("pap_input: UNHANDLED default: code: %d, id: %d, len: %d.\n", code, id, len)); + break; + } +} + + +/* + * upap_rauth - Receive Authenticate. + */ +static void +upap_rauthreq(upap_state *u, u_char *inp, u_char id, int len) +{ + u_char ruserlen, rpasswdlen; + char *ruser, *rpasswd; + u_char retcode; + char *msg; + int msglen; + + UPAPDEBUG(LOG_INFO, ("pap_rauth: Rcvd id %d.\n", id)); + + if (u->us_serverstate < UPAPSS_LISTEN) { + return; + } + + /* + * If we receive a duplicate authenticate-request, we are + * supposed to return the same status as for the first request. + */ + if (u->us_serverstate == UPAPSS_OPEN) { + upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ + return; + } + if (u->us_serverstate == UPAPSS_BADAUTH) { + upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ + return; + } + + /* + * Parse user/passwd. + */ + if (len < (int)sizeof (u_char)) { + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); + return; + } + GETCHAR(ruserlen, inp); + len -= sizeof (u_char) + ruserlen + sizeof (u_char); + if (len < 0) { + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); + return; + } + ruser = (char *) inp; + INCPTR(ruserlen, inp); + GETCHAR(rpasswdlen, inp); + if (len < rpasswdlen) { + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); + return; + } + rpasswd = (char *) inp; + + /* + * Check the username and password given. + */ + retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen); + /* lwip: currently retcode is always UPAP_AUTHACK */ + BZERO(rpasswd, rpasswdlen); + + upap_sresp(u, retcode, id, msg, msglen); + + if (retcode == UPAP_AUTHACK) { + u->us_serverstate = UPAPSS_OPEN; + auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen); + } else { + u->us_serverstate = UPAPSS_BADAUTH; + auth_peer_fail(u->us_unit, PPP_PAP); + } + + if (u->us_reqtimeout > 0) { + UNTIMEOUT(upap_reqtimeout, u); + } +} + + +/* + * upap_rauthack - Receive Authenticate-Ack. + */ +static void +upap_rauthack(upap_state *u, u_char *inp, int id, int len) +{ + u_char msglen; + char *msg; + + LWIP_UNUSED_ARG(id); + + UPAPDEBUG(LOG_INFO, ("pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ + UPAPDEBUG(LOG_INFO, ("pap_rauthack: us_clientstate != UPAPCS_AUTHREQ\n")); + return; + } + + /* + * Parse message. + */ + if (len < (int)sizeof (u_char)) { + UPAPDEBUG(LOG_INFO, ("pap_rauthack: ignoring missing msg-length.\n")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(LOG_INFO, ("pap_rauthack: rcvd short packet.\n")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ + u->us_clientstate = UPAPCS_OPEN; + + auth_withpeer_success(u->us_unit, PPP_PAP); +} + + +/* + * upap_rauthnak - Receive Authenticate-Nak. + */ +static void +upap_rauthnak(upap_state *u, u_char *inp, int id, int len) +{ + u_char msglen; + char *msg; + + LWIP_UNUSED_ARG(id); + + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ + return; + } + + /* + * Parse message. + */ + if (len < sizeof (u_char)) { + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: ignoring missing msg-length.\n")); + } else { + GETCHAR(msglen, inp); + if(msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: rcvd short packet.\n")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + u->us_clientstate = UPAPCS_BADAUTH; + + UPAPDEBUG(LOG_ERR, ("PAP authentication failed\n")); + auth_withpeer_fail(u->us_unit, PPP_PAP); +} + + +/* + * upap_sauthreq - Send an Authenticate-Request. + */ +static void +upap_sauthreq(upap_state *u) +{ + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + + u->us_userlen + u->us_passwdlen; + outp = outpacket_buf[u->us_unit]; + + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(UPAP_AUTHREQ, outp); + PUTCHAR(++u->us_id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(u->us_userlen, outp); + BCOPY(u->us_user, outp, u->us_userlen); + INCPTR(u->us_userlen, outp); + PUTCHAR(u->us_passwdlen, outp); + BCOPY(u->us_passwd, outp, u->us_passwdlen); + + pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); + + UPAPDEBUG(LOG_INFO, ("pap_sauth: Sent id %d\n", u->us_id)); + + TIMEOUT(upap_timeout, u, u->us_timeouttime); + ++u->us_transmits; + u->us_clientstate = UPAPCS_AUTHREQ; +} + + +/* + * upap_sresp - Send a response (ack or nak). + */ +static void +upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen) +{ + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; + outp = outpacket_buf[u->us_unit]; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(msglen, outp); + BCOPY(msg, outp, msglen); + pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); + + UPAPDEBUG(LOG_INFO, ("pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate)); +} + +#if PPP_ADDITIONAL_CALLBACKS +static char *upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + +/* + * upap_printpkt - print the contents of a PAP packet. + */ +static int upap_printpkt( + u_char *p, + int plen, + void (*printer) (void *, char *, ...), + void *arg +) +{ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(plen); + LWIP_UNUSED_ARG(printer); + LWIP_UNUSED_ARG(arg); + return 0; +} +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +#endif /* PAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/pap.h b/ext/lwip/src/netif/ppp/pap.h new file mode 100644 index 000000000..c99a20401 --- /dev/null +++ b/ext/lwip/src/netif/ppp/pap.h @@ -0,0 +1,118 @@ +/***************************************************************************** +* pap.h - PPP Password Authentication Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * upap.h - User/Password Authentication Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef PAP_H +#define PAP_H + +#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * Packet header = Code, id, length. + */ +#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) + + +/* + * UPAP codes. + */ +#define UPAP_AUTHREQ 1 /* Authenticate-Request */ +#define UPAP_AUTHACK 2 /* Authenticate-Ack */ +#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ + +/* + * Each interface is described by upap structure. + */ +typedef struct upap_state { + int us_unit; /* Interface unit number */ + const char *us_user; /* User */ + int us_userlen; /* User length */ + const char *us_passwd; /* Password */ + int us_passwdlen; /* Password length */ + int us_clientstate; /* Client state */ + int us_serverstate; /* Server state */ + u_char us_id; /* Current id */ + int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */ + int us_transmits; /* Number of auth-reqs sent */ + int us_maxtransmits; /* Maximum number of auth-reqs to send */ + int us_reqtimeout; /* Time to wait for auth-req from peer */ +} upap_state; + +/* + * Client states. + */ +#define UPAPCS_INITIAL 0 /* Connection down */ +#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ +#define UPAPCS_OPEN 4 /* We've received an Ack */ +#define UPAPCS_BADAUTH 5 /* We've received a Nak */ + +/* + * Server states. + */ +#define UPAPSS_INITIAL 0 /* Connection down */ +#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ +#define UPAPSS_OPEN 4 /* We've sent an Ack */ +#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ + + +extern upap_state upap[]; + +void upap_authwithpeer (int, char *, char *); +void upap_authpeer (int); + +extern struct protent pap_protent; + +#endif /* PAP_SUPPORT */ + +#endif /* PAP_H */ diff --git a/ext/lwip/src/netif/ppp/ppp.c b/ext/lwip/src/netif/ppp/ppp.c new file mode 100644 index 000000000..8e8fae9f9 --- /dev/null +++ b/ext/lwip/src/netif/ppp/ppp.c @@ -0,0 +1,2045 @@ +/***************************************************************************** +* ppp.c - Network Point to Point Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * ppp_defs.h - PPP definitions. + * + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "lwip/ip.h" /* for ip_input() */ + +#include "pppdebug.h" + +#include "randm.h" +#include "fsm.h" +#if PAP_SUPPORT +#include "pap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "chap.h" +#endif /* CHAP_SUPPORT */ +#include "ipcp.h" +#include "lcp.h" +#include "magic.h" +#include "auth.h" +#if VJ_SUPPORT +#include "vj.h" +#endif /* VJ_SUPPORT */ +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#endif /* PPPOE_SUPPORT */ + +#include "lwip/tcpip.h" +#include "lwip/api.h" +#include "lwip/snmp.h" + +#include + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +/** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback(). + * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1. + * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded). + */ +#ifndef PPP_INPROC_MULTITHREADED +#define PPP_INPROC_MULTITHREADED (NO_SYS==0) +#endif + +/** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session. + * Default is 0: call pppos_input() for received raw characters, charcater + * reception is up to the port */ +#ifndef PPP_INPROC_OWNTHREAD +#define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED +#endif + +#if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED + #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1" +#endif + +/* + * The basic PPP frame. + */ +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* PPP packet parser states. Current state indicates operation yet to be + * completed. */ +typedef enum { + PDIDLE = 0, /* Idle state - waiting. */ + PDSTART, /* Process start flag. */ + PDADDRESS, /* Process address field. */ + PDCONTROL, /* Process control field. */ + PDPROTOCOL1, /* Process protocol field 1. */ + PDPROTOCOL2, /* Process protocol field 2. */ + PDDATA /* Process data byte. */ +} PPPDevStates; + +#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07]) + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ + +/** RX buffer size: this may be configured smaller! */ +#ifndef PPPOS_RX_BUFSIZE +#define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN) +#endif + +typedef struct PPPControlRx_s { + /** unit number / ppp descriptor */ + int pd; + /** the rx file descriptor */ + sio_fd_t fd; + /** receive buffer - encoded data is stored here */ +#if PPP_INPROC_OWNTHREAD + u_char rxbuf[PPPOS_RX_BUFSIZE]; +#endif /* PPP_INPROC_OWNTHREAD */ + + /* The input packet. */ + struct pbuf *inHead, *inTail; + +#if PPPOS_SUPPORT + u16_t inProtocol; /* The input protocol code. */ + u16_t inFCS; /* Input Frame Check Sequence value. */ +#endif /* PPPOS_SUPPORT */ + PPPDevStates inState; /* The input process state. */ + char inEscaped; /* Escape next character. */ + ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ +} PPPControlRx; + +/* + * PPP interface control block. + */ +typedef struct PPPControl_s { + PPPControlRx rx; + char openFlag; /* True when in use. */ +#if PPPOE_SUPPORT + struct netif *ethif; + struct pppoe_softc *pppoe_sc; +#endif /* PPPOE_SUPPORT */ + int if_up; /* True when the interface is up. */ + int errCode; /* Code indicating why interface is down. */ +#if PPPOS_SUPPORT + sio_fd_t fd; /* File device ID of port. */ +#endif /* PPPOS_SUPPORT */ + u16_t mtu; /* Peer's mru */ + int pcomp; /* Does peer accept protocol compression? */ + int accomp; /* Does peer accept addr/ctl compression? */ + u_long lastXMit; /* Time of last transmission. */ + ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ +#if PPPOS_SUPPORT && VJ_SUPPORT + int vjEnabled; /* Flag indicating VJ compression enabled. */ + struct vjcompress vjComp; /* Van Jacobson compression header. */ +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + + struct netif netif; + + struct ppp_addrs addrs; + + void (*linkStatusCB)(void *ctx, int errCode, void *arg); + void *linkStatusCtx; + +} PPPControl; + + +/* + * Ioctl definitions. + */ + +struct npioctl { + int protocol; /* PPP procotol, e.g. PPP_IP */ + enum NPmode mode; +}; + + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +#if PPPOS_SUPPORT +#if PPP_INPROC_OWNTHREAD +static void pppInputThread(void *arg); +#endif /* PPP_INPROC_OWNTHREAD */ +static void pppDrop(PPPControlRx *pcrx); +static void pppInProc(PPPControlRx *pcrx, u_char *s, int l); +static void pppFreeCurrentInputPacket(PPPControlRx *pcrx); +#endif /* PPPOS_SUPPORT */ + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ +u_long subnetMask; + +static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */ + +/* + * PPP Data Link Layer "protocol" table. + * One entry per supported protocol. + * The last entry must be NULL. + */ +struct protent *ppp_protocols[] = { + &lcp_protent, +#if PAP_SUPPORT + &pap_protent, +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + &chap_protent, +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT + &cbcp_protent, +#endif /* CBCP_SUPPORT */ + &ipcp_protent, +#if CCP_SUPPORT + &ccp_protent, +#endif /* CCP_SUPPORT */ + NULL +}; + + +/* + * Buffers for outgoing packets. This must be accessed only from the appropriate + * PPP task so that it doesn't need to be protected to avoid collisions. + */ +u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; + + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ + +#if PPPOS_SUPPORT +/* + * FCS lookup table as calculated by genfcstab. + * @todo: smaller, slower implementation for lower memory footprint? + */ +static const u_short fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* PPP's Asynchronous-Control-Character-Map. The mask array is used + * to select the specific bit for a character. */ +static u_char pppACCMMask[] = { + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80 +}; + +#if PPP_INPROC_OWNTHREAD +/** Wake up the task blocked in reading from serial line (if any) */ +static void +pppRecvWakeup(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd)); + if (pppControl[pd].openFlag != 0) { + sio_read_abort(pppControl[pd].fd); + } +} +#endif /* PPP_INPROC_OWNTHREAD */ +#endif /* PPPOS_SUPPORT */ + +void +pppLinkTerminated(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd)); + +#if PPPOE_SUPPORT + if (pppControl[pd].ethif) { + pppoe_disconnect(pppControl[pd].pppoe_sc); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT + PPPControl* pc; +#if PPP_INPROC_OWNTHREAD + pppRecvWakeup(pd); +#endif /* PPP_INPROC_OWNTHREAD */ + pc = &pppControl[pd]; + + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); + } + + pc->openFlag = 0;/**/ +#endif /* PPPOS_SUPPORT */ + } + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n")); +} + +void +pppLinkDown(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd)); + +#if PPPOE_SUPPORT + if (pppControl[pd].ethif) { + pppoe_disconnect(pppControl[pd].pppoe_sc); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD + pppRecvWakeup(pd); +#endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD*/ + } +} + +/** Initiate LCP open request */ +static void +pppStart(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd)); + lcp_lowerup(pd); + lcp_open(pd); /* Start protocol */ + PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n")); +} + +/** LCP close request */ +static void +pppStop(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd)); + lcp_close(pd, "User request"); +} + +/** Called when carrier/link is lost */ +static void +pppHup(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd)); + lcp_lowerdown(pd); + link_terminated(pd); +} + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* Initialize the PPP subsystem. */ + +struct ppp_settings ppp_settings; + +void +pppInit(void) +{ + struct protent *protp; + int i, j; + + memset(&ppp_settings, 0, sizeof(ppp_settings)); + ppp_settings.usepeerdns = 1; + pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL); + + magicInit(); + + subnetMask = PP_HTONL(0xffffff00UL); + + for (i = 0; i < NUM_PPP; i++) { + /* Initialize each protocol to the standard option set. */ + for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) { + (*protp->init)(i); + } + } +} + +void +pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd) +{ + switch(authType) { + case PPPAUTHTYPE_NONE: + default: +#ifdef LWIP_PPP_STRICT_PAP_REJECT + ppp_settings.refuse_pap = 1; +#else /* LWIP_PPP_STRICT_PAP_REJECT */ + /* some providers request pap and accept an empty login/pw */ + ppp_settings.refuse_pap = 0; +#endif /* LWIP_PPP_STRICT_PAP_REJECT */ + ppp_settings.refuse_chap = 1; + break; + + case PPPAUTHTYPE_ANY: + /* Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + */ + ppp_settings.refuse_pap = 0; + ppp_settings.refuse_chap = 0; + break; + + case PPPAUTHTYPE_PAP: + ppp_settings.refuse_pap = 0; + ppp_settings.refuse_chap = 1; + break; + + case PPPAUTHTYPE_CHAP: + ppp_settings.refuse_pap = 1; + ppp_settings.refuse_chap = 0; + break; + } + + if(user) { + strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1); + ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0'; + } else { + ppp_settings.user[0] = '\0'; + } + + if(passwd) { + strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); + ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; + } else { + ppp_settings.passwd[0] = '\0'; + } +} + +#if PPPOS_SUPPORT +/** Open a new PPP connection using the given I/O device. + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. If this port + * connects to a modem, the modem connection must be + * established before calling this. + * Return a new PPP connection descriptor on success or + * an error code (negative) on failure. + * + * pppOpen() is directly defined to this function. + */ +int +pppOverSerialOpen(sio_fd_t fd, pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx) +{ + PPPControl *pc; + int pd; + + if (linkStatusCB == NULL) { + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + return PPPERR_PARAM; + } + + /* Find a free PPP session descriptor. */ + for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); + + if (pd >= NUM_PPP) { + pd = PPPERR_OPEN; + } else { + pc = &pppControl[pd]; + /* input pbuf left over from last session? */ + pppFreeCurrentInputPacket(&pc->rx); + /* @todo: is this correct or do I overwrite something? */ + memset(pc, 0, sizeof(PPPControl)); + pc->rx.pd = pd; + pc->rx.fd = fd; + + pc->openFlag = 1; + pc->fd = fd; + +#if VJ_SUPPORT + vj_compress_init(&pc->vjComp); +#endif /* VJ_SUPPORT */ + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */ + pc->outACCM[15] = 0x60; + + pc->linkStatusCB = linkStatusCB; + pc->linkStatusCtx = linkStatusCtx; + + /* + * Start the connection and handle incoming events (packet or timeout). + */ + PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd)); + pppStart(pd); +#if PPP_INPROC_OWNTHREAD + sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); +#endif /* PPP_INPROC_OWNTHREAD */ + } + + return pd; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static void pppOverEthernetLinkStatusCB(int pd, int up); + +void +pppOverEthernetClose(int pd) +{ + PPPControl* pc = &pppControl[pd]; + + /* *TJL* There's no lcp_deinit */ + lcp_close(pd, NULL); + + pppoe_destroy(&pc->netif); +} + +int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, + pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx) +{ + PPPControl *pc; + int pd; + + LWIP_UNUSED_ARG(service_name); + LWIP_UNUSED_ARG(concentrator_name); + + if (linkStatusCB == NULL) { + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + return PPPERR_PARAM; + } + + /* Find a free PPP session descriptor. Critical region? */ + for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); + if (pd >= NUM_PPP) { + pd = PPPERR_OPEN; + } else { + pc = &pppControl[pd]; + memset(pc, 0, sizeof(PPPControl)); + pc->openFlag = 1; + pc->ethif = ethif; + + pc->linkStatusCB = linkStatusCB; + pc->linkStatusCtx = linkStatusCtx; + + lcp_wantoptions[pd].mru = PPPOE_MAXMTU; + lcp_wantoptions[pd].neg_asyncmap = 0; + lcp_wantoptions[pd].neg_pcompression = 0; + lcp_wantoptions[pd].neg_accompression = 0; + + lcp_allowoptions[pd].mru = PPPOE_MAXMTU; + lcp_allowoptions[pd].neg_asyncmap = 0; + lcp_allowoptions[pd].neg_pcompression = 0; + lcp_allowoptions[pd].neg_accompression = 0; + + if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { + pc->openFlag = 0; + return PPPERR_OPEN; + } + + pppoe_connect(pc->pppoe_sc); + } + + return pd; +} +#endif /* PPPOE_SUPPORT */ + + +/* Close a PPP connection and release the descriptor. + * Any outstanding packets in the queues are dropped. + * Return 0 on success, an error code on failure. */ +int +pppClose(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 0; + + PPPDEBUG(LOG_DEBUG, ("pppClose() called\n")); + + /* Disconnect */ +#if PPPOE_SUPPORT + if(pc->ethif) { + PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); + pc->errCode = PPPERR_USER; + /* This will leave us at PHASE_DEAD. */ + pppStop(pd); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT + PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); + pc->errCode = PPPERR_USER; + /* This will leave us at PHASE_DEAD. */ + pppStop(pd); +#if PPP_INPROC_OWNTHREAD + pppRecvWakeup(pd); +#endif /* PPP_INPROC_OWNTHREAD */ +#endif /* PPPOS_SUPPORT */ + } + + return st; +} + +/* This function is called when carrier is lost on the PPP channel. */ +void +pppSigHUP(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); + pppHup(pd); +} + +#if PPPOS_SUPPORT +static void +nPut(PPPControl *pc, struct pbuf *nb) +{ + struct pbuf *b; + int c; + + for(b = nb; b != NULL; b = b->next) { + if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) { + PPPDEBUG(LOG_WARNING, + ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c)); + LINK_STATS_INC(link.err); + pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ + snmp_inc_ifoutdiscards(&pc->netif); + pbuf_free(nb); + return; + } + } + + snmp_add_ifoutoctets(&pc->netif, nb->tot_len); + snmp_inc_ifoutucastpkts(&pc->netif); + pbuf_free(nb); + LINK_STATS_INC(link.xmit); +} + +/* + * pppAppend - append given character to end of given pbuf. If outACCM + * is not NULL and the character needs to be escaped, do so. + * If pbuf is full, append another. + * Return the current pbuf. + */ +static struct pbuf * +pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM) +{ + struct pbuf *tb = nb; + + /* Make sure there is room for the character and an escape code. + * Sure we don't quite fill the buffer if the character doesn't + * get escaped but is one character worth complicating this? */ + /* Note: We assume no packet header. */ + if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) { + tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (tb) { + nb->next = tb; + } else { + LINK_STATS_INC(link.memerr); + } + nb = tb; + } + + if (nb) { + if (outACCM && ESCAPE_P(*outACCM, c)) { + *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE; + *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS; + } else { + *((u_char*)nb->payload + nb->len++) = c; + } + } + + return tb; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static err_t +pppifOutputOverEthernet(int pd, struct pbuf *p) +{ + PPPControl *pc = &pppControl[pd]; + struct pbuf *pb; + u_short protocol = PPP_IP; + int i=0; + u16_t tot_len; + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); + + pc->lastXMit = sys_jiffies(); + + if (!pc->pcomp || protocol > 0xFF) { + *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; + } + *((u_char*)pb->payload + i) = protocol & 0xFF; + + pbuf_chain(pb, p); + tot_len = pb->tot_len; + + if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { + LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_DEVICE; + } + + snmp_add_ifoutoctets(&pc->netif, tot_len); + snmp_inc_ifoutucastpkts(&pc->netif); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} +#endif /* PPPOE_SUPPORT */ + +/* Send a packet on the given connection. */ +static err_t +pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr) +{ + int pd = (int)(size_t)netif->state; + PPPControl *pc = &pppControl[pd]; +#if PPPOS_SUPPORT + u_short protocol = PPP_IP; + u_int fcsOut = PPP_INITFCS; + struct pbuf *headMB = NULL, *tailMB = NULL, *p; + u_char c; +#endif /* PPPOS_SUPPORT */ + + LWIP_UNUSED_ARG(ipaddr); + + /* Validate parameters. */ + /* We let any protocol value go through - it can't hurt us + * and the peer will just drop it if it's not accepting it. */ + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n", + pd, PPP_IP, pb)); + LINK_STATS_INC(link.opterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_ARG; + } + + /* Check that the link is up. */ + if (lcp_phase[pd] == PHASE_DEAD) { + PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd)); + LINK_STATS_INC(link.rterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_RTE; + } + +#if PPPOE_SUPPORT + if(pc->ethif) { + return pppifOutputOverEthernet(pd, pb); + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOS_SUPPORT + /* Grab an output buffer. */ + headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (headMB == NULL) { + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_MEM; + } + +#if VJ_SUPPORT + /* + * Attempt Van Jacobson header compression if VJ is configured and + * this is an IP packet. + */ + if (protocol == PPP_IP && pc->vjEnabled) { + switch (vj_compress_tcp(&pc->vjComp, pb)) { + case TYPE_IP: + /* No change... + protocol = PPP_IP_PROTOCOL; */ + break; + case TYPE_COMPRESSED_TCP: + protocol = PPP_VJC_COMP; + break; + case TYPE_UNCOMPRESSED_TCP: + protocol = PPP_VJC_UNCOMP; + break; + default: + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd)); + LINK_STATS_INC(link.proterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + pbuf_free(headMB); + return ERR_VAL; + } + } +#endif /* VJ_SUPPORT */ + + tailMB = headMB; + + /* Build the PPP header. */ + if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + } + + pc->lastXMit = sys_jiffies(); + if (!pc->accomp) { + fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); + tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); + fcsOut = PPP_FCS(fcsOut, PPP_UI); + tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); + } + if (!pc->pcomp || protocol > 0xFF) { + c = (protocol >> 8) & 0xFF; + fcsOut = PPP_FCS(fcsOut, c); + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + c = protocol & 0xFF; + fcsOut = PPP_FCS(fcsOut, c); + tailMB = pppAppend(c, tailMB, &pc->outACCM); + + /* Load packet. */ + for(p = pb; p; p = p->next) { + int n; + u_char *sPtr; + + sPtr = (u_char*)p->payload; + n = p->len; + while (n-- > 0) { + c = *sPtr++; + + /* Update FCS before checking for special characters. */ + fcsOut = PPP_FCS(fcsOut, c); + + /* Copy to output buffer escaping special characters. */ + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + } + + /* Add FCS and trailing flag. */ + c = ~fcsOut & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + c = (~fcsOut >> 8) & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + + /* If we failed to complete the packet, throw it away. */ + if (!tailMB) { + PPPDEBUG(LOG_WARNING, + ("pppifOutput[%d]: Alloc err - dropping proto=%d\n", + pd, protocol)); + pbuf_free(headMB); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_MEM; + } + + /* Send it. */ + PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol)); + + nPut(pc, headMB); +#endif /* PPPOS_SUPPORT */ + + return ERR_OK; +} + +/* Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. */ +int +pppIOCtl(int pd, int cmd, void *arg) +{ + PPPControl *pc = &pppControl[pd]; + int st = 0; + + if (pd < 0 || pd >= NUM_PPP) { + st = PPPERR_PARAM; + } else { + switch(cmd) { + case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ + if (arg) { + *(int *)arg = (int)(pc->if_up); + } else { + st = PPPERR_PARAM; + } + break; + case PPPCTLS_ERRCODE: /* Set the PPP error code. */ + if (arg) { + pc->errCode = *(int *)arg; + } else { + st = PPPERR_PARAM; + } + break; + case PPPCTLG_ERRCODE: /* Get the PPP error code. */ + if (arg) { + *(int *)arg = (int)(pc->errCode); + } else { + st = PPPERR_PARAM; + } + break; +#if PPPOS_SUPPORT + case PPPCTLG_FD: /* Get the fd associated with the ppp */ + if (arg) { + *(sio_fd_t *)arg = pc->fd; + } else { + st = PPPERR_PARAM; + } + break; +#endif /* PPPOS_SUPPORT */ + default: + st = PPPERR_PARAM; + break; + } + } + + return st; +} + +/* + * Return the Maximum Transmission Unit for the given PPP connection. + */ +u_short +pppMTU(int pd) +{ + PPPControl *pc = &pppControl[pd]; + u_short st; + + /* Validate parameters. */ + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + } else { + st = pc->mtu; + } + + return st; +} + +#if PPPOE_SUPPORT +int +pppWriteOverEthernet(int pd, const u_char *s, int n) +{ + PPPControl *pc = &pppControl[pd]; + struct pbuf *pb; + + /* skip address & flags */ + s += 2; + n -= 2; + + LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_ALLOC; + } + + pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); + + pc->lastXMit = sys_jiffies(); + + MEMCPY(pb->payload, s, n); + + if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { + LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_DEVICE; + } + + snmp_add_ifoutoctets(&pc->netif, (u16_t)n); + snmp_inc_ifoutucastpkts(&pc->netif); + LINK_STATS_INC(link.xmit); + return PPPERR_NONE; +} +#endif /* PPPOE_SUPPORT */ + +/* + * Write n characters to a ppp link. + * RETURN: >= 0 Number of characters written + * -1 Failed to write to device + */ +int +pppWrite(int pd, const u_char *s, int n) +{ + PPPControl *pc = &pppControl[pd]; +#if PPPOS_SUPPORT + u_char c; + u_int fcsOut; + struct pbuf *headMB, *tailMB; +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT + if(pc->ethif) { + return pppWriteOverEthernet(pd, s, n); + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOS_SUPPORT + headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (headMB == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_ALLOC; + } + + tailMB = headMB; + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + } + pc->lastXMit = sys_jiffies(); + + fcsOut = PPP_INITFCS; + /* Load output buffer. */ + while (n-- > 0) { + c = *s++; + + /* Update FCS before checking for special characters. */ + fcsOut = PPP_FCS(fcsOut, c); + + /* Copy to output buffer escaping special characters. */ + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + + /* Add FCS and trailing flag. */ + c = ~fcsOut & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + c = (~fcsOut >> 8) & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + + /* If we failed to complete the packet, throw it away. + * Otherwise send it. */ + if (!tailMB) { + PPPDEBUG(LOG_WARNING, + ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); + /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ + pbuf_free(headMB); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_ALLOC; + } + + PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len)); + /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ + nPut(pc, headMB); +#endif /* PPPOS_SUPPORT */ + + return PPPERR_NONE; +} + +/* + * ppp_send_config - configure the transmit characteristics of + * the ppp interface. + */ +void +ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp) +{ + PPPControl *pc = &pppControl[unit]; + int i; + + pc->mtu = mtu; + pc->pcomp = pcomp; + pc->accomp = accomp; + + /* Load the ACCM bits for the 32 control codes. */ + for (i = 0; i < 32/8; i++) { + pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF); + } + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n", + unit, + pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3])); +} + + +/* + * ppp_set_xaccm - set the extended transmit ACCM for the interface. + */ +void +ppp_set_xaccm(int unit, ext_accm *accm) +{ + SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm)); + PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", + unit, + pppControl[unit].outACCM[0], + pppControl[unit].outACCM[1], + pppControl[unit].outACCM[2], + pppControl[unit].outACCM[3])); +} + + +/* + * ppp_recv_config - configure the receive-side characteristics of + * the ppp interface. + */ +void +ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp) +{ + PPPControl *pc = &pppControl[unit]; + int i; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(accomp); + LWIP_UNUSED_ARG(pcomp); + LWIP_UNUSED_ARG(mru); + + /* Load the ACCM bits for the 32 control codes. */ + SYS_ARCH_PROTECT(lev); + for (i = 0; i < 32 / 8; i++) { + /* @todo: does this work? ext_accm has been modified from pppd! */ + pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8)); + } + SYS_ARCH_UNPROTECT(lev); + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n", + unit, + pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3])); +} + +#if 0 +/* + * ccp_test - ask kernel whether a given compression method + * is acceptable for use. Returns 1 if the method and parameters + * are OK, 0 if the method is known but the parameters are not OK + * (e.g. code size should be reduced), or -1 if the method is unknown. + */ +int +ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr) +{ + return 0; /* XXX Currently no compression. */ +} + +/* + * ccp_flags_set - inform kernel about the current state of CCP. + */ +void +ccp_flags_set(int unit, int isopen, int isup) +{ + /* XXX */ +} + +/* + * ccp_fatal_error - returns 1 if decompression was disabled as a + * result of an error detected after decompression of a packet, + * 0 otherwise. This is necessary because of patent nonsense. + */ +int +ccp_fatal_error(int unit) +{ + /* XXX */ + return 0; +} +#endif + +/* + * get_idle_time - return how long the link has been idle. + */ +int +get_idle_time(int u, struct ppp_idle *ip) +{ + /* XXX */ + LWIP_UNUSED_ARG(u); + LWIP_UNUSED_ARG(ip); + + return 0; +} + + +/* + * Return user specified netmask, modified by any mask we might determine + * for address `addr' (in network byte order). + * Here we scan through the system's list of interfaces, looking for + * any non-point-to-point interfaces which might appear to be on the same + * network as `addr'. If we find any, we OR in their netmask to the + * user-specified netmask. + */ +u32_t +GetMask(u32_t addr) +{ + u32_t mask, nmask; + + addr = htonl(addr); + if (IP_CLASSA(addr)) { /* determine network mask for address class */ + nmask = IP_CLASSA_NET; + } else if (IP_CLASSB(addr)) { + nmask = IP_CLASSB_NET; + } else { + nmask = IP_CLASSC_NET; + } + + /* class D nets are disallowed by bad_ip_adrs */ + mask = subnetMask | htonl(nmask); + + /* XXX + * Scan through the system's network interfaces. + * Get each netmask and OR them into our mask. + */ + + return mask; +} + +/* + * sifvjcomp - config tcp header compression + */ +int +sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid) +{ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPControl *pc = &pppControl[pd]; + + pc->vjEnabled = vjcomp; + pc->vjComp.compressSlot = cidcomp; + pc->vjComp.maxSlotIndex = maxcid; + PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", + vjcomp, cidcomp, maxcid)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + LWIP_UNUSED_ARG(pd); + LWIP_UNUSED_ARG(vjcomp); + LWIP_UNUSED_ARG(cidcomp); + LWIP_UNUSED_ARG(maxcid); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + + return 0; +} + +/* + * pppifNetifInit - netif init callback + */ +static err_t +pppifNetifInit(struct netif *netif) +{ + netif->name[0] = 'p'; + netif->name[1] = 'p'; + netif->output = pppifOutput; + netif->mtu = pppMTU((int)(size_t)netif->state); + netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP; +#if LWIP_NETIF_HOSTNAME + /* @todo: Initialize interface hostname */ + /* netif_set_hostname(netif, "lwip"); */ +#endif /* LWIP_NETIF_HOSTNAME */ + return ERR_OK; +} + + +/* + * sifup - Config the interface up and enable IP packets to pass. + */ +int +sifup(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + netif_remove(&pc->netif); + if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, + &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) { + netif_set_up(&pc->netif); + pc->if_up = 1; + pc->errCode = PPPERR_NONE; + + PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs); + } + } else { + st = 0; + PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd)); + } + } + + return st; +} + +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int +sifnpmode(int u, int proto, enum NPmode mode) +{ + LWIP_UNUSED_ARG(u); + LWIP_UNUSED_ARG(proto); + LWIP_UNUSED_ARG(mode); + return 0; +} + +/* + * sifdown - Config the interface down and disable IP. + */ +int +sifdown(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd)); + } else { + pc->if_up = 0; + /* make sure the netif status callback is called */ + netif_set_down(&pc->netif); + netif_remove(&pc->netif); + PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL); + } + } + return st; +} + +/** + * sifaddr - Config the interface IP addresses and netmask. + * @param pd Interface unit ??? + * @param o Our IP address ??? + * @param h His IP address ??? + * @param m IP subnet mask ??? + * @param ns1 Primary DNS + * @param ns2 Secondary DNS + */ +int +sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o)); + SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h)); + SMEMCPY(&pc->addrs.netmask, &m, sizeof(m)); + SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1)); + SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2)); + } + return st; +} + +/** + * cifaddr - Clear the interface IP addresses, and delete routes + * through the interface if possible. + * @param pd Interface unit ??? + * @param o Our IP address ??? + * @param h IP broadcast address ??? + */ +int +cifaddr( int pd, u32_t o, u32_t h) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(o); + LWIP_UNUSED_ARG(h); + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0); + IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0); + IP4_ADDR(&pc->addrs.netmask, 255,255,255,0); + IP4_ADDR(&pc->addrs.dns1, 0,0,0,0); + IP4_ADDR(&pc->addrs.dns2, 0,0,0,0); + } + return st; +} + +/* + * sifdefaultroute - assign a default route through the address given. + */ +int +sifdefaultroute(int pd, u32_t l, u32_t g) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(l); + LWIP_UNUSED_ARG(g); + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + netif_set_default(&pc->netif); + } + + /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */ + + return st; +} + +/* + * cifdefaultroute - delete a default route through the address given. + */ +int +cifdefaultroute(int pd, u32_t l, u32_t g) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(l); + LWIP_UNUSED_ARG(g); + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + netif_set_default(NULL); + } + + return st; +} + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +#if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD +/* The main PPP process function. This implements the state machine according + * to section 4 of RFC 1661: The Point-To-Point Protocol. */ +static void +pppInputThread(void *arg) +{ + int count; + PPPControlRx *pcrx = arg; + + while (lcp_phase[pcrx->pd] != PHASE_DEAD) { + count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE); + if(count > 0) { + pppInProc(pcrx, pcrx->rxbuf, count); + } else { + /* nothing received, give other tasks a chance to run */ + sys_msleep(1); + } + } +} +#endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */ + +#if PPPOE_SUPPORT + +void +pppOverEthernetInitFailed(int pd) +{ + PPPControl* pc; + + pppHup(pd); + pppStop(pd); + + pc = &pppControl[pd]; + pppoe_destroy(&pc->netif); + pc->openFlag = 0; + + if(pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); + } +} + +static void +pppOverEthernetLinkStatusCB(int pd, int up) +{ + if(up) { + PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd)); + pppStart(pd); + } else { + pppOverEthernetInitFailed(pd); + } +} +#endif /* PPPOE_SUPPORT */ + +struct pbuf * +pppSingleBuf(struct pbuf *p) +{ + struct pbuf *q, *b; + u_char *pl; + + if(p->tot_len == p->len) { + return p; + } + + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(!q) { + PPPDEBUG(LOG_ERR, + ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); + return p; /* live dangerously */ + } + + for(b = p, pl = q->payload; b != NULL; b = b->next) { + MEMCPY(pl, b->payload, b->len); + pl += b->len; + } + + pbuf_free(p); + + return q; +} + +struct pppInputHeader { + int unit; + u16_t proto; +}; + +/* + * Pass the processed input packet to the appropriate handler. + * This function and all handlers run in the context of the tcpip_thread + */ +static void +pppInput(void *arg) +{ + struct pbuf *nb = (struct pbuf *)arg; + u16_t protocol; + int pd; + + pd = ((struct pppInputHeader *)nb->payload)->unit; + protocol = ((struct pppInputHeader *)nb->payload)->proto; + + if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + + LINK_STATS_INC(link.recv); + snmp_inc_ifinucastpkts(&pppControl[pd].netif); + snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len); + + /* + * Toss all non-LCP packets unless LCP is OPEN. + * Until we get past the authentication phase, toss all packets + * except LCP, LQR and authentication packets. + */ + if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) { + if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) || + (lcp_phase[pd] != PHASE_AUTHENTICATE)) { + PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd])); + goto drop; + } + } + + switch(protocol) { + case PPP_VJC_COMP: /* VJ compressed TCP */ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); + /* + * Clip off the VJ header and prepend the rebuilt TCP/IP header and + * pass the result to IP. + */ + if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + /* No handler for this protocol so drop the packet. */ + PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + break; + + case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); + /* + * Process the TCP/IP header for VJ header compression and then pass + * the packet to IP. + */ + if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + /* No handler for this protocol so drop the packet. */ + PPPDEBUG(LOG_INFO, + ("pppInput[%d]: drop VJ UnComp in %d:.*H\n", + pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + break; + + case PPP_IP: /* Internet Protocol */ + PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); + if (pppControl[pd].netif.input) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + break; + + default: { + struct protent *protp; + int i; + + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol == protocol && protp->enabled_flag) { + PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); + nb = pppSingleBuf(nb); + (*protp->input)(pd, nb->payload, nb->len); + PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd)); + goto out; + } + } + + /* No handler for this protocol so reject the packet. */ + PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len)); + if (pbuf_header(nb, sizeof(protocol))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } +#if BYTE_ORDER == LITTLE_ENDIAN + protocol = htons(protocol); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + SMEMCPY(nb->payload, &protocol, sizeof(protocol)); + lcp_sprotrej(pd, nb->payload, nb->len); + } + break; + } + +drop: + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pd].netif); + +out: + pbuf_free(nb); + return; +} + +#if PPPOS_SUPPORT +/* + * Drop the input packet. + */ +static void +pppFreeCurrentInputPacket(PPPControlRx *pcrx) +{ + if (pcrx->inHead != NULL) { + if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) { + pbuf_free(pcrx->inTail); + } + pbuf_free(pcrx->inHead); + pcrx->inHead = NULL; + } + pcrx->inTail = NULL; +} + +/* + * Drop the input packet and increase error counters. + */ +static void +pppDrop(PPPControlRx *pcrx) +{ + if (pcrx->inHead != NULL) { +#if 0 + PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload)); +#endif + PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead)); + } + pppFreeCurrentInputPacket(pcrx); +#if VJ_SUPPORT + vj_uncompress_err(&pppControl[pcrx->pd].vjComp); +#endif /* VJ_SUPPORT */ + + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); +} + +#if !PPP_INPROC_OWNTHREAD +/** Pass received raw characters to PPPoS to be decoded. This function is + * thread-safe and can be called from a dedicated RX-thread or from a main-loop. + * + * @param pd PPP descriptor index, returned by pppOpen() + * @param data received data + * @param len length of received data + */ +void +pppos_input(int pd, u_char* data, int len) +{ + pppInProc(&pppControl[pd].rx, data, len); +} +#endif + +/** + * Process a received octet string. + */ +static void +pppInProc(PPPControlRx *pcrx, u_char *s, int l) +{ + struct pbuf *nextNBuf; + u_char curChar; + u_char escaped; + SYS_ARCH_DECL_PROTECT(lev); + + PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l)); + while (l-- > 0) { + curChar = *s++; + + SYS_ARCH_PROTECT(lev); + escaped = ESCAPE_P(pcrx->inACCM, curChar); + SYS_ARCH_UNPROTECT(lev); + /* Handle special characters. */ + if (escaped) { + /* Check for escape sequences. */ + /* XXX Note that this does not handle an escaped 0x5d character which + * would appear as an escape character. Since this is an ASCII ']' + * and there is no reason that I know of to escape it, I won't complicate + * the code to handle this case. GLL */ + if (curChar == PPP_ESCAPE) { + pcrx->inEscaped = 1; + /* Check for the flag character. */ + } else if (curChar == PPP_FLAG) { + /* If this is just an extra flag character, ignore it. */ + if (pcrx->inState <= PDADDRESS) { + /* ignore it */; + /* If we haven't received the packet header, drop what has come in. */ + } else if (pcrx->inState < PDDATA) { + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Dropping incomplete packet %d\n", + pcrx->pd, pcrx->inState)); + LINK_STATS_INC(link.lenerr); + pppDrop(pcrx); + /* If the fcs is invalid, drop the packet. */ + } else if (pcrx->inFCS != PPP_GOODFCS) { + PPPDEBUG(LOG_INFO, + ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", + pcrx->pd, pcrx->inFCS, pcrx->inProtocol)); + /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ + LINK_STATS_INC(link.chkerr); + pppDrop(pcrx); + /* Otherwise it's a good packet so pass it on. */ + } else { + struct pbuf *inp; + /* Trim off the checksum. */ + if(pcrx->inTail->len >= 2) { + pcrx->inTail->len -= 2; + + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + } + } else { + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + } + + pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2); + } + + /* Dispatch the packet thereby consuming it. */ + inp = pcrx->inHead; + /* Packet consumed, release our references. */ + pcrx->inHead = NULL; + pcrx->inTail = NULL; +#if PPP_INPROC_MULTITHREADED + if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) { + PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd)); + pbuf_free(inp); + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); + } +#else /* PPP_INPROC_MULTITHREADED */ + pppInput(inp); +#endif /* PPP_INPROC_MULTITHREADED */ + } + + /* Prepare for a new packet. */ + pcrx->inFCS = PPP_INITFCS; + pcrx->inState = PDADDRESS; + pcrx->inEscaped = 0; + /* Other characters are usually control characters that may have + * been inserted by the physical layer so here we just drop them. */ + } else { + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar)); + } + /* Process other characters. */ + } else { + /* Unencode escaped characters. */ + if (pcrx->inEscaped) { + pcrx->inEscaped = 0; + curChar ^= PPP_TRANS; + } + + /* Process character relative to current state. */ + switch(pcrx->inState) { + case PDIDLE: /* Idle state - waiting. */ + /* Drop the character if it's not 0xff + * we would have processed a flag character above. */ + if (curChar != PPP_ALLSTATIONS) { + break; + } + + /* Fall through */ + case PDSTART: /* Process start flag. */ + /* Prepare for a new packet. */ + pcrx->inFCS = PPP_INITFCS; + + /* Fall through */ + case PDADDRESS: /* Process address field. */ + if (curChar == PPP_ALLSTATIONS) { + pcrx->inState = PDCONTROL; + break; + } + /* Else assume compressed address and control fields so + * fall through to get the protocol... */ + case PDCONTROL: /* Process control field. */ + /* If we don't get a valid control code, restart. */ + if (curChar == PPP_UI) { + pcrx->inState = PDPROTOCOL1; + break; + } +#if 0 + else { + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar)); + pcrx->inState = PDSTART; + } +#endif + case PDPROTOCOL1: /* Process protocol field 1. */ + /* If the lower bit is set, this is the end of the protocol + * field. */ + if (curChar & 1) { + pcrx->inProtocol = curChar; + pcrx->inState = PDDATA; + } else { + pcrx->inProtocol = (u_int)curChar << 8; + pcrx->inState = PDPROTOCOL2; + } + break; + case PDPROTOCOL2: /* Process protocol field 2. */ + pcrx->inProtocol |= curChar; + pcrx->inState = PDDATA; + break; + case PDDATA: /* Process data byte. */ + /* Make space to receive processed data. */ + if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) { + if (pcrx->inTail != NULL) { + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + /* give up the inTail reference now */ + pcrx->inTail = NULL; + } + } + /* If we haven't started a packet, we need a packet header. */ + nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nextNBuf == NULL) { + /* No free buffers. Drop the input packet and let the + * higher layers deal with it. Continue processing + * the received pbuf chain in case a new packet starts. */ + PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd)); + LINK_STATS_INC(link.memerr); + pppDrop(pcrx); + pcrx->inState = PDSTART; /* Wait for flag sequence. */ + break; + } + if (pcrx->inHead == NULL) { + struct pppInputHeader *pih = nextNBuf->payload; + + pih->unit = pcrx->pd; + pih->proto = pcrx->inProtocol; + + nextNBuf->len += sizeof(*pih); + + pcrx->inHead = nextNBuf; + } + pcrx->inTail = nextNBuf; + } + /* Load character into buffer. */ + ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar; + break; + } + + /* update the frame check sequence number. */ + pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar); + } + } /* while (l-- > 0), all bytes processed */ + + avRandomize(); +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +void +pppInProcOverEthernet(int pd, struct pbuf *pb) +{ + struct pppInputHeader *pih; + u16_t inProtocol; + + if(pb->len < sizeof(inProtocol)) { + PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n")); + goto drop; + } + + inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; + + /* make room for pppInputHeader - should not fail */ + if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) { + PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n")); + goto drop; + } + + pih = pb->payload; + + pih->unit = pd; + pih->proto = inProtocol; + + /* Dispatch the packet thereby consuming it. */ + pppInput(pb); + return; + +drop: + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pd].netif); + pbuf_free(pb); + return; +} +#endif /* PPPOE_SUPPORT */ + +#if LWIP_NETIF_STATUS_CALLBACK +/** Set the status callback of a PPP's netif + * + * @param pd The PPP descriptor returned by pppOpen() + * @param status_callback pointer to the status callback function + * + * @see netif_set_status_callback + */ +void +ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback) +{ + netif_set_status_callback(&pppControl[pd].netif, status_callback); +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +/** Set the link callback of a PPP's netif + * + * @param pd The PPP descriptor returned by pppOpen() + * @param link_callback pointer to the link callback function + * + * @see netif_set_link_callback + */ +void +ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback) +{ + netif_set_link_callback(&pppControl[pd].netif, link_callback); +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/ppp.h b/ext/lwip/src/netif/ppp/ppp.h new file mode 100644 index 000000000..08d6e62d8 --- /dev/null +++ b/ext/lwip/src/netif/ppp/ppp.h @@ -0,0 +1,201 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#ifndef PPP_H +#define PPP_H + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/sio.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/timers.h" + + +#ifndef __u_char_defined + +/* Type definitions for BSD code. */ +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; + +#endif + + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ + +/* Error codes. */ +#define PPPERR_NONE 0 /* No error. */ +#define PPPERR_PARAM -1 /* Invalid parameter. */ +#define PPPERR_OPEN -2 /* Unable to open PPP session. */ +#define PPPERR_DEVICE -3 /* Invalid I/O device for PPP. */ +#define PPPERR_ALLOC -4 /* Unable to allocate resources. */ +#define PPPERR_USER -5 /* User interrupt. */ +#define PPPERR_CONNECT -6 /* Connection lost. */ +#define PPPERR_AUTHFAIL -7 /* Failed authentication challenge. */ +#define PPPERR_PROTOCOL -8 /* Failed to meet protocol. */ + +/* + * PPP IOCTL commands. + */ +/* + * Get the up status - 0 for down, non-zero for up. The argument must + * point to an int. + */ +#define PPPCTLG_UPSTATUS 100 /* Get the up status - 0 down else up */ +#define PPPCTLS_ERRCODE 101 /* Set the error code */ +#define PPPCTLG_ERRCODE 102 /* Get the error code */ +#define PPPCTLG_FD 103 /* Get the fd associated with the ppp */ + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +struct ppp_addrs { + ip_addr_t our_ipaddr, his_ipaddr, netmask, dns1, dns2; +}; + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* Initialize the PPP subsystem. */ +void pppInit(void); + +/* Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + */ +enum pppAuthType { + PPPAUTHTYPE_NONE, + PPPAUTHTYPE_ANY, + PPPAUTHTYPE_PAP, + PPPAUTHTYPE_CHAP +}; + +void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd); + +/* Link status callback function prototype */ +typedef void (*pppLinkStatusCB_fn)(void *ctx, int errCode, void *arg); + +#if PPPOS_SUPPORT +/* + * Open a new PPP connection using the given serial I/O device. + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. + * Return a new PPP connection descriptor on success or + * an error code (negative) on failure. + */ +int pppOverSerialOpen(sio_fd_t fd, pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx); +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +/* + * Open a new PPP Over Ethernet (PPPOE) connection. + */ +int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, + pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx); +#endif /* PPPOE_SUPPORT */ + +/* for source code compatibility */ +#define pppOpen(fd,cb,ls) pppOverSerialOpen(fd,cb,ls) + +/* + * Close a PPP connection and release the descriptor. + * Any outstanding packets in the queues are dropped. + * Return 0 on success, an error code on failure. + */ +int pppClose(int pd); + +/* + * Indicate to the PPP process that the line has disconnected. + */ +void pppSigHUP(int pd); + +/* + * Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. + */ +int pppIOCtl(int pd, int cmd, void *arg); + +/* + * Return the Maximum Transmission Unit for the given PPP connection. + */ +u_short pppMTU(int pd); + +#if PPPOS_SUPPORT && !PPP_INPROC_OWNTHREAD +/* + * PPP over Serial: this is the input function to be called for received data. + * If PPP_INPROC_OWNTHREAD==1, a seperate input thread using the blocking + * sio_read() is used, so this is deactivated. + */ +void pppos_input(int pd, u_char* data, int len); +#endif /* PPPOS_SUPPORT && !PPP_INPROC_OWNTHREAD */ + + +#if LWIP_NETIF_STATUS_CALLBACK +/* Set an lwIP-style status-callback for the selected PPP device */ +void ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK +/* Set an lwIP-style link-callback for the selected PPP device */ +void ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#endif /* PPP_SUPPORT */ + +#endif /* PPP_H */ diff --git a/ext/lwip/src/netif/ppp/ppp_impl.h b/ext/lwip/src/netif/ppp/ppp_impl.h new file mode 100644 index 000000000..89aea60be --- /dev/null +++ b/ext/lwip/src/netif/ppp/ppp_impl.h @@ -0,0 +1,363 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#ifndef PPP_IMPL_H +#define PPP_IMPL_H + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "lwip/def.h" +#include "lwip/sio.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/timers.h" + +/** Some defines for code we skip compared to the original pppd. + * These are just here to minimise the use of the ugly "#if 0". */ +#define PPP_ADDITIONAL_CALLBACKS 0 + +/** Some error checks to test for unsupported code */ +#if CBCP_SUPPORT +#error "CBCP is not supported in lwIP PPP" +#endif +#if CCP_SUPPORT +#error "CCP is not supported in lwIP PPP" +#endif + +/* + * pppd.h - PPP daemon global declarations. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ +/* + * ppp_defs.h - PPP definitions. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) +#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) + + +/* + * Constants and structures defined by the internet system, + * Per RFC 790, September 1981, and numerous additions. + */ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ + + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#define PPP_COMP 0xfd /* compressed packet */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ + +/* + * Values for FCS calculations. + */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u_char ext_accm[32]; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Inline versions of get/put char/short/long. + * Pointer is advanced; we assume that both arguments + * are lvalues and will already be in registers. + * cp MUST be u_char *. + */ +#define GETCHAR(c, cp) { \ + (c) = *(cp)++; \ +} +#define PUTCHAR(c, cp) { \ + *(cp)++ = (u_char) (c); \ +} + + +#define GETSHORT(s, cp) { \ + (s) = *(cp); (cp)++; (s) <<= 8; \ + (s) |= *(cp); (cp)++; \ +} +#define PUTSHORT(s, cp) { \ + *(cp)++ = (u_char) ((s) >> 8); \ + *(cp)++ = (u_char) (s & 0xff); \ +} + +#define GETLONG(l, cp) { \ + (l) = *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; \ +} +#define PUTLONG(l, cp) { \ + *(cp)++ = (u_char) ((l) >> 24); \ + *(cp)++ = (u_char) ((l) >> 16); \ + *(cp)++ = (u_char) ((l) >> 8); \ + *(cp)++ = (u_char) (l); \ +} + + +#define INCPTR(n, cp) ((cp) += (n)) +#define DECPTR(n, cp) ((cp) -= (n)) + +#define BCMP(s0, s1, l) memcmp((u_char *)(s0), (u_char *)(s1), (l)) +#define BCOPY(s, d, l) MEMCPY((d), (s), (l)) +#define BZERO(s, n) memset(s, 0, n) + +#if PPP_DEBUG +#define PRINTMSG(m, l) { m[l] = '\0'; LWIP_DEBUGF(LOG_INFO, ("Remote message: %s\n", m)); } +#else /* PPP_DEBUG */ +#define PRINTMSG(m, l) +#endif /* PPP_DEBUG */ + +/* + * MAKEHEADER - Add PPP Header fields to a packet. + */ +#define MAKEHEADER(p, t) { \ + PUTCHAR(PPP_ALLSTATIONS, p); \ + PUTCHAR(PPP_UI, p); \ + PUTSHORT(t, p); } + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * The following struct gives the addresses of procedures to call + * for a particular protocol. + */ +struct protent { + u_short protocol; /* PPP protocol number */ + /* Initialization procedure */ + void (*init) (int unit); + /* Process a received packet */ + void (*input) (int unit, u_char *pkt, int len); + /* Process a received protocol-reject */ + void (*protrej) (int unit); + /* Lower layer has come up */ + void (*lowerup) (int unit); + /* Lower layer has gone down */ + void (*lowerdown) (int unit); + /* Open the protocol */ + void (*open) (int unit); + /* Close the protocol */ + void (*close) (int unit, char *reason); +#if PPP_ADDITIONAL_CALLBACKS + /* Print a packet in readable form */ + int (*printpkt) (u_char *pkt, int len, + void (*printer) (void *, char *, ...), + void *arg); + /* Process a received data packet */ + void (*datainput) (int unit, u_char *pkt, int len); +#endif /* PPP_ADDITIONAL_CALLBACKS */ + int enabled_flag; /* 0 if protocol is disabled */ + char *name; /* Text name of protocol */ +#if PPP_ADDITIONAL_CALLBACKS + /* Check requested options, assign defaults */ + void (*check_options) (u_long); + /* Configure interface for demand-dial */ + int (*demand_conf) (int unit); + /* Say whether to bring up link for this pkt */ + int (*active_pkt) (u_char *pkt, int len); +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + u_short xmit_idle; /* seconds since last NP packet sent */ + u_short recv_idle; /* seconds since last NP packet received */ +}; + +struct ppp_settings { + + u_int disable_defaultip : 1; /* Don't use hostname for default IP addrs */ + u_int auth_required : 1; /* Peer is required to authenticate */ + u_int explicit_remote : 1; /* remote_name specified with remotename opt */ + u_int refuse_pap : 1; /* Don't wanna auth. ourselves with PAP */ + u_int refuse_chap : 1; /* Don't wanna auth. ourselves with CHAP */ + u_int usehostname : 1; /* Use hostname for our_name */ + u_int usepeerdns : 1; /* Ask peer for DNS adds */ + + u_short idle_time_limit; /* Shut down link if idle for this long */ + int maxconnect; /* Maximum connect time (seconds) */ + + char user [MAXNAMELEN + 1]; /* Username for PAP */ + char passwd [MAXSECRETLEN + 1]; /* Password for PAP, secret for CHAP */ + char our_name [MAXNAMELEN + 1]; /* Our name for authentication purposes */ + char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ +}; + +/***************************** +*** PUBLIC DATA STRUCTURES *** +*****************************/ + +/* Buffers for outgoing packets. */ +extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; + +extern struct ppp_settings ppp_settings; + +extern struct protent *ppp_protocols[]; /* Table of pointers to supported protocols */ + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* + * Write n characters to a ppp link. + * RETURN: >= 0 Number of characters written, -1 Failed to write to device. + */ +int pppWrite(int pd, const u_char *s, int n); + +void pppInProcOverEthernet(int pd, struct pbuf *pb); + +struct pbuf *pppSingleBuf(struct pbuf *p); + +void pppLinkTerminated(int pd); + +void pppLinkDown(int pd); + +/* Configure i/f transmit parameters */ +void ppp_send_config (int, u16_t, u32_t, int, int); +/* Set extended transmit ACCM */ +void ppp_set_xaccm (int, ext_accm *); +/* Configure i/f receive parameters */ +void ppp_recv_config (int, int, u32_t, int, int); +/* Find out how long link has been idle */ +int get_idle_time (int, struct ppp_idle *); + +/* Configure VJ TCP header compression */ +int sifvjcomp (int, int, u8_t, u8_t); +/* Configure i/f down (for IP) */ +int sifup (int); +/* Set mode for handling packets for proto */ +int sifnpmode (int u, int proto, enum NPmode mode); +/* Configure i/f down (for IP) */ +int sifdown (int); +/* Configure IP addresses for i/f */ +int sifaddr (int, u32_t, u32_t, u32_t, u32_t, u32_t); +/* Reset i/f IP addresses */ +int cifaddr (int, u32_t, u32_t); +/* Create default route through i/f */ +int sifdefaultroute (int, u32_t, u32_t); +/* Delete default route through i/f */ +int cifdefaultroute (int, u32_t, u32_t); + +/* Get appropriate netmask for address */ +u32_t GetMask (u32_t); + +#endif /* PPP_SUPPORT */ + +#endif /* PPP_IMPL_H */ diff --git a/ext/lwip/src/netif/ppp/ppp_oe.c b/ext/lwip/src/netif/ppp/ppp_oe.c new file mode 100644 index 000000000..fdf52ae23 --- /dev/null +++ b/ext/lwip/src/netif/ppp/ppp_oe.c @@ -0,0 +1,1132 @@ +/***************************************************************************** +* ppp_oe.c - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lwip/opt.h" + +#if PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp_oe.h" + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "lwip/timers.h" +#include "lwip/memp.h" + +#include +#include + + +/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ +#define PPPOE_ADD_16(PTR, VAL) \ + *(PTR)++ = (u8_t)((VAL) / 256); \ + *(PTR)++ = (u8_t)((VAL) % 256) + +/* Add a complete PPPoE header to the buffer pointed to by PTR */ +#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ + *(PTR)++ = PPPOE_VERTYPE; \ + *(PTR)++ = (CODE); \ + PPPOE_ADD_16(PTR, SESS); \ + PPPOE_ADD_16(PTR, LEN) + +#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ +#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ +#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ + +#ifdef PPPOE_SERVER +#error "PPPOE_SERVER is not yet supported under lwIP!" +/* from if_spppsubr.c */ +#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ +#endif + +#ifndef PPPOE_ERRORSTRING_LEN +#define PPPOE_ERRORSTRING_LEN 64 +#endif +static char pppoe_error_tmp[PPPOE_ERRORSTRING_LEN]; + + +/* input routines */ +static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *); + +/* management routines */ +static int pppoe_do_disconnect(struct pppoe_softc *); +static void pppoe_abort_connect(struct pppoe_softc *); +static void pppoe_clear_softc(struct pppoe_softc *, const char *); + +/* internal timeout handling */ +static void pppoe_timeout(void *); + +/* sending actual protocol controll packets */ +static err_t pppoe_send_padi(struct pppoe_softc *); +static err_t pppoe_send_padr(struct pppoe_softc *); +#ifdef PPPOE_SERVER +static err_t pppoe_send_pado(struct pppoe_softc *); +static err_t pppoe_send_pads(struct pppoe_softc *); +#endif +static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); + +/* internal helper functions */ +static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *); +static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *); + +/** linked list of created pppoe interfaces */ +static struct pppoe_softc *pppoe_softc_list; + +err_t +pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr) +{ + struct pppoe_softc *sc; + + sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF); + if (sc == NULL) { + *scptr = NULL; + return ERR_MEM; + } + memset(sc, 0, sizeof(struct pppoe_softc)); + + /* changed to real address later */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + + sc->sc_pd = pd; + sc->sc_linkStatusCB = linkStatusCB; + sc->sc_ethif = ethif; + + /* put the new interface at the head of the list */ + sc->next = pppoe_softc_list; + pppoe_softc_list = sc; + + *scptr = sc; + + return ERR_OK; +} + +err_t +pppoe_destroy(struct netif *ifp) +{ + struct pppoe_softc *sc, *prev = NULL; + + for (sc = pppoe_softc_list; sc != NULL; prev = sc, sc = sc->next) { + if (sc->sc_ethif == ifp) { + break; + } + } + + if(!(sc && (sc->sc_ethif == ifp))) { + return ERR_IF; + } + + sys_untimeout(pppoe_timeout, sc); + if (prev == NULL) { + /* remove sc from the head of the list */ + pppoe_softc_list = sc->next; + } else { + /* remove sc from the list */ + prev->next = sc->next; + } + +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name) { + mem_free(sc->sc_concentrator_name); + } + if (sc->sc_service_name) { + mem_free(sc->sc_service_name); + } +#endif /* PPPOE_TODO */ + memp_free(MEMP_PPPOE_IF, sc); + + return ERR_OK; +} + +/* + * Find the interface handling the specified session. + * Note: O(number of sessions open), this is a client-side only, mean + * and lean implementation, so number of open sessions typically should + * be 1. + */ +static struct pppoe_softc * +pppoe_find_softc_by_session(u_int session, struct netif *rcvif) +{ + struct pppoe_softc *sc; + + if (session == 0) { + return NULL; + } + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc->sc_state == PPPOE_STATE_SESSION + && sc->sc_session == session) { + if (sc->sc_ethif == rcvif) { + return sc; + } else { + return NULL; + } + } + } + return NULL; +} + +/* Check host unique token passed and return appropriate softc pointer, + * or NULL if token is bogus. */ +static struct pppoe_softc * +pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) +{ + struct pppoe_softc *sc, *t; + + if (pppoe_softc_list == NULL) { + return NULL; + } + + if (len != sizeof sc) { + return NULL; + } + MEMCPY(&t, token, len); + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc == t) { + break; + } + } + + if (sc == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); + return NULL; + } + + /* should be safe to access *sc now */ + if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { + printf("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state); + return NULL; + } + if (sc->sc_ethif != rcvif) { + printf("%c%c%"U16_F": wrong interface, not accepting host unique\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + return NULL; + } + return sc; +} + +static void +pppoe_linkstatus_up(struct pppoe_softc *sc) +{ + sc->sc_linkStatusCB(sc->sc_pd, 1); +} + +/* analyze and handle a single received packet while not in session state */ +static void +pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb) +{ + u16_t tag, len; + u16_t session, plen; + struct pppoe_softc *sc; + const char *err_msg; + char devname[6]; + u8_t *ac_cookie; + u16_t ac_cookie_len; +#ifdef PPPOE_SERVER + u8_t *hunique; + size_t hunique_len; +#endif + struct pppoehdr *ph; + struct pppoetag pt; + int off, err, errortag; + struct eth_hdr *ethhdr; + + pb = pppSingleBuf(pb); + + strcpy(devname, "pppoe"); /* as long as we don't know which instance */ + err_msg = NULL; + errortag = 0; + if (pb->len < sizeof(*ethhdr)) { + goto done; + } + ethhdr = (struct eth_hdr *)pb->payload; + off = sizeof(*ethhdr); + + ac_cookie = NULL; + ac_cookie_len = 0; +#ifdef PPPOE_SERVER + hunique = NULL; + hunique_len = 0; +#endif + session = 0; + if (pb->len - off < PPPOE_HEADERLEN) { + printf("pppoe: packet too short: %d\n", pb->len); + goto done; + } + + ph = (struct pppoehdr *) (ethhdr + 1); + if (ph->vertype != PPPOE_VERTYPE) { + printf("pppoe: unknown version/type packet: 0x%x\n", ph->vertype); + goto done; + } + session = ntohs(ph->session); + plen = ntohs(ph->plen); + off += sizeof(*ph); + + if (plen + off > pb->len) { + printf("pppoe: packet content does not fit: data available = %d, packet size = %u\n", + pb->len - off, plen); + goto done; + } + if(pb->tot_len == pb->len) { + pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ + } + tag = 0; + len = 0; + sc = NULL; + while (off + sizeof(pt) <= pb->len) { + MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); + tag = ntohs(pt.tag); + len = ntohs(pt.len); + if (off + sizeof(pt) + len > pb->len) { + printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len); + goto done; + } + switch (tag) { + case PPPOE_TAG_EOL: + goto breakbreak; + case PPPOE_TAG_SNAME: + break; /* ignored */ + case PPPOE_TAG_ACNAME: + break; /* ignored */ + case PPPOE_TAG_HUNIQUE: + if (sc != NULL) { + break; + } +#ifdef PPPOE_SERVER + hunique = (u8_t*)pb->payload + off + sizeof(pt); + hunique_len = len; +#endif + sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); + if (sc != NULL) { + snprintf(devname, sizeof(devname), "%c%c%"U16_F, sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + } + break; + case PPPOE_TAG_ACCOOKIE: + if (ac_cookie == NULL) { + ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); + ac_cookie_len = len; + } + break; + case PPPOE_TAG_SNAME_ERR: + err_msg = "SERVICE NAME ERROR"; + errortag = 1; + break; + case PPPOE_TAG_ACSYS_ERR: + err_msg = "AC SYSTEM ERROR"; + errortag = 1; + break; + case PPPOE_TAG_GENERIC_ERR: + err_msg = "GENERIC ERROR"; + errortag = 1; + break; + } + if (err_msg) { + if (errortag && len) { + u16_t error_len = LWIP_MIN(len, sizeof(pppoe_error_tmp)-1); + strncpy(pppoe_error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); + pppoe_error_tmp[error_len-1] = '\0'; + printf("%s: %s: %s\n", devname, err_msg, pppoe_error_tmp); + } else { + printf("%s: %s\n", devname, err_msg); + } + if (errortag) { + goto done; + } + } + off += sizeof(pt) + len; + } + +breakbreak:; + switch (ph->code) { + case PPPOE_CODE_PADI: +#ifdef PPPOE_SERVER + /* + * got service name, concentrator name, and/or host unique. + * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. + */ + if (LIST_EMPTY(&pppoe_softc_list)) { + goto done; + } + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { + continue; + } + if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + continue; + } + if (sc->sc_state == PPPOE_STATE_INITIAL) { + break; + } + } + if (sc == NULL) { + /* printf("pppoe: free passive interface is not found\n"); */ + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); + sc->sc_state = PPPOE_STATE_PADO_SENT; + pppoe_send_pado(sc); + break; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADR: +#ifdef PPPOE_SERVER + /* + * get sc from ac_cookie if IFF_PASSIVE + */ + if (ac_cookie == NULL) { + /* be quiet if there is not a single pppoe instance */ + printf("pppoe: received PADR but not includes ac_cookie\n"); + goto done; + } + sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + printf("pppoe: received PADR but could not find request for it\n"); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + printf("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + pppoe_send_pads(sc); + sc->sc_state = PPPOE_STATE_SESSION; + pppoe_linkstatus_up(sc); /* notify upper layers */ + break; +#else + /* ignore, we are no access concentrator */ + goto done; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADO: + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (pppoe_softc_list != NULL) { + printf("pppoe: received PADO but could not find request for it\n"); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADI_SENT) { + printf("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + goto done; + } + if (ac_cookie) { + sc->sc_ac_cookie_len = ac_cookie_len; + MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); + } + MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); + sys_untimeout(pppoe_timeout, sc); + sc->sc_padr_retried = 0; + sc->sc_state = PPPOE_STATE_PADR_SENT; + if ((err = pppoe_send_padr(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_CODE_PADS: + if (sc == NULL) { + goto done; + } + sc->sc_session = session; + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); + sc->sc_state = PPPOE_STATE_SESSION; + pppoe_linkstatus_up(sc); /* notify upper layers */ + break; + case PPPOE_CODE_PADT: + if (sc == NULL) { + goto done; + } + pppoe_clear_softc(sc, "received PADT"); + break; + default: + if(sc) { + printf("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + (u16_t)ph->code, session); + } else { + printf("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session); + } + break; + } + +done: + pbuf_free(pb); + return; +} + +void +pppoe_disc_input(struct netif *netif, struct pbuf *p) +{ + /* avoid error messages if there is not a single pppoe instance */ + if (pppoe_softc_list != NULL) { + pppoe_dispatch_disc_pkt(netif, p); + } else { + pbuf_free(p); + } +} + +void +pppoe_data_input(struct netif *netif, struct pbuf *pb) +{ + u16_t session, plen; + struct pppoe_softc *sc; + struct pppoehdr *ph; +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + u8_t shost[ETHER_ADDR_LEN]; +#endif + +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); +#endif + if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + pb = pppSingleBuf (pb); + + if (pb->len <= PPPOE_HEADERLEN) { + printf("pppoe (data): dropping too short packet: %d bytes\n", pb->len); + goto drop; + } + + if (pb->len < sizeof(*ph)) { + printf("pppoe_data_input: could not get PPPoE header\n"); + goto drop; + } + ph = (struct pppoehdr *)pb->payload; + + if (ph->vertype != PPPOE_VERTYPE) { + printf("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype); + goto drop; + } + if (ph->code != 0) { + goto drop; + } + + session = ntohs(ph->session); + sc = pppoe_find_softc_by_session(session, netif); + if (sc == NULL) { +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + printf("pppoe: input for unknown session 0x%x, sending PADT\n", session); + pppoe_send_padt(netif, session, shost); +#endif + goto drop; + } + + plen = ntohs(ph->plen); + + if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + pb->len, plen)); + + if (pb->len < plen) { + goto drop; + } + + pppInProcOverEthernet(sc->sc_pd, pb); + + return; + +drop: + pbuf_free(pb); +} + +static err_t +pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) +{ + struct eth_hdr *ethhdr; + u16_t etype; + err_t res; + + if (!sc->sc_ethif) { + pbuf_free(pb); + return ERR_IF; + } + + ethhdr = (struct eth_hdr *)pb->payload; + etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; + ethhdr->type = htons(etype); + MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); + MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr)); + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, + sc->sc_state, sc->sc_session, + sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], + pb->tot_len)); + + res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); + + pbuf_free(pb); + + return res; +} + +static err_t +pppoe_send_padi(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + int len; +#ifdef PPPOE_TODO + int l1 = 0, l2 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + if (sc->sc_state >PPPOE_STATE_PADI_SENT) { + PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state)); + } + + /* calculate length of frame (excluding ethernet header + pppoe header) */ + len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + l1 = (int)strlen(sc->sc_service_name); + len += l1; + } + if (sc->sc_concentrator_name != NULL) { + l2 = (int)strlen(sc->sc_concentrator_name); + len += 2 + 2 + l2; + } +#endif /* PPPOE_TODO */ + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + /* fill in pkt */ + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name != NULL) { + PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); + PPPOE_ADD_16(p, l2); + MEMCPY(p, sc->sc_concentrator_name, l2); + p += l2; + } +#endif /* PPPOE_TODO */ + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + /* send pkt */ + return pppoe_output(sc, pb); +} + +static void +pppoe_timeout(void *arg) +{ + int retry_wait, err; + struct pppoe_softc *sc = (struct pppoe_softc*)arg; + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + switch (sc->sc_state) { + case PPPOE_STATE_PADI_SENT: + /* + * We have two basic ways of retrying: + * - Quick retry mode: try a few times in short sequence + * - Slow retry mode: we already had a connection successfully + * established and will try infinitely (without user + * intervention) + * We only enter slow retry mode if IFF_LINK1 (aka autodial) + * is not set. + */ + + /* initialize for quick retry mode */ + retry_wait = PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried); + + sc->sc_padi_retried++; + if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { +#if 0 + if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { + /* slow retry mode */ + retry_wait = PPPOE_SLOW_RETRY; + } else +#endif + { + pppoe_abort_connect(sc); + return; + } + } + if ((err = pppoe_send_padi(sc)) != 0) { + sc->sc_padi_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(retry_wait, pppoe_timeout, sc); + break; + + case PPPOE_STATE_PADR_SENT: + sc->sc_padr_retried++; + if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); + return; + } + if ((err = pppoe_send_padr(sc)) != 0) { + sc->sc_padr_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_STATE_CLOSING: + pppoe_do_disconnect(sc); + break; + default: + return; /* all done, work in peace */ + } +} + +/* Start a connection (i.e. initiate discovery phase) */ +int +pppoe_connect(struct pppoe_softc *sc) +{ + int err; + + if (sc->sc_state != PPPOE_STATE_INITIAL) { + return EBUSY; + } + +#ifdef PPPOE_SERVER + /* wait PADI if IFF_PASSIVE */ + if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + return 0; + } +#endif + /* save state, in case we fail to send PADI */ + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + err = pppoe_send_padi(sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); + return err; +} + +/* disconnect */ +void +pppoe_disconnect(struct pppoe_softc *sc) +{ + if (sc->sc_state < PPPOE_STATE_SESSION) { + return; + } + /* + * Do not call pppoe_disconnect here, the upper layer state + * machine gets confused by this. We must return from this + * function and defer disconnecting to the timeout handler. + */ + sc->sc_state = PPPOE_STATE_CLOSING; + sys_timeout(20, pppoe_timeout, sc); +} + +static int +pppoe_do_disconnect(struct pppoe_softc *sc) +{ + int err; + + if (sc->sc_state < PPPOE_STATE_SESSION) { + err = EBUSY; + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); + } + + /* cleanup softc */ + sc->sc_state = PPPOE_STATE_INITIAL; + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; +#ifdef PPPOE_SERVER + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + sc->sc_hunique = NULL; + } + sc->sc_hunique_len = 0; +#endif + sc->sc_session = 0; + + sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ + + return err; +} + +/* Connection attempt aborted */ +static void +pppoe_abort_connect(struct pppoe_softc *sc) +{ + printf("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + sc->sc_state = PPPOE_STATE_CLOSING; + + sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ + + /* clear connection state */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_INITIAL; +} + +/* Send a PADR packet */ +static err_t +pppoe_send_padr(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; +#ifdef PPPOE_TODO + size_t l1 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + if (sc->sc_state != PPPOE_STATE_PADR_SENT) { + return ERR_CONN; + } + + len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } +#endif /* PPPOE_TODO */ + if (sc->sc_ac_cookie_len > 0) { + len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ + } + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } + if (sc->sc_ac_cookie_len > 0) { + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sc->sc_ac_cookie_len); + MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); + p += sc->sc_ac_cookie_len; + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + return pppoe_output(sc, pb); +} + +/* send a PADT packet */ +static err_t +pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) +{ + struct pbuf *pb; + struct eth_hdr *ethhdr; + err_t res; + u8_t *p; + + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + ethhdr = (struct eth_hdr *)pb->payload; + ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); + MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); + MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr)); + + p = (u8_t*)(ethhdr + 1); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); + + res = outgoing_if->linkoutput(outgoing_if, pb); + + pbuf_free(pb); + + return res; +} + +#ifdef PPPOE_SERVER +static err_t +pppoe_send_pado(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + /* calc length */ + len = 0; + /* include ac_cookie */ + len += 2 + 2 + sizeof(sc); + /* include hunique */ + len += 2 + 2 + sc->sc_hunique_len; + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof(sc)); + p += sizeof(sc); + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} + +static err_t +pppoe_send_pads(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len, l1 = 0; /* XXX: gcc */ + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + sc->sc_session = mono_time.tv_sec % 0xff + 1; + /* calc length */ + len = 0; + /* include hunique */ + len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} +#endif + +err_t +pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) +{ + u8_t *p; + size_t len; + + /* are we ready to process data yet? */ + if (sc->sc_state < PPPOE_STATE_SESSION) { + /*sppp_flush(&sc->sc_sppp.pp_if);*/ + pbuf_free(pb); + return ERR_CONN; + } + + len = pb->tot_len; + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload + sizeof(struct eth_hdr); + PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); + + return pppoe_output(sc, pb); +} + +#if 0 /*def PFIL_HOOKS*/ +static int +pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) +{ + struct pppoe_softc *sc; + int s; + + if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { + return 0; + } + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_ethif != ifp) { + continue; + } + if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { + sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); + printf("%c%c%"U16_F": ethernet interface detached, going down\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + } + sc->sc_ethif = NULL; + pppoe_clear_softc(sc, "ethernet interface detached"); + } + + return 0; +} +#endif + +static void +pppoe_clear_softc(struct pppoe_softc *sc, const char *message) +{ + LWIP_UNUSED_ARG(message); + + /* stop timer */ + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); + + /* fix our state */ + sc->sc_state = PPPOE_STATE_INITIAL; + + /* notify upper layers */ + sc->sc_linkStatusCB(sc->sc_pd, 0); + + /* clean up softc */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; + sc->sc_session = 0; +} + +#endif /* PPPOE_SUPPORT */ + diff --git a/ext/lwip/src/netif/ppp/pppdebug.h b/ext/lwip/src/netif/ppp/pppdebug.h new file mode 100644 index 000000000..81349971d --- /dev/null +++ b/ext/lwip/src/netif/ppp/pppdebug.h @@ -0,0 +1,73 @@ +/***************************************************************************** +* pppdebug.h - System debugging utilities. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* portions Copyright (c) 2001 by Cognizant Pty Ltd. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY (please don't use tabs!) +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-07-29 Guy Lancaster , Global Election Systems Inc. +* Original. +* +***************************************************************************** +*/ +#ifndef PPPDEBUG_H +#define PPPDEBUG_H + +/* Trace levels. */ +#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_INFO (PPP_DEBUG) +#define LOG_DETAIL (PPP_DEBUG) +#define LOG_DEBUG (PPP_DEBUG) + + +#define TRACELCP PPP_DEBUG + +#if PPP_DEBUG + +#define AUTHDEBUG(a, b) LWIP_DEBUGF(a, b) +#define IPCPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define UPAPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define LCPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define FSMDEBUG(a, b) LWIP_DEBUGF(a, b) +#define CHAPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) + +#else /* PPP_DEBUG */ + +#define AUTHDEBUG(a, b) +#define IPCPDEBUG(a, b) +#define UPAPDEBUG(a, b) +#define LCPDEBUG(a, b) +#define FSMDEBUG(a, b) +#define CHAPDEBUG(a, b) +#define PPPDEBUG(a, b) + +#endif /* PPP_DEBUG */ + +#endif /* PPPDEBUG_H */ diff --git a/ext/lwip/src/netif/ppp/randm.c b/ext/lwip/src/netif/ppp/randm.c new file mode 100644 index 000000000..b736091fc --- /dev/null +++ b/ext/lwip/src/netif/ppp/randm.c @@ -0,0 +1,249 @@ +/***************************************************************************** +* randm.c - Random number generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-06-03 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "md5.h" +#include "randm.h" + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include + +#if MD5_SUPPORT /* this module depends on MD5 */ +#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static char randPool[RANDPOOLSZ]; /* Pool of randomness. */ +static long randCount = 0; /* Pseudo-random incrementer */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * Initialize the random number generator. + * + * Since this is to be called on power up, we don't have much + * system randomess to work with. Here all we use is the + * real-time clock. We'll accumulate more randomness as soon + * as things start happening. + */ +void +avRandomInit() +{ + avChurnRand(NULL, 0); +} + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + */ +void +avChurnRand(char *randData, u32_t randLen) +{ + MD5_CTX md5; + + /* LWIP_DEBUGF(LOG_INFO, ("churnRand: %u@%P\n", randLen, randData)); */ + MD5Init(&md5); + MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); + if (randData) { + MD5Update(&md5, (u_char *)randData, randLen); + } else { + struct { + /* INCLUDE fields for any system sources of randomness */ + char foobar; + } sysData; + + /* Load sysData fields here. */ + MD5Update(&md5, (u_char *)&sysData, sizeof(sysData)); + } + MD5Final((u_char *)randPool, &md5); +/* LWIP_DEBUGF(LOG_INFO, ("churnRand: -> 0\n")); */ +} + +/* + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using churnRand(). + * Note: It's important that there be sufficient randomness in randPool + * before this is called for otherwise the range of the result may be + * narrow enough to make a search feasible. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + * + * XXX Why does he not just call churnRand() for each block? Probably + * so that you don't ever publish the seed which could possibly help + * predict future values. + * XXX Why don't we preserve md5 between blocks and just update it with + * randCount each time? Probably there is a weakness but I wish that + * it was documented. + */ +void +avGenRand(char *buf, u32_t bufLen) +{ + MD5_CTX md5; + u_char tmp[16]; + u32_t n; + + while (bufLen > 0) { + n = LWIP_MIN(bufLen, RANDPOOLSZ); + MD5Init(&md5); + MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); + MD5Update(&md5, (u_char *)&randCount, sizeof(randCount)); + MD5Final(tmp, &md5); + randCount++; + MEMCPY(buf, tmp, n); + buf += n; + bufLen -= n; + } +} + +/* + * Return a new random number. + */ +u32_t +avRandom() +{ + u32_t newRand; + + avGenRand((char *)&newRand, sizeof(newRand)); + + return newRand; +} + +#else /* MD5_SUPPORT */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static int avRandomized = 0; /* Set when truely randomized. */ +static u32_t avRandomSeed = 0; /* Seed used for random number generation. */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * Initialize the random number generator. + * + * Here we attempt to compute a random number seed but even if + * it isn't random, we'll randomize it later. + * + * The current method uses the fields from the real time clock, + * the idle process counter, the millisecond counter, and the + * hardware timer tick counter. When this is invoked + * in startup(), then the idle counter and timer values may + * repeat after each boot and the real time clock may not be + * operational. Thus we call it again on the first random + * event. + */ +void +avRandomInit() +{ +#if 0 + /* Get a pointer into the last 4 bytes of clockBuf. */ + u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]); + + /* + * Initialize our seed using the real-time clock, the idle + * counter, the millisecond timer, and the hardware timer + * tick counter. The real-time clock and the hardware + * tick counter are the best sources of randomness but + * since the tick counter is only 16 bit (and truncated + * at that), the idle counter and millisecond timer + * (which may be small values) are added to help + * randomize the lower 16 bits of the seed. + */ + readClk(); + avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr + + ppp_mtime() + ((u32_t)TM1 << 16) + TM1; +#else + avRandomSeed += sys_jiffies(); /* XXX */ +#endif + + /* Initialize the Borland random number generator. */ + srand((unsigned)avRandomSeed); +} + +/* + * Randomize our random seed value. Here we use the fact that + * this function is called at *truely random* times by the polling + * and network functions. Here we only get 16 bits of new random + * value but we use the previous value to randomize the other 16 + * bits. + */ +void +avRandomize(void) +{ + static u32_t last_jiffies; + + if (!avRandomized) { + avRandomized = !0; + avRandomInit(); + /* The initialization function also updates the seed. */ + } else { + /* avRandomSeed += (avRandomSeed << 16) + TM1; */ + avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */ + } + last_jiffies = sys_jiffies(); +} + +/* + * Return a new random number. + * Here we use the Borland rand() function to supply a pseudo random + * number which we make truely random by combining it with our own + * seed which is randomized by truely random events. + * Thus the numbers will be truely random unless there have been no + * operator or network events in which case it will be pseudo random + * seeded by the real time clock. + */ +u32_t +avRandom() +{ + return ((((u32_t)rand() << 16) + rand()) + avRandomSeed); +} + +#endif /* MD5_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/randm.h b/ext/lwip/src/netif/ppp/randm.h new file mode 100644 index 000000000..a0984b020 --- /dev/null +++ b/ext/lwip/src/netif/ppp/randm.h @@ -0,0 +1,81 @@ +/***************************************************************************** +* randm.h - Random number generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-05-29 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#ifndef RANDM_H +#define RANDM_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ +/* + * Initialize the random number generator. + */ +void avRandomInit(void); + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + */ +void avChurnRand(char *randData, u32_t randLen); + +/* + * Randomize our random seed value. To be called for truely random events + * such as user operations and network traffic. + */ +#if MD5_SUPPORT +#define avRandomize() avChurnRand(NULL, 0) +#else /* MD5_SUPPORT */ +void avRandomize(void); +#endif /* MD5_SUPPORT */ + +/* + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using churnRand(). + * Thus it's important to make sure that the results of this are not + * published directly because one could predict the next result to at + * least some degree. Also, it's important to get a good seed before + * the first use. + */ +void avGenRand(char *buf, u32_t bufLen); + +/* + * Return a new random number. + */ +u32_t avRandom(void); + + +#endif /* RANDM_H */ diff --git a/ext/lwip/src/netif/ppp/vj.c b/ext/lwip/src/netif/ppp/vj.c new file mode 100644 index 000000000..40fdad13d --- /dev/null +++ b/ext/lwip/src/netif/ppp/vj.c @@ -0,0 +1,652 @@ +/* + * Routines to compress and uncompess tcp packets (for transmission + * over low speed serial lines. + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * Initial distribution. + * + * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, + * so that the entire packet being decompressed doesn't have + * to be in contiguous memory (just the compressed header). + * + * Modified March 1998 by Guy Lancaster, glanca@gesn.com, + * for a 16 bit processor. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "vj.h" + +#include + +#if VJ_SUPPORT + +#if LINK_STATS +#define INCR(counter) ++comp->stats.counter +#else +#define INCR(counter) +#endif + +void +vj_compress_init(struct vjcompress *comp) +{ + register u_char i; + register struct cstate *tstate = comp->tstate; + +#if MAX_SLOTS == 0 + memset((char *)comp, 0, sizeof(*comp)); +#endif + comp->maxSlotIndex = MAX_SLOTS - 1; + comp->compressSlot = 0; /* Disable slot ID compression by default. */ + for (i = MAX_SLOTS - 1; i > 0; --i) { + tstate[i].cs_id = i; + tstate[i].cs_next = &tstate[i - 1]; + } + tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; + tstate[0].cs_id = 0; + comp->last_cs = &tstate[0]; + comp->last_recv = 255; + comp->last_xmit = 255; + comp->flags = VJF_TOSS; +} + + +/* ENCODE encodes a number that is known to be non-zero. ENCODEZ + * checks for zero (since zero has to be encoded in the long, 3 byte + * form). + */ +#define ENCODE(n) { \ + if ((u_short)(n) >= 256) { \ + *cp++ = 0; \ + cp[1] = (u_char)(n); \ + cp[0] = (u_char)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u_char)(n); \ + } \ +} +#define ENCODEZ(n) { \ + if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \ + *cp++ = 0; \ + cp[1] = (u_char)(n); \ + cp[0] = (u_char)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u_char)(n); \ + } \ +} + +#define DECODEL(f) { \ + if (*cp == 0) {\ + u32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \ + (f) = htonl(tmp); \ + cp += 3; \ + } else { \ + u32_t tmp = ntohl(f) + (u32_t)*cp++; \ + (f) = htonl(tmp); \ + } \ +} + +#define DECODES(f) { \ + if (*cp == 0) {\ + u_short tmp = ntohs(f) + (((u_short)cp[1] << 8) | cp[2]); \ + (f) = htons(tmp); \ + cp += 3; \ + } else { \ + u_short tmp = ntohs(f) + (u_short)*cp++; \ + (f) = htons(tmp); \ + } \ +} + +#define DECODEU(f) { \ + if (*cp == 0) {\ + (f) = htons(((u_short)cp[1] << 8) | cp[2]); \ + cp += 3; \ + } else { \ + (f) = htons((u_short)*cp++); \ + } \ +} + +/* + * vj_compress_tcp - Attempt to do Van Jacobson header compression on a + * packet. This assumes that nb and comp are not null and that the first + * buffer of the chain contains a valid IP header. + * Return the VJ type code indicating whether or not the packet was + * compressed. + */ +u_int +vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) +{ + register struct ip_hdr *ip = (struct ip_hdr *)pb->payload; + register struct cstate *cs = comp->last_cs->cs_next; + register u_short hlen = IPH_HL(ip); + register struct tcp_hdr *oth; + register struct tcp_hdr *th; + register u_short deltaS, deltaA; + register u_long deltaL; + register u_int changes = 0; + u_char new_seq[16]; + register u_char *cp = new_seq; + + /* + * Check that the packet is IP proto TCP. + */ + if (IPH_PROTO(ip) != IP_PROTO_TCP) { + return (TYPE_IP); + } + + /* + * Bail if this is an IP fragment or if the TCP packet isn't + * `compressible' (i.e., ACK isn't set or some other control bit is + * set). + */ + if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || pb->tot_len < 40) { + return (TYPE_IP); + } + th = (struct tcp_hdr *)&((long *)ip)[hlen]; + if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { + return (TYPE_IP); + } + /* + * Packet is compressible -- we're going to send either a + * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need + * to locate (or create) the connection state. Special case the + * most recently used connection since it's most likely to be used + * again & we don't have to do any reordering if it's used. + */ + INCR(vjs_packets); + if (!ip_addr_cmp(&ip->src, &cs->cs_ip.src) + || !ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) + || *(long *)th != ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { + /* + * Wasn't the first -- search for it. + * + * States are kept in a circularly linked list with + * last_cs pointing to the end of the list. The + * list is kept in lru order by moving a state to the + * head of the list whenever it is referenced. Since + * the list is short and, empirically, the connection + * we want is almost always near the front, we locate + * states via linear search. If we don't find a state + * for the datagram, the oldest state is (re-)used. + */ + register struct cstate *lcs; + register struct cstate *lastcs = comp->last_cs; + + do { + lcs = cs; cs = cs->cs_next; + INCR(vjs_searches); + if (ip_addr_cmp(&ip->src, &cs->cs_ip.src) + && ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) + && *(long *)th == ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { + goto found; + } + } while (cs != lastcs); + + /* + * Didn't find it -- re-use oldest cstate. Send an + * uncompressed packet that tells the other side what + * connection number we're using for this conversation. + * Note that since the state list is circular, the oldest + * state points to the newest and we only need to set + * last_cs to update the lru linkage. + */ + INCR(vjs_misses); + comp->last_cs = lcs; + hlen += TCPH_HDRLEN(th); + hlen <<= 2; + /* Check that the IP/TCP headers are contained in the first buffer. */ + if (hlen > pb->len) { + return (TYPE_IP); + } + goto uncompressed; + + found: + /* + * Found it -- move to the front on the connection list. + */ + if (cs == lastcs) { + comp->last_cs = lcs; + } else { + lcs->cs_next = cs->cs_next; + cs->cs_next = lastcs->cs_next; + lastcs->cs_next = cs; + } + } + + oth = (struct tcp_hdr *)&((long *)&cs->cs_ip)[hlen]; + deltaS = hlen; + hlen += TCPH_HDRLEN(th); + hlen <<= 2; + /* Check that the IP/TCP headers are contained in the first buffer. */ + if (hlen > pb->len) { + PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); + return (TYPE_IP); + } + + /* + * Make sure that only what we expect to change changed. The first + * line of the `if' checks the IP protocol version, header length & + * type of service. The 2nd line checks the "Don't fragment" bit. + * The 3rd line checks the time-to-live and protocol (the protocol + * check is unnecessary but costless). The 4th line checks the TCP + * header length. The 5th line checks IP options, if any. The 6th + * line checks TCP options, if any. If any of these things are + * different between the previous & current datagram, we send the + * current datagram `uncompressed'. + */ + if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] + || ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] + || ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] + || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) + || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) + || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { + goto uncompressed; + } + + /* + * Figure out which of the changing fields changed. The + * receiver expects changes in the order: urgent, window, + * ack, seq (the order minimizes the number of temporaries + * needed in this section of code). + */ + if (TCPH_FLAGS(th) & TCP_URG) { + deltaS = ntohs(th->urgp); + ENCODEZ(deltaS); + changes |= NEW_U; + } else if (th->urgp != oth->urgp) { + /* argh! URG not set but urp changed -- a sensible + * implementation should never do this but RFC793 + * doesn't prohibit the change so we have to deal + * with it. */ + goto uncompressed; + } + + if ((deltaS = (u_short)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) { + ENCODE(deltaS); + changes |= NEW_W; + } + + if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaA = (u_short)deltaL; + ENCODE(deltaA); + changes |= NEW_A; + } + + if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaS = (u_short)deltaL; + ENCODE(deltaS); + changes |= NEW_S; + } + + switch(changes) { + case 0: + /* + * Nothing changed. If this packet contains data and the + * last one didn't, this is probably a data packet following + * an ack (normal on an interactive connection) and we send + * it compressed. Otherwise it's probably a retransmit, + * retransmitted ack or window probe. Send it uncompressed + * in case the other side missed the compressed version. + */ + if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && + ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { + break; + } + + /* (fall through) */ + + case SPECIAL_I: + case SPECIAL_D: + /* + * actual changes match one of our special case encodings -- + * send packet uncompressed. + */ + goto uncompressed; + + case NEW_S|NEW_A: + if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for echoed terminal traffic */ + changes = SPECIAL_I; + cp = new_seq; + } + break; + + case NEW_S: + if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for data xfer */ + changes = SPECIAL_D; + cp = new_seq; + } + break; + } + + deltaS = (u_short)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip))); + if (deltaS != 1) { + ENCODEZ(deltaS); + changes |= NEW_I; + } + if (TCPH_FLAGS(th) & TCP_PSH) { + changes |= TCP_PUSH_BIT; + } + /* + * Grab the cksum before we overwrite it below. Then update our + * state with this packet's header. + */ + deltaA = ntohs(th->chksum); + BCOPY(ip, &cs->cs_ip, hlen); + + /* + * We want to use the original packet as our compressed packet. + * (cp - new_seq) is the number of bytes we need for compressed + * sequence numbers. In addition we need one byte for the change + * mask, one for the connection id and two for the tcp checksum. + * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how + * many bytes of the original packet to toss so subtract the two to + * get the new packet size. + */ + deltaS = (u_short)(cp - new_seq); + if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { + comp->last_xmit = cs->cs_id; + hlen -= deltaS + 4; + if(pbuf_header(pb, -hlen)){ + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u_char *)pb->payload; + *cp++ = (u_char)(changes | NEW_C); + *cp++ = cs->cs_id; + } else { + hlen -= deltaS + 3; + if(pbuf_header(pb, -hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u_char *)pb->payload; + *cp++ = (u_char)changes; + } + *cp++ = (u_char)(deltaA >> 8); + *cp++ = (u_char)deltaA; + BCOPY(new_seq, cp, deltaS); + INCR(vjs_compressed); + return (TYPE_COMPRESSED_TCP); + + /* + * Update connection state cs & send uncompressed packet (that is, + * a regular ip/tcp packet but with the 'conversation id' we hope + * to use on future compressed packets in the protocol field). + */ +uncompressed: + BCOPY(ip, &cs->cs_ip, hlen); + IPH_PROTO_SET(ip, cs->cs_id); + comp->last_xmit = cs->cs_id; + return (TYPE_UNCOMPRESSED_TCP); +} + +/* + * Called when we may have missed a packet. + */ +void +vj_uncompress_err(struct vjcompress *comp) +{ + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); +} + +/* + * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. + * Return 0 on success, -1 on failure. + */ +int +vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) +{ + register u_int hlen; + register struct cstate *cs; + register struct ip_hdr *ip; + + ip = (struct ip_hdr *)nb->payload; + hlen = IPH_HL(ip) << 2; + if (IPH_PROTO(ip) >= MAX_SLOTS + || hlen + sizeof(struct tcp_hdr) > nb->len + || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) + > nb->len + || hlen > MAX_HDR) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", + IPH_PROTO(ip), hlen, nb->len)); + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return -1; + } + cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; + comp->flags &=~ VJF_TOSS; + IPH_PROTO_SET(ip, IP_PROTO_TCP); + BCOPY(ip, &cs->cs_ip, hlen); + cs->cs_hlen = (u_short)hlen; + INCR(vjs_uncompressedin); + return 0; +} + +/* + * Uncompress a packet of type TYPE_COMPRESSED_TCP. + * The packet is composed of a buffer chain and the first buffer + * must contain an accurate chain length. + * The first buffer must include the entire compressed TCP/IP header. + * This procedure replaces the compressed header with the uncompressed + * header and returns the length of the VJ header. + */ +int +vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) +{ + u_char *cp; + struct tcp_hdr *th; + struct cstate *cs; + u_short *bp; + struct pbuf *n0 = *nb; + u32_t tmp; + u_int vjlen, hlen, changes; + + INCR(vjs_compressedin); + cp = (u_char *)n0->payload; + changes = *cp++; + if (changes & NEW_C) { + /* + * Make sure the state index is in range, then grab the state. + * If we have a good state index, clear the 'discard' flag. + */ + if (*cp >= MAX_SLOTS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); + goto bad; + } + + comp->flags &=~ VJF_TOSS; + comp->last_recv = *cp++; + } else { + /* + * this packet has an implicit state index. If we've + * had a line error since the last time we got an + * explicit state index, we have to toss the packet. + */ + if (comp->flags & VJF_TOSS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); + INCR(vjs_tossed); + return (-1); + } + } + cs = &comp->rstate[comp->last_recv]; + hlen = IPH_HL(&cs->cs_ip) << 2; + th = (struct tcp_hdr *)&((u_char *)&cs->cs_ip)[hlen]; + th->chksum = htons((*cp << 8) | cp[1]); + cp += 2; + if (changes & TCP_PUSH_BIT) { + TCPH_SET_FLAG(th, TCP_PSH); + } else { + TCPH_UNSET_FLAG(th, TCP_PSH); + } + + switch (changes & SPECIALS_MASK) { + case SPECIAL_I: + { + register u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->ackno) + i; + th->ackno = htonl(tmp); + tmp = ntohl(th->seqno) + i; + th->seqno = htonl(tmp); + } + break; + + case SPECIAL_D: + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + th->seqno = htonl(tmp); + break; + + default: + if (changes & NEW_U) { + TCPH_SET_FLAG(th, TCP_URG); + DECODEU(th->urgp); + } else { + TCPH_UNSET_FLAG(th, TCP_URG); + } + if (changes & NEW_W) { + DECODES(th->wnd); + } + if (changes & NEW_A) { + DECODEL(th->ackno); + } + if (changes & NEW_S) { + DECODEL(th->seqno); + } + break; + } + if (changes & NEW_I) { + DECODES(cs->cs_ip._id); + } else { + IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1); + IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip))); + } + + /* + * At this point, cp points to the first byte of data in the + * packet. Fill in the IP total length and update the IP + * header checksum. + */ + vjlen = (u_short)(cp - (u_char*)n0->payload); + if (n0->len < vjlen) { + /* + * We must have dropped some characters (crc should detect + * this but the old slip framing won't) + */ + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", + n0->len, vjlen)); + goto bad; + } + +#if BYTE_ORDER == LITTLE_ENDIAN + tmp = n0->tot_len - vjlen + cs->cs_hlen; + IPH_LEN_SET(&cs->cs_ip, htons((u_short)tmp)); +#else + IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen)); +#endif + + /* recompute the ip header checksum */ + bp = (u_short *) &cs->cs_ip; + IPH_CHKSUM_SET(&cs->cs_ip, 0); + for (tmp = 0; hlen > 0; hlen -= 2) { + tmp += *bp++; + } + tmp = (tmp & 0xffff) + (tmp >> 16); + tmp = (tmp & 0xffff) + (tmp >> 16); + IPH_CHKSUM_SET(&cs->cs_ip, (u_short)(~tmp)); + + /* Remove the compressed header and prepend the uncompressed header. */ + if(pbuf_header(n0, -((s16_t)(vjlen)))) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { + struct pbuf *np, *q; + u8_t *bufptr; + + np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); + goto bad; + } + + if(pbuf_header(np, -cs->cs_hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + bufptr = n0->payload; + for(q = np; q != NULL; q = q->next) { + MEMCPY(q->payload, bufptr, q->len); + bufptr += q->len; + } + + if(n0->next) { + pbuf_chain(np, n0->next); + pbuf_dechain(n0); + } + pbuf_free(n0); + n0 = np; + } + + if(pbuf_header(n0, cs->cs_hlen)) { + struct pbuf *np; + + LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); + np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); + goto bad; + } + pbuf_cat(np, n0); + n0 = np; + } + LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); + MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); + + *nb = n0; + + return vjlen; + +bad: + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return (-1); +} + +#endif /* VJ_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/ext/lwip/src/netif/ppp/vj.h b/ext/lwip/src/netif/ppp/vj.h new file mode 100644 index 000000000..fad121364 --- /dev/null +++ b/ext/lwip/src/netif/ppp/vj.h @@ -0,0 +1,156 @@ +/* + * Definitions for tcp compression routines. + * + * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + */ + +#ifndef VJ_H +#define VJ_H + +#include "lwip/ip.h" +#include "lwip/tcp_impl.h" + +#define MAX_SLOTS 16 /* must be > 2 and < 256 */ +#define MAX_HDR 128 + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowlegement, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + +/* packet types */ +#define TYPE_IP 0x40 +#define TYPE_UNCOMPRESSED_TCP 0x70 +#define TYPE_COMPRESSED_TCP 0x80 +#define TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + struct cstate *cs_next; /* next most recently used state (xmit only) */ + u_short cs_hlen; /* size of hdr (receive only) */ + u_char cs_id; /* connection # associated with this state */ + u_char cs_filler; + union { + char csu_hdr[MAX_HDR]; + struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ + } vjcs_u; +}; +#define cs_ip vjcs_u.csu_ip +#define cs_hdr vjcs_u.csu_hdr + + +struct vjstat { + unsigned long vjs_packets; /* outbound packets */ + unsigned long vjs_compressed; /* outbound compressed packets */ + unsigned long vjs_searches; /* searches for connection state */ + unsigned long vjs_misses; /* times couldn't find conn. state */ + unsigned long vjs_uncompressedin; /* inbound uncompressed packets */ + unsigned long vjs_compressedin; /* inbound compressed packets */ + unsigned long vjs_errorin; /* inbound unknown type packets */ + unsigned long vjs_tossed; /* inbound packets tossed because of error */ +}; + +/* + * all the state data for one serial line (we need one of these per line). + */ +struct vjcompress { + struct cstate *last_cs; /* most recently used tstate */ + u_char last_recv; /* last rcvd conn. id */ + u_char last_xmit; /* last sent conn. id */ + u_short flags; + u_char maxSlotIndex; + u_char compressSlot; /* Flag indicating OK to compress slot ID. */ +#if LINK_STATS + struct vjstat stats; +#endif + struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ + struct cstate rstate[MAX_SLOTS]; /* receive connection states */ +}; + +/* flag values */ +#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ + +extern void vj_compress_init (struct vjcompress *comp); +extern u_int vj_compress_tcp (struct vjcompress *comp, struct pbuf *pb); +extern void vj_uncompress_err (struct vjcompress *comp); +extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); +extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); + +#endif /* VJ_H */ diff --git a/ext/lwip/src/netif/slipif.c b/ext/lwip/src/netif/slipif.c new file mode 100644 index 000000000..277763090 --- /dev/null +++ b/ext/lwip/src/netif/slipif.c @@ -0,0 +1,510 @@ +/** + * @file + * SLIP Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is built upon the file: src/arch/rtxc/netif/sioslip.c + * + * Author: Magnus Ivarsson + * Simon Goldschmidt + * + * Usage: This netif can be used in three ways: + * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() + * until data is received. + * 2) In your main loop, call slipif_poll() to check for new RX bytes, + * completed packets are fed into netif->input(). + * 3) Call slipif_received_byte[s]() from your serial RX ISR and + * slipif_process_rxqueue() from your main loop. ISR level decodes + * packets and puts completed packets on a queue which is fed into + * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for + * pbuf_alloc to work on ISR level!). + * + */ + +/* + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send + */ + +#include "netif/slipif.h" +#include "lwip/opt.h" + +#if LWIP_HAVE_SLIPIF + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/sio.h" +#include "lwip/sys.h" + +#define SLIP_END 0xC0 /* 0300: start and end of every packet */ +#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ +#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ +#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ + +/** Maximum packet size that is received by this netif */ +#ifndef SLIP_MAX_SIZE +#define SLIP_MAX_SIZE 1500 +#endif + +/** Define this to the interface speed for SNMP + * (sio_fd is the sio_fd_t returned by sio_open). + * The default value of zero means 'unknown'. + */ +#ifndef SLIP_SIO_SPEED +#define SLIP_SIO_SPEED(sio_fd) 0 +#endif + +enum slipif_recv_state { + SLIP_RECV_NORMAL, + SLIP_RECV_ESCAPE, +}; + +struct slipif_priv { + sio_fd_t sd; + /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ + struct pbuf *p, *q; + u8_t state; + u16_t i, recved; +#if SLIP_RX_FROM_ISR + struct pbuf *rxpackets; +#endif +}; + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chaing packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +err_t +slipif_output(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr) +{ + struct slipif_priv *priv; + struct pbuf *q; + u16_t i; + u8_t c; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + LWIP_ASSERT("p != NULL", (p != NULL)); + + LWIP_UNUSED_ARG(ipaddr); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); + priv = netif->state; + + /* Send pbuf out on the serial I/O device. */ + /* Start with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { + c = ((u8_t *)q->payload)[i]; + switch (c) { + case SLIP_END: + /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_END, priv->sd); + break; + case SLIP_ESC: + /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_ESC, priv->sd); + break; + default: + /* normal byte - no need for escaping */ + sio_send(c, priv->sd); + break; + } + } + } + /* End with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + return ERR_OK; +} + +/** + * Handle the incoming SLIP stream character by character + * + * @param netif the lwip network interface structure for this slipif + * @param c received character (multiple calls to this function will + * return a complete packet, NULL is returned before - used for polling) + * @return The IP packet when SLIP_END is received + */ +static struct pbuf* +slipif_rxbyte(struct netif *netif, u8_t c) +{ + struct slipif_priv *priv; + struct pbuf *t; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = netif->state; + + switch (priv->state) { + case SLIP_RECV_NORMAL: + switch (c) { + case SLIP_END: + if (priv->recved > 0) { + /* Received whole packet. */ + /* Trim the pbuf to the size of the received packet. */ + pbuf_realloc(priv->q, priv->recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); + t = priv->q; + priv->p = priv->q = NULL; + priv->i = priv->recved = 0; + return t; + } + return NULL; + case SLIP_ESC: + priv->state = SLIP_RECV_ESCAPE; + return NULL; + } /* end switch (c) */ + break; + case SLIP_RECV_ESCAPE: + /* un-escape END or ESC bytes, leave other bytes + (although that would be a protocol error) */ + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + priv->state = SLIP_RECV_NORMAL; + break; + } /* end switch (priv->state) */ + + /* byte received, packet not yet completely received */ + if (priv->p == NULL) { + /* allocate a new pbuf */ + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL); + + if (priv->p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + /* don't process any further since we got no pbuf to receive to */ + return NULL; + } + + if (priv->q != NULL) { + /* 'chain' the pbuf to the existing chain */ + pbuf_cat(priv->q, priv->p); + } else { + /* p is the first pbuf in the chain */ + priv->q = priv->p; + } + } + + /* this automatically drops bytes if > SLIP_MAX_SIZE */ + if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { + ((u8_t *)priv->p->payload)[priv->i] = c; + priv->recved++; + priv->i++; + if (priv->i >= priv->p->len) { + /* on to the next pbuf */ + priv->i = 0; + if (priv->p->next != NULL && priv->p->next->len > 0) { + /* p is a chain, on to the next in the chain */ + priv->p = priv->p->next; + } else { + /* p is a single pbuf, set it to NULL so next time a new + * pbuf is allocated */ + priv->p = NULL; + } + } + } + return NULL; +} + +/** Like slipif_rxbyte, but passes completed packets to netif->input + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +static void +slipif_rxbyte_input(struct netif *netif, u8_t c) +{ + struct pbuf *p; + p = slipif_rxbyte(netif, c); + if (p != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } +} + +#if SLIP_USE_RX_THREAD +/** + * The SLIP input thread. + * + * Feed the IP layer with incoming packets + * + * @param nf the lwip network interface structure for this slipif + */ +static void +slipif_loop_thread(void *nf) +{ + u8_t c; + struct netif *netif = (struct netif *)nf; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + + while (1) { + if (sio_read(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } + } +} +#endif /* SLIP_USE_RX_THREAD */ + +/** + * SLIP netif initialization + * + * Call the arch specific sio_open and remember + * the opened device in the state field of the netif. + * + * @param netif the lwip network interface structure for this slipif + * @return ERR_OK if serial line could be opened, + * ERR_MEM if no memory could be allocated, + * ERR_IF is serial line couldn't be opened + * + * @note netif->num must contain the number of the serial port to open + * (0 by default). If netif->state is != NULL, it is interpreted as an + * u8_t pointer pointing to the serial port number instead of netif->num. + * + */ +err_t +slipif_init(struct netif *netif) +{ + struct slipif_priv *priv; + u8_t sio_num; + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); + + /* Allocate private data */ + priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); + if (!priv) { + return ERR_MEM; + } + + netif->name[0] = 's'; + netif->name[1] = 'l'; + netif->output = slipif_output; + netif->mtu = SLIP_MAX_SIZE; + netif->flags |= NETIF_FLAG_POINTTOPOINT; + + /* netif->state or netif->num contain the port number */ + if (netif->state != NULL) { + sio_num = *(u8_t*)netif->state; + } else { + sio_num = netif->num; + } + /* Try to open the serial port. */ + priv->sd = sio_open(sio_num); + if (!priv->sd) { + /* Opening the serial port failed. */ + mem_free(priv); + return ERR_IF; + } + + /* Initialize private data */ + priv->p = NULL; + priv->q = NULL; + priv->state = SLIP_RECV_NORMAL; + priv->i = 0; + priv->recved = 0; +#if SLIP_RX_FROM_ISR + priv->rxpackets = NULL; +#endif + + netif->state = priv; + + /* initialize the snmp variables and counters inside the struct netif */ + NETIF_INIT_SNMP(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); + +#if SLIP_USE_RX_THREAD + /* Create a thread to poll the serial line. */ + sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, + SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); +#endif /* SLIP_USE_RX_THREAD */ + return ERR_OK; +} + +/** + * Polls the serial device and feeds the IP layer with incoming packets. + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_poll(struct netif *netif) +{ + u8_t c; + struct slipif_priv *priv; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + while (sio_tryread(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } +} + +#if SLIP_RX_FROM_ISR +/** + * Feeds the IP layer with incoming packets that were receive + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_process_rxqueue(struct netif *netif) +{ + struct slipif_priv *priv; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + SYS_ARCH_PROTECT(old_level); + while (priv->rxpackets != NULL) { + struct pbuf *p = priv->rxpackets; +#if SLIP_RX_QUEUE + /* dequeue packet */ + struct pbuf *q = p; + while ((q->len != q->tot_len) && (q->next != NULL)) { + q = q->next; + } + priv->rxpackets = q->next; + q->next = NULL; +#else /* SLIP_RX_QUEUE */ + priv->rxpackets = NULL; +#endif /* SLIP_RX_QUEUE */ + SYS_ARCH_UNPROTECT(old_level); + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + SYS_ARCH_PROTECT(old_level); + } +} + +/** Like slipif_rxbyte, but queues completed packets. + * + * @param netif The lwip network interface structure for this slipif + * @param data Received serial byte + */ +static void +slipif_rxbyte_enqueue(struct netif *netif, u8_t data) +{ + struct pbuf *p; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + SYS_ARCH_DECL_PROTECT(old_level); + + p = slipif_rxbyte(netif, data); + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + if (priv->rxpackets != NULL) { +#if SLIP_RX_QUEUE + /* queue multiple pbufs */ + struct pbuf *q = p; + while(q->next != NULL) { + q = q->next; + } + q->next = p; + } else { +#else /* SLIP_RX_QUEUE */ + pbuf_free(priv->rxpackets); + } + { +#endif /* SLIP_RX_QUEUE */ + priv->rxpackets = p; + } + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Process a received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +void +slipif_received_byte(struct netif *netif, u8_t data) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + slipif_rxbyte_enqueue(netif, data); +} + +/** + * Process multiple received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + * @param len Number of received characters + */ +void +slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) +{ + u8_t i; + u8_t *rxdata = data; + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + for (i = 0; i < len; i++, rxdata++) { + slipif_rxbyte_enqueue(netif, *rxdata); + } +} +#endif /* SLIP_RX_FROM_ISR */ + +#endif /* LWIP_HAVE_SLIPIF */ diff --git a/ext/lwipopts.h b/ext/lwipopts.h new file mode 100644 index 000000000..710534612 --- /dev/null +++ b/ext/lwipopts.h @@ -0,0 +1,475 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "lwip/debug.h" + +#define LWIP_CHKSUM_ALGORITHM 2 + +#undef TCP_MSS +#define TCP_MSS 1460 + +/* +The TCP window size can be adjusted by changing the define TCP_WND. However, +do keep in mind that this should be at least twice the size of TCP_MSS (thus +on ethernet, where TCP_MSS is 1460, it should be set to at least 2920). If +memory allows it, set this as high as possible (16-bit, so 0xFFFF is the highest +value), but keep in mind that for every active connection, the full window may +have to be buffered until it is acknowledged by the remote side (although this +buffer size can still be controlled by TCP_SND_BUF and TCP_SND_QUEUELEN). The +reason for "twice" are both the nagle algorithm and delayed ACK from the +remote peer. +*/ + +#define TCP_WND TCP_MSS*10 // max = 0xffff + +#define LWIP_NOASSERT 1 +#define TCP_LISTEN_BACKLOG 0 + +/*------------------------------------------------------------------------------ +---------------------------------- Timers -------------------------------------- +------------------------------------------------------------------------------*/ +/* +Be careful about setting this too small. lwIP just counts the number +of times its timer is called and uses this to control time sensitive +operations (such as TCP retransmissions), rather than actually +measuring time using something more accurate. If you call the timer +functions very frequently you may see things (such as retransmissions) +happening sooner than they should. +*/ +/* these are originally defined in tcp_impl.h */ +#ifndef TCP_TMR_INTERVAL +/* The TCP timer interval in milliseconds. */ +#define TCP_TMR_INTERVAL 250 +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +/* the fine grained timeout in milliseconds */ +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVALs +/* the coarse grained timeout in milliseconds */ +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) +#endif /* TCP_SLOW_INTERVAL */ + + +/*------------------------------------------------------------------------------ +--------------------------- Platform specific locking ------------------------- +------------------------------------------------------------------------------*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 0 + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ + +/* set to 1 so we have no thread behaviour */ +#define NO_SYS 1 + +/* set to 1 so we can use our own timers */ +#define NO_SYS_NO_TIMERS 1 + + +/*------------------------------------------------------------------------------ +-------------------------------- Memory options -------------------------------- +------------------------------------------------------------------------------*/ + + + +/* Misc */ +#define MEM_LIBC_MALLOC 1 +#define MEMP_MEM_MALLOC 1 + + + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#define MEM_ALIGNMENT 1 + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#define MEM_SIZE 1024 * 1024 * 64 +#define TCP_SND_BUF 1024 * 63 +//#define TCP_OVERSIZE TCP_MSS + +#define TCP_SND_QUEUELEN 1024 + +/*------------------------------------------------------------------------------ +-------------------------------- Pbuf Options ---------------------------------- +------------------------------------------------------------------------------*/ + +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#define PBUF_LINK_HLEN 16 + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. +* + */ +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) + + +/*------------------------------------------------------------------------------ +-------------------------- Internal Memory Pool Sizes -------------------------- +------------------------------------------------------------------------------*/ + +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#define MEMP_NUM_PBUF 256 + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#define MEMP_NUM_RAW_PCB 128 + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#define MEMP_NUM_UDP_PCB 4 + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB 128 + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB_LISTEN 128 + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_SEG 1024 + +/** + * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for + * reassembly (whole packets, not fragments!) + */ +#define MEMP_NUM_REASSDATA 1 + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#define MEMP_NUM_ARP_QUEUE 2 + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + */ +#define MEMP_NUM_SYS_TIMEOUT 3 + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETBUF 2 + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETCONN 4 + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#define MEMP_NUM_TCPIP_MSG_API 8 + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#define MEMP_NUM_TCPIP_MSG_INPKT 8 + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#define PBUF_POOL_SIZE 2048 /* was 32 */ + + +/*------------------------------------------------------------------------------ +----------------------------------- ARP options -------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#define LWIP_ARP 1 + + +/*------------------------------------------------------------------------------ +------------------------------------ IP options--------------------------------- +------------------------------------------------------------------------------*/ + +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#define IP_FORWARD 0 + +/** + * IP_OPTIONS: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#define IP_OPTIONS_ALLOWED 1 + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#define IP_REASSEMBLY 1 + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#define IP_FRAG 1 + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#define IP_REASS_MAXAGE 3 + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#define IP_REASS_MAX_PBUFS 4 + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented. +*/ +#define IP_FRAG_USES_STATIC_BUF 0 + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#define IP_DEFAULT_TTL 255 + + +/*------------------------------------------------------------------------------ +------------------------------- ICMP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#define LWIP_ICMP 1 + + +/*------------------------------------------------------------------------------ +------------------------------- RAW Options ------------------------------------ +------------------------------------------------------------------------------*/ + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#define LWIP_RAW 1 + + +/*------------------------------------------------------------------------------ +------------------------------- DHCP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#define LWIP_DHCP 0 + + +/*------------------------------------------------------------------------------ +------------------------------ AUTOIP Options ---------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#define LWIP_AUTOIP 0 + + +/*------------------------------------------------------------------------------ +------------------------------- SNMP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#define LWIP_SNMP 0 + + +/*------------------------------------------------------------------------------ +------------------------------- IGMP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#define LWIP_IGMP 0 + + +/*------------------------------------------------------------------------------ +-------------------------------- DNS Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#define LWIP_DNS 0 + + +/*------------------------------------------------------------------------------ +-------------------------------- UDP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_UDP==1: Turn on UDP. + */ +#define LWIP_UDP 1 + + +/*------------------------------------------------------------------------------ +-------------------------------- TCP Options ----------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_TCP==1: Turn on TCP. + */ +#define LWIP_TCP 1 + +#define LWIP_LISTEN_BACKLOG 0 + + +/*------------------------------------------------------------------------------ +--------------------------------- LOOPIF Options ------------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#define LWIP_HAVE_LOOPIF 0 + + +/*------------------------------------------------------------------------------ +---------------------------- Sequential Layer Options -------------------------- +------------------------------------------------------------------------------*/ + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 0 + + +/*------------------------------------------------------------------------------ +--------------------------------- Socket Options ------------------------------- +------------------------------------------------------------------------------*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 0 + + +/*------------------------------------------------------------------------------ +------------------------------ Statistics Options ------------------------------ +------------------------------------------------------------------------------*/ + +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#define LWIP_STATS 0 + +/*------------------------------------------------------------------------------ +--------------------------------- PPP Options ---------------------------------- +------------------------------------------------------------------------------*/ + +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#define PPP_SUPPORT 0 + +#endif /* __LWIPOPTS_H__ */ \ No newline at end of file diff --git a/ext/lz4/lz4.c b/ext/lz4/lz4.c new file mode 100644 index 000000000..08cf6b5cd --- /dev/null +++ b/ext/lz4/lz4.c @@ -0,0 +1,1516 @@ +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2015, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 source repository : https://github.com/Cyan4973/lz4 + - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c +*/ + + +/************************************** +* Tuning parameters +**************************************/ +/* + * HEAPMODE : + * Select how default compression functions will allocate memory for their hash table, + * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). + */ +#define HEAPMODE 0 + +/* + * ACCELERATION_DEFAULT : + * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 + */ +#define ACCELERATION_DEFAULT 1 + + +/************************************** +* CPU Feature Detection +**************************************/ +/* + * LZ4_FORCE_SW_BITCOUNT + * Define this parameter if your target system or compiler does not support hardware bit count + */ +#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */ +# define LZ4_FORCE_SW_BITCOUNT +#endif + + +/************************************** +* Includes +**************************************/ +#include "lz4.h" + + +/************************************** +* Compiler Options +**************************************/ +#ifdef _MSC_VER /* Visual Studio */ +# define FORCE_INLINE static __forceinline +# include +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */ +#else +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +# if defined(__GNUC__) || defined(__clang__) +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +# else +# define FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +#endif /* _MSC_VER */ + +/* LZ4_GCC_VERSION is defined into lz4.h */ +#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) +# define expect(expr,value) (__builtin_expect ((expr),(value)) ) +#else +# define expect(expr,value) (expr) +#endif + +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) + + +/************************************** +* Memory routines +**************************************/ +#include /* malloc, calloc, free */ +#define ALLOCATOR(n,s) calloc(n,s) +#define FREEMEM free +#include /* memset, memcpy */ +#define MEM_INIT memset + + +/************************************** +* Basic Types +**************************************/ +#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +# include + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; +#else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; +#endif + + +/************************************** +* Reading and writing into memory +**************************************/ +#define STEPSIZE sizeof(size_t) + +static unsigned LZ4_64bits(void) { return sizeof(void*)==8; } + +static unsigned LZ4_isLittleEndian(void) +{ + const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} + + +static U16 LZ4_read16(const void* memPtr) +{ + U16 val16; + memcpy(&val16, memPtr, 2); + return val16; +} + +static U16 LZ4_readLE16(const void* memPtr) +{ + if (LZ4_isLittleEndian()) + { + return LZ4_read16(memPtr); + } + else + { + const BYTE* p = (const BYTE*)memPtr; + return (U16)((U16)p[0] + (p[1]<<8)); + } +} + +static void LZ4_writeLE16(void* memPtr, U16 value) +{ + if (LZ4_isLittleEndian()) + { + memcpy(memPtr, &value, 2); + } + else + { + BYTE* p = (BYTE*)memPtr; + p[0] = (BYTE) value; + p[1] = (BYTE)(value>>8); + } +} + +static U32 LZ4_read32(const void* memPtr) +{ + U32 val32; + memcpy(&val32, memPtr, 4); + return val32; +} + +static U64 LZ4_read64(const void* memPtr) +{ + U64 val64; + memcpy(&val64, memPtr, 8); + return val64; +} + +static size_t LZ4_read_ARCH(const void* p) +{ + if (LZ4_64bits()) + return (size_t)LZ4_read64(p); + else + return (size_t)LZ4_read32(p); +} + + +static void LZ4_copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); } + +static void LZ4_copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); } + +/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */ +static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd) +{ + BYTE* d = (BYTE*)dstPtr; + const BYTE* s = (const BYTE*)srcPtr; + BYTE* e = (BYTE*)dstEnd; + do { LZ4_copy8(d,s); d+=8; s+=8; } while (d>3); +# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctzll((U64)val) >> 3); +# else + static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; + return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; +# endif + } + else /* 32 bits */ + { +# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r; + _BitScanForward( &r, (U32)val ); + return (int)(r>>3); +# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctz((U32)val) >> 3); +# else + static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; + return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; +# endif + } + } + else /* Big Endian CPU */ + { + if (LZ4_64bits()) + { +# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse64( &r, val ); + return (unsigned)(r>>3); +# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clzll((U64)val) >> 3); +# else + unsigned r; + if (!(val>>32)) { r=4; } else { r=0; val>>=32; } + if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } + r += (!val); + return r; +# endif + } + else /* 32 bits */ + { +# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse( &r, (unsigned long)val ); + return (unsigned)(r>>3); +# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clz((U32)val) >> 3); +# else + unsigned r; + if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } + r += (!val); + return r; +# endif + } + } +} + +static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) +{ + const BYTE* const pStart = pIn; + + while (likely(pIn compression run slower on incompressible data */ + + +/************************************** +* Local Structures and types +**************************************/ +typedef struct { + U32 hashTable[HASH_SIZE_U32]; + U32 currentOffset; + U32 initCheck; + const BYTE* dictionary; + BYTE* bufferStart; /* obsolete, used for slideInputBuffer */ + U32 dictSize; +} LZ4_stream_t_internal; + +typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive; +typedef enum { byPtr, byU32, byU16 } tableType_t; + +typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive; +typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; + +typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; +typedef enum { full = 0, partial = 1 } earlyEnd_directive; + + +/************************************** +* Local Utils +**************************************/ +int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } +int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } +int LZ4_sizeofState() { return LZ4_STREAMSIZE; } + + + +/******************************** +* Compression functions +********************************/ + +static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType) +{ + if (tableType == byU16) + return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); + else + return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); +} + +static const U64 prime5bytes = 889523592379ULL; +static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType) +{ + const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; + const U32 hashMask = (1<> (40 - hashLog)) & hashMask; +} + +static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType) +{ + if (LZ4_64bits()) + return LZ4_hashSequence64(sequence, tableType); + return LZ4_hashSequence((U32)sequence, tableType); +} + +static U32 LZ4_hashPosition(const void* p, tableType_t tableType) { return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType); } + +static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) +{ + switch (tableType) + { + case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; } + case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; } + case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; } + } +} + +static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + U32 h = LZ4_hashPosition(p, tableType); + LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); +} + +static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; } + if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } + { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ +} + +static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + U32 h = LZ4_hashPosition(p, tableType); + return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); +} + +FORCE_INLINE int LZ4_compress_generic( + void* const ctx, + const char* const source, + char* const dest, + const int inputSize, + const int maxOutputSize, + const limitedOutput_directive outputLimited, + const tableType_t tableType, + const dict_directive dict, + const dictIssue_directive dictIssue, + const U32 acceleration) +{ + LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx; + + const BYTE* ip = (const BYTE*) source; + const BYTE* base; + const BYTE* lowLimit; + const BYTE* const lowRefLimit = ip - dictPtr->dictSize; + const BYTE* const dictionary = dictPtr->dictionary; + const BYTE* const dictEnd = dictionary + dictPtr->dictSize; + const size_t dictDelta = dictEnd - (const BYTE*)source; + const BYTE* anchor = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = iend - LASTLITERALS; + + BYTE* op = (BYTE*) dest; + BYTE* const olimit = op + maxOutputSize; + + U32 forwardH; + size_t refDelta=0; + + /* Init conditions */ + if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ + switch(dict) + { + case noDict: + default: + base = (const BYTE*)source; + lowLimit = (const BYTE*)source; + break; + case withPrefix64k: + base = (const BYTE*)source - dictPtr->currentOffset; + lowLimit = (const BYTE*)source - dictPtr->dictSize; + break; + case usingExtDict: + base = (const BYTE*)source - dictPtr->currentOffset; + lowLimit = (const BYTE*)source; + break; + } + if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ + if (inputSize> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimit)) goto _last_literals; + + match = LZ4_getPositionOnHash(h, ctx, tableType, base); + if (dict==usingExtDict) + { + if (match<(const BYTE*)source) + { + refDelta = dictDelta; + lowLimit = dictionary; + } + else + { + refDelta = 0; + lowLimit = (const BYTE*)source; + } + } + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putPositionOnHash(ip, h, ctx, tableType, base); + + } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0) + || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) + || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) ); + } + + /* Catch up */ + while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; } + + { + /* Encode Literal length */ + unsigned litLength = (unsigned)(ip - anchor); + token = op++; + if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) + return 0; /* Check output limit */ + if (litLength>=RUN_MASK) + { + int len = (int)litLength-RUN_MASK; + *token=(RUN_MASK<= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(litLength< matchlimit) limit = matchlimit; + matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); + ip += MINMATCH + matchLength; + if (ip==limit) + { + unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit); + matchLength += more; + ip += more; + } + } + else + { + matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); + ip += MINMATCH + matchLength; + } + + if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit))) + return 0; /* Check output limit */ + if (matchLength>=ML_MASK) + { + *token += ML_MASK; + matchLength -= ML_MASK; + for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; } + if (matchLength >= 255) { matchLength-=255; *op++ = 255; } + *op++ = (BYTE)matchLength; + } + else *token += (BYTE)(matchLength); + } + + anchor = ip; + + /* Test end of chunk */ + if (ip > mflimit) break; + + /* Fill table */ + LZ4_putPosition(ip-2, ctx, tableType, base); + + /* Test next position */ + match = LZ4_getPosition(ip, ctx, tableType, base); + if (dict==usingExtDict) + { + if (match<(const BYTE*)source) + { + refDelta = dictDelta; + lowLimit = dictionary; + } + else + { + refDelta = 0; + lowLimit = (const BYTE*)source; + } + } + LZ4_putPosition(ip, ctx, tableType, base); + if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1) + && (match+MAX_DISTANCE>=ip) + && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) ) + { token=op++; *token=0; goto _next_match; } + + /* Prepare next loop */ + forwardH = LZ4_hashPosition(++ip, tableType); + } + +_last_literals: + /* Encode Last Literals */ + { + const size_t lastRun = (size_t)(iend - anchor); + if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) + return 0; /* Check output limit */ + if (lastRun >= RUN_MASK) + { + size_t accumulator = lastRun - RUN_MASK; + *op++ = RUN_MASK << ML_BITS; + for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; + *op++ = (BYTE) accumulator; + } + else + { + *op++ = (BYTE)(lastRun<= LZ4_compressBound(inputSize)) + { + if (inputSize < LZ4_64Klimit) + return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); + else + return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); + } + else + { + if (inputSize < LZ4_64Klimit) + return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + else + return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); + } +} + + +int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ +#if (HEAPMODE) + void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ +#else + LZ4_stream_t ctx; + void* ctxPtr = &ctx; +#endif + + int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); + +#if (HEAPMODE) + FREEMEM(ctxPtr); +#endif + return result; +} + + +int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize) +{ + return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1); +} + + +/* hidden debug function */ +/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */ +int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ + LZ4_stream_t ctx; + + LZ4_resetStream(&ctx); + + if (inputSize < LZ4_64Klimit) + return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + else + return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); +} + + +/******************************** +* destSize variant +********************************/ + +static int LZ4_compress_destSize_generic( + void* const ctx, + const char* const src, + char* const dst, + int* const srcSizePtr, + const int targetDstSize, + const tableType_t tableType) +{ + const BYTE* ip = (const BYTE*) src; + const BYTE* base = (const BYTE*) src; + const BYTE* lowLimit = (const BYTE*) src; + const BYTE* anchor = ip; + const BYTE* const iend = ip + *srcSizePtr; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = iend - LASTLITERALS; + + BYTE* op = (BYTE*) dst; + BYTE* const oend = op + targetDstSize; + BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */; + BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */); + BYTE* const oMaxSeq = oMaxLit - 1 /* token */; + + U32 forwardH; + + + /* Init conditions */ + if (targetDstSize < 1) return 0; /* Impossible to store anything */ + if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ + if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ + if (*srcSizePtr> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimit)) + goto _last_literals; + + match = LZ4_getPositionOnHash(h, ctx, tableType, base); + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putPositionOnHash(ip, h, ctx, tableType, base); + + } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) + || (LZ4_read32(match) != LZ4_read32(ip)) ); + } + + /* Catch up */ + while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } + + { + /* Encode Literal length */ + unsigned litLength = (unsigned)(ip - anchor); + token = op++; + if (op + ((litLength+240)/255) + litLength > oMaxLit) + { + /* Not enough space for a last match */ + op--; + goto _last_literals; + } + if (litLength>=RUN_MASK) + { + unsigned len = litLength - RUN_MASK; + *token=(RUN_MASK<= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(litLength< oMaxMatch) + { + /* Match description too long : reduce it */ + matchLength = (15-1) + (oMaxMatch-op) * 255; + } + //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH); + ip += MINMATCH + matchLength; + + if (matchLength>=ML_MASK) + { + *token += ML_MASK; + matchLength -= ML_MASK; + while (matchLength >= 255) { matchLength-=255; *op++ = 255; } + *op++ = (BYTE)matchLength; + } + else *token += (BYTE)(matchLength); + } + + anchor = ip; + + /* Test end of block */ + if (ip > mflimit) break; + if (op > oMaxSeq) break; + + /* Fill table */ + LZ4_putPosition(ip-2, ctx, tableType, base); + + /* Test next position */ + match = LZ4_getPosition(ip, ctx, tableType, base); + LZ4_putPosition(ip, ctx, tableType, base); + if ( (match+MAX_DISTANCE>=ip) + && (LZ4_read32(match)==LZ4_read32(ip)) ) + { token=op++; *token=0; goto _next_match; } + + /* Prepare next loop */ + forwardH = LZ4_hashPosition(++ip, tableType); + } + +_last_literals: + /* Encode Last Literals */ + { + size_t lastRunSize = (size_t)(iend - anchor); + if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) + { + /* adapt lastRunSize to fill 'dst' */ + lastRunSize = (oend-op) - 1; + lastRunSize -= (lastRunSize+240)/255; + } + ip = anchor + lastRunSize; + + if (lastRunSize >= RUN_MASK) + { + size_t accumulator = lastRunSize - RUN_MASK; + *op++ = RUN_MASK << ML_BITS; + for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; + *op++ = (BYTE) accumulator; + } + else + { + *op++ = (BYTE)(lastRunSize<= LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */ + { + return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); + } + else + { + if (*srcSizePtr < LZ4_64Klimit) + return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16); + else + return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, LZ4_64bits() ? byU32 : byPtr); + } +} + + +int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) +{ +#if (HEAPMODE) + void* ctx = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ +#else + LZ4_stream_t ctxBody; + void* ctx = &ctxBody; +#endif + + int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); + +#if (HEAPMODE) + FREEMEM(ctx); +#endif + return result; +} + + + +/******************************** +* Streaming functions +********************************/ + +LZ4_stream_t* LZ4_createStream(void) +{ + LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64); + LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */ + LZ4_resetStream(lz4s); + return lz4s; +} + +void LZ4_resetStream (LZ4_stream_t* LZ4_stream) +{ + MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t)); +} + +int LZ4_freeStream (LZ4_stream_t* LZ4_stream) +{ + FREEMEM(LZ4_stream); + return (0); +} + + +#define HASH_UNIT sizeof(size_t) +int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) +{ + LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; + const BYTE* p = (const BYTE*)dictionary; + const BYTE* const dictEnd = p + dictSize; + const BYTE* base; + + if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */ + LZ4_resetStream(LZ4_dict); + + if (dictSize < (int)HASH_UNIT) + { + dict->dictionary = NULL; + dict->dictSize = 0; + return 0; + } + + if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB; + dict->currentOffset += 64 KB; + base = p - dict->currentOffset; + dict->dictionary = p; + dict->dictSize = (U32)(dictEnd - p); + dict->currentOffset += dict->dictSize; + + while (p <= dictEnd-HASH_UNIT) + { + LZ4_putPosition(p, dict->hashTable, byU32, base); + p+=3; + } + + return dict->dictSize; +} + + +static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) +{ + if ((LZ4_dict->currentOffset > 0x80000000) || + ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */ + { + /* rescale hash table */ + U32 delta = LZ4_dict->currentOffset - 64 KB; + const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; + int i; + for (i=0; ihashTable[i] < delta) LZ4_dict->hashTable[i]=0; + else LZ4_dict->hashTable[i] -= delta; + } + LZ4_dict->currentOffset = 64 KB; + if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB; + LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize; + } +} + + +int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ + LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream; + const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; + + const BYTE* smallest = (const BYTE*) source; + if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */ + if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd; + LZ4_renormDictT(streamPtr, smallest); + if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; + + /* Check overlapping input/dictionary space */ + { + const BYTE* sourceEnd = (const BYTE*) source + inputSize; + if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) + { + streamPtr->dictSize = (U32)(dictEnd - sourceEnd); + if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; + if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; + streamPtr->dictionary = dictEnd - streamPtr->dictSize; + } + } + + /* prefix mode : source data follows dictionary */ + if (dictEnd == (const BYTE*)source) + { + int result; + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) + result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration); + else + result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration); + streamPtr->dictSize += (U32)inputSize; + streamPtr->currentOffset += (U32)inputSize; + return result; + } + + /* external dictionary mode */ + { + int result; + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) + result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration); + else + result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration); + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)inputSize; + streamPtr->currentOffset += (U32)inputSize; + return result; + } +} + + +/* Hidden debug function, to force external dictionary mode */ +int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize) +{ + LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict; + int result; + const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; + + const BYTE* smallest = dictEnd; + if (smallest > (const BYTE*) source) smallest = (const BYTE*) source; + LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest); + + result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); + + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)inputSize; + streamPtr->currentOffset += (U32)inputSize; + + return result; +} + + +int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) +{ + LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; + const BYTE* previousDictEnd = dict->dictionary + dict->dictSize; + + if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */ + if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize; + + memmove(safeBuffer, previousDictEnd - dictSize, dictSize); + + dict->dictionary = (const BYTE*)safeBuffer; + dict->dictSize = (U32)dictSize; + + return dictSize; +} + + + +/******************************* +* Decompression functions +*******************************/ +/* + * This generic decompression function cover all use cases. + * It shall be instantiated several times, using different sets of directives + * Note that it is essential this generic function is really inlined, + * in order to remove useless branches during compilation optimization. + */ +FORCE_INLINE int LZ4_decompress_generic( + const char* const source, + char* const dest, + int inputSize, + int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */ + + int endOnInput, /* endOnOutputSize, endOnInputSize */ + int partialDecoding, /* full, partial */ + int targetOutputSize, /* only used if partialDecoding==partial */ + int dict, /* noDict, withPrefix64k, usingExtDict */ + const BYTE* const lowPrefix, /* == dest if dict == noDict */ + const BYTE* const dictStart, /* only if dict==usingExtDict */ + const size_t dictSize /* note : = 0 if noDict */ + ) +{ + /* Local Variables */ + const BYTE* ip = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + + BYTE* op = (BYTE*) dest; + BYTE* const oend = op + outputSize; + BYTE* cpy; + BYTE* oexit = op + targetOutputSize; + const BYTE* const lowLimit = lowPrefix - dictSize; + + const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize; + const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4}; + const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; + + const int safeDecode = (endOnInput==endOnInputSize); + const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); + + + /* Special cases */ + if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ + if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ + if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); + + + /* Main Loop */ + while (1) + { + unsigned token; + size_t length; + const BYTE* match; + + /* get literal length */ + token = *ip++; + if ((length=(token>>ML_BITS)) == RUN_MASK) + { + unsigned s; + do + { + s = *ip++; + length += s; + } + while (likely((endOnInput)?ip(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) + || ((!endOnInput) && (cpy>oend-COPYLENGTH))) + { + if (partialDecoding) + { + if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ + if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ + } + else + { + if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ + if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ + } + memcpy(op, ip, length); + ip += length; + op += length; + break; /* Necessarily EOF, due to parsing restrictions */ + } + LZ4_wildCopy(op, ip, cpy); + ip += length; op = cpy; + + /* get offset */ + match = cpy - LZ4_readLE16(ip); ip+=2; + if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */ + + /* get matchlength */ + length = token & ML_MASK; + if (length == ML_MASK) + { + unsigned s; + do + { + if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; + s = *ip++; + length += s; + } while (s==255); + if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */ + } + length += MINMATCH; + + /* check external dictionary */ + if ((dict==usingExtDict) && (match < lowPrefix)) + { + if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ + + if (length <= (size_t)(lowPrefix-match)) + { + /* match can be copied as a single segment from external dictionary */ + match = dictEnd - (lowPrefix-match); + memmove(op, match, length); op += length; + } + else + { + /* match encompass external dictionary and current segment */ + size_t copySize = (size_t)(lowPrefix-match); + memcpy(op, dictEnd - copySize, copySize); + op += copySize; + copySize = length - copySize; + if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */ + { + BYTE* const endOfMatch = op + copySize; + const BYTE* copyFrom = lowPrefix; + while (op < endOfMatch) *op++ = *copyFrom++; + } + else + { + memcpy(op, lowPrefix, copySize); + op += copySize; + } + } + continue; + } + + /* copy repeated sequence */ + cpy = op + length; + if (unlikely((op-match)<8)) + { + const size_t dec64 = dec64table[op-match]; + op[0] = match[0]; + op[1] = match[1]; + op[2] = match[2]; + op[3] = match[3]; + match += dec32table[op-match]; + LZ4_copy4(op+4, match); + op += 8; match -= dec64; + } else { LZ4_copy8(op, match); op+=8; match+=8; } + + if (unlikely(cpy>oend-12)) + { + if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */ + if (op < oend-8) + { + LZ4_wildCopy(op, match, oend-8); + match += (oend-8) - op; + op = oend-8; + } + while (opprefixSize = (size_t) dictSize; + lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; + lz4sd->externalDict = NULL; + lz4sd->extDictSize = 0; + return 1; +} + +/* +*_continue() : + These decoding functions allow decompression of multiple blocks in "streaming" mode. + Previously decoded blocks must still be available at the memory position where they were decoded. + If it's not possible, save the relevant part of decoded data into a safe buffer, + and indicate where it stands using LZ4_setStreamDecode() +*/ +int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) +{ + LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; + int result; + + if (lz4sd->prefixEnd == (BYTE*)dest) + { + result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + endOnInputSize, full, 0, + usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize += result; + lz4sd->prefixEnd += result; + } + else + { + lz4sd->extDictSize = lz4sd->prefixSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; + result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + endOnInputSize, full, 0, + usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize = result; + lz4sd->prefixEnd = (BYTE*)dest + result; + } + + return result; +} + +int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) +{ + LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; + int result; + + if (lz4sd->prefixEnd == (BYTE*)dest) + { + result = LZ4_decompress_generic(source, dest, 0, originalSize, + endOnOutputSize, full, 0, + usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize += originalSize; + lz4sd->prefixEnd += originalSize; + } + else + { + lz4sd->extDictSize = lz4sd->prefixSize; + lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize; + result = LZ4_decompress_generic(source, dest, 0, originalSize, + endOnOutputSize, full, 0, + usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize = originalSize; + lz4sd->prefixEnd = (BYTE*)dest + originalSize; + } + + return result; +} + + +/* +Advanced decoding functions : +*_usingDict() : + These decoding functions work the same as "_continue" ones, + the dictionary must be explicitly provided within parameters +*/ + +FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize) +{ + if (dictSize==0) + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0); + if (dictStart+dictSize == dest) + { + if (dictSize >= (int)(64 KB - 1)) + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0); + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0); + } + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); +} + +int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize); +} + +int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize); +} + +/* debug function */ +int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); +} + + +/*************************************************** +* Obsolete Functions +***************************************************/ +/* obsolete compression functions */ +int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); } +int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); } +int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); } +int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); } +int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); } +int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); } + +/* +These function names are deprecated and should no longer be used. +They are only provided here for compatibility with older user programs. +- LZ4_uncompress is totally equivalent to LZ4_decompress_fast +- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe +*/ +int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); } +int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); } + + +/* Obsolete Streaming functions */ + +int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; } + +static void LZ4_init(LZ4_stream_t_internal* lz4ds, BYTE* base) +{ + MEM_INIT(lz4ds, 0, LZ4_STREAMSIZE); + lz4ds->bufferStart = base; +} + +int LZ4_resetStreamState(void* state, char* inputBuffer) +{ + if ((((size_t)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ + LZ4_init((LZ4_stream_t_internal*)state, (BYTE*)inputBuffer); + return 0; +} + +void* LZ4_create (char* inputBuffer) +{ + void* lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64); + LZ4_init ((LZ4_stream_t_internal*)lz4ds, (BYTE*)inputBuffer); + return lz4ds; +} + +char* LZ4_slideInputBuffer (void* LZ4_Data) +{ + LZ4_stream_t_internal* ctx = (LZ4_stream_t_internal*)LZ4_Data; + int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB); + return (char*)(ctx->bufferStart + dictSize); +} + +/* Obsolete streaming decompression functions */ + +int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); +} + +int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize) +{ + return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); +} + +#endif /* LZ4_COMMONDEFS_ONLY */ + diff --git a/ext/lz4/lz4.h b/ext/lz4/lz4.h new file mode 100644 index 000000000..3e7400225 --- /dev/null +++ b/ext/lz4/lz4.h @@ -0,0 +1,360 @@ +/* + LZ4 - Fast LZ compression algorithm + Header File + Copyright (C) 2011-2015, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 source repository : https://github.com/Cyan4973/lz4 + - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c +*/ +#pragma once + +#if defined (__cplusplus) +extern "C" { +#endif + +/* + * lz4.h provides block compression functions, and gives full buffer control to programmer. + * If you need to generate inter-operable compressed data (respecting LZ4 frame specification), + * and can let the library handle its own memory, please use lz4frame.h instead. +*/ + +/************************************** +* Version +**************************************/ +#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ +#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */ +#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */ +#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) +int LZ4_versionNumber (void); + +/************************************** +* Tuning parameter +**************************************/ +/* + * LZ4_MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + * Increasing memory usage improves compression ratio + * Reduced memory usage can improve speed, due to cache effect + * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache + */ +#define LZ4_MEMORY_USAGE 14 + + +/************************************** +* Simple Functions +**************************************/ + +int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); +int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize); + +/* +LZ4_compress_default() : + Compresses 'sourceSize' bytes from buffer 'source' + into already allocated 'dest' buffer of size 'maxDestSize'. + Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize). + It also runs faster, so it's a recommended setting. + If the function cannot compress 'source' into a more limited 'dest' budget, + compression stops *immediately*, and the function result is zero. + As a consequence, 'dest' content is not valid. + This function never writes outside 'dest' buffer, nor read outside 'source' buffer. + sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE + maxDestSize : full or partial size of buffer 'dest' (which must be already allocated) + return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize) + or 0 if compression fails + +LZ4_decompress_safe() : + compressedSize : is the precise full size of the compressed block. + maxDecompressedSize : is the size of destination buffer, which must be already allocated. + return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize) + If destination buffer is not large enough, decoding will stop and output an error code (<0). + If the source stream is detected malformed, the function will stop decoding and return a negative result. + This function is protected against buffer overflow exploits, including malicious data packets. + It never writes outside output buffer, nor reads outside input buffer. +*/ + + +/************************************** +* Advanced Functions +**************************************/ +#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ +#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) + +/* +LZ4_compressBound() : + Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) + This function is primarily useful for memory allocation purposes (destination buffer size). + Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). + Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize) + inputSize : max supported value is LZ4_MAX_INPUT_SIZE + return : maximum output size in a "worst case" scenario + or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) +*/ +int LZ4_compressBound(int inputSize); + +/* +LZ4_compress_fast() : + Same as LZ4_compress_default(), but allows to select an "acceleration" factor. + The larger the acceleration value, the faster the algorithm, but also the lesser the compression. + It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. + An acceleration value of "1" is the same as regular LZ4_compress_default() + Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1. +*/ +int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); + + +/* +LZ4_compress_fast_extState() : + Same compression function, just using an externally allocated memory space to store compression state. + Use LZ4_sizeofState() to know how much memory must be allocated, + and allocate it on 8-bytes boundaries (using malloc() typically). + Then, provide it as 'void* state' to compression function. +*/ +int LZ4_sizeofState(void); +int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration); + + +/* +LZ4_compress_destSize() : + Reverse the logic, by compressing as much data as possible from 'source' buffer + into already allocated buffer 'dest' of size 'targetDestSize'. + This function either compresses the entire 'source' content into 'dest' if it's large enough, + or fill 'dest' buffer completely with as much data as possible from 'source'. + *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'. + New value is necessarily <= old value. + return : Nb bytes written into 'dest' (necessarily <= targetDestSize) + or 0 if compression fails +*/ +int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize); + + +/* +LZ4_decompress_fast() : + originalSize : is the original and therefore uncompressed size + return : the number of bytes read from the source buffer (in other words, the compressed size) + If the source stream is detected malformed, the function will stop decoding and return a negative result. + Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes. + note : This function fully respect memory boundaries for properly formed compressed data. + It is a bit faster than LZ4_decompress_safe(). + However, it does not provide any protection against intentionally modified data stream (malicious input). + Use this function in trusted environment only (data to decode comes from a trusted source). +*/ +int LZ4_decompress_fast (const char* source, char* dest, int originalSize); + +/* +LZ4_decompress_safe_partial() : + This function decompress a compressed block of size 'compressedSize' at position 'source' + into destination buffer 'dest' of size 'maxDecompressedSize'. + The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached, + reducing decompression time. + return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize) + Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller. + Always control how many bytes were decoded. + If the source stream is detected malformed, the function will stop decoding and return a negative result. + This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets +*/ +int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); + + +/*********************************************** +* Streaming Compression Functions +***********************************************/ +#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) +#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long)) +/* + * LZ4_stream_t + * information structure to track an LZ4 stream. + * important : init this structure content before first use ! + * note : only allocated directly the structure if you are statically linking LZ4 + * If you are using liblz4 as a DLL, please use below construction methods instead. + */ +typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t; + +/* + * LZ4_resetStream + * Use this function to init an allocated LZ4_stream_t structure + */ +void LZ4_resetStream (LZ4_stream_t* streamPtr); + +/* + * LZ4_createStream will allocate and initialize an LZ4_stream_t structure + * LZ4_freeStream releases its memory. + * In the context of a DLL (liblz4), please use these methods rather than the static struct. + * They are more future proof, in case of a change of LZ4_stream_t size. + */ +LZ4_stream_t* LZ4_createStream(void); +int LZ4_freeStream (LZ4_stream_t* streamPtr); + +/* + * LZ4_loadDict + * Use this function to load a static dictionary into LZ4_stream. + * Any previous data will be forgotten, only 'dictionary' will remain in memory. + * Loading a size of 0 is allowed. + * Return : dictionary size, in bytes (necessarily <= 64 KB) + */ +int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); + +/* + * LZ4_compress_fast_continue + * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. + * Important : Previous data blocks are assumed to still be present and unmodified ! + * 'dst' buffer must be already allocated. + * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. + * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero. + */ +int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration); + +/* + * LZ4_saveDict + * If previously compressed data block is not guaranteed to remain available at its memory location + * save it into a safer place (char* safeBuffer) + * Note : you don't need to call LZ4_loadDict() afterwards, + * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue() + * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error + */ +int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize); + + +/************************************************ +* Streaming Decompression Functions +************************************************/ + +#define LZ4_STREAMDECODESIZE_U64 4 +#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) +typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t; +/* + * LZ4_streamDecode_t + * information structure to track an LZ4 stream. + * init this structure content using LZ4_setStreamDecode or memset() before first use ! + * + * In the context of a DLL (liblz4) please prefer usage of construction methods below. + * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future. + * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure + * LZ4_freeStreamDecode releases its memory. + */ +LZ4_streamDecode_t* LZ4_createStreamDecode(void); +int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); + +/* + * LZ4_setStreamDecode + * Use this function to instruct where to find the dictionary. + * Setting a size of 0 is allowed (same effect as reset). + * Return : 1 if OK, 0 if error + */ +int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); + +/* +*_continue() : + These decoding functions allow decompression of multiple blocks in "streaming" mode. + Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB) + In the case of a ring buffers, decoding buffer must be either : + - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions) + In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB). + - Larger than encoding buffer, by a minimum of maxBlockSize more bytes. + maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block. + In which case, encoding and decoding buffers do not need to be synchronized, + and encoding ring buffer can have any size, including small ones ( < 64 KB). + - _At least_ 64 KB + 8 bytes + maxBlockSize. + In which case, encoding and decoding buffers do not need to be synchronized, + and encoding ring buffer can have any size, including larger than decoding buffer. + Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer, + and indicate where it is saved using LZ4_setStreamDecode() +*/ +int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize); +int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize); + + +/* +Advanced decoding functions : +*_usingDict() : + These decoding functions work the same as + a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue() + They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure. +*/ +int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize); +int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); + + + +/************************************** +* Obsolete Functions +**************************************/ +/* Deprecate Warnings */ +/* Should these warnings messages be a problem, + it is generally possible to disable them, + with -Wno-deprecated-declarations for gcc + or _CRT_SECURE_NO_WARNINGS in Visual for example. + You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */ +#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK +# define LZ4_DEPRECATE_WARNING_DEFBLOCK +# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +# if (LZ4_GCC_VERSION >= 405) || defined(__clang__) +# define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) +# elif (LZ4_GCC_VERSION >= 301) +# define LZ4_DEPRECATED(message) __attribute__((deprecated)) +# elif defined(_MSC_VER) +# define LZ4_DEPRECATED(message) __declspec(deprecated(message)) +# else +# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler") +# define LZ4_DEPRECATED(message) +# endif +#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */ + +/* Obsolete compression functions */ +/* These functions are planned to start generate warnings by r131 approximately */ +int LZ4_compress (const char* source, char* dest, int sourceSize); +int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); +int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); +int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); +int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); +int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); + +/* Obsolete decompression functions */ +/* These function names are completely deprecated and must no longer be used. + They are only provided here for compatibility with older programs. + - LZ4_uncompress is the same as LZ4_decompress_fast + - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe + These function prototypes are now disabled; uncomment them only if you really need them. + It is highly recommended to stop using these prototypes and migrate to maintained ones */ +/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */ +/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */ + +/* Obsolete streaming functions; use new streaming interface whenever possible */ +LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer); +LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void); +LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer); +LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state); + +/* Obsolete streaming decoding functions */ +LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize); +LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); + + +#if defined (__cplusplus) +} +#endif diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist new file mode 100644 index 000000000..c67923c7d --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist @@ -0,0 +1,59 @@ + + + + + BuildMachineOSBuild + 15B42 + CFBundleDevelopmentRegion + en + CFBundleExecutable + ZeroTier One + CFBundleIconFile + ZeroTierIcon + CFBundleIdentifier + com.zerotier.ZeroTier-One + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ZeroTier One + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 7B1005 + DTPlatformVersion + GM + DTSDKBuild + 15A278 + DTSDKName + macosx10.11 + DTXcode + 0711 + DTXcodeBuild + 7B1005 + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + 10.7 + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One new file mode 100755 index 000000000..8e38b861a Binary files /dev/null and b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One differ diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/PkgInfo b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/PkgInfo new file mode 100644 index 000000000..bd04210fb --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPL???? \ No newline at end of file diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/ZeroTierIcon.icns b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/ZeroTierIcon.icns new file mode 100644 index 000000000..17e60d587 Binary files /dev/null and b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/ZeroTierIcon.icns differ diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Credits.rtf b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Credits.rtf new file mode 100644 index 000000000..6f388f662 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Credits.rtf @@ -0,0 +1,13 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\vieww9600\viewh8400\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 + +\f0\b\fs24 \cf0 (c)2011-2015 ZeroTier, Inc.\ +Licensed under the GNU GPLv3\ +\ +UI Wrapper MacGap (c) Twitter, Inc.\ +Licensed under the MIT License\ +http://macgap.com/\ +} \ No newline at end of file diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/InfoPlist.strings b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..5e45963c3 Binary files /dev/null and b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/InfoPlist.strings differ diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib new file mode 100644 index 000000000..bac7faa79 Binary files /dev/null and b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib differ diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib new file mode 100644 index 000000000..e7b174a1c Binary files /dev/null and b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib differ diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources new file mode 100644 index 000000000..5e334db0c --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources @@ -0,0 +1,187 @@ + + + + + files + + Resources/ZeroTierIcon.icns + + 430Gd+4+jnim7WxXEEugp6G+Tgk= + + Resources/en.lproj/Credits.rtf + + hash + + ePttkAH2X1GJ6OL0UhDBAktxB3Y= + + optional + + + Resources/en.lproj/InfoPlist.strings + + hash + + MiLKDDnrUKr4EmuvhS5VQwxHGK8= + + optional + + + Resources/en.lproj/MainMenu.nib + + hash + + 8JZXf4/3df3LD+o74Y8WM0dV8io= + + optional + + + Resources/en.lproj/Window.nib + + hash + + aP0mIANPPnnTMmxYlELioz9ZO1I= + + optional + + + + files2 + + Resources/ZeroTierIcon.icns + + 430Gd+4+jnim7WxXEEugp6G+Tgk= + + Resources/en.lproj/Credits.rtf + + hash + + ePttkAH2X1GJ6OL0UhDBAktxB3Y= + + optional + + + Resources/en.lproj/InfoPlist.strings + + hash + + MiLKDDnrUKr4EmuvhS5VQwxHGK8= + + optional + + + Resources/en.lproj/MainMenu.nib + + hash + + 8JZXf4/3df3LD+o74Y8WM0dV8io= + + optional + + + Resources/en.lproj/Window.nib + + hash + + aP0mIANPPnnTMmxYlELioz9ZO1I= + + optional + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/ext/mac-ui-macgap1-wrapper/src/LICENSE b/ext/mac-ui-macgap1-wrapper/src/LICENSE new file mode 100644 index 000000000..c7fd4a4a5 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/LICENSE @@ -0,0 +1,25 @@ +MacGap was ported from phonegap-mac, and is under the same license (MIT) + +The MIT License +***************** + +Copyright (c) <2012> + + 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. + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj new file mode 100644 index 000000000..775c59641 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj @@ -0,0 +1,489 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1495814F15C15CCC00E1CFE5 /* Notice.m in Sources */ = {isa = PBXBuildFile; fileRef = 1495814E15C15CCC00E1CFE5 /* Notice.m */; }; + 6F169DA718CC332E005EDDF3 /* Command.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DA618CC332E005EDDF3 /* Command.m */; }; + 6F169DAA18CC35FD005EDDF3 /* CallbackDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */; }; + 6F169DAC18CD8A4A005EDDF3 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */; }; + 6F169DB118CD906F005EDDF3 /* MenuItemProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */; }; + 6F169DB218CD906F005EDDF3 /* MenuProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DB018CD906F005EDDF3 /* MenuProxy.m */; }; + 6FD672B618FE618E00C0DAAD /* UserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD672B518FE618E00C0DAAD /* UserDefaults.m */; }; + 6FD6E4ED18C2D48C00DFFBE6 /* fonts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */; }; + 88746BEE14CCA435001E160E /* JSEventHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 88746BED14CCA435001E160E /* JSEventHelper.m */; }; + 88C0646014BDE10A00E4BCE2 /* Window.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C0645F14BDE10A00E4BCE2 /* Window.m */; }; + 88C0646614BDEC5800E4BCE2 /* Window.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88C0646414BDEC5800E4BCE2 /* Window.xib */; }; + 88C0646D14BDF6A600E4BCE2 /* WindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C0646C14BDF6A600E4BCE2 /* WindowController.m */; }; + C14EFCA71B0986AF00894B5F /* ZeroTierIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = C14EFCA61B0986AF00894B5F /* ZeroTierIcon.icns */; }; + C1C2B9911AFB0CF10060D7C2 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1C2B9901AFB0CF10060D7C2 /* Security.framework */; }; + F2B80016179E0FC100B069A8 /* Clipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = F2B80015179E0FC100B069A8 /* Clipboard.m */; }; + FA32509D14BA813600BF0781 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA32509C14BA813600BF0781 /* WebKit.framework */; }; + FA3250C314BA85E700BF0781 /* ContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250BC14BA85E700BF0781 /* ContentView.m */; }; + FA3250C514BA85E700BF0781 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250BE14BA85E700BF0781 /* Utils.m */; }; + FA3250C714BA85E700BF0781 /* WebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250C014BA85E700BF0781 /* WebViewDelegate.m */; }; + FA3250D314BA860800BF0781 /* App.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250C914BA860800BF0781 /* App.m */; }; + FA3250D514BA860800BF0781 /* Dock.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CB14BA860800BF0781 /* Dock.m */; }; + FA3250D914BA860800BF0781 /* Path.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CF14BA860800BF0781 /* Path.m */; }; + FA3250DB14BA860800BF0781 /* Sound.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250D114BA860800BF0781 /* Sound.m */; }; + FA3F7742168F70790027B324 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA3F7741168F70780027B324 /* Cocoa.framework */; }; + FAE451C914BA79C600190544 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAE451C714BA79C600190544 /* InfoPlist.strings */; }; + FAE451CB14BA79C600190544 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE451CA14BA79C600190544 /* main.m */; }; + FAE451CF14BA79C600190544 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = FAE451CD14BA79C600190544 /* Credits.rtf */; }; + FAE451D214BA79C600190544 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE451D114BA79C600190544 /* AppDelegate.m */; }; + FAE451D514BA79C600190544 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAE451D314BA79C600190544 /* MainMenu.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + FA3250DD14BA876F00BF0781 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1495814D15C15CCC00E1CFE5 /* Notice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Notice.h; path = Classes/Commands/Notice.h; sourceTree = ""; }; + 1495814E15C15CCC00E1CFE5 /* Notice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Notice.m; path = Classes/Commands/Notice.m; sourceTree = ""; }; + 6F169DA518CC332E005EDDF3 /* Command.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Command.h; path = Classes/Commands/Command.h; sourceTree = ""; }; + 6F169DA618CC332E005EDDF3 /* Command.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Command.m; path = Classes/Commands/Command.m; sourceTree = ""; }; + 6F169DA818CC35FD005EDDF3 /* CallbackDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallbackDelegate.h; path = Classes/CallbackDelegate.h; sourceTree = ""; }; + 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CallbackDelegate.m; path = Classes/CallbackDelegate.m; sourceTree = ""; }; + 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + 6F169DAD18CD906F005EDDF3 /* MenuItemProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuItemProxy.h; path = Classes/Commands/MenuItemProxy.h; sourceTree = ""; }; + 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuItemProxy.m; path = Classes/Commands/MenuItemProxy.m; sourceTree = ""; }; + 6F169DAF18CD906F005EDDF3 /* MenuProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuProxy.h; path = Classes/Commands/MenuProxy.h; sourceTree = ""; }; + 6F169DB018CD906F005EDDF3 /* MenuProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuProxy.m; path = Classes/Commands/MenuProxy.m; sourceTree = ""; }; + 6FD672B418FE618E00C0DAAD /* UserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserDefaults.h; path = Classes/Commands/UserDefaults.h; sourceTree = ""; }; + 6FD672B518FE618E00C0DAAD /* UserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UserDefaults.m; path = Classes/Commands/UserDefaults.m; sourceTree = ""; }; + 6FD6E4EB18C2D48200DFFBE6 /* fonts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fonts.h; path = Classes/Commands/fonts.h; sourceTree = ""; }; + 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = fonts.m; path = Classes/Commands/fonts.m; sourceTree = ""; }; + 88746BEC14CCA435001E160E /* JSEventHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSEventHelper.h; path = Classes/JSEventHelper.h; sourceTree = ""; }; + 88746BED14CCA435001E160E /* JSEventHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSEventHelper.m; path = Classes/JSEventHelper.m; sourceTree = ""; }; + 88C0645E14BDE10A00E4BCE2 /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Window.h; path = Classes/Window.h; sourceTree = ""; }; + 88C0645F14BDE10A00E4BCE2 /* Window.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Window.m; path = Classes/Window.m; sourceTree = ""; }; + 88C0646514BDEC5800E4BCE2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Window.xib; sourceTree = ""; }; + 88C0646B14BDF6A600E4BCE2 /* WindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowController.h; sourceTree = ""; }; + 88C0646C14BDF6A600E4BCE2 /* WindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WindowController.m; sourceTree = ""; }; + C14EFCA61B0986AF00894B5F /* ZeroTierIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ZeroTierIcon.icns; path = ../../../../artwork/ZeroTierIcon.icns; sourceTree = ""; }; + C1C2B9901AFB0CF10060D7C2 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + F2B80014179E0FC100B069A8 /* Clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clipboard.h; sourceTree = ""; }; + F2B80015179E0FC100B069A8 /* Clipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Clipboard.m; sourceTree = ""; }; + FA32509C14BA813600BF0781 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + FA3250BA14BA85E700BF0781 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = Classes/Constants.h; sourceTree = ""; }; + FA3250BB14BA85E700BF0781 /* ContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ContentView.h; path = Classes/ContentView.h; sourceTree = ""; }; + FA3250BC14BA85E700BF0781 /* ContentView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ContentView.m; path = Classes/ContentView.m; sourceTree = ""; }; + FA3250BD14BA85E700BF0781 /* Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = Classes/Utils.h; sourceTree = ""; }; + FA3250BE14BA85E700BF0781 /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Utils.m; path = Classes/Utils.m; sourceTree = ""; }; + FA3250BF14BA85E700BF0781 /* WebViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebViewDelegate.h; path = Classes/WebViewDelegate.h; sourceTree = ""; }; + FA3250C014BA85E700BF0781 /* WebViewDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WebViewDelegate.m; path = Classes/WebViewDelegate.m; sourceTree = ""; }; + FA3250C814BA860800BF0781 /* App.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = App.h; path = Classes/Commands/App.h; sourceTree = ""; }; + FA3250C914BA860800BF0781 /* App.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = App.m; path = Classes/Commands/App.m; sourceTree = ""; }; + FA3250CA14BA860800BF0781 /* Dock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Dock.h; path = Classes/Commands/Dock.h; sourceTree = ""; }; + FA3250CB14BA860800BF0781 /* Dock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Dock.m; path = Classes/Commands/Dock.m; sourceTree = ""; }; + FA3250CE14BA860800BF0781 /* Path.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Path.h; path = Classes/Commands/Path.h; sourceTree = ""; }; + FA3250CF14BA860800BF0781 /* Path.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Path.m; path = Classes/Commands/Path.m; sourceTree = ""; }; + FA3250D014BA860800BF0781 /* Sound.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Sound.h; path = Classes/Commands/Sound.h; sourceTree = ""; }; + FA3250D114BA860800BF0781 /* Sound.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Sound.m; path = Classes/Commands/Sound.m; sourceTree = ""; }; + FA3F7741168F70780027B324 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; + FAE451BA14BA79C600190544 /* ZeroTier One.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ZeroTier One.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + FAE451BE14BA79C600190544 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + FAE451C114BA79C600190544 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + FAE451C214BA79C600190544 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + FAE451C314BA79C600190544 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + FAE451C614BA79C600190544 /* MacGap-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MacGap-Info.plist"; sourceTree = ""; }; + FAE451C814BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + FAE451CA14BA79C600190544 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + FAE451CC14BA79C600190544 /* MacGap-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MacGap-Prefix.pch"; sourceTree = ""; }; + FAE451CE14BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; + FAE451D014BA79C600190544 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + FAE451D114BA79C600190544 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + FAE451D414BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FAE451B714BA79C600190544 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C1C2B9911AFB0CF10060D7C2 /* Security.framework in Frameworks */, + 6F169DAC18CD8A4A005EDDF3 /* JavaScriptCore.framework in Frameworks */, + FA3F7742168F70790027B324 /* Cocoa.framework in Frameworks */, + FA32509D14BA813600BF0781 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FA3250E014BA87B800BF0781 /* Classes */ = { + isa = PBXGroup; + children = ( + FA3250E114BA87DD00BF0781 /* Commands */, + FA3250BA14BA85E700BF0781 /* Constants.h */, + 6F169DA818CC35FD005EDDF3 /* CallbackDelegate.h */, + 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */, + FA3250BB14BA85E700BF0781 /* ContentView.h */, + FA3250BC14BA85E700BF0781 /* ContentView.m */, + FA3250BF14BA85E700BF0781 /* WebViewDelegate.h */, + FA3250C014BA85E700BF0781 /* WebViewDelegate.m */, + 88C0646B14BDF6A600E4BCE2 /* WindowController.h */, + 88C0646C14BDF6A600E4BCE2 /* WindowController.m */, + ); + name = Classes; + sourceTree = ""; + }; + FA3250E114BA87DD00BF0781 /* Commands */ = { + isa = PBXGroup; + children = ( + 6F169DA518CC332E005EDDF3 /* Command.h */, + 6F169DA618CC332E005EDDF3 /* Command.m */, + 1495814D15C15CCC00E1CFE5 /* Notice.h */, + 1495814E15C15CCC00E1CFE5 /* Notice.m */, + FA3250CA14BA860800BF0781 /* Dock.h */, + FA3250CB14BA860800BF0781 /* Dock.m */, + 6FD6E4EB18C2D48200DFFBE6 /* fonts.h */, + 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */, + FA3250BD14BA85E700BF0781 /* Utils.h */, + FA3250BE14BA85E700BF0781 /* Utils.m */, + 6FD672B418FE618E00C0DAAD /* UserDefaults.h */, + 6FD672B518FE618E00C0DAAD /* UserDefaults.m */, + FA3250CE14BA860800BF0781 /* Path.h */, + FA3250CF14BA860800BF0781 /* Path.m */, + FA3250D014BA860800BF0781 /* Sound.h */, + FA3250D114BA860800BF0781 /* Sound.m */, + FA3250C814BA860800BF0781 /* App.h */, + FA3250C914BA860800BF0781 /* App.m */, + 6F169DAD18CD906F005EDDF3 /* MenuItemProxy.h */, + 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */, + 6F169DAF18CD906F005EDDF3 /* MenuProxy.h */, + 6F169DB018CD906F005EDDF3 /* MenuProxy.m */, + 88C0645E14BDE10A00E4BCE2 /* Window.h */, + 88C0645F14BDE10A00E4BCE2 /* Window.m */, + 88746BEC14CCA435001E160E /* JSEventHelper.h */, + 88746BED14CCA435001E160E /* JSEventHelper.m */, + F2B80014179E0FC100B069A8 /* Clipboard.h */, + F2B80015179E0FC100B069A8 /* Clipboard.m */, + ); + name = Commands; + sourceTree = ""; + }; + FAE451AF14BA79C600190544 = { + isa = PBXGroup; + children = ( + FA3F7741168F70780027B324 /* Cocoa.framework */, + FAE451C414BA79C600190544 /* MacGap */, + FAE451BD14BA79C600190544 /* Frameworks */, + FAE451BB14BA79C600190544 /* Products */, + ); + sourceTree = ""; + }; + FAE451BB14BA79C600190544 /* Products */ = { + isa = PBXGroup; + children = ( + FAE451BA14BA79C600190544 /* ZeroTier One.app */, + ); + name = Products; + sourceTree = ""; + }; + FAE451BD14BA79C600190544 /* Frameworks */ = { + isa = PBXGroup; + children = ( + C1C2B9901AFB0CF10060D7C2 /* Security.framework */, + 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */, + FA32509C14BA813600BF0781 /* WebKit.framework */, + FAE451BE14BA79C600190544 /* Cocoa.framework */, + FAE451C014BA79C600190544 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + FAE451C014BA79C600190544 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + FAE451C114BA79C600190544 /* AppKit.framework */, + FAE451C214BA79C600190544 /* CoreData.framework */, + FAE451C314BA79C600190544 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + FAE451C414BA79C600190544 /* MacGap */ = { + isa = PBXGroup; + children = ( + FA3250E014BA87B800BF0781 /* Classes */, + FAE451D014BA79C600190544 /* AppDelegate.h */, + FAE451D114BA79C600190544 /* AppDelegate.m */, + C14EFCA61B0986AF00894B5F /* ZeroTierIcon.icns */, + FAE451D314BA79C600190544 /* MainMenu.xib */, + 88C0646414BDEC5800E4BCE2 /* Window.xib */, + FAE451C514BA79C600190544 /* Supporting Files */, + ); + path = MacGap; + sourceTree = ""; + }; + FAE451C514BA79C600190544 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + FAE451C614BA79C600190544 /* MacGap-Info.plist */, + FAE451C714BA79C600190544 /* InfoPlist.strings */, + FAE451CA14BA79C600190544 /* main.m */, + FAE451CC14BA79C600190544 /* MacGap-Prefix.pch */, + FAE451CD14BA79C600190544 /* Credits.rtf */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FAE451B914BA79C600190544 /* MacGap */ = { + isa = PBXNativeTarget; + buildConfigurationList = FAE451D814BA79C600190544 /* Build configuration list for PBXNativeTarget "MacGap" */; + buildPhases = ( + FAE451B814BA79C600190544 /* Resources */, + FAE451B614BA79C600190544 /* Sources */, + FAE451B714BA79C600190544 /* Frameworks */, + FA3250DD14BA876F00BF0781 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MacGap; + productName = MacGap; + productReference = FAE451BA14BA79C600190544 /* ZeroTier One.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FAE451B114BA79C600190544 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + ORGANIZATIONNAME = Twitter; + }; + buildConfigurationList = FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = FAE451AF14BA79C600190544; + productRefGroup = FAE451BB14BA79C600190544 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FAE451B914BA79C600190544 /* MacGap */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + FAE451B814BA79C600190544 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C14EFCA71B0986AF00894B5F /* ZeroTierIcon.icns in Resources */, + FAE451C914BA79C600190544 /* InfoPlist.strings in Resources */, + FAE451CF14BA79C600190544 /* Credits.rtf in Resources */, + FAE451D514BA79C600190544 /* MainMenu.xib in Resources */, + 88C0646614BDEC5800E4BCE2 /* Window.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FAE451B614BA79C600190544 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F169DAA18CC35FD005EDDF3 /* CallbackDelegate.m in Sources */, + FA3250D314BA860800BF0781 /* App.m in Sources */, + FA3250D514BA860800BF0781 /* Dock.m in Sources */, + FA3250D914BA860800BF0781 /* Path.m in Sources */, + FA3250DB14BA860800BF0781 /* Sound.m in Sources */, + FA3250C314BA85E700BF0781 /* ContentView.m in Sources */, + FA3250C514BA85E700BF0781 /* Utils.m in Sources */, + FA3250C714BA85E700BF0781 /* WebViewDelegate.m in Sources */, + FAE451CB14BA79C600190544 /* main.m in Sources */, + 6F169DB118CD906F005EDDF3 /* MenuItemProxy.m in Sources */, + FAE451D214BA79C600190544 /* AppDelegate.m in Sources */, + 6F169DA718CC332E005EDDF3 /* Command.m in Sources */, + 6FD672B618FE618E00C0DAAD /* UserDefaults.m in Sources */, + 88C0646014BDE10A00E4BCE2 /* Window.m in Sources */, + 6F169DB218CD906F005EDDF3 /* MenuProxy.m in Sources */, + 88C0646D14BDF6A600E4BCE2 /* WindowController.m in Sources */, + 6FD6E4ED18C2D48C00DFFBE6 /* fonts.m in Sources */, + 88746BEE14CCA435001E160E /* JSEventHelper.m in Sources */, + 1495814F15C15CCC00E1CFE5 /* Notice.m in Sources */, + F2B80016179E0FC100B069A8 /* Clipboard.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 88C0646414BDEC5800E4BCE2 /* Window.xib */ = { + isa = PBXVariantGroup; + children = ( + 88C0646514BDEC5800E4BCE2 /* en */, + ); + name = Window.xib; + sourceTree = ""; + }; + FAE451C714BA79C600190544 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + FAE451C814BA79C600190544 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + FAE451CD14BA79C600190544 /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + FAE451CE14BA79C600190544 /* en */, + ); + name = Credits.rtf; + sourceTree = ""; + }; + FAE451D314BA79C600190544 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + FAE451D414BA79C600190544 /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + FAE451D614BA79C600190544 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "ZeroTier One"; + SDKROOT = ""; + }; + name = Debug; + }; + FAE451D714BA79C600190544 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "ZeroTier One"; + SDKROOT = ""; + }; + name = Release; + }; + FAE451D914BA79C600190544 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/MacGap\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "MacGap/MacGap-Prefix.pch"; + GCC_VERSION = ""; + INFOPLIST_FILE = "MacGap/MacGap-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "ZeroTier One"; + SDKROOT = macosx; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + FAE451DA14BA79C600190544 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/MacGap\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "MacGap/MacGap-Prefix.pch"; + GCC_VERSION = ""; + INFOPLIST_FILE = "MacGap/MacGap-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "ZeroTier One"; + SDKROOT = macosx; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FAE451D614BA79C600190544 /* Debug */, + FAE451D714BA79C600190544 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FAE451D814BA79C600190544 /* Build configuration list for PBXNativeTarget "MacGap" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FAE451D914BA79C600190544 /* Debug */, + FAE451DA14BA79C600190544 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FAE451B114BA79C600190544 /* Project object */; +} diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..88f36fc7b --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout new file mode 100644 index 000000000..7fdde8531 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 4D486E78-E297-4CC3-AAAE-1A58EDAC87E6 + IDESourceControlProjectName + MacGap + IDESourceControlProjectOriginsDictionary + + ABA3617E9F0148F844A82502F0D808DE6591AA97 + http://adam.ierymenko@git.int.zerotier.com/zerotier/zerotierone + + IDESourceControlProjectPath + ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + ABA3617E9F0148F844A82502F0D808DE6591AA97 + ../../../../.. + + IDESourceControlProjectURL + http://adam.ierymenko@git.int.zerotier.com/zerotier/zerotierone + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + ABA3617E9F0148F844A82502F0D808DE6591AA97 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + ABA3617E9F0148F844A82502F0D808DE6591AA97 + IDESourceControlWCCName + ZeroTierOne + + + + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 000000000..20281812b Binary files /dev/null and b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/WorkspaceSettings.xcsettings b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..659c8766e --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + SnapshotAutomaticallyBeforeSignificantChanges + + + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 000000000..822ed3cb6 Binary files /dev/null and b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..6ff33e603 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges + + + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.h new file mode 100644 index 000000000..bf7370b50 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.h @@ -0,0 +1,18 @@ +// +// AppDelegate.h +// MacGap +// +// Created by Alex MacCaw on 08/01/2012. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import "Classes/ContentView.h" + +#import "WindowController.h" + +@interface AppDelegate : NSObject + +@property (retain, nonatomic) WindowController *windowController; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m new file mode 100644 index 000000000..45923bb36 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m @@ -0,0 +1,159 @@ +// +// AppDelegate.m +// MacGap +// +// Created by Alex MacCaw on 08/01/2012. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "AppDelegate.h" +#include +#include + +@implementation AppDelegate + +@synthesize windowController; + +- (void) applicationWillFinishLaunching:(NSNotification *)aNotification +{ +} + +-(BOOL)applicationShouldHandleReopen:(NSApplication*)application + hasVisibleWindows:(BOOL)visibleWindows{ + if(!visibleWindows){ + [self.windowController.window makeKeyAndOrderFront: nil]; + } + return YES; +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { + return YES; +} + +- (void) applicationDidFinishLaunching:(NSNotification *)aNotification { + char buf[16384],userAuthTokenPath[4096]; + struct stat systemAuthTokenStat,userAuthTokenStat; + + FILE *pf = fopen("/Library/Application Support/ZeroTier/One/zerotier-one.port","r"); + long port = 9993; // default + if (pf) { + long n = fread(buf,1,sizeof(buf)-1,pf); + if (n > 0) { + buf[n] = (char)0; + port = strtol(buf,(char **)0,10); + } + fclose(pf); + } + + char url[16384]; + memset(url,0,sizeof(url)); + + const char *homeDir = getenv("HOME"); + if (homeDir) { + snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",homeDir); + + bool userAuthTokenOutOfDate = false; + memset(&systemAuthTokenStat,0,sizeof(systemAuthTokenStat)); + memset(&userAuthTokenStat,0,sizeof(userAuthTokenStat)); + if (stat("/Library/Application Support/ZeroTier/One/authtoken.secret",&systemAuthTokenStat) == 0) { + if (stat(userAuthTokenPath,&userAuthTokenStat) == 0) { + if (userAuthTokenStat.st_mtimespec.tv_sec < systemAuthTokenStat.st_mtimespec.tv_sec) + userAuthTokenOutOfDate = true; + } + } + + if (!userAuthTokenOutOfDate) { + pf = fopen(userAuthTokenPath,"r"); + if (pf) { + long n = fread(buf,1,sizeof(buf)-1,pf); + if (n > 0) { + buf[n] = (char)0; + snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf); + } + fclose(pf); + } + } + } + + if (!url[0]) { + // Create authorization reference + OSStatus status; + AuthorizationRef authorizationRef; + + // AuthorizationCreate and pass NULL as the initial + // AuthorizationRights set so that the AuthorizationRef gets created + // successfully, and then later call AuthorizationCopyRights to + // determine or extend the allowable rights. + // http://developer.apple.com/qa/qa2001/qa1172.html + status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); + if (status != errAuthorizationSuccess) + { + NSLog(@"Error Creating Initial Authorization: %d", status); + return; + } + + // kAuthorizationRightExecute == "system.privilege.admin" + AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0}; + AuthorizationRights rights = {1, &right}; + AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights; + + // Call AuthorizationCopyRights to determine or extend the allowable rights. + status = AuthorizationCopyRights(authorizationRef, &rights, NULL, flags, NULL); + if (status != errAuthorizationSuccess) + { + NSLog(@"Copy Rights Unsuccessful: %d", status); + return; + } + + // use rm tool with -rf + char *tool = "/bin/cat"; + char *args[] = {"/Library/Application Support/ZeroTier/One/authtoken.secret", NULL}; + FILE *pipe = NULL; + + status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe); + if (status != errAuthorizationSuccess) + { + NSLog(@"Error: %d", status); + } + + if (pipe) { + long n = (long)fread(buf,1,sizeof(buf)-1,pipe); + if (n > 0) { + buf[n] = (char)0; + snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf); + + if (homeDir) { + snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier",homeDir); + mkdir(userAuthTokenPath,0755); + snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One",homeDir); + mkdir(userAuthTokenPath,0755); + snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",homeDir); + pf = fopen(userAuthTokenPath,"w"); + if (pf) { + fwrite(buf,1,strlen(buf),pf); + fclose(pf); + chmod(userAuthTokenPath,0600); + } + } + } + fclose(pipe); + } + + // The only way to guarantee that a credential acquired when you + // request a right is not shared with other authorization instances is + // to destroy the credential. To do so, call the AuthorizationFree + // function with the flag kAuthorizationFlagDestroyRights. + // http://developer.apple.com/documentation/Security/Conceptual/authorization_concepts/02authconcepts/chapter_2_section_7.html + status = AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); + } + + NSString *urlStr = [[NSString alloc] initWithCString:url]; + self.windowController = [[WindowController alloc] initWithURL: urlStr]; + [self.windowController showWindow: [NSApplication sharedApplication].delegate]; + self.windowController.contentView.webView.alphaValue = 1.0; + self.windowController.contentView.alphaValue = 1.0; + [self.windowController showWindow:self]; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.h new file mode 100755 index 000000000..0f31ee417 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.h @@ -0,0 +1,20 @@ +// +// CallbackDelegate.h +// MacGap +// +// Created by Joe Hildebrand on 1/10/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Command.h" + +@interface CallbackDelegate : Command { +} + +@property JSObjectRef callback; + +- (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback; +- (id) call; +- (id) callWithParams:(id)firstOrNil, ... NS_REQUIRES_NIL_TERMINATION; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.m new file mode 100755 index 000000000..5ce8fbe33 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.m @@ -0,0 +1,168 @@ +// +// CallbackDelegate.m +// MacGap +// +// Created by Joe Hildebrand on 1/10/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "CallbackDelegate.h" +#import + +@implementation CallbackDelegate + +@synthesize callback; + +- (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback +{ + if (!aCallback) + return nil; + if ([aCallback isKindOfClass:[WebUndefined class]]) + return nil; + + self = [super initWithContext:aContext]; + if (!self) + return nil; + + callback = [aCallback JSObject]; + JSValueProtect(context, callback); + return self; +} + +- (void) dealloc +{ + if (callback) + { + JSValueUnprotect(context, callback); + callback = nil; + } +} + +- (id) objectFromValue:(JSValueRef)val +{ + JSStringRef jstr; + NSString *rets; + + switch(JSValueGetType(context, val)) + { + case kJSTypeUndefined: + case kJSTypeNull: + return nil; + case kJSTypeBoolean: + return [NSNumber numberWithBool:JSValueToBoolean(context, val)]; + case kJSTypeNumber: + return [NSNumber numberWithDouble:JSValueToNumber(context, val, NULL)]; + case kJSTypeString: + jstr = JSValueToStringCopy(context, val, NULL); + size_t sz = JSStringGetMaximumUTF8CStringSize(jstr); + char *buf = (char*)malloc(sz); + JSStringGetUTF8CString(jstr, buf, sz); + rets = [NSString stringWithUTF8String:buf]; + free(buf); + return rets; + case kJSTypeObject: + // TODO: dictionary or something + return nil; + default: + NSAssert(false, @"Invalid JavaScript type"); + return nil; + } +} + +- (JSValueRef) valueFromObject:(id)obj +{ + JSValueRef val = nil; + if (!obj) + { + val = JSValueMakeNull(context); + } + else if ([obj isKindOfClass:[NSString class]]) + { + JSStringRef jstr = JSStringCreateWithUTF8CString([obj UTF8String]); + val = JSValueMakeString(context, jstr); + JSStringRelease(jstr); + } + else if ([obj isKindOfClass:[NSNumber class]]) + { + val = JSValueMakeNumber(context, [obj doubleValue]); + } + else if ([obj isKindOfClass:[NSDictionary class]]) + { + JSObjectRef o = JSObjectMake(context, NULL, NULL); + for (NSString *key in obj) + { + JSStringRef kstr = JSStringCreateWithUTF8CString([key UTF8String]); + JSValueRef v = [self valueFromObject:[obj objectForKey:key]]; + + JSObjectSetProperty(context, o, kstr, v, kJSPropertyAttributeNone, NULL); + JSStringRelease(kstr); + } + val = o; + } + else if ([obj isKindOfClass:[NSArray class]]) + { + NSUInteger pcount = [obj count]; + JSValueRef jsArgs[pcount]; + NSUInteger i=0; + for (id v in obj) + { + jsArgs[i++] = [self valueFromObject:v]; + } + val = JSObjectMakeArray(context, pcount, jsArgs, NULL); + } + else if ([obj isKindOfClass:[NSDate class]]) + { + NSTimeInterval secs = [obj timeIntervalSince1970]; + JSValueRef jsArgs[1]; + // call the Date(milliseconds) constructor in JS + jsArgs[0] = JSValueMakeNumber(context, secs * 1000.0); + val = JSObjectMakeDate(context, 1, jsArgs, NULL); + } + else + { + NSLog(@"Warning: unknown object type for: %@", obj); + val = JSValueMakeUndefined(context); + } + return val; +} + +- (id) call +{ + NSAssert(callback, @"Callback required"); + if (!JSObjectIsFunction(context, callback)) + return nil; + + JSValueRef jsArgs[0]; + JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, 0, jsArgs, NULL); + return [self objectFromValue:ret]; +} + +- (id) callWithParams:(id)firstOrNil, ... +{ + NSAssert(callback, @"Callback required"); + if (!JSObjectIsFunction(context, callback)) + return nil; + NSUInteger pcount = 0; + id p; + va_list args; + va_start(args, firstOrNil); + for (p=firstOrNil; p; p=va_arg(args, id)) + { + pcount++; + } + va_end(args); + + JSValueRef jsArgs[pcount]; + NSUInteger j = 0; + va_start(args, firstOrNil); + for (p=firstOrNil; p; p=va_arg(args, id)) + { + jsArgs[j++] = [self valueFromObject:p]; + } + va_end(args); + + JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, j, jsArgs, NULL); + return [self objectFromValue:ret]; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.h new file mode 100644 index 000000000..f65ba61e1 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.h @@ -0,0 +1,21 @@ +#import + +#import "WindowController.h" + +@interface App : NSObject { + +} + +@property (nonatomic, retain) WebView *webView; + +- (id) initWithWebView:(WebView *)view; + +- (void) terminate; +- (void) activate; +- (void) hide; +- (void) unhide; +- (void) beep; +- (void) bounce; +- (void) setCustomUserAgent:(NSString *)userAgentString; +- (NSNumber*) systemIdleTime; +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.m new file mode 100644 index 000000000..6d47a17e1 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.m @@ -0,0 +1,128 @@ +#import "App.h" + +#import "JSEventHelper.h" + +@implementation App + +@synthesize webView; + +- (id) initWithWebView:(WebView *) view{ + self = [super init]; + + if (self) { + self.webView = view; + [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self + selector: @selector(receiveSleepNotification:) + name: NSWorkspaceWillSleepNotification object: NULL]; + [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self + selector: @selector(receiveWakeNotification:) + name: NSWorkspaceDidWakeNotification object: NULL]; + [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self + selector: @selector(receiveActivateNotification:) + name: NSWorkspaceDidActivateApplicationNotification object: NULL]; + } + + return self; +} + +- (void) terminate { + [NSApp terminate:nil]; +} + +- (void) activate { + [NSApp activateIgnoringOtherApps:YES]; +} + +- (void) hide { + [NSApp hide:nil]; +} + +- (void) unhide { + [NSApp unhide:nil]; +} + +- (void)beep { + NSBeep(); +} + +- (void) bounce { + [NSApp requestUserAttention:NSInformationalRequest]; +} + +- (void)setCustomUserAgent:(NSString *)userAgentString { + [self.webView setCustomUserAgent: userAgentString]; +} + +- (void) open:(NSString*)url { + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]]; +} + +- (void) launch:(NSString *)name { + [[NSWorkspace sharedWorkspace] launchApplication:name]; +} + +- (void)receiveSleepNotification:(NSNotification*)note{ + [JSEventHelper triggerEvent:@"sleep" forWebView:self.webView]; +} + +- (void) receiveWakeNotification:(NSNotification*)note{ + [JSEventHelper triggerEvent:@"wake" forWebView:self.webView]; +} + +- (void) receiveActivateNotification:(NSNotification*)notification{ + NSDictionary* userInfo = [notification userInfo]; + NSRunningApplication* runningApplication = [userInfo objectForKey:NSWorkspaceApplicationKey]; + if (runningApplication) { + NSMutableDictionary* applicationDidGetFocusDict = [[NSMutableDictionary alloc] initWithCapacity:2]; + [applicationDidGetFocusDict setObject:runningApplication.localizedName + forKey:@"localizedName"]; + [applicationDidGetFocusDict setObject:[runningApplication.bundleURL absoluteString] + forKey:@"bundleURL"]; + + [JSEventHelper triggerEvent:@"appActivated" withArgs:applicationDidGetFocusDict forWebView:self.webView]; + } +} + + + + +/* + To get the elapsed time since the previous input event—keyboard, mouse, or tablet—specify kCGAnyInputEventType. + */ +- (NSNumber*)systemIdleTime { + CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType); + + return [NSNumber numberWithDouble:timeSinceLastEvent]; +} + + + + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(open:)) { + result = @"open"; + } else if (selector == @selector(launch:)) { + result = @"launch"; + } else if (selector == @selector(setCustomUserAgent:)) { + result = @"setCustomUserAgent"; + } else if (selector == @selector(systemIdleTime)) { + result = @"systemIdleTime"; + } + + return result; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.h new file mode 100755 index 000000000..65d6b6d48 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.h @@ -0,0 +1,18 @@ +// +// Command.h +// MacGap +// +// Created by Joe Hildebrand on 1/10/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import + +@interface Command : NSObject { + JSContextRef context; +} + +- (id) initWithContext:(JSContextRef)aContext; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.m new file mode 100755 index 000000000..39b85630a --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.m @@ -0,0 +1,28 @@ +// +// Command.m +// MacGap +// +// Created by Joe Hildebrand on 1/10/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Command.h" +#import + +@implementation Command + +- (id) initWithContext:(JSContextRef)aContext { + self = [super init]; + if (!self) + return nil; + context = aContext; + JSGlobalContextRetain((JSGlobalContextRef)context); + return self; +} + +- (void)dealloc +{ + if (context) + JSGlobalContextRelease((JSGlobalContextRef)context); +} +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.h new file mode 100644 index 000000000..b3c533d79 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.h @@ -0,0 +1,11 @@ +#import + +@interface Dock : NSObject { + +} +- (void) setBadge:(NSString*)value; +- (NSString *) badge; + +@property (readwrite, copy) NSString *badge; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.m new file mode 100644 index 000000000..a4494d165 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.m @@ -0,0 +1,31 @@ +#import "Dock.h" + +@implementation Dock + +@synthesize badge; + +- (void) setBadge:(NSString *)value +{ + NSDockTile *tile = [[NSApplication sharedApplication] dockTile]; + [tile setBadgeLabel:value]; +} + +- (NSString *) badge +{ + NSDockTile *tile = [[NSApplication sharedApplication] dockTile]; + return [tile badgeLabel]; +} + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return NO; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.h new file mode 100755 index 000000000..d765978fa --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.h @@ -0,0 +1,31 @@ +// +// MenuItemProxy.h +// MacGap +// +// Created by Joe Hildebrand on 1/15/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Command.h" +#import "CallbackDelegate.h" + +@class MenuProxy; + +@interface MenuItemProxy : Command { + NSMenuItem *item; + CallbackDelegate *callback; +} + ++ (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem; + +- (MenuProxy*)addSubmenu; + +- (void) remove; +- (void) setCallback:(WebScriptObject*)aCallback; +- (void) setKey:(NSString*)keyCommand; +- (void) setTitle:(NSString*)title; +- (void) enable; +- (void) disable; +- (MenuProxy*)submenu; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.m new file mode 100755 index 000000000..7b9702cc4 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.m @@ -0,0 +1,150 @@ +// +// MenuItemProxy.m +// MacGap +// +// Created by Joe Hildebrand on 1/15/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "MenuItemProxy.h" +#import "MenuProxy.h" + +@implementation MenuItemProxy + +- (id) initWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem +{ + NSAssert(anItem, @"anItem required"); + self = [super initWithContext:aContext]; + if (!self) + return nil; + item = anItem; + item.representedObject = self; + + return self; +} + ++ (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem +{ + MenuItemProxy *proxy = [anItem representedObject]; + if (proxy) + { + NSLog(@"MIP Cache hit"); + NSAssert([proxy class] == [MenuItemProxy class], @"Bad proxy"); + return proxy; + } + return [[MenuItemProxy alloc] initWithContext:aContext andMenuItem:anItem]; +} + +- (NSString*) description +{ + return [item description]; +} + +- (MenuProxy*)addSubmenu +{ + NSMenu *s = [item submenu]; + if (!s) + { + s = [[NSMenu alloc] initWithTitle:@"FFFFFFOOOOO"]; + [item setSubmenu:s]; + } + return [MenuProxy proxyWithContext:context andMenu:s]; +} + +- (void) remove +{ + NSMenu *menu = [item menu]; + [menu removeItem:item]; +} + +- (void)callCallback:(id)sender +{ + [callback callWithParams:[sender title], nil]; +} + +- (void) setCallback:(WebScriptObject*)aCallback +{ + NSAssert(item, @"item required"); + callback = [[CallbackDelegate alloc] initWithContext:context forCallback:aCallback]; + [item setAction:@selector(callCallback:)]; + [item setTarget:self]; +} + +- (void)setKey:(NSString*)keyCommand +{ + NSString *aKey = [MenuProxy getKeyFromString:keyCommand]; + [item setKeyEquivalent:aKey]; + + NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand]; + [item setKeyEquivalentModifierMask:modifiers]; +} + +- (void) setTitle:(NSString*)title +{ + [item setTitle:title]; +} + +- (MenuProxy*)submenu; +{ + // TODO: make this work as a property + NSMenu *s = [item submenu]; + if (!s) + return nil; + return [MenuProxy proxyWithContext:context andMenu:s]; +} + +- (void) enable +{ + [item setEnabled:YES]; +} + +- (void) disable +{ + [item setEnabled:NO]; +} + +#pragma mark WebScripting protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return [self webScriptNameForSelector:selector] == nil; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(addSubmenu)) { + result = @"addSubmenu"; + } + else if (selector == @selector(remove)) { + result = @"remove"; + } + else if (selector == @selector(setCallback:)) { + result = @"setCallback"; + } + else if (selector == @selector(setKey:)) { + result = @"setKey"; + } + else if (selector == @selector(setTitle:)) { + result = @"setTitle"; + } + else if (selector == @selector(submenu)) { + result = @"submenu"; + } + else if (selector == @selector(enable)) { + result = @"enable"; + } + else if (selector == @selector(disable)) { + result = @"disable"; + } + + return result; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.h new file mode 100755 index 000000000..afd6c6edb --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.h @@ -0,0 +1,31 @@ +// +// MenuProxy.h +// MacGap +// +// Created by Joe Hildebrand on 1/14/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Command.h" + +@class MenuItemProxy; + +@interface MenuProxy : Command { + NSMenu *menu; +} + ++ (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu; + +- (MenuItemProxy*)addItemWithTitle:(NSString*)title + keyEquivalent:(NSString*)aKey + callback:(WebScriptObject*)aCallback + atIndex:(NSInteger)index; + +- (MenuItemProxy*)addSeparator; +- (MenuItemProxy*)itemForKey:(id)key; +- (MenuProxy*)removeItem:(id)key; + ++ (NSString*)getKeyFromString:(NSString*)keyCommand; ++ (NSUInteger*)getModifiersFromString:(NSString*)keyCommand; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.m new file mode 100755 index 000000000..5bc10a763 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.m @@ -0,0 +1,233 @@ +// +// MenuProxy.m +// MacGap +// +// Created by Joe Hildebrand on 1/14/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import + +#import "MenuProxy.h" +#import "MenuItemProxy.h" + +static char REPRESENTED_OBJECT; + +@interface NSMenu (represented) +@property (strong) id representedObject; +@end + +@implementation NSMenu (represented) + +- (id) representedObject +{ + return objc_getAssociatedObject(self, &REPRESENTED_OBJECT); +} + +- (void) setRepresentedObject:(id)representedObject +{ + objc_setAssociatedObject(self, + &REPRESENTED_OBJECT, + representedObject, + OBJC_ASSOCIATION_RETAIN); +} + +@end + +@implementation MenuProxy + +- (id) initWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu +{ + self = [super initWithContext:aContext]; + if (!self) + return nil; + menu = aMenu; + menu.representedObject = self; + return self; +} + ++ (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu +{ + // singleton-ish. + MenuProxy *ret = [aMenu representedObject]; + if (ret) + { + NSLog(@"MP cache hit"); + return ret; + } + return [[MenuProxy alloc] initWithContext:aContext andMenu:aMenu]; +} + +- (void) dealloc +{ + menu.representedObject = nil; +} + +- (NSString*) description +{ + return [menu description]; +} + +static BOOL isNullish(id o) +{ + if (!o) + return YES; + if ([o isKindOfClass:[WebUndefined class]]) + return YES; + return NO; +} + +- (MenuItemProxy*)addItemWithTitle:(NSString*)title + keyEquivalent:(NSString*)keyCommand + callback:(WebScriptObject*)aCallback + atIndex:(NSInteger)index +{ + if (isNullish(title)) + title = @""; + + NSString *aKey = [MenuProxy getKeyFromString:keyCommand]; + NSMenuItem *item = nil; + + if(index) { + item = [menu insertItemWithTitle:title action:nil keyEquivalent:aKey atIndex:index ]; + } else { + item = [menu addItemWithTitle:title action:nil keyEquivalent:aKey ]; + + } + + // Set the modifiers. + NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand]; + [item setKeyEquivalentModifierMask:modifiers]; + + if(!menu.supermenu) { + NSMenu *s = [[NSMenu alloc] initWithTitle:title]; + [item setSubmenu:s]; + } + + MenuItemProxy *mip = [MenuItemProxy proxyWithContext:context andMenuItem:item]; + if (!isNullish(aCallback)) + [mip setCallback:aCallback]; + + + return mip; +} + ++ (NSString*)getKeyFromString:(NSString*)keyCommand { + if (isNullish(keyCommand)) + keyCommand = @""; + + // Obtain the key (if there are modifiers, it will be the last character). + NSString *aKey = @""; + if ([keyCommand length] > 0) { + aKey = [keyCommand substringFromIndex:[keyCommand length] - 1]; + } + + return aKey; +} + ++ (NSUInteger*)getModifiersFromString:(NSString*)keyCommand { + // aKeys may optionally specify one or more modifiers. + NSUInteger modifiers = 0; + + if ([keyCommand rangeOfString:@"caps"].location != NSNotFound) modifiers += NSAlphaShiftKeyMask; + if ([keyCommand rangeOfString:@"shift"].location != NSNotFound) modifiers += NSShiftKeyMask; + if ([keyCommand rangeOfString:@"cmd"].location != NSNotFound) modifiers += NSCommandKeyMask; + if ([keyCommand rangeOfString:@"ctrl"].location != NSNotFound) modifiers += NSControlKeyMask; + if ([keyCommand rangeOfString:@"opt"].location != NSNotFound) modifiers += NSAlternateKeyMask; + if ([keyCommand rangeOfString:@"alt"].location != NSNotFound) modifiers += NSAlternateKeyMask; + + return modifiers; +} + +- (MenuItemProxy*)addSeparator +{ + NSMenuItem *sep = [NSMenuItem separatorItem]; + [menu addItem:sep]; + return [MenuItemProxy proxyWithContext:context andMenuItem:sep]; +} + +- (MenuItemProxy*)itemForKey:(id)key +{ + if (isNullish(key)) + return nil; + NSMenuItem *item = nil; + if ([key isKindOfClass:[NSNumber class]]) + { + item = [menu itemAtIndex:[key intValue]]; + } + else if ([key isKindOfClass:[NSString class]]) + { + item = [menu itemWithTitle:key]; + if (!item) + { + // Try again, with ... appended. e.g. "Save..." + item = [menu itemWithTitle: + [key stringByAppendingString:@"\u2026"]]; + } + } + if (!item) + return nil; + + return [MenuItemProxy proxyWithContext:context andMenuItem:item]; +} + +- (MenuProxy*)removeItem:(id)key +{ + if (isNullish(key)) + return nil; + + NSMenuItem *item = nil; + if ([key isKindOfClass:[NSNumber class]]) + { + item = [menu itemAtIndex:[key intValue]]; + } + else if ([key isKindOfClass:[NSString class]]) + { + item = [menu itemWithTitle:key]; + if (!item) + { + // Try again, with ... appended. e.g. "Save..." + item = [menu itemWithTitle: + [key stringByAppendingString:@"\u2026"]]; + } + } + if (!item) + return nil; + + [menu removeItem:item]; + return [MenuProxy proxyWithContext:context andMenu:menu]; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return [self webScriptNameForSelector:selector] == nil; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(addItemWithTitle:keyEquivalent:callback:atIndex:)) { + result = @"addItem"; + } + else if (selector == @selector(addSeparator)) { + result = @"addSeparator"; + } + else if (selector == @selector(itemForKey:)) { + result = @"getItem"; + } + else if (selector == @selector(removeItem:)) { + result = @"removeMenu"; + } + + return result; +} + + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.h new file mode 100644 index 000000000..51077a434 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.h @@ -0,0 +1,26 @@ +// +// Notice.h +// MacGap +// +// Created by Christian Sullivan on 7/26/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import "WindowController.h" + +#define APP_NOTICE_NOTIFICATION @"Notice" + +@interface Notice : NSObject { + +} + +@property (nonatomic, retain) WebView *webView; + +- (id) initWithWebView:(WebView *)view; +- (void) notify:(NSDictionary*)message; +- (void) close:(NSString*)notificationId; ++ (BOOL) available; + +@end + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.m new file mode 100644 index 000000000..a4095f9f2 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.m @@ -0,0 +1,108 @@ +// +// Notice.m +// MacGap +// +// Created by Christian Sullivan on 7/26/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Notice.h" + +#import "JSEventHelper.h" + +@implementation Notice + +- (id) initWithWebView:(WebView*)view +{ + if(self = [super init]) { + self.webView = view; + [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self]; + } + return self; +} + +- (void) notify:(NSDictionary *)message { + NSUserNotification *notification = [[NSUserNotification alloc] init]; + [notification setTitle:[message valueForKey:@"title"]]; + [notification setInformativeText:[message valueForKey:@"content"]]; + [notification setDeliveryDate:[NSDate dateWithTimeInterval:0 sinceDate:[NSDate date]]]; + BOOL playSound = true; // optional parameter, false only when {sound: false} + @try { + NSNumber *s = [message valueForKey:@"sound"]; + if ([[s className] isEqual: @"__NSCFBoolean"]) { + playSound = [s boolValue]; + } + } + @catch (NSException *exception) { + } + if (playSound) { + [notification setSoundName:NSUserNotificationDefaultSoundName]; + } + NSString *id = @""; // optional, needed for close + @try { + id = [message valueForKey:@"id"]; + } + @catch (NSException *exception) { + } + [notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:id, @"id", nil]]; + NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; + [center scheduleNotification:notification]; +} + +// close all notifications with id == notificationId or close all notifications if notificationId == "*" +- (void) close:(NSString*)notificationId { + NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; + for(NSUserNotification * deliveredNote in center.deliveredNotifications) { + if ([notificationId isEqualToString:@"*"] || [deliveredNote.userInfo[@"id"] isEqualToString:notificationId]) { + [center removeDeliveredNotification: deliveredNote]; + } + } +} + ++ (BOOL) available { + if ([NSUserNotificationCenter respondsToSelector:@selector(defaultUserNotificationCenter)]) + return YES; + + return NO; +} + +- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification +{ + NSString *notificationId = [notification.userInfo valueForKey:@"id"]; + [JSEventHelper triggerEvent:@"macgap.notify.activated" forDetail:notificationId forWebView:self.webView]; +} + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + BOOL result = YES; + if (selector == @selector(notify:)) + result = NO; + if (selector == @selector(close:)) + result = NO; + + return result; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(notify:)) { + result = @"notify"; + } + if (selector == @selector(close:)) { + result = @"close"; + } + + return result; +} + +// right now exclude all properties (eg keys) ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.h new file mode 100644 index 000000000..f931340d0 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.h @@ -0,0 +1,21 @@ +#import + +@interface Path : NSObject { + +} + +- (NSString *) application; +- (NSString *) resource; +- (NSString *) documents; +- (NSString *) library; +- (NSString *) home; +- (NSString *) temp; + +@property (readonly,copy) NSString* application; +@property (readonly,copy) NSString* resource; +@property (readonly,copy) NSString* documents; +@property (readonly,copy) NSString* library; +@property (readonly,copy) NSString* home; +@property (readonly,copy) NSString* temp; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.m new file mode 100644 index 000000000..8c54100f7 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.m @@ -0,0 +1,53 @@ +#import "Path.h" + +@implementation Path + +@synthesize application; +@synthesize resource; +@synthesize documents; +@synthesize library; +@synthesize home; +@synthesize temp; + +- (NSString *)application { + return [[NSBundle mainBundle] bundlePath]; +} + +- (NSString *)resource { + return [[NSBundle mainBundle] resourcePath]; +} + +- (NSString *)documents { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + return [paths objectAtIndex:0]; +} + +- (NSString *)library { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); + NSLog( @"%@", paths ); + return [paths objectAtIndex:0]; +} + +- (NSString *)home { + return NSHomeDirectory(); +} + +- (NSString *)temp { + return NSTemporaryDirectory(); +} + +#pragma mark WebScripting Protocol + +/* checks whether a selector is acceptable to be called from JavaScript */ ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + +// right now exclude all properties (eg keys) ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return NO; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.h new file mode 100644 index 000000000..067076439 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.h @@ -0,0 +1,17 @@ +#import +#import "Command.h" +#import "CallbackDelegate.h" + + +@interface Sound : Command { + +} + +// pending callbacks for sounds being played, to keep +// ARC from freeing them too early +@property (nonatomic, strong) NSMutableSet *pending; + +- (void) play:(NSString*)file onComplete:(WebScriptObject*)callback; +- (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.m new file mode 100644 index 000000000..9f4a44dbc --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.m @@ -0,0 +1,97 @@ +#import "Sound.h" + + +@interface PlayDelegate : CallbackDelegate { +} + +@property (nonatomic, weak) Sound *sound; + +- (id) initWithContext:(JSContextRef)aContext + forCallback:(WebScriptObject*)aCallback + withSound:(Sound*)aSound; +@end + +@implementation PlayDelegate + +@synthesize sound; + +- (id) initWithContext:(JSContextRef)aContext + forCallback:(WebScriptObject*)aCallback + withSound:(Sound*)aSound +{ + self = [super initWithContext:aContext forCallback:aCallback]; + if (!self) + return nil; + sound = aSound; + return self; +} + +- (void)sound:(NSSound *)aSound didFinishPlaying:(BOOL)finishedPlaying { + [self callWithParams:[aSound name], nil]; + [sound.pending removeObject:self]; +} + +@end + +@implementation Sound + +@synthesize pending; + +- (id) initWithContext:(JSContextRef)aContext { + self = [super initWithContext:aContext]; + if (!self) { + return nil; + } + + pending = [NSMutableSet new]; + return self; +} + +- (void) playSound:(NSSound*)sound onComplete:(WebScriptObject*)callback { + if (callback != (id)[WebUndefined undefined]) { + PlayDelegate *d = [[PlayDelegate alloc] initWithContext:context + forCallback:callback + withSound:self]; + [pending addObject:d]; + [sound setDelegate:d]; + } + [sound play]; +} + +- (void) play:(NSString*)file onComplete:(WebScriptObject*)callback { + NSURL* fileUrl = [NSURL fileURLWithPath:[[Utils sharedInstance] pathForResource:file]]; + DebugNSLog(@"Sound file:%@", [fileUrl description]); + + NSSound* sound = [[NSSound alloc] initWithContentsOfURL:fileUrl byReference:YES]; + [self playSound:sound onComplete:callback]; +} + +- (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback { + NSSound *systemSound = [NSSound soundNamed:name]; + [self playSound:systemSound onComplete:callback]; +} + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return [self webScriptNameForSelector:selector] == nil; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name { + return YES; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector { + id result = nil; + + if (selector == @selector(play:onComplete:)) { + result = @"play"; + } + else if (selector == @selector(playSystem:onComplete:)) { + result = @"playSystem"; + } + + return result; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.h new file mode 100644 index 000000000..269191b39 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.h @@ -0,0 +1,43 @@ +// +// UserDefaults.h +// MacGap +// +// Created by Jeff Hanbury on 16/04/2014. +// Copyright (c) 2014 Twitter. All rights reserved. +// + +#import + +#import "WindowController.h" + +@interface UserDefaults : NSObject + +@property (nonatomic, retain) WebView *webView; + +- (id) initWithWebView:(WebView *)view; +- (NSString*) getMyDefaults; +- (NSDictionary*) myDefaultsDictionary; +- (void) removeObjectForKey:(NSString*)key; +- (NSArray*) getUserDefaultsKeys; + +- (NSString*) addPrefix:(NSString*)key; + +- (void) setString:(NSString*)key withValue:(NSString*)value; +- (NSString*) getString:(NSString*)key; + +- (void) setInteger:(NSString*)key withValue:(NSString*)value; +- (NSNumber*) getInteger:(NSString*)key; + +- (void) setBool:(NSString*)key withValue:(NSString*)value; +- (NSNumber*) getBool:(NSString*)key; + +- (void) setFloat:(NSString*)key withValue:(NSString*)value; +- (NSNumber*) getFloat:(NSString*)key; + +// Could also be implemented: +//– setObject:forKey: +//– setDouble:forKey: +//– setURL:forKey: + +@end + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.m new file mode 100644 index 000000000..485687108 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.m @@ -0,0 +1,211 @@ +// +// UserDefaults.m +// MacGap +// +// Created by Jeff Hanbury on 16/04/2014. +// Copyright (c) 2014 Twitter. All rights reserved. +// + +#import "UserDefaults.h" +#import "JSEventHelper.h" + +@interface UserDefaults() { + +} + +-(void) setupNotificationCenter; + +@end + + +@implementation UserDefaults + +- (id) initWithWebView:(WebView *) view{ + self = [super init]; + + if (self) { + self.webView = view; + [self setupNotificationCenter]; + } + + return self; +} + + +-(void) setupNotificationCenter{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(defaultsChanged:) + name:NSUserDefaultsDidChangeNotification + object:nil]; +} + +- (void)defaultsChanged:(NSNotification *)notification { + NSDictionary* returnDict = [self myDefaultsDictionary]; + [JSEventHelper triggerEvent:@"userDefaultsChanged" withArgs:returnDict forWebView:self.webView]; +} + +- (NSString*) getMyDefaults { + NSDictionary* myDefaults = [self myDefaultsDictionary]; + + return [[Utils sharedInstance] convertDictionaryToJSON:myDefaults]; +} + +- (NSDictionary*) myDefaultsDictionary { + NSString* prefix = [kWebScriptNamespace stringByAppendingString:@"_"]; + NSMutableDictionary* returnDict = [[NSMutableDictionary alloc] init]; + + // Get the user defaults. + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + // Build up a dictionary containing just the items beginning with our + // prefix. + for (NSString* key in [self getUserDefaultsKeys]) { + if ([key hasPrefix:prefix]) { + id val = [defaults valueForKey:key]; + [returnDict setObject:val forKey:key]; + } + } + + return returnDict; +} + +- (NSArray*) getUserDefaultsKeys { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [[prefs dictionaryRepresentation] allKeys]; +} + +- (void) removeObjectForKey:(NSString*)key { + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:prefixedKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +// Check we have a standard prefix for JS-modified keys, for security purposes. +// If not, add it. This stops JavaScript from ever being able to modify keys +// it did not create. +- (NSString*) addPrefix:(NSString*)key { + NSString* prefix; + prefix = [kWebScriptNamespace stringByAppendingString:@"_"]; + + if (![key hasPrefix:prefix]) { + key = [prefix stringByAppendingString:key]; + } + return key; +} + +// String + +- (void) setString:(NSString*)key withValue:(NSString*)value { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + [prefs setObject:value forKey:prefixedKey]; +} + +- (NSString*) getString:(NSString *)key { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [prefs stringForKey:key]; +} + +// All the following must convert their type to NSNumber for JavaScript. + +// Integer + +- (void) setInteger:(NSString*)key withValue:(NSString*)value { + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + NSInteger myInt = [value intValue]; + [prefs setInteger:myInt forKey:prefixedKey]; +} + +- (NSNumber*) getInteger:(NSString *)key { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [NSNumber numberWithInteger:[prefs integerForKey:key]]; +} + +// Boolean + +- (void) setBool:(NSString*)key withValue:(NSString*)value { + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + BOOL myBool = [value boolValue]; + [prefs setBool:myBool forKey:prefixedKey]; +} + +- (NSNumber*) getBool:(NSString *)key { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [NSNumber numberWithBool:[prefs boolForKey:key]]; +} + +// Float + +- (void) setFloat:(NSString*)key withValue:(NSString*)value { + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + float myFloat = [value floatValue]; + [prefs setFloat:myFloat forKey:prefixedKey]; +} + +- (NSNumber*) getFloat:(NSString *)key { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [NSNumber numberWithFloat:[prefs floatForKey:key]]; +} + + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return NO; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector { + id result = nil; + + if (selector == @selector(getMyDefaults)) { + result = @"getMyDefaults"; + } + + if (selector == @selector(removeObjectForKey:)) { + result = @"removeObjectForKey"; + } + + else if (selector == @selector(setString:withValue:)) { + result = @"setString"; + } else if (selector == @selector(getString:)) { + result = @"getString"; + } + + else if (selector == @selector(setInteger:withValue:)) { + result = @"setInteger"; + } else if (selector == @selector(getInteger:)) { + result = @"getInteger"; + } + + else if (selector == @selector(setBool:withValue:)) { + result = @"setBool"; + } else if (selector == @selector(getBool:)) { + result = @"getBool"; + } + + else if (selector == @selector(setFloat:withValue:)) { + result = @"setFloat"; + } else if (selector == @selector(getFloat:)) { + result = @"getFloat"; + } + + return result; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name { + return NO; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.h new file mode 100644 index 000000000..62c7b7e83 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.h @@ -0,0 +1,9 @@ +@interface Fonts : NSObject { +} + +- (NSArray*) availableFonts; +- (NSArray*) availableFontFamilies; +- (NSArray*) availableMembersOfFontFamily:(NSString*)fontFamily; +- (CGFloat) defaultLineHeightForFont:(NSString *)theFontName ofSize:(CGFloat)theFontSize; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.m new file mode 100644 index 000000000..b17818a53 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.m @@ -0,0 +1,48 @@ +#import "fonts.h" + +@implementation Fonts + + +- (NSArray*) availableFonts { + return [[NSFontManager sharedFontManager] availableFonts]; +} + +- (NSArray*) availableFontFamilies { + return [[NSFontManager sharedFontManager] availableFontFamilies]; +} + +- (NSArray*) availableMembersOfFontFamily:(NSString *)fontFamily { + return [[NSFontManager sharedFontManager] availableMembersOfFontFamily:fontFamily]; +} + +- (CGFloat) defaultLineHeightForFont:(NSString*)theFontName ofSize:(CGFloat)theFontSize { + NSFont *theFont = [NSFont fontWithName:theFontName size:theFontSize]; + NSLayoutManager *lm = [[NSLayoutManager alloc] init]; + + return [lm defaultLineHeightForFont:theFont]; +} + + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return NO; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector { + id result = nil; + + if (selector == @selector(availableMembersOfFontFamily:)) { + result = @"availableMembersOfFontFamily"; + } else if (selector == @selector(defaultLineHeightForFont:ofSize:)) { + result = @"defaultLineHeightForFont"; + } + + return result; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name { + return NO; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Constants.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Constants.h new file mode 100644 index 000000000..1fe59d6cc --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Constants.h @@ -0,0 +1,7 @@ +// Application constants + +#define kStartPage @"http://127.0.0.1:9993/" + +#define kStartFolder @"." + +#define kWebScriptNamespace @"macgap" \ No newline at end of file diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.h new file mode 100644 index 000000000..65890a5ee --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.h @@ -0,0 +1,15 @@ +#import +#import + +@class WebViewDelegate; + +@interface ContentView : NSView { + IBOutlet WebView* webView; + WebViewDelegate* delegate; +} + +@property (retain) WebView* webView; +@property (retain) WebViewDelegate* delegate; +@property (strong) IBOutlet NSMenu *mainMenu; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m new file mode 100644 index 000000000..6558a191f --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m @@ -0,0 +1,68 @@ +#import "ContentView.h" +#import "WebViewDelegate.h" +#import "AppDelegate.h" +#import "JSEventHelper.h" + +@interface WebPreferences (WebPreferencesPrivate) + - (void)_setLocalStorageDatabasePath:(NSString *)path; + - (void) setLocalStorageEnabled: (BOOL) localStorageEnabled; + - (void) setDatabasesEnabled:(BOOL)databasesEnabled; + - (void) setDeveloperExtrasEnabled:(BOOL)developerExtrasEnabled; + - (void) setWebGLEnabled:(BOOL)webGLEnabled; + - (void) setOfflineWebApplicationCacheEnabled:(BOOL)offlineWebApplicationCacheEnabled; +@end + +@implementation ContentView + +@synthesize webView, delegate, mainMenu; + +- (void) awakeFromNib +{ + WebPreferences *webPrefs = [WebPreferences standardPreferences]; + + NSString *cappBundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; + NSString *applicationSupportFile = [@"~/Library/Application Support/" stringByExpandingTildeInPath]; + NSString *savePath = [NSString pathWithComponents:[NSArray arrayWithObjects:applicationSupportFile, cappBundleName, @"LocalStorage", nil]]; + [webPrefs _setLocalStorageDatabasePath:savePath]; + [webPrefs setLocalStorageEnabled:YES]; + [webPrefs setDatabasesEnabled:YES]; + [webPrefs setDeveloperExtrasEnabled:[[NSUserDefaults standardUserDefaults] boolForKey: @"developer"]]; + [webPrefs setOfflineWebApplicationCacheEnabled:YES]; + [webPrefs setWebGLEnabled:YES]; + + [self.webView setPreferences:webPrefs]; + + NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage + sharedHTTPCookieStorage]; + [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways]; + + [self.webView setApplicationNameForUserAgent: @"MacGap"]; + + self.delegate = [[WebViewDelegate alloc] initWithMenu:[NSApp mainMenu]]; +// [self.webView setFrameLoadDelegate:self.delegate]; +// [self.webView setUIDelegate:self.delegate]; +// [self.webView setResourceLoadDelegate:self.delegate]; +// [self.webView setDownloadDelegate:self.delegate]; +// [self.webView setPolicyDelegate:self.delegate]; + [self.webView setDrawsBackground:NO]; + [self.webView setShouldCloseWithWindow:NO]; + + [self.webView setGroupName:@"MacGap"]; + +} + +- (void) windowResized:(NSNotification*)notification; +{ + NSWindow* window = (NSWindow*)notification.object; + NSSize size = [window frame].size; + + DebugNSLog(@"window width = %f, window height = %f", size.width, size.height); + + bool isFullScreen = (window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask; + int titleBarHeight = isFullScreen ? 0 : [[Utils sharedInstance] titleBarHeight:window]; + + [self.webView setFrame:NSMakeRect(0, 0, size.width, size.height - titleBarHeight)]; + [JSEventHelper triggerEvent:@"orientationchange" forWebView:self.webView]; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.h new file mode 100644 index 000000000..401f3e396 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.h @@ -0,0 +1,20 @@ +// +// Helper.h +// MacGap +// +// Created by Liam Kaufman Simpkins on 12-01-22. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import "WindowController.h" + +@interface JSEventHelper : NSObject + ++ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView; ++ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView; ++ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView; ++ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView; ++ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.m new file mode 100644 index 000000000..65406b3c0 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.m @@ -0,0 +1,41 @@ +// +// Helper.m +// MacGap +// +// Created by Liam Kaufman Simpkins on 12-01-22. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "JSEventHelper.h" + +@implementation JSEventHelper + ++ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView { + [self triggerEvent:event withArgs:[NSMutableDictionary dictionary] forObject:@"document" forWebView:webView]; +} + ++ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView { + [self triggerEvent:event withArgs:args forObject:@"document" forWebView:webView]; +} + ++ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView { + + // Convert args Dictionary to JSON. + NSString* jsonString = [[Utils sharedInstance] convertDictionaryToJSON:args]; + + // Create the event JavaScript and run it. + NSString * str = [NSString stringWithFormat:@"var e = document.createEvent('Events'); e.initEvent('%@', true, false); e.data=%@; %@.dispatchEvent(e); ", event, jsonString, objName]; + [webView stringByEvaluatingJavaScriptFromString:str]; +} + ++ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView { + [self triggerEvent:event forDetail:detail forObject:@"document" forWebView:webView]; +} + ++ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView { + NSString *detailEscaped = [detail stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; + NSString *str = [NSString stringWithFormat:@"var e = new CustomEvent('%@', { 'detail': decodeURIComponent(\"%@\") }); %@.dispatchEvent(e); ", event, detailEscaped, objName]; + [webView stringByEvaluatingJavaScriptFromString:str]; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.h new file mode 100644 index 000000000..f573d881a --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.h @@ -0,0 +1,20 @@ +#import +#import + +#define DEG_EPS 0.001 +#define fequal(a,b) (fabs((a) - (b)) < DEG_EPS) +#define fequalzero(a) (fabs(a) < DEG_EPS) + +@class LoadingView; + +@interface Utils : NSObject { +} + +- (float) titleBarHeight:(NSWindow*)aWindow; +- (NSString*) pathForResource:(NSString*)resourcepath; +- (NSString*) convertDictionaryToJSON:(NSDictionary*)dict; +- (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray; + ++ (Utils*) sharedInstance; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.m new file mode 100644 index 000000000..8d85c2949 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.m @@ -0,0 +1,93 @@ +#import "Utils.h" +#import + +static Utils* sharedInstance = nil; + +@implementation Utils + +- (float) titleBarHeight:(NSWindow*)aWindow +{ + NSRect frame = [aWindow frame]; + NSRect contentRect = [NSWindow contentRectForFrameRect: frame + styleMask: NSTitledWindowMask]; + + return (frame.size.height - contentRect.size.height); +} + +- (NSString*) pathForResource:(NSString*)resourcepath +{ + NSBundle * mainBundle = [NSBundle mainBundle]; + NSMutableArray *directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]]; + NSString *filename = [directoryParts lastObject]; + [directoryParts removeLastObject]; + + NSString *directoryStr = [NSString stringWithFormat:@"%@/%@", kStartFolder, [directoryParts componentsJoinedByString:@"/"]]; + return [mainBundle pathForResource:filename + ofType:@"" + inDirectory:directoryStr]; +} + +- (NSString*) convertDictionaryToJSON:(NSDictionary*)dict { + // Convert defaults Dictionary to JSON. + NSError *error; + NSData *jsonData = [NSJSONSerialization + dataWithJSONObject:dict + options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string + error:&error]; + + NSString *jsonString; + if (! jsonData) { + NSLog(@"Got an error converting to JSON: %@", error); + } + else { + jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + } + + return jsonString; +} + +// Convert JavaScript array (arrives as a WebScriptObject) into an NSArray of strings. +- (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray { + NSInteger count = [[jsArray valueForKey:@"length"] integerValue]; + + NSMutableArray *args = [NSMutableArray array]; + for (int i = 0; i < count; i++) { + NSString *item = [jsArray webScriptValueAtIndex:i]; + if ([item isKindOfClass:[NSString class]]) { + [args addObject:item]; + } + } + + return args; +} + +#pragma mark - +#pragma mark Singleton methods + ++ (Utils*) sharedInstance +{ + @synchronized(self) + { + if (sharedInstance == nil){ + sharedInstance = [[Utils alloc] init]; + } + } + return sharedInstance; +} + ++ (id) allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (sharedInstance == nil) { + sharedInstance = [super allocWithZone:zone]; + return sharedInstance; // assignment and return on first allocation + } + } + return nil; // on subsequent allocation attempts return nil +} + +- (id) copyWithZone:(NSZone *)zone +{ + return self; +} + +@end \ No newline at end of file diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.h new file mode 100644 index 000000000..49c6da6b9 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.h @@ -0,0 +1,49 @@ +#import +#import + +@class Sound; +@class Dock; +@class Growl; +@class Notice; +@class Path; +@class App; +@class Window; +@class Clipboard; +@class Fonts; +@class MenuProxy; +@class UserDefaults; + +@class WindowController; + +@interface WebViewDelegate : NSObject { + Sound* sound; + Dock* dock; + Growl* growl; + Notice* notice; + Path* path; + App* app; + Window* window; + Clipboard* clipboard; + Fonts* fonts; + NSMenu *mainMenu; + UserDefaults* userDefaults; +} + + + +@property (nonatomic, retain) Sound* sound; +@property (nonatomic, retain) Dock* dock; +@property (nonatomic, retain) Growl* growl; +@property (nonatomic, retain) Notice* notice; +@property (nonatomic, retain) Path* path; +@property (nonatomic, retain) App* app; +@property (nonatomic, retain) Window* window; +@property (nonatomic, retain) Clipboard* clipboard; +@property (nonatomic, retain) Fonts* fonts; +@property (nonatomic, retain) MenuProxy* menu; +@property (nonatomic, retain) UserDefaults* userDefaults; + +@property (nonatomic, retain) WindowController *requestedWindow; + +- (id) initWithMenu:(NSMenu*)menu; +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.m new file mode 100644 index 000000000..505780183 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.m @@ -0,0 +1,206 @@ +#import "WebViewDelegate.h" +#import "Sound.h" +#import "Dock.h" +#import "Notice.h" +#import "Path.h" +#import "App.h" +#import "Window.h" +#import "WindowController.h" +#import "Clipboard.h" +#import "Fonts.h" +#import "MenuProxy.h" +#import "UserDefaults.h" + +@implementation WebViewDelegate + +@synthesize sound; +@synthesize dock; +@synthesize growl; +@synthesize notice; +@synthesize path; +@synthesize app; +@synthesize window; +@synthesize requestedWindow; +@synthesize clipboard; +@synthesize fonts; +@synthesize menu; +@synthesize userDefaults; + +- (id) initWithMenu:(NSMenu*)aMenu +{ + self = [super init]; + if (!self) + return nil; + + mainMenu = aMenu; + return self; +} + +- (void) webView:(WebView*)webView didClearWindowObject:(WebScriptObject*)windowScriptObject forFrame:(WebFrame *)frame +{ + JSContextRef context = [frame globalContext]; + if (self.sound == nil) { self.sound = [[Sound alloc] initWithContext:context]; } + if (self.dock == nil) { self.dock = [Dock new]; } + if (self.path == nil) { self.path = [Path new]; } + if (self.clipboard == nil) { self.clipboard = [Clipboard new]; } + if (self.fonts == nil) { self.fonts = [Fonts new]; } + + if (self.notice == nil && [Notice available] == YES) { + self.notice = [[Notice alloc] initWithWebView:webView]; + } + + if (self.app == nil) { + self.app = [[App alloc] initWithWebView:webView]; + } + + if (self.window == nil) { + self.window = [[Window alloc] initWithWebView:webView]; + } + + if (self.menu == nil) { + self.menu = [MenuProxy proxyWithContext:context andMenu:mainMenu]; + } + + if (self.userDefaults == nil) { + self.userDefaults = [[UserDefaults alloc] initWithWebView:webView]; + } + + [windowScriptObject setValue:self forKey:kWebScriptNamespace]; +} + + +- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener allowMultipleFiles:(BOOL)allowMultipleFiles{ + + NSOpenPanel * openDlg = [NSOpenPanel openPanel]; + + [openDlg setCanChooseFiles:YES]; + [openDlg setCanChooseDirectories:NO]; + + [openDlg beginWithCompletionHandler:^(NSInteger result){ + if (result == NSFileHandlingPanelOKButton) { + NSArray * files = [[openDlg URLs] valueForKey: @"relativePath"]; + [resultListener chooseFilenames: files]; + } else { + [resultListener cancel]; + } + }]; +} + +- (void) webView:(WebView*)webView addMessageToConsole:(NSDictionary*)message +{ + if (![message isKindOfClass:[NSDictionary class]]) { + return; + } + + NSLog(@"JavaScript console: %@:%@: %@", + [[message objectForKey:@"sourceURL"] lastPathComponent], // could be nil + [message objectForKey:@"lineNumber"], + [message objectForKey:@"message"]); +} + +- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert addButtonWithTitle:@"OK"]; + [alert setMessageText:message]; + [alert setAlertStyle:NSWarningAlertStyle]; + [alert runModal]; +} + +- (BOOL)webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert addButtonWithTitle:@"Yes"]; + [alert addButtonWithTitle:@"No"]; + [alert setMessageText:message]; + [alert setAlertStyle:NSWarningAlertStyle]; + + if ([alert runModal] == NSAlertFirstButtonReturn) + return YES; + else + return NO; +} + +/* + By default the size of a database is set to 0 [1]. When a database is being created + it calls this delegate method to get an increase in quota size - or call an error. + PS this method is defined in WebUIDelegatePrivate and may make it difficult, but + not impossible [2], to get an app accepted into the mac app store. + + Further reading: + [1] http://stackoverflow.com/questions/353808/implementing-a-webview-database-quota-delegate + [2] http://stackoverflow.com/questions/4527905/how-do-i-enable-local-storage-in-my-webkit-based-application/4608549#4608549 + */ +- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(id) origin database:(NSString *)databaseIdentifier +{ + static const unsigned long long defaultQuota = 5 * 1024 * 1024; + if ([origin respondsToSelector: @selector(setQuota:)]) { + [origin performSelector:@selector(setQuota:) withObject:[NSNumber numberWithLongLong: defaultQuota]]; + } else { + NSLog(@"could not increase quota for %lld", defaultQuota); + } +} + +- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems +{ + NSMutableArray *webViewMenuItems = [defaultMenuItems mutableCopy]; + + if (webViewMenuItems) + { + NSEnumerator *itemEnumerator = [defaultMenuItems objectEnumerator]; + NSMenuItem *menuItem = nil; + while ((menuItem = [itemEnumerator nextObject])) + { + NSInteger tag = [menuItem tag]; + + switch (tag) + { + case WebMenuItemTagOpenLinkInNewWindow: + case WebMenuItemTagDownloadLinkToDisk: + case WebMenuItemTagCopyLinkToClipboard: + case WebMenuItemTagOpenImageInNewWindow: + case WebMenuItemTagDownloadImageToDisk: + case WebMenuItemTagCopyImageToClipboard: + case WebMenuItemTagOpenFrameInNewWindow: + case WebMenuItemTagGoBack: + case WebMenuItemTagGoForward: + case WebMenuItemTagStop: + case WebMenuItemTagOpenWithDefaultApplication: + case WebMenuItemTagReload: + [webViewMenuItems removeObjectIdenticalTo: menuItem]; + } + } + } + + return webViewMenuItems; +} + +- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request{ + requestedWindow = [[WindowController alloc] initWithRequest:request]; + return requestedWindow.contentView.webView; +} + +- (void)webViewShow:(WebView *)sender{ + [requestedWindow showWindow:sender]; +} + +- (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener +{ + [[NSWorkspace sharedWorkspace] openURL:[request URL]]; + [listener ignore]; +} + +#pragma mark WebScripting protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return YES; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return NO; +} + + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.h new file mode 100644 index 000000000..f721376e0 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.h @@ -0,0 +1,23 @@ +#import + +#import "WindowController.h" + +@interface Window : NSObject{ + CGRect _oldRestoreFrame; +} + +@property (retain, nonatomic) WindowController *windowController; +@property (nonatomic, retain) WebView *webView; + +- (id) initWithWebView:(WebView *)view; +- (void) open:(NSDictionary *)properties; +- (void) move:(NSDictionary *)properties; +- (void) resize:(NSDictionary *) properties; +- (Boolean) isMaximized; +- (CGFloat) getX; +- (CGFloat) getY; +- (void) maximize; +- (void) restore; +- (void) toggleFullscreen; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.m new file mode 100644 index 000000000..2444f62ea --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.m @@ -0,0 +1,94 @@ +#import "Window.h" + +@implementation Window + +@synthesize windowController, webView; + +- (id) initWithWebView:(WebView*)view +{ + if(self = [super init]) { + self.webView = view; + } + return self; +} + +- (void) open:(NSDictionary *)properties +{ + self.windowController = [[WindowController alloc] initWithURL:[properties valueForKey:@"url"]]; + [self.windowController showWindow: [NSApplication sharedApplication].delegate]; + [self.windowController.window makeKeyWindow]; +} + +- (void) minimize { + [[NSApp mainWindow] miniaturize:[NSApp mainWindow]]; +} + +- (void) toggleFullscreen { + [[NSApp mainWindow] toggleFullScreen:[NSApp mainWindow]]; +} + +- (void) maximize { + CGRect a = [NSApp mainWindow].frame; + _oldRestoreFrame = CGRectMake(a.origin.x, a.origin.y, a.size.width, a.size.height); + [[NSApp mainWindow] setFrame:[[NSScreen mainScreen] visibleFrame] display:YES]; +} + +- (Boolean) isMaximized { + NSRect a = [NSApp mainWindow].frame; + NSRect b = [[NSScreen mainScreen] visibleFrame]; + return a.origin.x == b.origin.x && a.origin.y == b.origin.y && a.size.width == b.size.width && a.size.height == b.size.height; +} + +- (CGFloat) getX { + NSRect frame = [self.webView window].frame; + return frame.origin.x; +} + +- (CGFloat) getY { + NSRect frame = [self.webView window].frame; + return frame.origin.y; +} + +- (void) move:(NSDictionary *)properties +{ + NSRect frame = [self.webView window].frame; + frame.origin.x = [[properties valueForKey:@"x"] doubleValue]; + frame.origin.y = [[properties valueForKey:@"y"] doubleValue]; + [[self.webView window] setFrame:frame display:YES]; + +} + +- (void) resize:(NSDictionary *) properties +{ + NSRect frame = [self.webView window].frame; + frame.size.width = [[properties valueForKey:@"width"] doubleValue]; + frame.size.height = [[properties valueForKey:@"height"] doubleValue]; + [[self.webView window] setFrame:frame display:YES]; +} + + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector{ + id result = nil; + + if (selector == @selector(open:)) { + result = @"open"; + }else if (selector == @selector(move:)){ + result = @"move"; + }else if (selector == @selector(resize:)){ + result = @"resize"; + } + + return result; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.h new file mode 100644 index 000000000..6c1a2f513 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.h @@ -0,0 +1,10 @@ +#import + +@interface Clipboard : NSObject { + +} + +- (void) copy:(NSString*)text; +- (NSString *) paste; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.m new file mode 100644 index 000000000..1c18dea38 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.m @@ -0,0 +1,51 @@ +// +// clipboard.m +// MacGap +// +// Created by David Zorychta on 2013-07-22. +// Copyright (c) 2013 Twitter. All rights reserved. +// + +#import "Clipboard.h" + +@implementation Clipboard + +- (void) copy:(NSString*)text { + [[NSPasteboard generalPasteboard] clearContents]; + [[NSPasteboard generalPasteboard] setString:text forType:NSStringPboardType]; +} + +- (NSString *) paste { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSDictionary *options = [NSDictionary dictionary]; + BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; + if (ok) { + NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options]; + return (NSString *) [objectsToPaste objectAtIndex:0]; + } + return @""; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(copy:)) { + result = @"copy"; + } + + return result; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist b/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist new file mode 100644 index 000000000..7f71ea229 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist @@ -0,0 +1,39 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ZeroTier One + CFBundleIconFile + ZeroTierIcon + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ZeroTier One + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Prefix.pch b/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Prefix.pch new file mode 100644 index 000000000..ad05e8420 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Prefix.pch @@ -0,0 +1,15 @@ +// +// Prefix header for all source files of the 'MacGap' target in the 'MacGap' project +// + +#ifdef __OBJC__ + #ifdef _DEBUG + #define DebugNSLog(format, ...) NSLog(format, ## __VA_ARGS__) + #else + #define DebugNSLog(format, ...) + #endif + + #import + #import "Constants.h" + #import "Utils.h" +#endif diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/WindowController.h b/ext/mac-ui-macgap1-wrapper/src/MacGap/WindowController.h new file mode 100644 index 000000000..72927effa --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/WindowController.h @@ -0,0 +1,13 @@ +#import +#import "ContentView.h" + +@interface WindowController : NSWindowController { + +} + +- (id) initWithURL:(NSString *) url; +- (id) initWithRequest: (NSURLRequest *)request; +@property (retain) NSURL * url; +@property (retain) IBOutlet ContentView *contentView; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/WindowController.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/WindowController.m new file mode 100644 index 000000000..2765a2e3c --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/WindowController.m @@ -0,0 +1,54 @@ +#import "WindowController.h" + + +@interface WindowController() { + +} + +-(void) notificationCenter; + +@end + +@implementation WindowController + +@synthesize contentView, url; + +- (id) initWithURL:(NSString *) relativeURL{ + self = [super initWithWindowNibName:@"Window"]; + self.url = [NSURL URLWithString:relativeURL relativeToURL:[[NSBundle mainBundle] resourceURL]]; + + [self.window setFrameAutosaveName:@"MacGapWindow"]; + [self notificationCenter]; + + return self; +} + +-(id) initWithRequest: (NSURLRequest *)request{ + self = [super initWithWindowNibName:@"Window"]; + [self notificationCenter]; + [[self.contentView.webView mainFrame] loadRequest:request]; + + return self; +} + +-(void) notificationCenter{ + [[NSNotificationCenter defaultCenter] addObserver:self.contentView + selector:@selector(windowResized:) + name:NSWindowDidResizeNotification + object:[self window]]; +} + +- (void)windowDidLoad +{ + [super windowDidLoad]; + + if (self.url != nil) { + [self.contentView.webView setMainFrameURL:[self.url absoluteString]]; + } + + + // Implement this method to handle any initialization after your + // window controller's window has been loaded from its nib file. +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Credits.rtf b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Credits.rtf new file mode 100644 index 000000000..6f388f662 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Credits.rtf @@ -0,0 +1,13 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\vieww9600\viewh8400\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 + +\f0\b\fs24 \cf0 (c)2011-2015 ZeroTier, Inc.\ +Licensed under the GNU GPLv3\ +\ +UI Wrapper MacGap (c) Twitter, Inc.\ +Licensed under the MIT License\ +http://macgap.com/\ +} \ No newline at end of file diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/InfoPlist.strings b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..477b28ff8 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib new file mode 100644 index 000000000..dd67a86ae --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib @@ -0,0 +1,3404 @@ + + + + 1070 + 14D136 + 7702 + 1347.57 + 758.70 + + com.apple.InterfaceBuilder.CocoaPlugin + 7702 + + + NSCustomObject + NSMenu + NSMenuItem + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AppDelegate + + + AMainMenu + + + + ZeroTier One + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + + ZeroTier One + + + + About ZeroTier One + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + + Services + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide ZeroTier One + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit ZeroTier One + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + + Open Recent + + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save… + s + 1048576 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find and Replace… + f + 1572864 + 2147483647 + + + 12 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + + Spelling and Grammar + + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + + Substitutions + + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + + Transformations + + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + + Speech + + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + + Format + + + + Font + + 2147483647 + + + submenuAction: + + + Font + + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + + Kern + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + + Ligature + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + + Baseline + + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + + Text + + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + + Writing Direction + + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + + View + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + + Help + + + + ZeroTier One Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 547 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + performFindPanelAction: + + + + 535 + + + + delegate + + + + 545 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + + + + + 19 + + + + + + + + 56 + + + + + + + + 217 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + + + 75 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + + + + + + 126 + + + + + 205 + + + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + + + + + + 216 + + + + + + + + 200 + + + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + + + + + + 296 + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + + + + + + 212 + + + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + + + + + + 349 + + + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 375 + + + + + + + + 376 + + + + + + + + + 377 + + + + + + + + 388 + + + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + + + + + + 398 + + + + + + + + 399 + + + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 450 + + + + + + + + 451 + + + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + + + + + + 491 + + + + + + + + 492 + + + + + 496 + + + + + + + + 497 + + + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 534 + + + + + 546 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 547 + + + + + AppDelegate + NSObject + + IBProjectSource + ../MacGap/AppDelegate.h + + + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + id + id + id + id + id + id + + + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocumentController + NSObject + + id + id + id + id + + + + clearRecentDocuments: + id + + + newDocument: + id + + + openDocument: + id + + + saveAllDocuments: + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSPopover + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSPopover.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSViewController + NSResponder + + view + NSView + + + view + + view + NSView + + + + IBFrameworkSource + AppKit.framework/Headers/NSViewController.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + WebView + NSView + + id + id + id + id + id + id + id + id + id + id + id + + + + goBack: + id + + + goForward: + id + + + makeTextLarger: + id + + + makeTextSmaller: + id + + + makeTextStandardSize: + id + + + reload: + id + + + reloadFromOrigin: + id + + + stopLoading: + id + + + takeStringURLFrom: + id + + + toggleContinuousSpellChecking: + id + + + toggleSmartInsertDelete: + id + + + + IBFrameworkSource + WebKit.framework/Headers/WebView.h + + + + + 0 + IBCocoaFramework + NO + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + {12, 12} + {10, 2} + + + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib new file mode 100644 index 000000000..fa70acaa5 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/main.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/main.m new file mode 100644 index 000000000..4ad50ad59 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/main.m @@ -0,0 +1,14 @@ +// +// main.m +// MacGap +// +// Created by Alex MacCaw on 08/01/2012. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} diff --git a/ext/mac-ui-macgap1-wrapper/src/README.md b/ext/mac-ui-macgap1-wrapper/src/README.md new file mode 100644 index 000000000..daf3eae9c --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/src/README.md @@ -0,0 +1,6 @@ +Mac Web UI Wrapper +====== + +This is a modified version of MacGap1 which launches a WebKit view and accesses the local ZeroTier service at its web URL. It builds the URL from the authtoken.secret file in the system home (or the user home) and the zerotier-one.port file that ZeroTier creates to advertise its control port. + +It's based on the original MacGap1 source by Twitter, Inc. which is licensed under the MIT license. diff --git a/ext/miniupnpc/CMakeLists.txt b/ext/miniupnpc/CMakeLists.txt new file mode 100644 index 000000000..dacb1f692 --- /dev/null +++ b/ext/miniupnpc/CMakeLists.txt @@ -0,0 +1,178 @@ +cmake_minimum_required (VERSION 2.6) + +project (miniupnpc C) +set (MINIUPNPC_VERSION 1.9) +set (MINIUPNPC_API_VERSION 15) + +if (NOT CMAKE_BUILD_TYPE) + if (WIN32) + set (DEFAULT_BUILD_TYPE MinSizeRel) + else (WIN32) + set (DEFAULT_BUILD_TYPE RelWithDebInfo) + endif(WIN32) + set (CMAKE_BUILD_TYPE ${DEFAULT_BUILD_TYPE} CACHE STRING + "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." + FORCE) +endif() + +option (UPNPC_BUILD_STATIC "Build static library" TRUE) +option (UPNPC_BUILD_SHARED "Build shared library" TRUE) +if (NOT WIN32) + option (UPNPC_BUILD_TESTS "Build test executables" TRUE) +endif (NOT WIN32) +option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE) + +mark_as_advanced (NO_GETADDRINFO) + +if (NO_GETADDRINFO) + add_definitions (-DNO_GETADDRINFO) +endif (NO_GETADDRINFO) + +if (NOT WIN32) + add_definitions (-DMINIUPNPC_SET_SOCKET_TIMEOUT) + add_definitions (-D_BSD_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112L) +else (NOT WIN32) + add_definitions (-D_WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends +endif (NOT WIN32) + +if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + add_definitions (-D_DARWIN_C_SOURCE) +endif () + +# Set compiler specific build flags +if (CMAKE_COMPILER_IS_GNUC) + # Set our own default flags at first run. + if (NOT CONFIGURED) + + if (NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") + set (_PIC -fPIC) + endif (CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") + + set (CMAKE_C_FLAGS "${_PIC} -Wall $ENV{CFLAGS}" # CMAKE_C_FLAGS gets appended to the other C flags + CACHE STRING "Flags used by the C compiler during normal builds." FORCE) + set (CMAKE_C_FLAGS_DEBUG "-g -DDDEBUG" + CACHE STRING "Flags used by the C compiler during debug builds." FORCE) + set (CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG" + CACHE STRING "Flags used by the C compiler during release builds." FORCE) + set (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG" + CACHE STRING "Flags used by the C compiler during release builds." FORCE) + set (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" + CACHE STRING "Flags used by the C compiler during release builds." FORCE) + + endif (NOT CONFIGURED) +endif () + +configure_file (${CMAKE_SOURCE_DIR}/miniupnpcstrings.h.cmake ${CMAKE_BINARY_DIR}/miniupnpcstrings.h) +include_directories (${CMAKE_BINARY_DIR}) + +set (MINIUPNPC_SOURCES + igd_desc_parse.c + miniupnpc.c + minixml.c + minisoap.c + minissdpc.c + miniwget.c + upnpc.c + upnpcommands.c + upnpdev.c + upnpreplyparse.c + upnperrors.c + connecthostport.c + portlistingparse.c + receivedata.c +) + +if (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") + set (MINIUPNPC_SOURCES ${MINIUPNPC_SOURCES} minissdpc.c) +endif (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") + +if (WIN32) + set_source_files_properties (${MINIUPNPC_SOURCES} PROPERTIES + COMPILE_DEFINITIONS "MINIUPNP_STATICLIB;MINIUPNP_EXPORTS" + ) +endif (WIN32) + +if (WIN32) + find_library (WINSOCK2_LIBRARY NAMES ws2_32 WS2_32 Ws2_32) + find_library (IPHLPAPI_LIBRARY NAMES iphlpapi) + set (LDLIBS ${WINSOCK2_LIBRARY} ${IPHLPAPI_LIBRARY} ${LDLIBS}) +#elseif (CMAKE_SYSTEM_NAME STREQUAL "Solaris") +# find_library (SOCKET_LIBRARY NAMES socket) +# find_library (NSL_LIBRARY NAMES nsl) +# find_library (RESOLV_LIBRARY NAMES resolv) +# set (LDLIBS ${SOCKET_LIBRARY} ${NSL_LIBRARY} ${RESOLV_LIBRARY} ${LDLIBS}) +endif (WIN32) + +if (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) + message (FATAL "Both shared and static libraries are disabled!") +endif (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) + +if (UPNPC_BUILD_STATIC) + add_library (upnpc-static STATIC ${MINIUPNPC_SOURCES}) + set_target_properties (upnpc-static PROPERTIES OUTPUT_NAME "miniupnpc") + target_link_libraries (upnpc-static ${LDLIBS}) + set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-static) + set (UPNPC_LIBRARY_TARGET upnpc-static) +endif (UPNPC_BUILD_STATIC) + +if (UPNPC_BUILD_SHARED) + add_library (upnpc-shared SHARED ${MINIUPNPC_SOURCES}) + set_target_properties (upnpc-shared PROPERTIES OUTPUT_NAME "miniupnpc") + set_target_properties (upnpc-shared PROPERTIES VERSION ${MINIUPNPC_VERSION}) + set_target_properties (upnpc-shared PROPERTIES SOVERSION ${MINIUPNPC_API_VERSION}) + target_link_libraries (upnpc-shared ${LDLIBS}) + set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-shared) + set (UPNPC_LIBRARY_TARGET upnpc-shared) +endif (UPNPC_BUILD_SHARED) + +if (UPNPC_BUILD_TESTS) + add_executable (testminixml testminixml.c minixml.c igd_desc_parse.c) + target_link_libraries (testminixml ${LDLIBS}) + + add_executable (minixmlvalid minixmlvalid.c minixml.c) + target_link_libraries (minixmlvalid ${LDLIBS}) + + add_executable (testupnpreplyparse testupnpreplyparse.c + minixml.c upnpreplyparse.c) + target_link_libraries (testupnpreplyparse ${LDLIBS}) + + add_executable (testigddescparse testigddescparse.c + igd_desc_parse.c minixml.c miniupnpc.c miniwget.c minissdpc.c + upnpcommands.c upnpreplyparse.c minisoap.c connecthostport.c + portlistingparse.c receivedata.c + ) + target_link_libraries (testigddescparse ${LDLIBS}) + + add_executable (testminiwget testminiwget.c + miniwget.c miniupnpc.c minisoap.c upnpcommands.c minissdpc.c + upnpreplyparse.c minixml.c igd_desc_parse.c connecthostport.c + portlistingparse.c receivedata.c + ) + target_link_libraries (testminiwget ${LDLIBS}) + +# set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} testminixml minixmlvalid testupnpreplyparse testigddescparse testminiwget) +endif (UPNPC_BUILD_TESTS) + + +install (TARGETS ${UPNPC_INSTALL_TARGETS} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX} +) +install (FILES + miniupnpc.h + miniwget.h + upnpcommands.h + igd_desc_parse.h + upnpreplyparse.h + upnperrors.h + upnpdev.h + miniupnpctypes.h + portlistingparse.h + miniupnpc_declspec.h + DESTINATION include/miniupnpc +) + +set (CONFIGURED YES CACHE INTERNAL "") + +# vim: ts=2:sw=2 diff --git a/ext/miniupnpc/Changelog.txt b/ext/miniupnpc/Changelog.txt index 37562c6af..bef61f59e 100644 --- a/ext/miniupnpc/Changelog.txt +++ b/ext/miniupnpc/Changelog.txt @@ -1,30 +1,6 @@ -$Id: Changelog.txt,v 1.229 2017/12/12 11:26:25 nanard Exp $ +$Id: Changelog.txt,v 1.219 2015/10/26 17:05:06 nanard Exp $ miniUPnP client Changelog. -2017/12/11: - Fix buffer over run in minixml.c - Fix uninitialized variable access in upnpreplyparse.c - -2017/05/05: - Fix CVE-2017-8798 Thanks to tin/Team OSTStrom - -2016/11/11: - check strlen before memcmp in XML parsing portlistingparse.c - fix build under SOLARIS and CYGWIN - -2016/10/11: - Add python 3 compatibility to IGD test - -VERSION 2.0 : released 2016/04/19 - -2016/01/24: - change miniwget to return HTTP status code - increments API_VERSION to 16 - -2016/01/22: - Improve UPNPIGD_IsConnected() to check if WAN address is not private. - parse HTTP response status line in miniwget.c - 2015/10/26: snprintf() overflow check. check overflow in simpleUPnPcommand2() diff --git a/ext/miniupnpc/LICENSE b/ext/miniupnpc/LICENSE index 081673370..cb5a06044 100644 --- a/ext/miniupnpc/LICENSE +++ b/ext/miniupnpc/LICENSE @@ -1,5 +1,5 @@ MiniUPnPc -Copyright (c) 2005-2016, Thomas BERNARD +Copyright (c) 2005-2015, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/ext/miniupnpc/MANIFEST.in b/ext/miniupnpc/MANIFEST.in new file mode 100644 index 000000000..54b86f95e --- /dev/null +++ b/ext/miniupnpc/MANIFEST.in @@ -0,0 +1,5 @@ +include README +include miniupnpcmodule.c +include setup.py +include *.h +include libminiupnpc.a diff --git a/ext/miniupnpc/Makefile b/ext/miniupnpc/Makefile new file mode 100644 index 000000000..4a4f16126 --- /dev/null +++ b/ext/miniupnpc/Makefile @@ -0,0 +1,379 @@ +# $Id: Makefile,v 1.132 2015/10/26 16:59:54 nanard Exp $ +# MiniUPnP Project +# http://miniupnp.free.fr/ +# http://miniupnp.tuxfamily.org/ +# https://github.com/miniupnp/miniupnp +# (c) 2005-2015 Thomas Bernard +# to install use : +# $ make DESTDIR=/tmp/dummylocation install +# or +# $ INSTALLPREFIX=/usr/local make install +# or +# $ make install (default INSTALLPREFIX is /usr) +OS = $(shell uname -s) +VERSION = $(shell cat VERSION) + +ifeq ($(OS), Darwin) +JARSUFFIX=mac +LIBTOOL ?= $(shell which libtool) +endif +ifeq ($(OS), Linux) +JARSUFFIX=linux +endif +ifneq (,$(findstring NT-5.1,$(OS))) +JARSUFFIX=win32 +endif + +HAVE_IPV6 ?= yes +export HAVE_IPV6 + +CC ?= gcc +#AR = gar +#CFLAGS = -O -g -DDEBUG +CFLAGS ?= -O +CFLAGS += -Wall +CFLAGS += -W -Wstrict-prototypes +CFLAGS += -fno-common +CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT +CFLAGS += -DMINIUPNPC_GET_SRC_ADDR +CFLAGS += -D_BSD_SOURCE +CFLAGS += -D_DEFAULT_SOURCE +ifneq ($(OS), FreeBSD) +ifneq ($(OS), Darwin) +#CFLAGS += -D_POSIX_C_SOURCE=200112L +CFLAGS += -D_XOPEN_SOURCE=600 +endif +endif +#CFLAGS += -ansi +# -DNO_GETADDRINFO +INSTALL = install +SH = /bin/sh +JAVA = java +# see http://code.google.com/p/jnaerator/ +#JNAERATOR = jnaerator-0.9.7.jar +#JNAERATOR = jnaerator-0.9.8-shaded.jar +#JNAERATORARGS = -library miniupnpc +#JNAERATOR = jnaerator-0.10-shaded.jar +#JNAERATOR = jnaerator-0.11-shaded.jar +# https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12/jnaerator-0.12-shaded.jar +JNAERATOR = jnaerator-0.12-shaded.jar +JNAERATORARGS = -mode StandaloneJar -runtime JNAerator -library miniupnpc +#JNAERATORBASEURL = http://jnaerator.googlecode.com/files/ +JNAERATORBASEURL = https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12 + +ifeq (SunOS, $(OS)) + LDFLAGS=-lsocket -lnsl -lresolv +endif + +# APIVERSION is used to build SONAME +APIVERSION = 15 + +SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \ + upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \ + minixmlvalid.c testupnpreplyparse.c minissdpc.c \ + upnperrors.c testigddescparse.c testminiwget.c \ + connecthostport.c portlistingparse.c receivedata.c \ + upnpdev.c testportlistingparse.c miniupnpcmodule.c \ + minihttptestserver.c \ + listdevices.c + +LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \ + miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ + connecthostport.o portlistingparse.o receivedata.o upnpdev.o + +ifneq ($(OS), AmigaOS) +CFLAGS := -fPIC $(CFLAGS) +LIBOBJS := $(LIBOBJS) minissdpc.o +endif + +OBJS = $(patsubst %.c,%.o,$(SRCS)) + +# HEADERS to install +HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \ + upnpreplyparse.h upnperrors.h miniupnpctypes.h \ + portlistingparse.h \ + upnpdev.h \ + miniupnpc_declspec.h + +# library names +LIBRARY = libminiupnpc.a +ifeq ($(OS), Darwin) + SHAREDLIBRARY = libminiupnpc.dylib + SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib + CFLAGS := -D_DARWIN_C_SOURCE $(CFLAGS) +else +ifeq ($(JARSUFFIX), win32) + SHAREDLIBRARY = miniupnpc.dll +else + # Linux/BSD/etc. + SHAREDLIBRARY = libminiupnpc.so + SONAME = $(SHAREDLIBRARY).$(APIVERSION) +endif +endif + +EXECUTABLES = upnpc-static listdevices +EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \ + testigddescparse testminiwget testportlistingparse + +TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o + +TESTMINIWGETOBJS = miniwget.o testminiwget.o connecthostport.o receivedata.o + +TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o + +TESTPORTLISTINGPARSE = testportlistingparse.o minixml.o portlistingparse.o + +TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.o \ + miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \ + minisoap.o connecthostport.o receivedata.o \ + portlistingparse.o + +ifneq ($(OS), AmigaOS) +EXECUTABLES := $(EXECUTABLES) upnpc-shared +TESTMINIWGETOBJS := $(TESTMINIWGETOBJS) minissdpc.o +TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o +endif + +LIBDIR ?= lib +# install directories +INSTALLPREFIX ?= $(PREFIX)/usr +INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc +INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR) +INSTALLDIRBIN = $(INSTALLPREFIX)/bin +INSTALLDIRMAN = $(INSTALLPREFIX)/share/man + +FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES) +ifneq ($(OS), AmigaOS) +FILESTOINSTALL := $(FILESTOINSTALL) $(SHAREDLIBRARY) +endif + + +.PHONY: install clean depend all check test everything \ + installpythonmodule updateversion +# validateminixml validateminiwget + +all: $(LIBRARY) $(EXECUTABLES) + +test: check + +check: validateminixml validateminiwget validateupnpreplyparse \ + validateportlistingparse validateigddescparse + +everything: all $(EXECUTABLES_ADDTESTS) + +pythonmodule: $(LIBRARY) miniupnpcmodule.c setup.py + python setup.py build + touch $@ + +installpythonmodule: pythonmodule + python setup.py install + +pythonmodule3: $(LIBRARY) miniupnpcmodule.c setup.py + python3 setup.py build + touch $@ + +installpythonmodule3: pythonmodule3 + python3 setup.py install + +validateminixml: minixmlvalid + @echo "minixml validation test" + ./minixmlvalid + touch $@ + +validateminiwget: testminiwget minihttptestserver testminiwget.sh + @echo "miniwget validation test" + ./testminiwget.sh + touch $@ + +validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh + @echo "upnpreplyparse validation test" + ./testupnpreplyparse.sh + touch $@ + +validateportlistingparse: testportlistingparse + @echo "portlistingparse validation test" + ./testportlistingparse + touch $@ + +validateigddescparse: testigddescparse + @echo "igd desc parse validation test" + ./testigddescparse testdesc/new_LiveBox_desc.xml testdesc/new_LiveBox_desc.values + ./testigddescparse testdesc/linksys_WAG200G_desc.xml testdesc/linksys_WAG200G_desc.values + touch $@ + +clean: + $(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h + $(RM) $(EXECUTABLES_ADDTESTS) + # clean python stuff + $(RM) pythonmodule pythonmodule3 + $(RM) validateminixml validateminiwget validateupnpreplyparse + $(RM) validateigddescparse + $(RM) minihttptestserver + $(RM) -r build/ dist/ + #python setup.py clean + # clean jnaerator stuff + $(RM) _jnaerator.* java/miniupnpc_$(OS).jar + +distclean: clean + $(RM) $(JNAERATOR) java/*.jar java/*.class out.errors.txt + +updateversion: miniupnpc.h + cp miniupnpc.h miniupnpc.h.bak + sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h + +install: updateversion $(FILESTOINSTALL) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC) + $(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB) + $(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB) +ifneq ($(OS), AmigaOS) + $(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME) + ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY) +endif + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN) +ifeq ($(OS), AmigaOS) + $(INSTALL) -m 755 upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc +else + $(INSTALL) -m 755 upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc +endif + $(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip +ifneq ($(OS), AmigaOS) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3 + $(INSTALL) -m 644 man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3 +ifeq ($(OS), Linux) + gzip -f $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3 +endif +endif + +install-static: updateversion $(FILESTOINSTALL) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC) + $(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB) + $(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN) + $(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip + +cleaninstall: + $(RM) -r $(DESTDIR)$(INSTALLDIRINC) + $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY) + $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY) + +depend: + makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null + +$(LIBRARY): $(LIBOBJS) +ifeq ($(OS), Darwin) + $(LIBTOOL) -static -o $@ $? +else + $(AR) crs $@ $? +endif + +$(SHAREDLIBRARY): $(LIBOBJS) +ifeq ($(OS), Darwin) +# $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^ + $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(INSTALLDIRLIB)/$(SONAME) -o $@ $^ +else + $(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^ +endif + +upnpc-static: upnpc.o $(LIBRARY) + $(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS) + +upnpc-shared: upnpc.o $(SHAREDLIBRARY) + $(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS) + +listdevices: listdevices.o $(LIBRARY) + +testminixml: $(TESTMINIXMLOBJS) + +testminiwget: $(TESTMINIWGETOBJS) + +minixmlvalid: minixml.o minixmlvalid.o + +testupnpreplyparse: $(TESTUPNPREPLYPARSE) + +testigddescparse: $(TESTIGDDESCPARSE) + +testportlistingparse: $(TESTPORTLISTINGPARSE) + +miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION + $(SH) updateminiupnpcstrings.sh + +# ftp tool supplied with OpenBSD can download files from http. +jnaerator-%.jar: + wget $(JNAERATORBASEURL)/$@ || \ + curl -o $@ $(JNAERATORBASEURL)/$@ || \ + ftp $(JNAERATORBASEURL)/$@ + +jar: $(SHAREDLIBRARY) $(JNAERATOR) + $(JAVA) -jar $(JNAERATOR) $(JNAERATORARGS) \ + miniupnpc.h miniupnpc_declspec.h upnpcommands.h upnpreplyparse.h \ + igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \ + -package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v + +mvn_install: + mvn install:install-file -Dfile=java/miniupnpc_$(JARSUFFIX).jar \ + -DgroupId=com.github \ + -DartifactId=miniupnp \ + -Dversion=$(VERSION) \ + -Dpackaging=jar \ + -Dclassifier=$(JARSUFFIX) \ + -DgeneratePom=true \ + -DcreateChecksum=true + +# make .deb packages +deb: /usr/share/pyshared/stdeb all + (python setup.py --command-packages=stdeb.command bdist_deb) + +# install .deb packages +ideb: + (sudo dpkg -i deb_dist/*.deb) + +/usr/share/pyshared/stdeb: /usr/share/doc/python-all-dev + (sudo apt-get install python-stdeb) + +/usr/share/doc/python-all-dev: + (sudo apt-get install python-all-dev) + +minihttptestserver: minihttptestserver.o + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +igd_desc_parse.o: igd_desc_parse.h +miniupnpc.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h +miniupnpc.o: minissdpc.h miniwget.h minisoap.h minixml.h upnpcommands.h +miniupnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h +miniupnpc.o: connecthostport.h +minixml.o: minixml.h +minisoap.o: minisoap.h miniupnpcstrings.h +miniwget.o: miniupnpcstrings.h miniwget.h miniupnpc_declspec.h +miniwget.o: connecthostport.h receivedata.h +upnpc.o: miniwget.h miniupnpc_declspec.h miniupnpc.h igd_desc_parse.h +upnpc.o: upnpdev.h upnpcommands.h upnpreplyparse.h portlistingparse.h +upnpc.o: miniupnpctypes.h upnperrors.h miniupnpcstrings.h +upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h +upnpcommands.o: miniupnpc_declspec.h miniupnpctypes.h miniupnpc.h +upnpcommands.o: igd_desc_parse.h upnpdev.h +upnpreplyparse.o: upnpreplyparse.h minixml.h +testminixml.o: minixml.h igd_desc_parse.h +minixmlvalid.o: minixml.h +testupnpreplyparse.o: upnpreplyparse.h +minissdpc.o: minissdpc.h miniupnpc_declspec.h upnpdev.h miniupnpc.h +minissdpc.o: igd_desc_parse.h receivedata.h codelength.h +upnperrors.o: upnperrors.h miniupnpc_declspec.h upnpcommands.h +upnperrors.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h +upnperrors.o: miniupnpc.h igd_desc_parse.h upnpdev.h +testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h +testigddescparse.o: miniupnpc_declspec.h upnpdev.h +testminiwget.o: miniwget.h miniupnpc_declspec.h +connecthostport.o: connecthostport.h +portlistingparse.o: portlistingparse.h miniupnpc_declspec.h miniupnpctypes.h +portlistingparse.o: minixml.h +receivedata.o: receivedata.h +upnpdev.o: upnpdev.h miniupnpc_declspec.h +testportlistingparse.o: portlistingparse.h miniupnpc_declspec.h +testportlistingparse.o: miniupnpctypes.h +miniupnpcmodule.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h +miniupnpcmodule.o: upnpdev.h upnpcommands.h upnpreplyparse.h +miniupnpcmodule.o: portlistingparse.h miniupnpctypes.h upnperrors.h +listdevices.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h diff --git a/ext/miniupnpc/Makefile.mingw b/ext/miniupnpc/Makefile.mingw new file mode 100644 index 000000000..6de325fe1 --- /dev/null +++ b/ext/miniupnpc/Makefile.mingw @@ -0,0 +1,98 @@ +# $Id: Makefile.mingw,v 1.22 2015/10/26 16:59:54 nanard Exp $ +# Miniupnp project. +# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ +# (c) 2005-2015 Thomas Bernard +# This Makefile is made for MinGW +# +CC ?= gcc +#CFLAGS = -Wall -g -DDEBUG -D_WIN32_WINNT=0X501 +CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501 +LDLIBS = -lws2_32 -liphlpapi +# -lwsock32 +# -liphlpapi is needed for GetBestRoute() and GetIpAddrTable() +PYTHON=\utils\python25\python +OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \ + minissdpc.o \ + miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ + connecthostport.o portlistingparse.o receivedata.o \ + upnpdev.o +OBJSDLL=$(addprefix dll/, $(OBJS)) + +all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll + +init: + mkdir dll + echo init > init + +clean: + del upnpc testminixml *.o + del dll\*.o + del *.exe + del miniupnpc.dll + del libminiupnpc.a + +libminiupnpc.a: $(OBJS) + $(AR) cr $@ $? + +pythonmodule: libminiupnpc.a + $(PYTHON) setupmingw32.py build --compiler=mingw32 + $(PYTHON) setupmingw32.py install --skip-build + +miniupnpc.dll: libminiupnpc.a $(OBJSDLL) + dllwrap -k --driver-name gcc \ + --def miniupnpc.def \ + --output-def miniupnpc.dll.def \ + --implib miniupnpc.lib -o $@ \ + $(OBJSDLL) $(LDLIBS) + +miniupnpc.lib: miniupnpc.dll +# echo $@ generated with $< + +dll/upnpc.o: upnpc.o +# echo $@ generated with $< + +.c.o: + $(CC) $(CFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $< + $(CC) $(CFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $< + +upnpc.o: upnpc.c + $(CC) $(CFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $< + $(CC) $(CFLAGS) -c -o dll/$@ $< + +# --enable-stdcall-fixup +upnpc-static: upnpc.o libminiupnpc.a + $(CC) -o $@ $^ $(LDLIBS) + +upnpc-shared: dll/upnpc.o miniupnpc.lib + $(CC) -o $@ $^ $(LDLIBS) + +wingenminiupnpcstrings: wingenminiupnpcstrings.o + +wingenminiupnpcstrings.o: wingenminiupnpcstrings.c + +miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings + wingenminiupnpcstrings $< $@ + +minixml.o: minixml.c minixml.h + +upnpc.o: miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h +upnpc.o: upnpreplyparse.h upnpcommands.h upnperrors.h miniupnpcstrings.h + +miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h + +minisoap.o: minisoap.c minisoap.h miniupnpcstrings.h + +miniupnpc.o: miniupnpc.c miniupnpc.h minisoap.h miniwget.h minixml.h + +igd_desc_parse.o: igd_desc_parse.c igd_desc_parse.h + +testminixml: minixml.o igd_desc_parse.o testminixml.c + +upnpreplyparse.o: upnpreplyparse.c upnpreplyparse.h minixml.h + +upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h + +minissdpc.o: minissdpc.c minissdpc.h receivedata.h + +upnpdev.o: upnpdev.c upnpdev.h + diff --git a/ext/miniupnpc/README b/ext/miniupnpc/README index 0d3b8054c..ab08de942 100644 --- a/ext/miniupnpc/README +++ b/ext/miniupnpc/README @@ -1,8 +1,9 @@ Project: miniupnp -Project web page: http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ +Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ github: https://github.com/miniupnp/miniupnp +freecode: http://freecode.com/projects/miniupnp Author: Thomas Bernard -Copyright (c) 2005-2017 Thomas Bernard +Copyright (c) 2005-2014 Thomas Bernard This software is subject to the conditions detailed in the LICENSE file provided within this distribution. @@ -31,7 +32,6 @@ To use the libminiupnpc in your application, link it with libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h, upnpcommands.h and miniwget.h : - upnpDiscover() -- UPNP_GetValidIGD() - miniwget() - parserootdesc() - GetUPNPUrls() @@ -57,7 +57,5 @@ If you are using libminiupnpc in your application, please send me an email ! For any question, you can use the web forum : -https://miniupnp.tuxfamily.org/forum/ +http://miniupnp.tuxfamily.org/forum/ -Bugs should be reported on github : -https://github.com/miniupnp/miniupnp/issues diff --git a/ext/miniupnpc/VERSION b/ext/miniupnpc/VERSION index cd5ac039d..2e0e38c63 100644 --- a/ext/miniupnpc/VERSION +++ b/ext/miniupnpc/VERSION @@ -1 +1 @@ -2.0 +1.9 diff --git a/ext/miniupnpc/apiversions.txt b/ext/miniupnpc/apiversions.txt new file mode 100644 index 000000000..3e9ebef21 --- /dev/null +++ b/ext/miniupnpc/apiversions.txt @@ -0,0 +1,167 @@ +$Id: apiversions.txt,v 1.8 2015/10/08 16:15:47 nanard Exp $ + +Differences in API between miniUPnPc versions + +API version 15 + changed "sameport" argument of upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice() + to "localport". When 0 or 1, behaviour is not changed, but it can take + any other value between 2 and 65535 + Existing programs should be compatible + updated macro : + #define MINIUPNPC_API_VERSION 15 + +API version 14 +miniupnpc.h + add ttl argument to upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice() + upnpDiscoverDevices() + getDevicesFromMiniSSDPD() : + connectToMiniSSDPD() / disconnectFromMiniSSDPD() + requestDevicesFromMiniSSDPD() / receiveDevicesFromMiniSSDPD() + updated macro : + #define MINIUPNPC_API_VERSION 14 + +API version 13 +miniupnpc.h: + add searchalltype param to upnpDiscoverDevices() function + updated macro : + #define MINIUPNPC_API_VERSION 13 + +API version 12 +miniupnpc.h : + add upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices() + functions + updated macros : + #define MINIUPNPC_API_VERSION 12 + +API version 11 + +upnpreplyparse.h / portlistingparse.h : + removed usage of sys/queue.h / bsdqueue.h + +miniupnpc.h: + updated macros : + #define MINIUPNPC_API_VERSION 11 + +====================== miniUPnPc version 1.9 ====================== +API version 10 + +upnpcommands.h: + added argument remoteHost to UPNP_GetSpecificPortMappingEntry() + +miniupnpc.h: + updated macros : + #define MINIUPNPC_VERSION "1.9" + #define MINIUPNPC_API_VERSION 10 + +====================== miniUPnPc version 1.8 ====================== +API version 9 + +miniupnpc.h: + updated macros : + #define MINIUPNPC_VERSION "1.8" + #define MINIUPNPC_API_VERSION 9 + added "unsigned int scope_id;" to struct UPNPDev + added scope_id argument to GetUPNPUrls() + + + +====================== miniUPnPc version 1.7 ====================== +API version 8 + +miniupnpc.h : + add new macros : + #define MINIUPNPC_VERSION "1.7" + #define MINIUPNPC_API_VERSION 8 + add rootdescURL to struct UPNPUrls + + + +====================== miniUPnPc version 1.6 ====================== +API version 8 + +Adding support for IPv6. +igd_desc_parse.h : + struct IGDdatas_service : + add char presentationurl[MINIUPNPC_URL_MAXSIZE]; + struct IGDdatas : + add struct IGDdatas_service IPv6FC; +miniupnpc.h : + new macros : + #define UPNPDISCOVER_SUCCESS (0) + #define UPNPDISCOVER_UNKNOWN_ERROR (-1) + #define UPNPDISCOVER_SOCKET_ERROR (-101) + #define UPNPDISCOVER_MEMORY_ERROR (-102) + simpleUPnPcommand() prototype changed (but is normaly not used by API users) + add arguments ipv6 and error to upnpDiscover() : + struct UPNPDev * + upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int sameport, + int ipv6, + int * error); + add controlURL_6FC member to struct UPNPUrls : + struct UPNPUrls { + char * controlURL; + char * ipcondescURL; + char * controlURL_CIF; + char * controlURL_6FC; + }; + +upnpcommands.h : + add leaseDuration argument to UPNP_AddPortMapping() + add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry() + add UPNP_GetListOfPortMappings() function (IGDv2) + add IGDv2 IPv6 related functions : + UPNP_GetFirewallStatus() + UPNP_GetOutboundPinholeTimeout() + UPNP_AddPinhole() + UPNP_UpdatePinhole() + UPNP_DeletePinhole() + UPNP_CheckPinholeWorking() + UPNP_GetPinholePackets() + + + +====================== miniUPnPc version 1.5 ====================== +API version 5 + +new function : +int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); +new macro in upnpcommands.h : +#define UPNPCOMMAND_HTTP_ERROR + +====================== miniUPnPc version 1.4 ====================== +Same API as version 1.3 + +====================== miniUPnPc version 1.3 ====================== +API version 4 + +Use UNSIGNED_INTEGER type for +UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(), +UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived() +Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping() + +====================== miniUPnPc version 1.2 ====================== +API version 3 + +added sameport argument to upnpDiscover() +struct UPNPDev * +upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int sameport); + +====================== miniUPnPc Version 1.1 ====================== +Same API as 1.0 + + +====================== miniUPnPc Version 1.0 ====================== +API version 2 + + +struct UPNPDev { + struct UPNPDev * pNext; + char * descURL; + char * st; + char buffer[2]; +}; +struct UPNPDev * upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock); + diff --git a/ext/miniupnpc/connecthostport.c b/ext/miniupnpc/connecthostport.c index aed62c76e..854203e03 100644 --- a/ext/miniupnpc/connecthostport.c +++ b/ext/miniupnpc/connecthostport.c @@ -1,10 +1,12 @@ -/* $Id: connecthostport.c,v 1.17 2017/04/21 09:58:30 nanard Exp $ */ +/* $Id: connecthostport.c,v 1.15 2015/10/09 16:26:19 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2010-2017 Thomas Bernard + * Copyright (c) 2010-2015 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ +#define _CRT_SECURE_NO_WARNINGS + /* use getaddrinfo() or gethostbyname() * uncomment the following line in order to use gethostbyname() */ #ifdef NO_GETADDRINFO @@ -36,13 +38,15 @@ /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions * during the connect() call */ #define MINIUPNPC_IGNORE_EINTR +#ifndef USE_GETHOSTBYNAME #include #include +#endif /* #ifndef USE_GETHOSTBYNAME */ #endif /* #else _WIN32 */ /* definition of PRINT_SOCKET_ERROR */ #ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError()); +#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #else #define PRINT_SOCKET_ERROR(x) perror(x) #endif @@ -98,13 +102,13 @@ int connecthostport(const char * host, unsigned short port, timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) { - PRINT_SOCKET_ERROR("setsockopt SO_RCVTIMEO"); + PRINT_SOCKET_ERROR("setsockopt"); } timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) { - PRINT_SOCKET_ERROR("setsockopt SO_SNDTIMEO"); + PRINT_SOCKET_ERROR("setsockopt"); } #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ dest.sin_family = AF_INET; diff --git a/ext/miniupnpc/external-ip.sh b/ext/miniupnpc/external-ip.sh new file mode 100755 index 000000000..965d86b2a --- /dev/null +++ b/ext/miniupnpc/external-ip.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $ +# (c) 2010 Reuben Hawkins +upnpc -s | grep ExternalIPAddress | sed 's/[^0-9\.]//g' diff --git a/ext/miniupnpc/java/JavaBridgeTest.java b/ext/miniupnpc/java/JavaBridgeTest.java new file mode 100644 index 000000000..c658c5990 --- /dev/null +++ b/ext/miniupnpc/java/JavaBridgeTest.java @@ -0,0 +1,97 @@ +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import fr.free.miniupnp.*; + +/** + * + * @author syuu + */ +public class JavaBridgeTest { + public static void main(String[] args) { + int UPNP_DELAY = 2000; + MiniupnpcLibrary miniupnpc = MiniupnpcLibrary.INSTANCE; + UPNPDev devlist = null; + UPNPUrls urls = new UPNPUrls(); + IGDdatas data = new IGDdatas(); + ByteBuffer lanaddr = ByteBuffer.allocate(16); + ByteBuffer intClient = ByteBuffer.allocate(16); + ByteBuffer intPort = ByteBuffer.allocate(6); + ByteBuffer desc = ByteBuffer.allocate(80); + ByteBuffer enabled = ByteBuffer.allocate(4); + ByteBuffer leaseDuration = ByteBuffer.allocate(16); + int ret; + int i; + + if(args.length < 2) { + System.err.println("Usage : java [...] JavaBridgeTest port protocol"); + System.out.println(" port is numeric, protocol is TCP or UDP"); + return; + } + + devlist = miniupnpc.upnpDiscover(UPNP_DELAY, (String) null, (String) null, 0, 0, (byte)2, IntBuffer.allocate(1)); + if (devlist != null) { + System.out.println("List of UPNP devices found on the network :"); + for (UPNPDev device = devlist; device != null; device = device.pNext) { + System.out.println("desc: " + device.descURL.getString(0) + " st: " + device.st.getString(0)); + } + if ((i = miniupnpc.UPNP_GetValidIGD(devlist, urls, data, lanaddr, 16)) != 0) { + switch (i) { + case 1: + System.out.println("Found valid IGD : " + urls.controlURL.getString(0)); + break; + case 2: + System.out.println("Found a (not connected?) IGD : " + urls.controlURL.getString(0)); + System.out.println("Trying to continue anyway"); + break; + case 3: + System.out.println("UPnP device found. Is it an IGD ? : " + urls.controlURL.getString(0)); + System.out.println("Trying to continue anyway"); + break; + default: + System.out.println("Found device (igd ?) : " + urls.controlURL.getString(0)); + System.out.println("Trying to continue anyway"); + + } + System.out.println("Local LAN ip address : " + new String(lanaddr.array())); + ByteBuffer externalAddress = ByteBuffer.allocate(16); + miniupnpc.UPNP_GetExternalIPAddress(urls.controlURL.getString(0), + new String(data.first.servicetype), externalAddress); + System.out.println("ExternalIPAddress = " + new String(externalAddress.array())); + ret = miniupnpc.UPNP_AddPortMapping( + urls.controlURL.getString(0), // controlURL + new String(data.first.servicetype), // servicetype + args[0], // external Port + args[0], // internal Port + new String(lanaddr.array()), // internal client + "added via miniupnpc/JAVA !", // description + args[1], // protocol UDP or TCP + null, // remote host (useless) + "0"); // leaseDuration + if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) + System.out.println("AddPortMapping() failed with code " + ret); + ret = miniupnpc.UPNP_GetSpecificPortMappingEntry( + urls.controlURL.getString(0), new String(data.first.servicetype), + args[0], args[1], null, intClient, intPort, + desc, enabled, leaseDuration); + if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) + System.out.println("GetSpecificPortMappingEntry() failed with code " + ret); + System.out.println("InternalIP:Port = " + + new String(intClient.array()) + ":" + new String(intPort.array()) + + " (" + new String(desc.array()) + ")"); + ret = miniupnpc.UPNP_DeletePortMapping( + urls.controlURL.getString(0), + new String(data.first.servicetype), + args[0], args[1], null); + if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) + System.out.println("DelPortMapping() failed with code " + ret); + miniupnpc.FreeUPNPUrls(urls); + } else { + System.out.println("No valid UPNP Internet Gateway Device found."); + } + miniupnpc.freeUPNPDevlist(devlist); + } else { + System.out.println("No IGD UPnP Device found on the network !\n"); + } + } +} diff --git a/ext/miniupnpc/java/testjava.bat b/ext/miniupnpc/java/testjava.bat new file mode 100755 index 000000000..b836da149 --- /dev/null +++ b/ext/miniupnpc/java/testjava.bat @@ -0,0 +1,8 @@ +@echo off +set JAVA=java +set JAVAC=javac +REM notice the semicolon for Windows. Write once, run ... oh nevermind +set CP=miniupnpc_win32.jar;. + +%JAVAC% -cp "%CP%" JavaBridgeTest.java || exit 1 +%JAVA% -cp "%CP%" JavaBridgeTest 12345 UDP || exit 1 diff --git a/ext/miniupnpc/java/testjava.sh b/ext/miniupnpc/java/testjava.sh new file mode 100755 index 000000000..9880523a1 --- /dev/null +++ b/ext/miniupnpc/java/testjava.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +JAVA=java +JAVAC=javac +CP=$(for i in *.jar; do echo -n $i:; done). + +$JAVAC -cp $CP JavaBridgeTest.java || exit 1 +$JAVA -cp $CP JavaBridgeTest 12345 UDP || exit 1 diff --git a/ext/miniupnpc/man3/miniupnpc.3 b/ext/miniupnpc/man3/miniupnpc.3 new file mode 100644 index 000000000..7b997d475 --- /dev/null +++ b/ext/miniupnpc/man3/miniupnpc.3 @@ -0,0 +1,55 @@ +.TH MINIUPNPC 3 +.SH NAME +miniupnpc \- UPnP client library +.SH SYNOPSIS +.SH DESCRIPTION +The miniupnpc library implement the UPnP protocol defined +to dialog with Internet Gateway Devices. It also has +the ability to use data gathered by minissdpd(1) about +UPnP devices up on the network in order to skip the +long UPnP device discovery process. +.PP +At first, upnpDiscover(3) has to be used to discover UPnP IGD present +on the network. Then UPNP_GetValidIGD(3) to select the right one. +Alternatively, UPNP_GetIGDFromUrl(3) could be used to bypass discovery +process if the root description url of the device to use is known. +Then all the UPNP_* functions can be used, such as +UPNP_GetConnectionTypeInfo(3), UPNP_AddPortMapping(3), etc... +.SH "HEADER FILES" +.IP miniupnpc.h +That's the main header file for the miniupnpc library API. +It contains all the functions and structures related to device discovery. +.IP upnpcommands.h +This header file contain the UPnP IGD methods that are accessible +through the miniupnpc API. The name of the C functions are matching +the UPnP methods names. ie: GetGenericPortMappingEntry is +UPNP_GetGenericPortMappingEntry. +.SH "API FUNCTIONS" +.IP "struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, int * error);" +execute the discovery process. +delay (in millisecond) is the maximum time for waiting any device response. +If available, device list will be obtained from MiniSSDPd. +Default path for minissdpd socket will be used if minissdpdsock argument is NULL. +If multicastif is not NULL, it will be used instead of the default multicast interface for sending SSDP discover packets. +If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent +from the source port 1900 (same as destination port), if set to +UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will +be attempted as the source port. +If ipv6 is not 0, IPv6 is used instead of IPv4 for the discovery process. +.IP "void freeUPNPDevlist(struct UPNPDev * devlist);" +free the list returned by upnpDiscover(). +.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" +browse the list of device returned by upnpDiscover(), find +a live UPnP internet gateway device and fill structures passed as arguments +with data used for UPNP methods invokation. +.IP "int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" +permit to bypass the upnpDiscover() call if the xml root description +URL of the UPnP IGD is known. +Fill structures passed as arguments +with data used for UPNP methods invokation. +.IP "void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);" +.IP "void FreeUPNPUrls(struct UPNPUrls *);" + +.SH "SEE ALSO" +minissdpd(1) +.SH BUGS diff --git a/ext/miniupnpc/mingw32make.bat b/ext/miniupnpc/mingw32make.bat new file mode 100644 index 000000000..c5d3cc4ff --- /dev/null +++ b/ext/miniupnpc/mingw32make.bat @@ -0,0 +1,8 @@ +@mingw32-make -f Makefile.mingw %1 +@if errorlevel 1 goto end +@if not exist upnpc-static.exe goto end +@strip upnpc-static.exe +@upx --best upnpc-static.exe +@strip upnpc-shared.exe +@upx --best upnpc-shared.exe +:end diff --git a/ext/miniupnpc/minihttptestserver.c b/ext/miniupnpc/minihttptestserver.c new file mode 100644 index 000000000..32e3cb78a --- /dev/null +++ b/ext/miniupnpc/minihttptestserver.c @@ -0,0 +1,655 @@ +/* $Id: minihttptestserver.c,v 1.18 2015/07/15 12:41:15 nanard Exp $ */ +/* Project : miniUPnP + * Author : Thomas Bernard + * Copyright (c) 2011-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CRAP_LENGTH (2048) + +volatile sig_atomic_t quit = 0; +volatile sig_atomic_t child_to_wait_for = 0; + +/** + * signal handler for SIGCHLD (child status has changed) + */ +void handle_signal_chld(int sig) +{ + (void)sig; + /* printf("handle_signal_chld(%d)\n", sig); */ + ++child_to_wait_for; +} + +/** + * signal handler for SIGINT (CRTL C) + */ +void handle_signal_int(int sig) +{ + (void)sig; + /* printf("handle_signal_int(%d)\n", sig); */ + quit = 1; +} + +/** + * build a text/plain content of the specified length + */ +void build_content(char * p, int n) +{ + char line_buffer[80]; + int k; + int i = 0; + + while(n > 0) { + k = snprintf(line_buffer, sizeof(line_buffer), + "%04d_ABCDEFGHIJKL_This_line_is_64_bytes_long_ABCDEFGHIJKL_%04d\r\n", + i, i); + if(k != 64) { + fprintf(stderr, "snprintf() returned %d in build_content()\n", k); + } + ++i; + if(n >= 64) { + memcpy(p, line_buffer, 64); + p += 64; + n -= 64; + } else { + memcpy(p, line_buffer, n); + p += n; + n = 0; + } + } +} + +/** + * build crappy content + */ +void build_crap(char * p, int n) +{ + static const char crap[] = "_CRAP_\r\n"; + int i; + + while(n > 0) { + i = sizeof(crap) - 1; + if(i > n) + i = n; + memcpy(p, crap, i); + p += i; + n -= i; + } +} + +/** + * build chunked response. + * return a malloc'ed buffer + */ +char * build_chunked_response(int content_length, int * response_len) +{ + char * response_buffer; + char * content_buffer; + int buffer_length; + int i, n; + + /* allocate to have some margin */ + buffer_length = 256 + content_length + (content_length >> 4); + response_buffer = malloc(buffer_length); + if(response_buffer == NULL) + return NULL; + *response_len = snprintf(response_buffer, buffer_length, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n"); + + /* build the content */ + content_buffer = malloc(content_length); + if(content_buffer == NULL) { + free(response_buffer); + return NULL; + } + build_content(content_buffer, content_length); + + /* chunk it */ + i = 0; + while(i < content_length) { + n = (rand() % 199) + 1; + if(i + n > content_length) { + n = content_length - i; + } + /* TODO : check buffer size ! */ + *response_len += snprintf(response_buffer + *response_len, + buffer_length - *response_len, + "%x\r\n", n); + memcpy(response_buffer + *response_len, content_buffer + i, n); + *response_len += n; + i += n; + response_buffer[(*response_len)++] = '\r'; + response_buffer[(*response_len)++] = '\n'; + } + /* the last chunk : "0\r\n" a empty body and then + * the final "\r\n" */ + memcpy(response_buffer + *response_len, "0\r\n\r\n", 5); + *response_len += 5; + free(content_buffer); + + printf("resp_length=%d buffer_length=%d content_length=%d\n", + *response_len, buffer_length, content_length); + return response_buffer; +} + +/* favicon.ico generator */ +#ifdef OLD_HEADER +#define FAVICON_LENGTH (6 + 16 + 12 + 8 + 32 * 4) +#else +#define FAVICON_LENGTH (6 + 16 + 40 + 8 + 32 * 4) +#endif +void build_favicon_content(char * p, int n) +{ + int i; + if(n < FAVICON_LENGTH) + return; + /* header : 6 bytes */ + *p++ = 0; + *p++ = 0; + *p++ = 1; /* type : ICO */ + *p++ = 0; + *p++ = 1; /* number of images in file */ + *p++ = 0; + /* image directory (1 entry) : 16 bytes */ + *p++ = 16; /* width */ + *p++ = 16; /* height */ + *p++ = 2; /* number of colors in the palette. 0 = no palette */ + *p++ = 0; /* reserved */ + *p++ = 1; /* color planes */ + *p++ = 0; /* " */ + *p++ = 1; /* bpp */ + *p++ = 0; /* " */ +#ifdef OLD_HEADER + *p++ = 12 + 8 + 32 * 4; /* bmp size */ +#else + *p++ = 40 + 8 + 32 * 4; /* bmp size */ +#endif + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 6 + 16; /* bmp offset */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + /* BMP */ +#ifdef OLD_HEADER + /* BITMAPCOREHEADER */ + *p++ = 12; /* size of this header */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 16; /* width */ + *p++ = 0; /* " */ + *p++ = 16 * 2; /* height x 2 ! */ + *p++ = 0; /* " */ + *p++ = 1; /* color planes */ + *p++ = 0; /* " */ + *p++ = 1; /* bpp */ + *p++ = 0; /* " */ +#else + /* BITMAPINFOHEADER */ + *p++ = 40; /* size of this header */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 16; /* width */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 16 * 2; /* height x 2 ! */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 0; /* " */ + *p++ = 1; /* color planes */ + *p++ = 0; /* " */ + *p++ = 1; /* bpp */ + *p++ = 0; /* " */ + /* compression method, image size, ppm x, ppm y */ + /* colors in the palette ? */ + /* important colors */ + for(i = 4 * 6; i > 0; --i) + *p++ = 0; +#endif + /* palette */ + *p++ = 0; /* b */ + *p++ = 0; /* g */ + *p++ = 0; /* r */ + *p++ = 0; /* reserved */ + *p++ = 255; /* b */ + *p++ = 255; /* g */ + *p++ = 255; /* r */ + *p++ = 0; /* reserved */ + /* pixel data */ + for(i = 16; i > 0; --i) { + if(i & 1) { + *p++ = 0125; + *p++ = 0125; + } else { + *p++ = 0252; + *p++ = 0252; + } + *p++ = 0; + *p++ = 0; + } + /* Opacity MASK */ + for(i = 16 * 4; i > 0; --i) { + *p++ = 0; + } +} + +enum modes { + MODE_INVALID, MODE_CHUNKED, MODE_ADDCRAP, MODE_NORMAL, MODE_FAVICON +}; + +const struct { + const enum modes mode; + const char * text; +} modes_array[] = { + {MODE_CHUNKED, "chunked"}, + {MODE_ADDCRAP, "addcrap"}, + {MODE_NORMAL, "normal"}, + {MODE_FAVICON, "favicon.ico"}, + {MODE_INVALID, NULL} +}; + +/** + * write the response with random behaviour ! + */ +void send_response(int c, const char * buffer, int len) +{ + int n; + while(len > 0) { + n = (rand() % 99) + 1; + if(n > len) + n = len; + n = write(c, buffer, n); + if(n < 0) { + if(errno != EINTR) { + perror("write"); + return; + } + /* if errno == EINTR, try again */ + } else { + len -= n; + buffer += n; + } + usleep(10000); /* 10ms */ + } +} + +/** + * handle the HTTP connection + */ +void handle_http_connection(int c) +{ + char request_buffer[2048]; + int request_len = 0; + int headers_found = 0; + int n, i; + char request_method[16]; + char request_uri[256]; + char http_version[16]; + char * p; + char * response_buffer; + int response_len; + enum modes mode; + int content_length = 16*1024; + + /* read the request */ + while(request_len < (int)sizeof(request_buffer) && !headers_found) { + n = read(c, + request_buffer + request_len, + sizeof(request_buffer) - request_len); + if(n < 0) { + if(errno == EINTR) + continue; + perror("read"); + return; + } else if(n==0) { + /* remote host closed the connection */ + break; + } else { + request_len += n; + for(i = 0; i < request_len - 3; i++) { + if(0 == memcmp(request_buffer + i, "\r\n\r\n", 4)) { + /* found the end of headers */ + headers_found = 1; + break; + } + } + } + } + if(!headers_found) { + /* error */ + printf("no HTTP header found in the request\n"); + return; + } + printf("headers :\n%.*s", request_len, request_buffer); + /* the request have been received, now parse the request line */ + p = request_buffer; + for(i = 0; i < (int)sizeof(request_method) - 1; i++) { + if(*p == ' ' || *p == '\r') + break; + request_method[i] = *p; + ++p; + } + request_method[i] = '\0'; + while(*p == ' ') + p++; + for(i = 0; i < (int)sizeof(request_uri) - 1; i++) { + if(*p == ' ' || *p == '\r') + break; + request_uri[i] = *p; + ++p; + } + request_uri[i] = '\0'; + while(*p == ' ') + p++; + for(i = 0; i < (int)sizeof(http_version) - 1; i++) { + if(*p == ' ' || *p == '\r') + break; + http_version[i] = *p; + ++p; + } + http_version[i] = '\0'; + printf("Method = %s, URI = %s, %s\n", + request_method, request_uri, http_version); + /* check if the request method is allowed */ + if(0 != strcmp(request_method, "GET")) { + const char response405[] = "HTTP/1.1 405 Method Not Allowed\r\n" + "Allow: GET\r\n\r\n"; + const char * pc; + /* 405 Method Not Allowed */ + /* The response MUST include an Allow header containing a list + * of valid methods for the requested resource. */ + n = sizeof(response405) - 1; + pc = response405; + while(n > 0) { + i = write(c, pc, n); + if(i<0) { + if(errno != EINTR) { + perror("write"); + return; + } + } else { + n -= i; + pc += i; + } + } + return; + } + + mode = MODE_INVALID; + /* use the request URI to know what to do */ + for(i = 0; modes_array[i].mode != MODE_INVALID; i++) { + if(strstr(request_uri, modes_array[i].text)) { + mode = modes_array[i].mode; /* found */ + break; + } + } + + switch(mode) { + case MODE_CHUNKED: + response_buffer = build_chunked_response(content_length, &response_len); + break; + case MODE_ADDCRAP: + response_len = content_length+256; + response_buffer = malloc(response_len); + if(!response_buffer) + break; + n = snprintf(response_buffer, response_len, + "HTTP/1.1 200 OK\r\n" + "Server: minihttptestserver\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: %d\r\n" + "\r\n", content_length); + response_len = content_length+n+CRAP_LENGTH; + p = realloc(response_buffer, response_len); + if(p == NULL) { + /* error 500 */ + free(response_buffer); + response_buffer = NULL; + break; + } + response_buffer = p; + build_content(response_buffer + n, content_length); + build_crap(response_buffer + n + content_length, CRAP_LENGTH); + break; + case MODE_FAVICON: + content_length = FAVICON_LENGTH; + response_len = content_length + 256; + response_buffer = malloc(response_len); + if(!response_buffer) + break; + n = snprintf(response_buffer, response_len, + "HTTP/1.1 200 OK\r\n" + "Server: minihttptestserver\r\n" + "Content-Type: image/vnd.microsoft.icon\r\n" + "Content-Length: %d\r\n" + "\r\n", content_length); + /* image/x-icon */ + build_favicon_content(response_buffer + n, content_length); + response_len = content_length + n; + break; + default: + response_len = content_length+256; + response_buffer = malloc(response_len); + if(!response_buffer) + break; + n = snprintf(response_buffer, response_len, + "HTTP/1.1 200 OK\r\n" + "Server: minihttptestserver\r\n" + "Content-Type: text/plain\r\n" + "\r\n"); + response_len = content_length+n; + p = realloc(response_buffer, response_len); + if(p == NULL) { + /* Error 500 */ + free(response_buffer); + response_buffer = NULL; + break; + } + response_buffer = p; + build_content(response_buffer + n, response_len - n); + } + + if(response_buffer) { + send_response(c, response_buffer, response_len); + free(response_buffer); + } else { + /* Error 500 */ + } +} + +/** + */ +int main(int argc, char * * argv) { + int ipv6 = 0; + int s, c, i; + unsigned short port = 0; + struct sockaddr_storage server_addr; + socklen_t server_addrlen; + struct sockaddr_storage client_addr; + socklen_t client_addrlen; + pid_t pid; + int child = 0; + int status; + const char * expected_file_name = NULL; + struct sigaction sa; + + for(i = 1; i < argc; i++) { + if(argv[i][0] == '-') { + switch(argv[i][1]) { + case '6': + ipv6 = 1; + break; + case 'e': + /* write expected file ! */ + expected_file_name = argv[++i]; + break; + case 'p': + /* port */ + if(++i < argc) { + port = (unsigned short)atoi(argv[i]); + } + break; + default: + fprintf(stderr, "unknown command line switch '%s'\n", argv[i]); + } + } else { + fprintf(stderr, "unkown command line argument '%s'\n", argv[i]); + } + } + + srand(time(NULL)); + + memset(&sa, 0, sizeof(struct sigaction)); + + /*signal(SIGCHLD, handle_signal_chld);*/ + sa.sa_handler = handle_signal_chld; + if(sigaction(SIGCHLD, &sa, NULL) < 0) { + perror("sigaction"); + return 1; + } + /*signal(SIGINT, handle_signal_int);*/ + sa.sa_handler = handle_signal_int; + if(sigaction(SIGINT, &sa, NULL) < 0) { + perror("sigaction"); + return 1; + } + + s = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0); + if(s < 0) { + perror("socket"); + return 1; + } + memset(&server_addr, 0, sizeof(struct sockaddr_storage)); + memset(&client_addr, 0, sizeof(struct sockaddr_storage)); + if(ipv6) { + struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr; + addr->sin6_family = AF_INET6; + addr->sin6_port = htons(port); + addr->sin6_addr = in6addr_loopback; + } else { + struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr; + addr->sin_family = AF_INET; + addr->sin_port = htons(port); + addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + if(bind(s, (struct sockaddr *)&server_addr, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + return 1; + } + if(listen(s, 5) < 0) { + perror("listen"); + } + if(port == 0) { + server_addrlen = sizeof(struct sockaddr_storage); + if(getsockname(s, (struct sockaddr *)&server_addr, &server_addrlen) < 0) { + perror("getsockname"); + return 1; + } + if(ipv6) { + struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr; + port = ntohs(addr->sin6_port); + } else { + struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr; + port = ntohs(addr->sin_port); + } + printf("Listening on port %hu\n", port); + fflush(stdout); + } + + /* write expected file */ + if(expected_file_name) { + FILE * f; + f = fopen(expected_file_name, "wb"); + if(f) { + char * buffer; + buffer = malloc(16*1024); + if(buffer == NULL) { + fprintf(stderr, "memory allocation error\n"); + } else { + build_content(buffer, 16*1024); + i = fwrite(buffer, 1, 16*1024, f); + if(i != 16*1024) { + fprintf(stderr, "error writing to file %s : %dbytes written (out of %d)\n", expected_file_name, i, 16*1024); + } + free(buffer); + } + fclose(f); + } else { + fprintf(stderr, "error opening file %s for writing\n", expected_file_name); + } + } + + /* fork() loop */ + while(!child && !quit) { + while(child_to_wait_for > 0) { + pid = wait(&status); + if(pid < 0) { + perror("wait"); + } else { + printf("child(%d) terminated with status %d\n", pid, status); + } + --child_to_wait_for; + } + client_addrlen = sizeof(struct sockaddr_storage); + c = accept(s, (struct sockaddr *)&client_addr, + &client_addrlen); + if(c < 0) { + if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + continue; + perror("accept"); + return 1; + } + printf("accept...\n"); + pid = fork(); + if(pid < 0) { + perror("fork"); + return 1; + } else if(pid == 0) { + /* child */ + child = 1; + close(s); + s = -1; + handle_http_connection(c); + } + close(c); + } + if(s >= 0) { + close(s); + s = -1; + } + if(!child) { + while(child_to_wait_for > 0) { + pid = wait(&status); + if(pid < 0) { + perror("wait"); + } else { + printf("child(%d) terminated with status %d\n", pid, status); + } + --child_to_wait_for; + } + printf("Bye...\n"); + } + return 0; +} + diff --git a/ext/miniupnpc/minisoap.c b/ext/miniupnpc/minisoap.c index 11f4635ad..c685aac5b 100644 --- a/ext/miniupnpc/minisoap.c +++ b/ext/miniupnpc/minisoap.c @@ -1,4 +1,5 @@ -/* $Id: minisoap.c,v 1.25 2017/04/21 10:03:24 nanard Exp $ */ +#define _CRT_SECURE_NO_WARNINGS +/* $Id: minisoap.c,v 1.24 2015/10/26 17:05:07 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard @@ -19,18 +20,9 @@ #include #endif #include "minisoap.h" - #ifdef _WIN32 -#undef OS_STRING #define OS_STRING "Win32" -#define MINIUPNPC_VERSION_STRING "2.0" -#define UPNP_VERSION_STRING "UPnP/1.1" -#endif - -#ifdef __ANDROID__ -#undef OS_STRING -#define OS_STRING "Android" -#define MINIUPNPC_VERSION_STRING "2.0" +#define MINIUPNPC_VERSION_STRING "1.9" #define UPNP_VERSION_STRING "UPnP/1.1" #endif @@ -38,7 +30,7 @@ #include #ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError()); +#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #else #define PRINT_SOCKET_ERROR(x) perror(x) #endif @@ -132,5 +124,3 @@ int soapPostSubmit(int fd, #endif return httpWrite(fd, body, bodysize, headerbuf, headerssize); } - - diff --git a/ext/miniupnpc/minissdpc.c b/ext/miniupnpc/minissdpc.c index 3479de8ec..a371d1610 100644 --- a/ext/miniupnpc/minissdpc.c +++ b/ext/miniupnpc/minissdpc.c @@ -1,9 +1,10 @@ -/* $Id: minissdpc.c,v 1.35 2017/11/02 15:34:36 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp +#define _CRT_SECURE_NO_WARNINGS + +/* $Id: minissdpc.c,v 1.30 2015/10/26 17:05:07 nanard Exp $ */ +/* Project : miniupnp * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD - * copyright (c) 2005-2017 Thomas Bernard + * copyright (c) 2005-2015 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ /*#include */ @@ -11,9 +12,6 @@ #include #include #include -#if defined (__NetBSD__) -#include -#endif #if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) #ifdef _WIN32 #include @@ -62,7 +60,7 @@ struct sockaddr_un { #endif #ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError()); +#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #else #define PRINT_SOCKET_ERROR(x) perror(x) #endif @@ -71,13 +69,6 @@ struct sockaddr_un { #define HAS_IP_MREQN #endif -#if !defined(HAS_IP_MREQN) && !defined(_WIN32) -#include -#if defined(__sun) -#include -#endif -#endif - #if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN) /* Several versions of glibc don't define this structure, * define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */ @@ -172,7 +163,7 @@ connectToMiniSSDPD(const char * socketpath) { int s; struct sockaddr_un addr; -#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun) +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT struct timeval timeout; #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ @@ -183,25 +174,23 @@ connectToMiniSSDPD(const char * socketpath) perror("socket(unix)"); return MINISSDPC_SOCKET_ERROR; } -#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun) +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT /* setting a 3 seconds timeout */ - /* not supported for AF_UNIX sockets under Solaris */ timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) { - perror("setsockopt SO_RCVTIMEO unix"); + perror("setsockopt"); } timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) { - perror("setsockopt SO_SNDTIMEO unix"); + perror("setsockopt"); } #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ if(!socketpath) socketpath = "/var/run/minissdpd.sock"; - memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path)); /* TODO : check if we need to handle the EINTR */ @@ -503,7 +492,6 @@ ssdpDiscoverDevices(const char * const deviceTypes[], unsigned long _ttl = (unsigned long)ttl; #endif int linklocal = 1; - int sentok; if(error) *error = MINISSDPC_UNKNOWN_ERROR; @@ -614,27 +602,14 @@ ssdpDiscoverDevices(const char * const deviceTypes[], return NULL; } - if(ipv6) { #ifdef _WIN32 - DWORD mcastHops = ttl; - if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&mcastHops, sizeof(mcastHops)) < 0) + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0) #else /* _WIN32 */ - int mcastHops = ttl; - if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastHops, sizeof(mcastHops)) < 0) + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) #endif /* _WIN32 */ - { - PRINT_SOCKET_ERROR("setsockopt(IPV6_MULTICAST_HOPS,...)"); - } - } else { -#ifdef _WIN32 - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0) -#else /* _WIN32 */ - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) -#endif /* _WIN32 */ - { - /* not a fatal error */ - PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)"); - } + { + /* not a fatal error */ + PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)"); } if(multicastif) @@ -647,7 +622,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) { - PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF"); + PRINT_SOCKET_ERROR("setsockopt"); } #else #ifdef DEBUG @@ -662,7 +637,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { - PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); + PRINT_SOCKET_ERROR("setsockopt"); } } else { #ifdef HAS_IP_MREQN @@ -672,27 +647,13 @@ ssdpDiscoverDevices(const char * const deviceTypes[], reqn.imr_ifindex = if_nametoindex(multicastif); if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) { - PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); + PRINT_SOCKET_ERROR("setsockopt"); } -#elif !defined(_WIN32) - struct ifreq ifr; - int ifrlen = sizeof(ifr); - strncpy(ifr.ifr_name, multicastif, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ-1] = '\0'; - if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0) - { - PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)"); - } - mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); - } -#else /* _WIN32 */ +#else #ifdef DEBUG printf("Setting of multicast interface not supported with interface name.\n"); #endif -#endif /* #ifdef HAS_IP_MREQN / !defined(_WIN32) */ +#endif } } } @@ -719,7 +680,6 @@ ssdpDiscoverDevices(const char * const deviceTypes[], } /* receiving SSDP response packet */ for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { - sentok = 0; /* sending the SSDP M-SEARCH packet */ n = snprintf(bufr, sizeof(bufr), MSearchMsgFmt, @@ -763,8 +723,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], if(error) *error = MINISSDPC_SOCKET_ERROR; PRINT_SOCKET_ERROR("sendto"); - } else { - sentok = 1; + break; } #else /* #ifdef NO_GETADDRINFO */ memset(&hints, 0, sizeof(hints)); @@ -796,20 +755,19 @@ ssdpDiscoverDevices(const char * const deviceTypes[], #endif PRINT_SOCKET_ERROR("sendto"); continue; - } else { - sentok = 1; } } freeaddrinfo(servinfo); - if(!sentok) { + if(n < 0) { if(error) *error = MINISSDPC_SOCKET_ERROR; + break; } #endif /* #ifdef NO_GETADDRINFO */ /* Waiting for SSDP REPLY packet to M-SEARCH * if searchalltypes is set, enter the loop only * when the last deviceType is reached */ - if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do { + if(!searchalltypes || !deviceTypes[deviceIndex + 1]) do { n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); if (n < 0) { /* error */ diff --git a/ext/miniupnpc/miniupnpc.c b/ext/miniupnpc/miniupnpc.c index 2dc5c95cd..566388818 100644 --- a/ext/miniupnpc/miniupnpc.c +++ b/ext/miniupnpc/miniupnpc.c @@ -1,9 +1,10 @@ -/* $Id: miniupnpc.c,v 1.149 2016/02/09 09:50:46 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp +#define _CRT_SECURE_NO_WARNINGS +/* $Id: miniupnpc.c,v 1.141 2015/10/26 17:05:07 nanard Exp $ */ +/* vim: tabstop=4 shiftwidth=4 noexpandtab */ +/* Project : miniupnp * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD - * copyright (c) 2005-2016 Thomas Bernard + * copyright (c) 2005-2015 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #include @@ -72,25 +73,6 @@ #define SERVICEPREFIX "u" #define SERVICEPREFIX2 'u' -/* check if an ip address is a private (LAN) address - * see https://tools.ietf.org/html/rfc1918 */ -static int is_rfc1918addr(const char * addr) -{ - /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */ - if(COMPARE(addr, "192.168.")) - return 1; - /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */ - if(COMPARE(addr, "10.")) - return 1; - /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */ - if(COMPARE(addr, "172.")) { - int i = atoi(addr + 4); - if((16 <= i) && (i <= 31)) - return 1; - } - return 0; -} - /* root description parsing */ MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data) { @@ -126,7 +108,6 @@ char * simpleUPnPcommand2(int s, const char * url, const char * service, int soapbodylen; char * buf; int n; - int status_code; *bufsize = 0; snprintf(soapact, sizeof(soapact), "%s#%s", service, action); @@ -230,15 +211,11 @@ char * simpleUPnPcommand2(int s, const char * url, const char * service, return NULL; } - buf = getHTTPResponse(s, bufsize, &status_code); + buf = getHTTPResponse(s, bufsize); #ifdef DEBUG if(*bufsize > 0 && buf) { - printf("HTTP %d SOAP Response :\n%.*s\n", status_code, *bufsize, buf); - } - else - { - printf("HTTP %d, empty SOAP response. size=%d\n", status_code, *bufsize); + printf("SOAP Response :\n%.*s\n", *bufsize, buf); } #endif closesocket(s); @@ -550,7 +527,7 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) * 3 = an UPnP device has been found but was not recognized as an IGD * * In any positive non zero return case, the urls and data structures - * passed as parameters are set. Dont forget to call FreeUPNPUrls(urls) to + * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. */ MINIUPNP_LIBSPEC int @@ -570,9 +547,6 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ int n_igd = 0; char extIpAddr[16]; - char myLanAddr[40]; - int status_code = -1; - if(!devlist) { #ifdef DEBUG @@ -595,8 +569,8 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, /* we should choose an internet gateway device. * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), - myLanAddr, sizeof(myLanAddr), - dev->scope_id, &status_code); + lanaddr, lanaddrlen, + dev->scope_id); #ifdef DEBUG if(!desc[i].xml) { @@ -613,8 +587,6 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, { desc[i].is_igd = 1; n_igd++; - if(lanaddr) - strncpy(lanaddr, myLanAddr, lanaddrlen); } } } @@ -630,25 +602,20 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, parserootdesc(desc[i].xml, desc[i].size, data); if(desc[i].is_igd || state >= 3 ) { - int is_connected; - GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); /* in state 2 and 3 we dont test if device is connected ! */ if(state >= 2) goto free_and_return; - is_connected = UPNPIGD_IsConnected(urls, data); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", - urls->controlURL, is_connected); + urls->controlURL, + UPNPIGD_IsConnected(urls, data)); #endif /* checks that status is connected AND there is a external IP address assigned */ - if(is_connected && - (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') - && (0 != strcmp(extIpAddr, "0.0.0.0"))) - goto free_and_return; - } + if(UPNPIGD_IsConnected(urls, data) + && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) + goto free_and_return; FreeUPNPUrls(urls); if(data->second.servicetype[0] != '\0') { #ifdef DEBUG @@ -660,17 +627,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); - is_connected = UPNPIGD_IsConnected(urls, data); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", - urls->controlURL, is_connected); + urls->controlURL, + UPNPIGD_IsConnected(urls, data)); #endif - if(is_connected && - (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') - && (0 != strcmp(extIpAddr, "0.0.0.0"))) - goto free_and_return; - } + if(UPNPIGD_IsConnected(urls, data) + && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) + goto free_and_return; FreeUPNPUrls(urls); } } @@ -704,9 +668,8 @@ UPNP_GetIGDFromUrl(const char * rootdescurl, { char * descXML; int descXMLsize = 0; - descXML = miniwget_getaddr(rootdescurl, &descXMLsize, - lanaddr, lanaddrlen, 0, NULL); + lanaddr, lanaddrlen, 0); if(descXML) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); diff --git a/ext/miniupnpc/miniupnpc.h b/ext/miniupnpc/miniupnpc.h index 4a805b11f..dfbfa01f2 100644 --- a/ext/miniupnpc/miniupnpc.h +++ b/ext/miniupnpc/miniupnpc.h @@ -1,8 +1,8 @@ -/* $Id: miniupnpc.h,v 1.50 2016/04/19 21:06:21 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.48 2015/10/08 16:19:40 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard - * Copyright (c) 2005-2016 Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINIUPNPC_H_INCLUDED @@ -19,8 +19,8 @@ #define UPNPDISCOVER_MEMORY_ERROR (-102) /* versions : */ -#define MINIUPNPC_VERSION "2.0.20171212" -#define MINIUPNPC_API_VERSION 16 +#define MINIUPNPC_VERSION "1.9.20151026" +#define MINIUPNPC_API_VERSION 15 /* Source port: Using "1" as an alias for 1900 for backwards compatability diff --git a/ext/miniupnpc/miniupnpcmodule.c b/ext/miniupnpc/miniupnpcmodule.c index bbff07382..a5bdce44f 100644 --- a/ext/miniupnpc/miniupnpcmodule.c +++ b/ext/miniupnpc/miniupnpcmodule.c @@ -1,8 +1,8 @@ -/* $Id: miniupnpcmodule.c,v 1.31 2017/11/02 15:37:28 nanard Exp $*/ +/* $Id: miniupnpcmodule.c,v 1.29 2015/10/26 17:01:30 nanard Exp $*/ /* Project : miniupnp * Author : Thomas BERNARD * website : http://miniupnp.tuxfamily.org/ - * copyright (c) 2007-2016 Thomas Bernard + * copyright (c) 2007-2014 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ #include @@ -12,10 +12,6 @@ #include "upnpcommands.h" #include "upnperrors.h" -#ifdef _WIN32 -#include -#endif - /* for compatibility with Python < 2.4 */ #ifndef Py_RETURN_NONE #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None @@ -307,7 +303,7 @@ UPnP_addportmapping(UPnPObject *self, PyObject *args) const char * remoteHost; const char * leaseDuration = "0"; int r; - if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, + if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto, &host, &iPort, &desc, &remoteHost)) return NULL; Py_BEGIN_ALLOW_THREADS @@ -349,7 +345,7 @@ UPnP_addanyportmapping(UPnPObject *self, PyObject *args) const char * remoteHost; const char * leaseDuration = "0"; int r; - if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost)) + if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto, &host, &iPort, &desc, &remoteHost)) return NULL; Py_BEGIN_ALLOW_THREADS sprintf(extPort, "%hu", ePort); @@ -673,10 +669,6 @@ initminiupnpc(void) PyObject* m; #ifdef _WIN32 - /* initialize Winsock. */ - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - UPnPType.tp_new = PyType_GenericNew; #endif if (PyType_Ready(&UPnPType) < 0) diff --git a/ext/miniupnpc/miniupnpcstrings.h.cmake b/ext/miniupnpc/miniupnpcstrings.h.cmake new file mode 100644 index 000000000..78c8fe9c5 --- /dev/null +++ b/ext/miniupnpc/miniupnpcstrings.h.cmake @@ -0,0 +1,15 @@ +#ifndef MINIUPNPCSTRINGS_H_INCLUDED +#define MINIUPNPCSTRINGS_H_INCLUDED + +#define OS_STRING "${CMAKE_SYSTEM_NAME}" +#define MINIUPNPC_VERSION_STRING "${MINIUPNPC_VERSION}" + +#if 0 +/* according to "UPnP Device Architecture 1.0" */ +#define UPNP_VERSION_STRING "UPnP/1.0" +#else +/* according to "UPnP Device Architecture 1.1" */ +#define UPNP_VERSION_STRING "UPnP/1.1" +#endif + +#endif diff --git a/ext/miniupnpc/miniwget.c b/ext/miniupnpc/miniwget.c index 0c461734f..4b11ea9b8 100644 --- a/ext/miniupnpc/miniwget.c +++ b/ext/miniupnpc/miniwget.c @@ -1,8 +1,9 @@ -/* $Id: miniwget.c,v 1.77 2017/05/09 10:04:57 nanard Exp $ */ +#define _CRT_SECURE_NO_WARNINGS +/* $Id: miniwget.c,v 1.72 2015/10/26 17:05:08 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2017 Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -48,20 +49,12 @@ #define MIN(x,y) (((x)<(y))?(x):(y)) #endif /* MIN */ + #ifdef _WIN32 -#undef OS_STRING #define OS_STRING "Win32" -#define MINIUPNPC_VERSION_STRING "2.0" +#define MINIUPNPC_VERSION_STRING "1.9" #define UPNP_VERSION_STRING "UPnP/1.1" #endif - -#ifdef __ANDROID__ -#undef OS_STRING -#define OS_STRING "Android" -#define MINIUPNPC_VERSION_STRING "2.0" -#define UPNP_VERSION_STRING "UPnP/1.1" -#endif - #include "miniwget.h" #include "connecthostport.h" #include "receivedata.h" @@ -77,7 +70,7 @@ * to the length parameter. */ void * -getHTTPResponse(int s, int * size, int * status_code) +getHTTPResponse(int s, int * size) { char buf[2048]; int n; @@ -95,12 +88,7 @@ getHTTPResponse(int s, int * size, int * status_code) unsigned int content_buf_used = 0; char chunksize_buf[32]; unsigned int chunksize_buf_index; -#ifdef DEBUG - char * reason_phrase = NULL; - int reason_phrase_len = 0; -#endif - if(status_code) *status_code = -1; header_buf = malloc(header_buf_len); if(header_buf == NULL) { @@ -123,7 +111,7 @@ getHTTPResponse(int s, int * size, int * status_code) chunksize_buf[0] = '\0'; chunksize_buf_index = 0; - while((n = receivedata(s, buf, sizeof(buf), 5000, NULL)) > 0) + while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0) { if(endofheaders == 0) { @@ -172,7 +160,7 @@ getHTTPResponse(int s, int * size, int * status_code) continue; /* parse header lines */ for(i = 0; i < endofheaders - 1; i++) { - if(linestart > 0 && colon <= linestart && header_buf[i]==':') + if(colon <= linestart && header_buf[i]==':') { colon = i; while(i < (endofheaders-1) @@ -183,31 +171,7 @@ getHTTPResponse(int s, int * size, int * status_code) /* detecting end of line */ else if(header_buf[i]=='\r' || header_buf[i]=='\n') { - if(linestart == 0 && status_code) - { - /* Status line - * HTTP-Version SP Status-Code SP Reason-Phrase CRLF */ - int sp; - for(sp = 0; sp < i; sp++) - if(header_buf[sp] == ' ') - { - if(*status_code < 0) - *status_code = atoi(header_buf + sp + 1); - else - { -#ifdef DEBUG - reason_phrase = header_buf + sp + 1; - reason_phrase_len = i - sp - 1; -#endif - break; - } - } -#ifdef DEBUG - printf("HTTP status code = %d, Reason phrase = %.*s\n", - *status_code, reason_phrase_len, reason_phrase); -#endif - } - else if(colon > linestart && valuestart > colon) + if(colon > linestart && valuestart > colon) { #ifdef DEBUG printf("header='%.*s', value='%.*s'\n", @@ -296,12 +260,11 @@ getHTTPResponse(int s, int * size, int * status_code) goto end_of_stream; } } - /* it is guaranteed that (n >= i) */ - bytestocopy = (chunksize < (unsigned int)(n - i))?chunksize:(unsigned int)(n - i); + bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i); if((content_buf_used + bytestocopy) > content_buf_len) { char * tmp; - if((content_length >= 0) && ((unsigned int)content_length >= (content_buf_used + bytestocopy))) { + if(content_length >= (int)(content_buf_used + bytestocopy)) { content_buf_len = content_length; } else { content_buf_len = content_buf_used + bytestocopy; @@ -326,15 +289,14 @@ getHTTPResponse(int s, int * size, int * status_code) { /* not chunked */ if(content_length > 0 - && (content_buf_used + n) > (unsigned int)content_length) { + && (int)(content_buf_used + n) > content_length) { /* skipping additional bytes */ n = content_length - content_buf_used; } if(content_buf_used + n > content_buf_len) { char * tmp; - if(content_length >= 0 - && (unsigned int)content_length >= (content_buf_used + n)) { + if(content_length >= (int)(content_buf_used + n)) { content_buf_len = content_length; } else { content_buf_len = content_buf_used + n; @@ -354,7 +316,7 @@ getHTTPResponse(int s, int * size, int * status_code) } } /* use the Content-Length header value if available */ - if(content_length > 0 && content_buf_used >= (unsigned int)content_length) + if(content_length > 0 && (int)content_buf_used >= content_length) { #ifdef DEBUG printf("End of HTTP content\n"); @@ -380,8 +342,7 @@ static void * miniwget3(const char * host, unsigned short port, const char * path, int * size, char * addr_str, int addr_str_len, - const char * httpversion, unsigned int scope_id, - int * status_code) + const char * httpversion, unsigned int scope_id) { char buf[2048]; int s; @@ -479,7 +440,7 @@ miniwget3(const char * host, sent += n; } } - content = getHTTPResponse(s, size, status_code); + content = getHTTPResponse(s, size); closesocket(s); return content; } @@ -488,20 +449,18 @@ miniwget3(const char * host, * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */ static void * miniwget2(const char * host, - unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len, - unsigned int scope_id, int * status_code) + unsigned short port, const char * path, + int * size, char * addr_str, int addr_str_len, + unsigned int scope_id) { char * respbuffer; #if 1 respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.1", - scope_id, status_code); + addr_str, addr_str_len, "1.1", scope_id); #else respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.0", - scope_id, status_code); + addr_str, addr_str_len, "1.0", scope_id); if (*size == 0) { #ifdef DEBUG @@ -509,8 +468,7 @@ miniwget2(const char * host, #endif free(respbuffer); respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.1", - scope_id, status_code); + addr_str, addr_str_len, "1.1", scope_id); } #endif return respbuffer; @@ -635,8 +593,7 @@ parseURL(const char * url, } void * -miniwget(const char * url, int * size, - unsigned int scope_id, int * status_code) +miniwget(const char * url, int * size, unsigned int scope_id) { unsigned short port; char * path; @@ -649,13 +606,12 @@ miniwget(const char * url, int * size, printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", hostname, port, path, scope_id); #endif - return miniwget2(hostname, port, path, size, 0, 0, scope_id, status_code); + return miniwget2(hostname, port, path, size, 0, 0, scope_id); } void * miniwget_getaddr(const char * url, int * size, - char * addr, int addrlen, unsigned int scope_id, - int * status_code) + char * addr, int addrlen, unsigned int scope_id) { unsigned short port; char * path; @@ -670,6 +626,5 @@ miniwget_getaddr(const char * url, int * size, printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", hostname, port, path, scope_id); #endif - return miniwget2(hostname, port, path, size, addr, addrlen, scope_id, status_code); + return miniwget2(hostname, port, path, size, addr, addrlen, scope_id); } - diff --git a/ext/miniupnpc/miniwget.h b/ext/miniupnpc/miniwget.h index 0701494d0..d6db71a85 100644 --- a/ext/miniupnpc/miniwget.h +++ b/ext/miniupnpc/miniwget.h @@ -1,7 +1,7 @@ -/* $Id: miniwget.h,v 1.12 2016/01/24 17:24:36 nanard Exp $ */ +/* $Id: miniwget.h,v 1.10 2015/07/21 13:16:55 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2016 Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ @@ -14,11 +14,11 @@ extern "C" { #endif -MINIUPNP_LIBSPEC void * getHTTPResponse(int s, int * size, int * status_code); +MINIUPNP_LIBSPEC void * getHTTPResponse(int s, int * size); -MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int, int *); +MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int); -MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int, int *); +MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int); int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); diff --git a/ext/miniupnpc/minixml.c b/ext/miniupnpc/minixml.c index 935ec443e..5c79b3c9d 100644 --- a/ext/miniupnpc/minixml.c +++ b/ext/miniupnpc/minixml.c @@ -1,11 +1,11 @@ -/* $Id: minixml.c,v 1.12 2017/12/12 11:17:40 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * minixml.c : the minimum size a xml parser can be ! */ +#define _CRT_SECURE_NO_WARNINGS +/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */ +/* minixml.c : the minimum size a xml parser can be ! */ /* Project : miniupnp * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard -Copyright (c) 2005-2017, Thomas BERNARD +Copyright (c) 2005-2014, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without @@ -162,8 +162,7 @@ static void parseelt(struct xmlparser * p) if (p->xml >= p->xmlend) return; } - /* CDATA are at least 9 + 3 characters long : */ - if((p->xmlend >= (p->xml + (9 + 3))) && (memcmp(p->xml, "xml, "xml += 9; diff --git a/ext/miniupnpc/minixmlvalid.c b/ext/miniupnpc/minixmlvalid.c index dad148812..a86beba8b 100644 --- a/ext/miniupnpc/minixmlvalid.c +++ b/ext/miniupnpc/minixmlvalid.c @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS /* $Id: minixmlvalid.c,v 1.7 2015/07/15 12:41:15 nanard Exp $ */ /* MiniUPnP Project * http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ diff --git a/ext/miniupnpc/msvc/miniupnpc.sln b/ext/miniupnpc/msvc/miniupnpc.sln new file mode 100644 index 000000000..b3da1919e --- /dev/null +++ b/ext/miniupnpc/msvc/miniupnpc.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc.vcproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static.vcproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}" + ProjectSection(ProjectDependencies) = postProject + {D28CE435-CB33-4BAE-8A52-C6EF915956F5} = {D28CE435-CB33-4BAE-8A52-C6EF915956F5} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ext/miniupnpc/msvc/miniupnpc.vcproj b/ext/miniupnpc/msvc/miniupnpc.vcproj new file mode 100644 index 000000000..fb301e3b8 --- /dev/null +++ b/ext/miniupnpc/msvc/miniupnpc.vcproj @@ -0,0 +1,283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/miniupnpc/msvc/upnpc-static.vcproj b/ext/miniupnpc/msvc/upnpc-static.vcproj new file mode 100644 index 000000000..c88c9a6e9 --- /dev/null +++ b/ext/miniupnpc/msvc/upnpc-static.vcproj @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/miniupnpc/portlistingparse.c b/ext/miniupnpc/portlistingparse.c index d1954f59f..0e0927803 100644 --- a/ext/miniupnpc/portlistingparse.c +++ b/ext/miniupnpc/portlistingparse.c @@ -1,7 +1,7 @@ -/* $Id: portlistingparse.c,v 1.10 2016/12/16 08:53:21 nanard Exp $ */ +/* $Id: portlistingparse.c,v 1.9 2015/07/15 12:41:13 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2016 Thomas Bernard + * (c) 2011-2015 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include @@ -55,7 +55,7 @@ startelt(void * d, const char * name, int l) pdata->curelt = PortMappingEltNone; for(i = 0; elements[i].str; i++) { - if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0) + if(memcmp(name, elements[i].str, l) == 0) { pdata->curelt = elements[i].code; break; diff --git a/ext/miniupnpc/pymoduletest.py b/ext/miniupnpc/pymoduletest.py new file mode 100644 index 000000000..9fddd9c29 --- /dev/null +++ b/ext/miniupnpc/pymoduletest.py @@ -0,0 +1,88 @@ +#! /usr/bin/python +# vim: tabstop=2 shiftwidth=2 expandtab +# MiniUPnP project +# Author : Thomas Bernard +# This Sample code is public domain. +# website : http://miniupnp.tuxfamily.org/ + +# import the python miniupnpc module +import miniupnpc +import sys + +try: + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('-m', '--multicastif') + parser.add_argument('-p', '--minissdpdsocket') + parser.add_argument('-d', '--discoverdelay', type=int, default=200) + parser.add_argument('-z', '--localport', type=int, default=0) + # create the object + u = miniupnpc.UPnP(**vars(parser.parse_args())) +except: + print 'argparse not available' + i = 1 + multicastif = None + minissdpdsocket = None + discoverdelay = 200 + localport = 0 + while i < len(sys.argv): + print sys.argv[i] + if sys.argv[i] == '-m' or sys.argv[i] == '--multicastif': + multicastif = sys.argv[i+1] + elif sys.argv[i] == '-p' or sys.argv[i] == '--minissdpdsocket': + minissdpdsocket = sys.argv[i+1] + elif sys.argv[i] == '-d' or sys.argv[i] == '--discoverdelay': + discoverdelay = int(sys.argv[i+1]) + elif sys.argv[i] == '-z' or sys.argv[i] == '--localport': + localport = int(sys.argv[i+1]) + else: + raise Exception('invalid argument %s' % sys.argv[i]) + i += 2 + # create the object + u = miniupnpc.UPnP(multicastif, minissdpdsocket, discoverdelay, localport) + +print 'inital(default) values :' +print ' discoverdelay', u.discoverdelay +print ' lanaddr', u.lanaddr +print ' multicastif', u.multicastif +print ' minissdpdsocket', u.minissdpdsocket +#u.minissdpdsocket = '../minissdpd/minissdpd.sock' +# discovery process, it usualy takes several seconds (2 seconds or more) +print 'Discovering... delay=%ums' % u.discoverdelay +print u.discover(), 'device(s) detected' +# select an igd +try: + u.selectigd() +except Exception, e: + print 'Exception :', e + sys.exit(1) +# display information about the IGD and the internet connection +print 'local ip address :', u.lanaddr +print 'external ip address :', u.externalipaddress() +print u.statusinfo(), u.connectiontype() +print 'total bytes : sent', u.totalbytesent(), 'received', u.totalbytereceived() +print 'total packets : sent', u.totalpacketsent(), 'received', u.totalpacketreceived() + +#print u.addportmapping(64000, 'TCP', +# '192.168.1.166', 63000, 'port mapping test', '') +#print u.deleteportmapping(64000, 'TCP') + +port = 0 +proto = 'UDP' +# list the redirections : +i = 0 +while True: + p = u.getgenericportmapping(i) + if p==None: + break + print i, p + (port, proto, (ihost,iport), desc, c, d, e) = p + #print port, desc + i = i + 1 + +print u.getspecificportmapping(port, proto) +try: + print u.getportmappingnumberofentries() +except Exception, e: + print 'GetPortMappingNumberOfEntries() is not supported :', e + diff --git a/ext/miniupnpc/receivedata.c b/ext/miniupnpc/receivedata.c index 5dbd227b2..fb05e09db 100644 --- a/ext/miniupnpc/receivedata.c +++ b/ext/miniupnpc/receivedata.c @@ -1,4 +1,4 @@ -/* $Id: receivedata.c,v 1.8 2017/04/21 10:16:45 nanard Exp $ */ +/* $Id: receivedata.c,v 1.6 2014/11/13 13:51:52 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard @@ -28,7 +28,7 @@ #endif /* _WIN32 */ #ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError()); +#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #else #define PRINT_SOCKET_ERROR(x) perror(x) #endif @@ -40,7 +40,7 @@ receivedata(int socket, char * data, int length, int timeout, unsigned int * scope_id) { -#ifdef MINIUPNPC_GET_SRC_ADDR +#if MINIUPNPC_GET_SRC_ADDR struct sockaddr_storage src_addr; socklen_t src_addr_len = sizeof(src_addr); #endif /* MINIUPNPC_GET_SRC_ADDR */ @@ -80,7 +80,7 @@ receivedata(int socket, return 0; } #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ -#ifdef MINIUPNPC_GET_SRC_ADDR +#if MINIUPNPC_GET_SRC_ADDR memset(&src_addr, 0, sizeof(src_addr)); n = recvfrom(socket, data, length, 0, (struct sockaddr *)&src_addr, &src_addr_len); @@ -90,7 +90,7 @@ receivedata(int socket, if(n<0) { PRINT_SOCKET_ERROR("recv"); } -#ifdef MINIUPNPC_GET_SRC_ADDR +#if MINIUPNPC_GET_SRC_ADDR if (src_addr.ss_family == AF_INET6) { const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; #ifdef DEBUG diff --git a/ext/miniupnpc/setup.py b/ext/miniupnpc/setup.py new file mode 100644 index 000000000..97e42bf18 --- /dev/null +++ b/ext/miniupnpc/setup.py @@ -0,0 +1,28 @@ +#! /usr/bin/python +# vim: tabstop=8 shiftwidth=8 expandtab +# $Id: setup.py,v 1.12 2015/10/26 17:03:17 nanard Exp $ +# the MiniUPnP Project (c) 2007-2014 Thomas Bernard +# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ +# +# python script to build the miniupnpc module under unix +# +# replace libminiupnpc.a by libminiupnpc.so for shared library usage +try: + from setuptools import setup, Extension +except ImportError: + from distutils.core import setup, Extension +from distutils import sysconfig +sysconfig.get_config_vars()["OPT"] = '' +sysconfig.get_config_vars()["CFLAGS"] = '' +setup(name="miniupnpc", + version=open('VERSION').read().strip(), + author='Thomas BERNARD', + author_email='miniupnp@free.fr', + license=open('LICENSE').read(), + url='http://miniupnp.free.fr/', + description='miniUPnP client', + ext_modules=[ + Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], + extra_objects=["libminiupnpc.a"]) + ]) + diff --git a/ext/miniupnpc/setupmingw32.py b/ext/miniupnpc/setupmingw32.py new file mode 100644 index 000000000..43dfb465d --- /dev/null +++ b/ext/miniupnpc/setupmingw32.py @@ -0,0 +1,28 @@ +#! /usr/bin/python +# vim: tabstop=8 shiftwidth=8 expandtab +# $Id: setupmingw32.py,v 1.10 2015/10/26 17:03:17 nanard Exp $ +# the MiniUPnP Project (c) 2007-2014 Thomas Bernard +# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ +# +# python script to build the miniupnpc module under windows (using mingw32) +# +try: + from setuptools import setup, Extension +except ImportError: + from distutils.core import setup, Extension +from distutils import sysconfig +sysconfig.get_config_vars()["OPT"] = '' +sysconfig.get_config_vars()["CFLAGS"] = '' +setup(name="miniupnpc", + version=open('VERSION').read().strip(), + author='Thomas BERNARD', + author_email='miniupnp@free.fr', + license=open('LICENSE').read(), + url='http://miniupnp.free.fr/', + description='miniUPnP client', + ext_modules=[ + Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], + libraries=["ws2_32", "iphlpapi"], + extra_objects=["libminiupnpc.a"]) + ]) + diff --git a/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values new file mode 100644 index 000000000..cf4222187 --- /dev/null +++ b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values @@ -0,0 +1,14 @@ +# values for linksys_WAG200G_desc.xml + +CIF: + servicetype = urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + controlurl = /upnp/control/WANCommonIFC1 + eventsuburl = /upnp/event/WANCommonIFC1 + scpdurl = /cmnicfg.xml + +first: + servicetype = urn:schemas-upnp-org:service:WANPPPConnection:1 + controlurl = /upnp/control/WANPPPConn1 + eventsuburl = /upnp/event/WANPPPConn1 + scpdurl = /pppcfg.xml + diff --git a/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml new file mode 100644 index 000000000..d428d73b0 --- /dev/null +++ b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml @@ -0,0 +1,110 @@ + + + +1 +0 + +http://192.168.1.1:49152 + +urn:schemas-upnp-org:device:InternetGatewayDevice:1 +LINKSYS WAG200G Gateway +LINKSYS +http://www.linksys.com +LINKSYS WAG200G Gateway +Wireless-G ADSL Home Gateway +WAG200G +http://www.linksys.com +123456789 +uuid:8ca2eb37-1dd2-11b2-86f1-001a709b5aa8 +WAG200G + + +urn:schemas-upnp-org:service:Layer3Forwarding:1 +urn:upnp-org:serviceId:L3Forwarding1 +/upnp/control/L3Forwarding1 +/upnp/event/L3Forwarding1 +/l3frwd.xml + + + + +urn:schemas-upnp-org:device:WANDevice:1 +WANDevice +LINKSYS +http://www.linksys.com/ +Residential Gateway +Internet Connection Sharing +1 +http://www.linksys.com/ +0000001 +uuid:8ca2eb36-1dd2-11b2-86f1-001a709b5aa8 +WAG200G + + +urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 +urn:upnp-org:serviceId:WANCommonIFC1 +/upnp/control/WANCommonIFC1 +/upnp/event/WANCommonIFC1 +/cmnicfg.xml + + + + +urn:schemas-upnp-org:device:WANConnectionDevice:1 +WANConnectionDevice +LINKSYS +http://www.linksys.com/ +Residential Gateway +Internet Connection Sharing +1 +http://www.linksys.com/ +0000001 +uuid:8ca2eb37-1dd2-11b2-86f0-001a709b5aa8 +WAG200G + + +urn:schemas-upnp-org:service:WANEthernetLinkConfig:1 +urn:upnp-org:serviceId:WANEthLinkC1 +/upnp/control/WANEthLinkC1 +/upnp/event/WANEthLinkC1 +/wanelcfg.xml + + +urn:schemas-upnp-org:service:WANPPPConnection:1 +urn:upnp-org:serviceId:WANPPPConn1 +/upnp/control/WANPPPConn1 +/upnp/event/WANPPPConn1 +/pppcfg.xml + + + + + + +urn:schemas-upnp-org:device:LANDevice:1 +LANDevice +LINKSYS +http://www.linksys.com/ +Residential Gateway +Residential Gateway +1 +http://www.linksys.com/ +0000001 +uuid:8ca2eb36-1dd2-11b2-86f0-001a709b5aa +8 +WAG200G + + +urn:schemas-upnp-org:service:LANHostConfigManagement:1 +urn:upnp-org:serviceId:LANHostCfg1 +/upnp/control/LANHostCfg1 +/upnp/event/LANHostCfg1 +/lanhostc.xml + + + + +http://192.168.1.1/index.htm + + + diff --git a/ext/miniupnpc/testdesc/new_LiveBox_desc.values b/ext/miniupnpc/testdesc/new_LiveBox_desc.values new file mode 100644 index 000000000..c55552e58 --- /dev/null +++ b/ext/miniupnpc/testdesc/new_LiveBox_desc.values @@ -0,0 +1,20 @@ +# values for new_LiveBox_desc.xml + +CIF: + servicetype = urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + controlurl = /87895a19/upnp/control/WANCommonIFC1 + eventsuburl = /87895a19/upnp/control/WANCommonIFC1 + scpdurl = /87895a19/gateicfgSCPD.xml + +first: + servicetype = urn:schemas-upnp-org:service:WANPPPConnection:2 + controlurl = /87895a19/upnp/control/WANIPConn1 + eventsuburl = /87895a19/upnp/control/WANIPConn1 + scpdurl = /87895a19/gateconnSCPD_PPP.xml + +IPv6FC: + servicetype = urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + controlurl = /87895a19/upnp/control/WANIPv6FwCtrl1 + eventsuburl = /87895a19/upnp/control/WANIPv6FwCtrl1 + scpdurl = /87895a19/wanipv6fwctrlSCPD.xml + diff --git a/ext/miniupnpc/testdesc/new_LiveBox_desc.xml b/ext/miniupnpc/testdesc/new_LiveBox_desc.xml new file mode 100644 index 000000000..620eb55af --- /dev/null +++ b/ext/miniupnpc/testdesc/new_LiveBox_desc.xml @@ -0,0 +1,90 @@ + + + + 1 + 0 + + + VEN_0129&DEV_0000&SUBSYS_03&REV_250417 + GenericUmPass + NetworkInfrastructure.Gateway + Network.Gateway + urn:schemas-upnp-org:device:InternetGatewayDevice:2 + Orange Livebox + Sagemcom + http://www.sagemcom.com/ + Residential Livebox,(DSL,WAN Ethernet) + uuid:87895a19-50f9-3736-a87f-115c230155f8 + Sagemcom,fr,SG30_sip-fr-4.28.35.1 + 3 + LK14129DP441489 + http://192.168.1.1 + + + + image/png + 16 + 16 + 8 + /87895a19/ligd.png + + + + + urn:schemas-upnp-org:device:WANDevice:2 + WANDevice + Sagemcom + http://www.sagemcom.com/ + WAN Device on Sagemcom,fr,SG30_sip-fr-4.28.35.1 + Residential Livebox,(DSL,WAN Ethernet) + 3 + http://www.sagemcom.com/ + LK14129DP441489 + http://192.168.1.1 + uuid:e2397374-53d8-3fc6-8306-593ba1a34625 + + + + urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + urn:upnp-org:serviceId:WANCommonIFC1 + /87895a19/upnp/control/WANCommonIFC1 + /87895a19/upnp/control/WANCommonIFC1 + /87895a19/gateicfgSCPD.xml + + + + + urn:schemas-upnp-org:device:WANConnectionDevice:2 + WANConnectionDevice + Sagemcom + http://www.sagemcom.com/ + WanConnectionDevice on Sagemcom,fr,SG30_sip-fr-4.28.35.1 + Residential Livebox,(DSL,WAN Ethernet) + 3 + http://www.sagemcom.com/ + LK14129DP441489 + http://192.168.1.1 + uuid:44598a08-288e-32c9-8a4d-d3c008ede331 + + + + urn:schemas-upnp-org:service:WANPPPConnection:2 + urn:upnp-org:serviceId:WANIPConn1 + /87895a19/upnp/control/WANIPConn1 + /87895a19/upnp/control/WANIPConn1 + /87895a19/gateconnSCPD_PPP.xml + + + urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + urn:upnp-org:serviceId:WANIPv6FwCtrl1 + /87895a19/upnp/control/WANIPv6FwCtrl1 + /87895a19/upnp/control/WANIPv6FwCtrl1 + /87895a19/wanipv6fwctrlSCPD.xml + + + + + + + + \ No newline at end of file diff --git a/ext/miniupnpc/testigddescparse.c b/ext/miniupnpc/testigddescparse.c new file mode 100644 index 000000000..c1907fd05 --- /dev/null +++ b/ext/miniupnpc/testigddescparse.c @@ -0,0 +1,187 @@ +/* $Id: testigddescparse.c,v 1.10 2015/08/06 09:55:24 nanard Exp $ */ +/* Project : miniupnp + * http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2008-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#include +#include +#include +#include "igd_desc_parse.h" +#include "minixml.h" +#include "miniupnpc.h" + +/* count number of differences */ +int compare_service(struct IGDdatas_service * s, FILE * f) +{ + int n = 0; + char line[1024]; + + while(fgets(line, sizeof(line), f)) { + char * value; + char * equal; + char * name; + char * parsedvalue; + int l; + l = strlen(line); + while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n') || (line[l-1] == ' '))) + line[--l] = '\0'; + if(l == 0) + break; /* end on blank line */ + if(line[0] == '#') + continue; /* skip comments */ + equal = strchr(line, '='); + if(equal == NULL) { + fprintf(stderr, "Warning, line does not contain '=' : %s\n", line); + continue; + } + *equal = '\0'; + name = line; + while(*name == ' ' || *name == '\t') + name++; + l = strlen(name); + while((l > 0) && (name[l-1] == ' ' || name[l-1] == '\t')) + name[--l] = '\0'; + value = equal + 1; + while(*value == ' ' || *value == '\t') + value++; + if(strcmp(name, "controlurl") == 0) + parsedvalue = s->controlurl; + else if(strcmp(name, "eventsuburl") == 0) + parsedvalue = s->eventsuburl; + else if(strcmp(name, "scpdurl") == 0) + parsedvalue = s->scpdurl; + else if(strcmp(name, "servicetype") == 0) + parsedvalue = s->servicetype; + else { + fprintf(stderr, "unknown field '%s'\n", name); + continue; + } + if(0 != strcmp(parsedvalue, value)) { + fprintf(stderr, "difference : '%s' != '%s'\n", parsedvalue, value); + n++; + } + } + return n; +} + +int compare_igd(struct IGDdatas * p, FILE * f) +{ + int n = 0; + char line[1024]; + struct IGDdatas_service * s; + + while(fgets(line, sizeof(line), f)) { + char * colon; + int l = (int)strlen(line); + while((l > 0) && (line[l-1] == '\r' || (line[l-1] == '\n'))) + line[--l] = '\0'; + if(l == 0 || line[0] == '#') + continue; /* skip blank lines and comments */ + colon = strchr(line, ':'); + if(colon == NULL) { + fprintf(stderr, "Warning, no ':' : %s\n", line); + continue; + } + s = NULL; + *colon = '\0'; + if(strcmp(line, "CIF") == 0) + s = &p->CIF; + else if(strcmp(line, "first") == 0) + s = &p->first; + else if(strcmp(line, "second") == 0) + s = &p->second; + else if(strcmp(line, "IPv6FC") == 0) + s = &p->IPv6FC; + else { + s = NULL; + fprintf(stderr, "*** unknown service '%s' ***\n", line); + n++; + continue; + } + n += compare_service(s, f); + } + if(n > 0) + fprintf(stderr, "*** %d difference%s ***\n", n, (n > 1) ? "s" : ""); + return n; +} + +int test_igd_desc_parse(char * buffer, int len, FILE * f) +{ + int n; + struct IGDdatas igd; + struct xmlparser parser; + struct UPNPUrls urls; + + memset(&igd, 0, sizeof(struct IGDdatas)); + memset(&parser, 0, sizeof(struct xmlparser)); + parser.xmlstart = buffer; + parser.xmlsize = len; + parser.data = &igd; + parser.starteltfunc = IGDstartelt; + parser.endeltfunc = IGDendelt; + parser.datafunc = IGDdata; + parsexml(&parser); +#ifdef DEBUG + printIGD(&igd); +#endif /* DEBUG */ + GetUPNPUrls(&urls, &igd, "http://fake/desc/url/file.xml", 0); + printf("ipcondescURL='%s'\n", urls.ipcondescURL); + printf("controlURL='%s'\n", urls.controlURL); + printf("controlURL_CIF='%s'\n", urls.controlURL_CIF); + n = f ? compare_igd(&igd, f) : 0; + FreeUPNPUrls(&urls); + return n; +} + +int main(int argc, char * * argv) +{ + FILE * f; + char * buffer; + int len; + int r; + if(argc<2) { + fprintf(stderr, "Usage: %s file.xml [file.values]\n", argv[0]); + return 1; + } + f = fopen(argv[1], "r"); + if(!f) { + fprintf(stderr, "Cannot open %s for reading.\n", argv[1]); + return 1; + } + fseek(f, 0, SEEK_END); + len = ftell(f); + fseek(f, 0, SEEK_SET); + buffer = malloc(len); + if(!buffer) { + fprintf(stderr, "Memory allocation error.\n"); + fclose(f); + return 1; + } + r = (int)fread(buffer, 1, len, f); + if(r != len) { + fprintf(stderr, "Failed to read file %s. %d out of %d bytes.\n", + argv[1], r, len); + fclose(f); + free(buffer); + return 1; + } + fclose(f); + f = NULL; + if(argc > 2) { + f = fopen(argv[2], "r"); + if(!f) { + fprintf(stderr, "Cannot open %s for reading.\n", argv[2]); + free(buffer); + return 1; + } + } + r = test_igd_desc_parse(buffer, len, f); + free(buffer); + if(f) + fclose(f); + return r; +} + diff --git a/ext/miniupnpc/testminiwget.c b/ext/miniupnpc/testminiwget.c new file mode 100644 index 000000000..8ae90320e --- /dev/null +++ b/ext/miniupnpc/testminiwget.c @@ -0,0 +1,53 @@ +/* $Id: testminiwget.c,v 1.4 2012/06/23 22:35:59 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#include +#include +#include "miniwget.h" + +/** + * This program uses the miniwget / miniwget_getaddr function + * from miniwget.c in order to retreive a web ressource using + * a GET HTTP method, and store it in a file. + */ +int main(int argc, char * * argv) +{ + void * data; + int size, writtensize; + FILE *f; + char addr[64]; + + if(argc < 3) { + fprintf(stderr, "Usage:\t%s url file\n", argv[0]); + fprintf(stderr, "Example:\t%s http://www.google.com/ out.html\n", argv[0]); + return 1; + } + data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr), 0); + if(!data) { + fprintf(stderr, "Error fetching %s\n", argv[1]); + return 1; + } + printf("local address : %s\n", addr); + printf("got %d bytes\n", size); + f = fopen(argv[2], "wb"); + if(!f) { + fprintf(stderr, "Cannot open file %s for writing\n", argv[2]); + free(data); + return 1; + } + writtensize = fwrite(data, 1, size, f); + if(writtensize != size) { + fprintf(stderr, "Could only write %d bytes out of %d to %s\n", + writtensize, size, argv[2]); + } else { + printf("%d bytes written to %s\n", writtensize, argv[2]); + } + fclose(f); + free(data); + return 0; +} + diff --git a/ext/miniupnpc/testminiwget.sh b/ext/miniupnpc/testminiwget.sh new file mode 100755 index 000000000..690b4056f --- /dev/null +++ b/ext/miniupnpc/testminiwget.sh @@ -0,0 +1,96 @@ +#!/bin/sh +# $Id: testminiwget.sh,v 1.13 2015/09/03 17:57:44 nanard Exp $ +# project miniupnp : http://miniupnp.free.fr/ +# (c) 2011-2015 Thomas Bernard +# +# test program for miniwget.c +# is usually invoked by "make check" +# +# This test program : +# 1 - launches a local HTTP server (minihttptestserver) +# 2 - uses testminiwget to retreive data from this server +# 3 - compares served and received data +# 4 - kills the local HTTP server and exits +# +# The script was tested and works with ksh, bash +# it should now also run with dash + +TMPD=`mktemp -d -t miniwgetXXXXXXXXXX` +HTTPSERVEROUT="${TMPD}/httpserverout" +EXPECTEDFILE="${TMPD}/expectedfile" +DOWNLOADEDFILE="${TMPD}/downloadedfile" +PORT= +RET=0 + +case "$HAVE_IPV6" in + n|no|0) + ADDR=localhost + SERVERARGS="" + ;; + *) + ADDR="[::1]" + SERVERARGS="-6" + ;; + +esac + +#make minihttptestserver +#make testminiwget + +# launching the test HTTP server +./minihttptestserver $SERVERARGS -e $EXPECTEDFILE > $HTTPSERVEROUT & +SERVERPID=$! +while [ -z "$PORT" ]; do + sleep 1 + PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' ` +done +echo "Test HTTP server is listening on $PORT" + +URL1="http://$ADDR:$PORT/index.html" +URL2="http://$ADDR:$PORT/chunked" +URL3="http://$ADDR:$PORT/addcrap" + +echo "standard test ..." +./testminiwget $URL1 "${DOWNLOADEDFILE}.1" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.1" ; then + echo "ok" +else + echo "standard test FAILED" + RET=1 +fi + +echo "chunked transfert encoding test ..." +./testminiwget $URL2 "${DOWNLOADEDFILE}.2" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.2" ; then + echo "ok" +else + echo "chunked transfert encoding test FAILED" + RET=1 +fi + +echo "response too long test ..." +./testminiwget $URL3 "${DOWNLOADEDFILE}.3" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.3" ; then + echo "ok" +else + echo "response too long test FAILED" + RET=1 +fi + +# kill the test HTTP server +kill $SERVERPID +wait $SERVERPID + +# remove temporary files (for success cases) +if [ $RET -eq 0 ]; then + rm -f "${DOWNLOADEDFILE}.1" + rm -f "${DOWNLOADEDFILE}.2" + rm -f "${DOWNLOADEDFILE}.3" + rm -f $EXPECTEDFILE $HTTPSERVEROUT + rmdir ${TMPD} +else + echo "at least one of the test FAILED" + echo "directory ${TMPD} is left intact" +fi +exit $RET + diff --git a/ext/miniupnpc/testminixml.c b/ext/miniupnpc/testminixml.c new file mode 100644 index 000000000..57c4a85eb --- /dev/null +++ b/ext/miniupnpc/testminixml.c @@ -0,0 +1,89 @@ +/* $Id: testminixml.c,v 1.10 2014/11/17 17:19:13 nanard Exp $ + * MiniUPnP project + * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author : Thomas Bernard. + * Copyright (c) 2005-2014 Thomas Bernard + * + * testminixml.c + * test program for the "minixml" functions. + */ +#include +#include +#include +#include "minixml.h" +#include "igd_desc_parse.h" + +/* ---------------------------------------------------------------------- */ +void printeltname1(void * d, const char * name, int l) +{ + int i; + (void)d; + printf("element "); + for(i=0;i +#include +#include "portlistingparse.h" + +struct port_mapping { + unsigned int leasetime; + unsigned short externalport; + unsigned short internalport; + const char * remotehost; + const char * client; + const char * proto; + const char * desc; + unsigned char enabled; +}; + +/* return the number of differences */ +int test(const char * portListingXml, int portListingXmlLen, + const struct port_mapping * ref, int count) +{ + int i; + int r = 0; + struct PortMappingParserData data; + struct PortMapping * pm; + + memset(&data, 0, sizeof(data)); + ParsePortListing(portListingXml, portListingXmlLen, &data); + for(i = 0, pm = data.l_head; + (pm != NULL) && (i < count); + i++, pm = pm->l_next) { + printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", + i, pm->protocol, pm->externalPort, pm->internalClient, + pm->internalPort, + pm->description, pm->remoteHost, + (unsigned)pm->leaseTime); + if(0 != strcmp(pm->protocol, ref[i].proto)) { + printf("protocol : '%s' != '%s'\n", pm->protocol, ref[i].proto); + r++; + } + if(pm->externalPort != ref[i].externalport) { + printf("externalPort : %hu != %hu\n", + pm->externalPort, ref[i].externalport); + r++; + } + if(0 != strcmp(pm->internalClient, ref[i].client)) { + printf("client : '%s' != '%s'\n", + pm->internalClient, ref[i].client); + r++; + } + if(pm->internalPort != ref[i].internalport) { + printf("internalPort : %hu != %hu\n", + pm->internalPort, ref[i].internalport); + r++; + } + if(0 != strcmp(pm->description, ref[i].desc)) { + printf("description : '%s' != '%s'\n", + pm->description, ref[i].desc); + r++; + } + if(0 != strcmp(pm->remoteHost, ref[i].remotehost)) { + printf("remoteHost : '%s' != '%s'\n", + pm->remoteHost, ref[i].remotehost); + r++; + } + if((unsigned)pm->leaseTime != ref[i].leasetime) { + printf("leaseTime : %u != %u\n", + (unsigned)pm->leaseTime, ref[i].leasetime); + r++; + } + if(pm->enabled != ref[i].enabled) { + printf("enabled : %d != %d\n", + (int)pm->enabled, (int)ref[i].enabled); + r++; + } + } + if((i != count) || (pm != NULL)) { + printf("count mismatch : i=%d count=%d pm=%p\n", i, count, pm); + r++; + } + FreePortListing(&data); + return r; +} + +const char test_document[] = +"\n" +"\n" +" \n" +" \n" +" 5002\n" +" UDP\n" +" 4001\n" +" 192.168.1.123\n" +" 1\n" +" xxx\n" +" 0\n" +" \n" +" \n" +" 202.233.2.1\n" +" 2345\n" +" TCP\n" +" 2349\n" +" 192.168.1.137\n" +" 1\n" +" dooom\n" +" 346\n" +" \n" +" \n" +" 134.231.2.11\n" +" 12345\n" +" TCP\n" +" 12345\n" +" 192.168.1.137\n" +" 1\n" +" dooom A\n" +" 347\n" +" \n" +""; + +#define PORT_MAPPINGS_COUNT 3 +const struct port_mapping port_mappings[PORT_MAPPINGS_COUNT] = { +{347, 12345, 12345, "134.231.2.11", "192.168.1.137", "TCP", "dooom A", 1}, +{346, 2345, 2349, "202.233.2.1", "192.168.1.137", "TCP", "dooom", 1}, +{0, 5002, 4001, "", "192.168.1.123", "UDP", "xxx", 1} +}; + +/* --- main --- */ +int main(void) +{ + int r; + r = test(test_document, sizeof(test_document) - 1, + port_mappings, PORT_MAPPINGS_COUNT); + if(r == 0) { + printf("test of portlistingparse OK\n"); + return 0; + } else { + printf("test FAILED (%d differences counted)\n", r); + return 1; + } +} + diff --git a/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue b/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue new file mode 100644 index 000000000..48ca0cccb --- /dev/null +++ b/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue @@ -0,0 +1,3 @@ +NewRemoteHost= +NewExternalPort=123 +NewProtocol=TCP diff --git a/ext/miniupnpc/testreplyparse/DeletePortMapping.xml b/ext/miniupnpc/testreplyparse/DeletePortMapping.xml new file mode 100644 index 000000000..a955c53fc --- /dev/null +++ b/ext/miniupnpc/testreplyparse/DeletePortMapping.xml @@ -0,0 +1,6 @@ + +123 +TCP + + + diff --git a/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue new file mode 100644 index 000000000..5aa75f882 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue @@ -0,0 +1,2 @@ +NewExternalIPAddress=1.2.3.4 + diff --git a/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml new file mode 100644 index 000000000..db7ec1f9c --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml @@ -0,0 +1,2 @@ +1.2.3.4 + diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue new file mode 100644 index 000000000..26b169c35 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue @@ -0,0 +1,3 @@ +NewProtocol=UDP +NewExternalPort=12345 +NewRemoteHost= diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml new file mode 100644 index 000000000..bbb540eac --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml @@ -0,0 +1,3 @@ + +12345UDP + diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue new file mode 100644 index 000000000..2189789b4 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue @@ -0,0 +1,5 @@ +NewInternalPort=12345 +NewInternalClient=192.168.10.110 +NewEnabled=1 +NewPortMappingDescription=libminiupnpc +NewLeaseDuration=0 diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml new file mode 100644 index 000000000..77e8d9c7c --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml @@ -0,0 +1,2 @@ +12345192.168.10.1101libminiupnpc0 + diff --git a/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue new file mode 100644 index 000000000..f78c7e2ae --- /dev/null +++ b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue @@ -0,0 +1 @@ +NewDefaultConnectionService=uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID diff --git a/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml new file mode 100644 index 000000000..ac04c07a9 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml @@ -0,0 +1 @@ +uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID diff --git a/ext/miniupnpc/testreplyparse/readme.txt b/ext/miniupnpc/testreplyparse/readme.txt new file mode 100644 index 000000000..3eb1f015f --- /dev/null +++ b/ext/miniupnpc/testreplyparse/readme.txt @@ -0,0 +1,7 @@ +This directory contains files used for validation of upnpreplyparse.c code. + +Each .xml file to parse should give the results which are in the .namevalue +file. + +A .namevalue file contain name=value lines. + diff --git a/ext/miniupnpc/testupnpigd.py b/ext/miniupnpc/testupnpigd.py new file mode 100755 index 000000000..6d167a4ce --- /dev/null +++ b/ext/miniupnpc/testupnpigd.py @@ -0,0 +1,84 @@ +#! /usr/bin/python +# $Id: testupnpigd.py,v 1.4 2008/10/11 10:27:20 nanard Exp $ +# MiniUPnP project +# Author : Thomas Bernard +# This Sample code is public domain. +# website : http://miniupnp.tuxfamily.org/ + +# import the python miniupnpc module +import miniupnpc +import socket +import BaseHTTPServer + +# function definition +def list_redirections(): + i = 0 + while True: + p = u.getgenericportmapping(i) + if p==None: + break + print i, p + i = i + 1 + +#define the handler class for HTTP connections +class handler_class(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(self): + self.send_response(200) + self.end_headers() + self.wfile.write("OK MON GARS") + +# create the object +u = miniupnpc.UPnP() +#print 'inital(default) values :' +#print ' discoverdelay', u.discoverdelay +#print ' lanaddr', u.lanaddr +#print ' multicastif', u.multicastif +#print ' minissdpdsocket', u.minissdpdsocket +u.discoverdelay = 200; + +try: + print 'Discovering... delay=%ums' % u.discoverdelay + ndevices = u.discover() + print ndevices, 'device(s) detected' + + # select an igd + u.selectigd() + # display information about the IGD and the internet connection + print 'local ip address :', u.lanaddr + externalipaddress = u.externalipaddress() + print 'external ip address :', externalipaddress + print u.statusinfo(), u.connectiontype() + + #instanciate a HTTPd object. The port is assigned by the system. + httpd = BaseHTTPServer.HTTPServer((u.lanaddr, 0), handler_class) + eport = httpd.server_port + + # find a free port for the redirection + r = u.getspecificportmapping(eport, 'TCP') + while r != None and eport < 65536: + eport = eport + 1 + r = u.getspecificportmapping(eport, 'TCP') + + print 'trying to redirect %s port %u TCP => %s port %u TCP' % (externalipaddress, eport, u.lanaddr, httpd.server_port) + + b = u.addportmapping(eport, 'TCP', u.lanaddr, httpd.server_port, + 'UPnP IGD Tester port %u' % eport, '') + if b: + print 'Success. Now waiting for some HTTP request on http://%s:%u' % (externalipaddress ,eport) + try: + httpd.handle_request() + httpd.server_close() + except KeyboardInterrupt, details: + print "CTRL-C exception!", details + b = u.deleteportmapping(eport, 'TCP') + if b: + print 'Successfully deleted port mapping' + else: + print 'Failed to remove port mapping' + else: + print 'Failed' + + httpd.server_close() + +except Exception, e: + print 'Exception :', e diff --git a/ext/miniupnpc/testupnpreplyparse.c b/ext/miniupnpc/testupnpreplyparse.c new file mode 100644 index 000000000..7ba7131ea --- /dev/null +++ b/ext/miniupnpc/testupnpreplyparse.c @@ -0,0 +1,96 @@ +/* $Id: testupnpreplyparse.c,v 1.4 2014/01/27 11:45:19 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2014 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ +#include +#include +#include +#include "upnpreplyparse.h" + +int +test_parsing(const char * buf, int len, FILE * f) +{ + char line[1024]; + struct NameValueParserData pdata; + int ok = 1; + ParseNameValue(buf, len, &pdata); + /* check result */ + if(f != NULL) + { + while(fgets(line, sizeof(line), f)) + { + char * value; + char * equal; + char * parsedvalue; + int l; + l = strlen(line); + while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n'))) + line[--l] = '\0'; + /* skip empty lines */ + if(l == 0) + continue; + equal = strchr(line, '='); + if(equal == NULL) + { + fprintf(stderr, "Warning, line does not contain '=' : %s\n", line); + continue; + } + *equal = '\0'; + value = equal + 1; + parsedvalue = GetValueFromNameValueList(&pdata, line); + if((parsedvalue == NULL) || (strcmp(parsedvalue, value) != 0)) + { + fprintf(stderr, "Element <%s> : expecting value '%s', got '%s'\n", + line, value, parsedvalue ? parsedvalue : ""); + ok = 0; + } + } + } + ClearNameValueList(&pdata); + return ok; +} + +int main(int argc, char * * argv) +{ + FILE * f; + char buffer[4096]; + int l; + int ok; + + if(argc<2) + { + fprintf(stderr, "Usage: %s file.xml [file.namevalues]\n", argv[0]); + return 1; + } + f = fopen(argv[1], "r"); + if(!f) + { + fprintf(stderr, "Error : can not open file %s\n", argv[1]); + return 2; + } + l = fread(buffer, 1, sizeof(buffer)-1, f); + fclose(f); + f = NULL; + buffer[l] = '\0'; + if(argc > 2) + { + f = fopen(argv[2], "r"); + if(!f) + { + fprintf(stderr, "Error : can not open file %s\n", argv[2]); + return 2; + } + } +#ifdef DEBUG + DisplayNameValueList(buffer, l); +#endif + ok = test_parsing(buffer, l, f); + if(f) + { + fclose(f); + } + return ok ? 0 : 3; +} + diff --git a/ext/miniupnpc/testupnpreplyparse.sh b/ext/miniupnpc/testupnpreplyparse.sh new file mode 100755 index 000000000..992930b7b --- /dev/null +++ b/ext/miniupnpc/testupnpreplyparse.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +for f in testreplyparse/*.xml ; do + bf="`dirname $f`/`basename $f .xml`" + if ./testupnpreplyparse $f $bf.namevalue ; then + echo "$f : passed" + else + echo "$f : FAILED" + exit 1 + fi +done + +exit 0 + diff --git a/ext/miniupnpc/upnpc.c b/ext/miniupnpc/upnpc.c index e719ecec5..8bc552efe 100644 --- a/ext/miniupnpc/upnpc.c +++ b/ext/miniupnpc/upnpc.c @@ -1,7 +1,7 @@ -/* $Id: upnpc.c,v 1.117 2017/05/26 15:26:55 nanard Exp $ */ +/* $Id: upnpc.c,v 1.112 2015/10/08 16:15:48 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2017 Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -66,7 +66,7 @@ static void DisplayInfos(struct UPNPUrls * urls, char connectionType[64]; char status[64]; char lastconnerr[64]; - unsigned int uptime = 0; + unsigned int uptime; unsigned int brUp, brDown; time_t timenow, timestarted; int r; @@ -82,11 +82,9 @@ static void DisplayInfos(struct UPNPUrls * urls, else printf("Status : %s, uptime=%us, LastConnectionError : %s\n", status, uptime, lastconnerr); - if(uptime > 0) { - timenow = time(NULL); - timestarted = timenow - uptime; - printf(" Time started : %s", ctime(×tarted)); - } + timenow = time(NULL); + timestarted = timenow - uptime; + printf(" Time started : %s", ctime(×tarted)); if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype, &brDown, &brUp) != UPNPCOMMAND_SUCCESS) { printf("GetLinkLayerMaxBitRates failed.\n"); @@ -242,7 +240,7 @@ static void NewListRedirections(struct UPNPUrls * urls, * 2 - get extenal ip address * 3 - Add port mapping * 4 - get this port mapping from the IGD */ -static int SetRedirectAndTest(struct UPNPUrls * urls, +static void SetRedirectAndTest(struct UPNPUrls * urls, struct IGDdatas * data, const char * iaddr, const char * iport, @@ -262,13 +260,13 @@ static int SetRedirectAndTest(struct UPNPUrls * urls, if(!iaddr || !iport || !eport || !proto) { fprintf(stderr, "Wrong arguments\n"); - return -1; + return; } proto = protofix(proto); if(!proto) { fprintf(stderr, "invalid protocol\n"); - return -1; + return; } r = UPNP_GetExternalIPAddress(urls->controlURL, @@ -292,11 +290,9 @@ static int SetRedirectAndTest(struct UPNPUrls * urls, r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, eport, iport, iaddr, description, proto, 0, leaseDuration); - if(r!=UPNPCOMMAND_SUCCESS) { + if(r!=UPNPCOMMAND_SUCCESS) printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", eport, iport, iaddr, r, strupnperror(r)); - return -2; - } } r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, @@ -304,19 +300,17 @@ static int SetRedirectAndTest(struct UPNPUrls * urls, eport, proto, NULL/*remoteHost*/, intClient, intPort, NULL/*desc*/, NULL/*enabled*/, duration); - if(r!=UPNPCOMMAND_SUCCESS) { + if(r!=UPNPCOMMAND_SUCCESS) printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", r, strupnperror(r)); - return -2; - } else { + else { printf("InternalIP:Port = %s:%s\n", intClient, intPort); printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", externalIPAddress, eport, proto, intClient, intPort, duration); } - return 0; } -static int +static void RemoveRedirect(struct UPNPUrls * urls, struct IGDdatas * data, const char * eport, @@ -327,25 +321,19 @@ RemoveRedirect(struct UPNPUrls * urls, if(!proto || !eport) { fprintf(stderr, "invalid arguments\n"); - return -1; + return; } proto = protofix(proto); if(!proto) { fprintf(stderr, "protocol invalid\n"); - return -1; + return; } r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("UPNP_DeletePortMapping() failed with code : %d\n", r); - return -2; - }else { - printf("UPNP_DeletePortMapping() returned : %d\n", r); - } - return 0; + printf("UPNP_DeletePortMapping() returned : %d\n", r); } -static int +static void RemoveRedirectRange(struct UPNPUrls * urls, struct IGDdatas * data, const char * ePortStart, char const * ePortEnd, @@ -359,22 +347,16 @@ RemoveRedirectRange(struct UPNPUrls * urls, if(!proto || !ePortStart || !ePortEnd) { fprintf(stderr, "invalid arguments\n"); - return -1; + return; } proto = protofix(proto); if(!proto) { fprintf(stderr, "protocol invalid\n"); - return -1; + return; } r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r); - return -2; - }else { - printf("UPNP_DeletePortMappingRange() returned : %d\n", r); - } - return 0; + printf("UPNP_DeletePortMappingRange() returned : %d\n", r); } /* IGD:2, functions for service WANIPv6FirewallControl:1 */ @@ -556,7 +538,7 @@ int main(int argc, char ** argv) char ** commandargv = 0; int commandargc = 0; struct UPNPDev * devlist = 0; - char lanaddr[64] = "unset"; /* my ip address on the LAN */ + char lanaddr[64]; /* my ip address on the LAN */ int i; const char * rootdescurl = 0; const char * multicastif = 0; @@ -578,8 +560,8 @@ int main(int argc, char ** argv) } #endif printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING); - printf(" (c) 2005-2017 Thomas Bernard.\n"); - printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n" + printf(" (c) 2005-2015 Thomas Bernard.\n"); + printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" "for more information.\n"); /* command line processing */ for(i=1; i 4)?commandargv[4]:"0", - description, 0) < 0) - retcode = 2; + description, 0); break; case 'd': - if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1], - commandargc > 2 ? commandargv[2] : NULL) < 0) - retcode = 2; + RemoveRedirect(&urls, &data, commandargv[0], commandargv[1], + commandargc > 2 ? commandargv[2] : NULL); break; case 'n': /* aNy */ - if (SetRedirectAndTest(&urls, &data, + SetRedirectAndTest(&urls, &data, commandargv[0], commandargv[1], commandargv[2], commandargv[3], (commandargc > 4)?commandargv[4]:"0", - description, 1) < 0) - retcode = 2; + description, 1); break; case 'N': if (commandargc < 3) fprintf(stderr, "too few arguments\n"); - if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2], - commandargc > 3 ? commandargv[3] : NULL) < 0) - retcode = 2; + RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2], + commandargc > 3 ? commandargv[3] : NULL); break; case 's': GetConnectionStatus(&urls, &data); @@ -769,19 +747,17 @@ int main(int argc, char ** argv) break; } else if(is_int(commandargv[i+1])){ /* 2nd parameter is an integer : */ - if (SetRedirectAndTest(&urls, &data, + SetRedirectAndTest(&urls, &data, lanaddr, commandargv[i], commandargv[i+1], commandargv[i+2], "0", - description, 0) < 0) - retcode = 2; + description, 0); i+=3; /* 3 parameters parsed */ } else { /* 2nd parameter not an integer : */ - if (SetRedirectAndTest(&urls, &data, + SetRedirectAndTest(&urls, &data, lanaddr, commandargv[i], commandargv[i], commandargv[i+1], "0", - description, 0) < 0) - retcode = 2; + description, 0); i+=2; /* 2 parameters parsed */ } } diff --git a/ext/miniupnpc/upnpcommands.c b/ext/miniupnpc/upnpcommands.c index d786e5338..660b5d9f2 100644 --- a/ext/miniupnpc/upnpcommands.c +++ b/ext/miniupnpc/upnpcommands.c @@ -1,8 +1,8 @@ -/* $Id: upnpcommands.c,v 1.48 2017/04/21 10:22:40 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp +#define _CRT_SECURE_NO_WARNINGS +/* $Id: upnpcommands.c,v 1.46 2015/07/15 12:19:00 nanard Exp $ */ +/* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2017 Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ @@ -373,11 +373,10 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; AddPortMappingArgs[7].elt = "NewLeaseDuration"; AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "AddPortMapping", AddPortMappingArgs, - &bufsize); - free(AddPortMappingArgs); - if(!buffer) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddPortMapping", AddPortMappingArgs, + &bufsize))) { + free(AddPortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ @@ -394,6 +393,7 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); + free(AddPortMappingArgs); return ret; } @@ -437,11 +437,10 @@ UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; AddPortMappingArgs[7].elt = "NewLeaseDuration"; AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "AddAnyPortMapping", AddPortMappingArgs, - &bufsize); - free(AddPortMappingArgs); - if(!buffer) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddAnyPortMapping", AddPortMappingArgs, + &bufsize))) { + free(AddPortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); @@ -463,6 +462,7 @@ UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, } } ClearNameValueList(&pdata); + free(AddPortMappingArgs); return ret; } @@ -491,11 +491,10 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, DeletePortMappingArgs[1].val = extPort; DeletePortMappingArgs[2].elt = "NewProtocol"; DeletePortMappingArgs[2].val = proto; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePortMapping", - DeletePortMappingArgs, &bufsize); - free(DeletePortMappingArgs); - if(!buffer) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "DeletePortMapping", + DeletePortMappingArgs, &bufsize))) { + free(DeletePortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ @@ -509,6 +508,7 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); + free(DeletePortMappingArgs); return ret; } @@ -540,11 +540,10 @@ UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, DeletePortMappingArgs[3].elt = "NewManage"; DeletePortMappingArgs[3].val = manage; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePortMappingRange", - DeletePortMappingArgs, &bufsize); - free(DeletePortMappingArgs); - if(!buffer) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "DeletePortMappingRange", + DeletePortMappingArgs, &bufsize))) { + free(DeletePortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); @@ -557,6 +556,7 @@ UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); + free(DeletePortMappingArgs); return ret; } @@ -588,11 +588,10 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, return UPNPCOMMAND_MEM_ALLOC_ERROR; GetPortMappingArgs[0].elt = "NewPortMappingIndex"; GetPortMappingArgs[0].val = index; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetGenericPortMappingEntry", - GetPortMappingArgs, &bufsize); - free(GetPortMappingArgs); - if(!buffer) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetGenericPortMappingEntry", + GetPortMappingArgs, &bufsize))) { + free(GetPortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); @@ -618,14 +617,14 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, protocol[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewInternalClient"); - if(p) + if(p && intClient) { strncpy(intClient, p, 16); intClient[15] = '\0'; r = 0; } p = GetValueFromNameValueList(&pdata, "NewInternalPort"); - if(p) + if(p && intPort) { strncpy(intPort, p, 6); intPort[5] = '\0'; @@ -654,6 +653,7 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, sscanf(p, "%d", &r); } ClearNameValueList(&pdata); + free(GetPortMappingArgs); return r; } @@ -729,11 +729,10 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, GetPortMappingArgs[1].val = extPort; GetPortMappingArgs[2].elt = "NewProtocol"; GetPortMappingArgs[2].val = proto; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetSpecificPortMappingEntry", - GetPortMappingArgs, &bufsize); - free(GetPortMappingArgs); - if(!buffer) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetSpecificPortMappingEntry", + GetPortMappingArgs, &bufsize))) { + free(GetPortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ @@ -781,6 +780,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, } ClearNameValueList(&pdata); + free(GetPortMappingArgs); return ret; } @@ -825,13 +825,13 @@ UPNP_GetListOfPortMappings(const char * controlURL, GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts"; GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000"; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetListOfPortMappings", - GetListOfPortMappingsArgs, &bufsize); - free(GetListOfPortMappingsArgs); - if(!buffer) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetListOfPortMappings", + GetListOfPortMappingsArgs, &bufsize))) { + free(GetListOfPortMappingsArgs); return UPNPCOMMAND_HTTP_ERROR; } + free(GetListOfPortMappingsArgs); /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); @@ -955,7 +955,6 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype GetOutboundPinholeTimeoutArgs[4].val = intClient; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize); - free(GetOutboundPinholeTimeoutArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); @@ -974,6 +973,7 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype *opTimeout = my_atoui(p); } ClearNameValueList(&pdata); + free(GetOutboundPinholeTimeoutArgs); return ret; } @@ -1032,7 +1032,6 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype, AddPinholeArgs[5].val = leaseTime; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "AddPinhole", AddPinholeArgs, &bufsize); - free(AddPinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); @@ -1055,6 +1054,7 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype, ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); + free(AddPinholeArgs); return ret; } @@ -1082,7 +1082,6 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, UpdatePinholeArgs[1].val = leaseTime; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "UpdatePinhole", UpdatePinholeArgs, &bufsize); - free(UpdatePinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); @@ -1099,6 +1098,7 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); + free(UpdatePinholeArgs); return ret; } @@ -1123,7 +1123,6 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char DeletePinholeArgs[0].val = uniqueID; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "DeletePinhole", DeletePinholeArgs, &bufsize); - free(DeletePinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; /*DisplayNameValueList(buffer, bufsize);*/ @@ -1140,6 +1139,7 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); + free(DeletePinholeArgs); return ret; } @@ -1164,11 +1164,8 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, CheckPinholeWorkingArgs[0].val = uniqueID; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize); - free(CheckPinholeWorkingArgs); if(!buffer) - { return UPNPCOMMAND_HTTP_ERROR; - } ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; @@ -1189,6 +1186,7 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, } ClearNameValueList(&pdata); + free(CheckPinholeWorkingArgs); return ret; } @@ -1213,7 +1211,6 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, GetPinholePacketsArgs[0].val = uniqueID; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetPinholePackets", GetPinholePacketsArgs, &bufsize); - free(GetPinholePacketsArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); @@ -1234,6 +1231,7 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, } ClearNameValueList(&pdata); + free(GetPinholePacketsArgs); return ret; } diff --git a/ext/miniupnpc/upnpreplyparse.c b/ext/miniupnpc/upnpreplyparse.c index 5921349d3..88d77a66a 100644 --- a/ext/miniupnpc/upnpreplyparse.c +++ b/ext/miniupnpc/upnpreplyparse.c @@ -1,8 +1,8 @@ -/* $Id: upnpreplyparse.c,v 1.20 2017/12/12 11:26:25 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project +#define _CRT_SECURE_NO_WARNINGS +/* $Id: upnpreplyparse.c,v 1.19 2015/07/15 10:29:11 nanard Exp $ */ +/* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard + * (c) 2006-2015 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -27,12 +27,12 @@ NameValueParserStartElt(void * d, const char * name, int l) } static void -NameValueParserEndElt(void * d, const char * name, int namelen) +NameValueParserEndElt(void * d, const char * name, int l) { struct NameValueParserData * data = (struct NameValueParserData *)d; struct NameValue * nv; (void)name; - (void)namelen; + (void)l; if(!data->topelt) return; if(strcmp(data->curelt, "NewPortListing") != 0) @@ -105,7 +105,9 @@ ParseNameValue(const char * buffer, int bufsize, struct NameValueParserData * data) { struct xmlparser parser; - memset(data, 0, sizeof(struct NameValueParserData)); + data->l_head = NULL; + data->portListing = NULL; + data->portListingLength = 0; /* init xmlparser object */ parser.xmlstart = buffer; parser.xmlsize = bufsize; diff --git a/ext/misc/linux-old-glibc-compat.c b/ext/misc/linux-old-glibc-compat.c deleted file mode 100644 index 6d793a2d0..000000000 --- a/ext/misc/linux-old-glibc-compat.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -__asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); - -#ifdef __cplusplus -extern "C" { -#endif - -extern void *__wrap_memcpy(void *dest,const void *src,size_t n) -{ - return memcpy(dest,src,n); -} - -#ifdef __cplusplus -} -#endif diff --git a/ext/nlohmann/LICENSE.MIT b/ext/nlohmann/LICENSE.MIT deleted file mode 100644 index 00599afe6..000000000 --- a/ext/nlohmann/LICENSE.MIT +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2013-2017 Niels Lohmann - -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. diff --git a/ext/nlohmann/README.md b/ext/nlohmann/README.md deleted file mode 100644 index f3bbf847c..000000000 --- a/ext/nlohmann/README.md +++ /dev/null @@ -1,1123 +0,0 @@ -[![JSON for Modern C++](https://raw.githubusercontent.com/nlohmann/json/master/doc/json.gif)](https://github.com/nlohmann/json/releases) - -[![Build Status](https://travis-ci.org/nlohmann/json.svg?branch=master)](https://travis-ci.org/nlohmann/json) -[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json) -[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json) -[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json) -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f3732b3327e34358a0e9d1fe9f661f08)](https://www.codacy.com/app/nlohmann/json?utm_source=github.com&utm_medium=referral&utm_content=nlohmann/json&utm_campaign=Badge_Grade) -[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/TarF5pPn9NtHQjhf) -[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json) -[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) -[![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases) -[![GitHub Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](http://github.com/nlohmann/json/issues) -[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/nlohmann/json.svg)](http://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue") -[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289) - -- [Design goals](#design-goals) -- [Integration](#integration) -- [Examples](#examples) - - [JSON as first-class data type](#json-as-first-class-data-type) - - [Serialization / Deserialization](#serialization--deserialization) - - [STL-like access](#stl-like-access) - - [Conversion from STL containers](#conversion-from-stl-containers) - - [JSON Pointer and JSON Patch](#json-pointer-and-json-patch) - - [JSON Merge Patch](#json-merge-patch) - - [Implicit conversions](#implicit-conversions) - - [Conversions to/from arbitrary types](#arbitrary-types-conversions) - - [Binary formats (CBOR, MessagePack, and UBJSON)](#binary-formats-cbor-messagepack-and-ubjson) -- [Supported compilers](#supported-compilers) -- [License](#license) -- [Contact](#contact) -- [Thanks](#thanks) -- [Used third-party tools](#used-third-party-tools) -- [Projects using JSON for Modern C++](#projects-using-json-for-modern-c) -- [Notes](#notes) -- [Execute unit tests](#execute-unit-tests) - -## Design goals - -There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals: - -- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you'll know what I mean. - -- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings. - -- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/test/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests agains all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289). - -Other aspects were not so important to us: - -- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs. - -- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set. - -See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information. - - -## Integration - -[`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) is the single required file in `single_include/nlohmann` or [released here](https://github.com/nlohmann/json/releases). You need to add - -```cpp -#include - -// for convenience -using json = nlohmann::json; -``` - -to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang). - -You can further use file [`include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/json_fwd.hpp) for forward-declarations. The installation of json_fwd.hpp (as part of cmake's install step), can be achieved by setting `-DJSON_MultipleHeaders=ON`. - -### Package Managers - -:beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann_json --HEAD`. - -If you are using the [Meson Build System](http://mesonbuild.com), then you can wrap this repository as a subproject. - -If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `jsonformoderncpp/x.y.z@vthiery/stable` to your `conanfile.py`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/vthiery/conan-jsonformoderncpp/issues) if you experience problems with the packages. - -If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the `nlohmann_json` package. Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging. - -If you are using [hunter](https://github.com/ruslo/hunter/) on your project for external dependencies, then you can use the [nlohmann_json package](https://docs.hunter.sh/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging. - -If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo install nlohmann/json`. Please file issues [here](https://github.com/LoopPerfect/buckaroo-recipes/issues/new?title=nlohmann/nlohmann/json). - -If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can use the [nlohmann-json package](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json). Please see the vcpkg project for any issues regarding the packaging. - -If you are using [cget](http://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install nlohmann/json`. A specific version can be installed with `cget install nlohmann/json@v3.1.0`. Also, the multiple header version can be installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`). - -If you are using [CocoaPods](https://cocoapods.org), you can use the library by adding pod `"nlohmann_json", '~>3.1.2'` to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues [here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open). - -## Examples - -Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)). - -### JSON as first-class data type - -Here are some examples to give you an idea how to use the class. - -Assume you want to create the JSON object - -```json -{ - "pi": 3.141, - "happy": true, - "name": "Niels", - "nothing": null, - "answer": { - "everything": 42 - }, - "list": [1, 0, 2], - "object": { - "currency": "USD", - "value": 42.99 - } -} -``` - -With this library, you could write: - -```cpp -// create an empty structure (null) -json j; - -// add a number that is stored as double (note the implicit conversion of j to an object) -j["pi"] = 3.141; - -// add a Boolean that is stored as bool -j["happy"] = true; - -// add a string that is stored as std::string -j["name"] = "Niels"; - -// add another null object by passing nullptr -j["nothing"] = nullptr; - -// add an object inside the object -j["answer"]["everything"] = 42; - -// add an array that is stored as std::vector (using an initializer list) -j["list"] = { 1, 0, 2 }; - -// add another object (using an initializer list of pairs) -j["object"] = { {"currency", "USD"}, {"value", 42.99} }; - -// instead, you could also write (which looks very similar to the JSON above) -json j2 = { - {"pi", 3.141}, - {"happy", true}, - {"name", "Niels"}, - {"nothing", nullptr}, - {"answer", { - {"everything", 42} - }}, - {"list", {1, 0, 2}}, - {"object", { - {"currency", "USD"}, - {"value", 42.99} - }} -}; -``` - -Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aa80485befaffcadaa39965494e0b4d2e.html#aa80485befaffcadaa39965494e0b4d2e) and [`json::object`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aa13f7c0615867542ce80337cbcf13ada.html#aa13f7c0615867542ce80337cbcf13ada) will help: - -```cpp -// a way to express the empty array [] -json empty_array_explicit = json::array(); - -// ways to express the empty object {} -json empty_object_implicit = json({}); -json empty_object_explicit = json::object(); - -// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]] -json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} }); -``` - -### Serialization / Deserialization - -#### To/from strings - -You can create a JSON value (deserialization) by appending `_json` to a string literal: - -```cpp -// create object from string literal -json j = "{ \"happy\": true, \"pi\": 3.141 }"_json; - -// or even nicer with a raw string literal -auto j2 = R"( - { - "happy": true, - "pi": 3.141 - } -)"_json; -``` - -Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object. - -The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aa9676414f2e36383c4b181fe856aa3c0.html#aa9676414f2e36383c4b181fe856aa3c0): - -```cpp -// parse explicitly -auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }"); -``` - -You can also get a string representation of a JSON value (serialize): - -```cpp -// explicit conversion to string -std::string s = j.dump(); // {\"happy\":true,\"pi\":3.141} - -// serialization with pretty printing -// pass in the amount of spaces to indent -std::cout << j.dump(4) << std::endl; -// { -// "happy": true, -// "pi": 3.141 -// } -``` - -Note the difference between serialization and assignment: - -```cpp -// store a string in a JSON value -json j_string = "this is a string"; - -// retrieve the string value (implicit JSON to std::string conversion) -std::string cpp_string = j_string; -// retrieve the string value (explicit JSON to std::string conversion) -auto cpp_string2 = j_string.get(); - -// retrieve the serialized value (explicit JSON serialization) -std::string serialized_string = j_string.dump(); - -// output of original string -std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get() << '\n'; -// output of serialized value -std::cout << j_string << " == " << serialized_string << std::endl; -``` - -[`.dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5adea76fedba9898d404fef8598aa663.html#a5adea76fedba9898d404fef8598aa663) always returns the serialized value, and [`.get()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a16f9445f7629f634221a42b967cdcd43.html#a16f9445f7629f634221a42b967cdcd43) returns the originally stored string value. - -Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5adea76fedba9898d404fef8598aa663.html#a5adea76fedba9898d404fef8598aa663) may throw an exception. - -#### To/from streams (e.g. files, string streams) - -You can also use streams to serialize and deserialize: - -```cpp -// deserialize from standard input -json j; -std::cin >> j; - -// serialize to standard output -std::cout << j; - -// the setw manipulator was overloaded to set the indentation for pretty printing -std::cout << std::setw(4) << j << std::endl; -``` - -These operators work for any subclasses of `std::istream` or `std::ostream`. Here is the same example with files: - -```cpp -// read a JSON file -std::ifstream i("file.json"); -json j; -i >> j; - -// write prettified JSON to another file -std::ofstream o("pretty.json"); -o << std::setw(4) << j << std::endl; -``` - -Please note that setting the exception bit for `failbit` is inappropriate for this use case. It will result in program termination due to the `noexcept` specifier in use. - -#### Read from iterator range - -You can also parse JSON from an iterator range; that is, from any container accessible by iterators whose content is stored as contiguous byte sequence, for instance a `std::vector`: - -```cpp -std::vector v = {'t', 'r', 'u', 'e'}; -json j = json::parse(v.begin(), v.end()); -``` - -You may leave the iterators for the range [begin, end): - -```cpp -std::vector v = {'t', 'r', 'u', 'e'}; -json j = json::parse(v); -``` - -#### SAX interface - -The library uses a SAX-like interface with the following functions: - -```cpp -// called when null is parsed -bool null(); - -// called when a boolean is parsed; value is passed -bool boolean(bool val); - -// called when a signed or unsigned integer number is parsed; value is passed -bool number_integer(number_integer_t val); -bool number_unsigned(number_unsigned_t val); - -// called when a floating-point number is parsed; value and original string is passed -bool number_float(number_float_t val, const string_t& s); - -// called when a string is parsed; value is passed and can be safely moved away -bool string(string_t& val); - -// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known) -bool start_object(std::size_t elements); -bool end_object(); -bool start_array(std::size_t elements); -bool end_array(); -// called when an object key is parsed; value is passed and can be safely moved away -bool key(string_t& val); - -// called when a parse error occurs; byte position, the last token, and an exception is passed -bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex); -``` - -The return value of each function determines whether parsing should proceed. - -To implement your own SAX handler, proceed as follows: - -1. Implement the SAX interface in a class. You can use class `nlohmann::json_sax` as base class, but you can also use any class where the functions described above are implemented and public. -2. Create an object of your SAX interface class, e.g. `my_sax`. -3. Call `bool json::sax_parse(input, &my_sax)`; where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface. - -Note the `sax_parse` function only returns a `bool` indicating the result of the last executed SAX event. It does not return a `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp). - - -### STL-like access - -We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) requirement. - -```cpp -// create an array using push_back -json j; -j.push_back("foo"); -j.push_back(1); -j.push_back(true); - -// also use emplace_back -j.emplace_back(1.78); - -// iterate the array -for (json::iterator it = j.begin(); it != j.end(); ++it) { - std::cout << *it << '\n'; -} - -// range-based for -for (auto& element : j) { - std::cout << element << '\n'; -} - -// getter/setter -const std::string tmp = j[0]; -j[1] = 42; -bool foo = j.at(2); - -// comparison -j == "[\"foo\", 1, true]"_json; // true - -// other stuff -j.size(); // 3 entries -j.empty(); // false -j.type(); // json::value_t::array -j.clear(); // the array is empty again - -// convenience type checkers -j.is_null(); -j.is_boolean(); -j.is_number(); -j.is_object(); -j.is_array(); -j.is_string(); - -// create an object -json o; -o["foo"] = 23; -o["bar"] = false; -o["baz"] = 3.141; - -// also use emplace -o.emplace("weather", "sunny"); - -// special iterator member functions for objects -for (json::iterator it = o.begin(); it != o.end(); ++it) { - std::cout << it.key() << " : " << it.value() << "\n"; -} - -// find an entry -if (o.find("foo") != o.end()) { - // there is an entry with key "foo" -} - -// or simpler using count() -int foo_present = o.count("foo"); // 1 -int fob_present = o.count("fob"); // 0 - -// delete an entry -o.erase("foo"); -``` - - -### Conversion from STL containers - -Any sequence container (`std::array`, `std::vector`, `std::deque`, `std::forward_list`, `std::list`) whose values can be used to construct JSON values (e.g., integers, floating point numbers, Booleans, string types, or again STL containers described in this section) can be used to create a JSON array. The same holds for similar associative containers (`std::set`, `std::multiset`, `std::unordered_set`, `std::unordered_multiset`), but in these cases the order of the elements of the array depends on how the elements are ordered in the respective STL container. - -```cpp -std::vector c_vector {1, 2, 3, 4}; -json j_vec(c_vector); -// [1, 2, 3, 4] - -std::deque c_deque {1.2, 2.3, 3.4, 5.6}; -json j_deque(c_deque); -// [1.2, 2.3, 3.4, 5.6] - -std::list c_list {true, true, false, true}; -json j_list(c_list); -// [true, true, false, true] - -std::forward_list c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543}; -json j_flist(c_flist); -// [12345678909876, 23456789098765, 34567890987654, 45678909876543] - -std::array c_array {{1, 2, 3, 4}}; -json j_array(c_array); -// [1, 2, 3, 4] - -std::set c_set {"one", "two", "three", "four", "one"}; -json j_set(c_set); // only one entry for "one" is used -// ["four", "one", "three", "two"] - -std::unordered_set c_uset {"one", "two", "three", "four", "one"}; -json j_uset(c_uset); // only one entry for "one" is used -// maybe ["two", "three", "four", "one"] - -std::multiset c_mset {"one", "two", "one", "four"}; -json j_mset(c_mset); // both entries for "one" are used -// maybe ["one", "two", "one", "four"] - -std::unordered_multiset c_umset {"one", "two", "one", "four"}; -json j_umset(c_umset); // both entries for "one" are used -// maybe ["one", "two", "one", "four"] -``` - -Likewise, any associative key-value containers (`std::map`, `std::multimap`, `std::unordered_map`, `std::unordered_multimap`) whose keys can construct an `std::string` and whose values can be used to construct JSON values (see examples above) can be used to create a JSON object. Note that in case of multimaps only one key is used in the JSON object and the value depends on the internal order of the STL container. - -```cpp -std::map c_map { {"one", 1}, {"two", 2}, {"three", 3} }; -json j_map(c_map); -// {"one": 1, "three": 3, "two": 2 } - -std::unordered_map c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} }; -json j_umap(c_umap); -// {"one": 1.2, "two": 2.3, "three": 3.4} - -std::multimap c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; -json j_mmap(c_mmap); // only one entry for key "three" is used -// maybe {"one": true, "two": true, "three": true} - -std::unordered_multimap c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; -json j_ummap(c_ummap); // only one entry for key "three" is used -// maybe {"one": true, "two": true, "three": true} -``` - -### JSON Pointer and JSON Patch - -The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address structured values. On top of this, **JSON Patch** ([RFC 6902](https://tools.ietf.org/html/rfc6902)) allows to describe differences between two JSON values - effectively allowing patch and diff operations known from Unix. - -```cpp -// a JSON value -json j_original = R"({ - "baz": ["one", "two", "three"], - "foo": "bar" -})"_json; - -// access members with a JSON pointer (RFC 6901) -j_original["/baz/1"_json_pointer]; -// "two" - -// a JSON patch (RFC 6902) -json j_patch = R"([ - { "op": "replace", "path": "/baz", "value": "boo" }, - { "op": "add", "path": "/hello", "value": ["world"] }, - { "op": "remove", "path": "/foo"} -])"_json; - -// apply the patch -json j_result = j_original.patch(j_patch); -// { -// "baz": "boo", -// "hello": ["world"] -// } - -// calculate a JSON patch from two JSON values -json::diff(j_result, j_original); -// [ -// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] }, -// { "op": "remove","path": "/hello" }, -// { "op": "add", "path": "/foo", "value": "bar" } -// ] -``` - -### JSON Merge Patch - -The library supports **JSON Merge Patch** ([RFC 7386](https://tools.ietf.org/html/rfc7386)) as a patch format. Instead of using JSON Pointer (see above) to specify values to be manipulated, it describes the changes using a syntax that closely mimics the document being modified. - -```cpp -// a JSON value -json j_document = R"({ - "a": "b", - "c": { - "d": "e", - "f": "g" - } -})"_json; - -// a patch -json j_patch = R"({ - "a":"z", - "c": { - "f": null - } -})"_json; - -// apply the patch -j_original.merge_patch(j_patch); -// { -// "a": "z", -// "c": { -// "d": "e" -// } -// } -``` - -### Implicit conversions - -The type of the JSON object is determined automatically by the expression to store. Likewise, the stored value is implicitly converted. - -```cpp -// strings -std::string s1 = "Hello, world!"; -json js = s1; -std::string s2 = js; - -// Booleans -bool b1 = true; -json jb = b1; -bool b2 = jb; - -// numbers -int i = 42; -json jn = i; -double f = jn; - -// etc. -``` - -You can also explicitly ask for the value: - -```cpp -std::string vs = js.get(); -bool vb = jb.get(); -int vi = jn.get(); - -// etc. -``` - -Note that `char` types are not automatically converted to JSON strings, but to integer numbers. A conversion to a string must be specified explicitly: - -```cpp -char ch = 'A'; // ASCII value 65 -json j_default = ch; // stores integer number 65 -json j_string = std::string(1, ch); // stores string "A" -``` - -### Arbitrary types conversions - -Every type can be serialized in JSON, not just STL containers and scalar types. Usually, you would do something along those lines: - -```cpp -namespace ns { - // a simple struct to model a person - struct person { - std::string name; - std::string address; - int age; - }; -} - -ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; - -// convert to JSON: copy each value into the JSON object -json j; -j["name"] = p.name; -j["address"] = p.address; -j["age"] = p.age; - -// ... - -// convert from JSON: copy each value from the JSON object -ns::person p { - j["name"].get(), - j["address"].get(), - j["age"].get() -}; -``` - -It works, but that's quite a lot of boilerplate... Fortunately, there's a better way: - -```cpp -// create a person -ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60}; - -// conversion: person -> json -json j = p; - -std::cout << j << std::endl; -// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} - -// conversion: json -> person -ns::person p2 = j; - -// that's it -assert(p == p2); -``` - -#### Basic usage - -To make this work with one of your types, you only need to provide two functions: - -```cpp -using nlohmann::json; - -namespace ns { - void to_json(json& j, const person& p) { - j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}}; - } - - void from_json(const json& j, person& p) { - p.name = j.at("name").get(); - p.address = j.at("address").get(); - p.age = j.at("age").get(); - } -} // namespace ns -``` - -That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called. -Likewise, when calling `get()`, the `from_json` method will be called. - -Some important things: - -* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). -* Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use the implicit conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. -* When using `get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) -* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. -* In case your type contains several `operator=` definitions, code like `your_variable = your_json;` [may not compile](https://github.com/nlohmann/json/issues/667). You need to write `your_variable = your_json.get();` instead. -* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. -* Be careful with the definition order of the `from_json`/`to_json` functions: If a type `B` has a member of type `A`, you **MUST** define `to_json(A)` before `to_json(B)`. Look at [issue 561](https://github.com/nlohmann/json/issues/561) for more details. - - -#### How do I convert third-party types? - -This requires a bit more advanced technique. But first, let's see how this conversion mechanism works: - -The library uses **JSON Serializers** to convert types to json. -The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](https://en.cppreference.com/w/cpp/language/adl)). - -It is implemented like this (simplified): - -```cpp -template -struct adl_serializer { - static void to_json(json& j, const T& value) { - // calls the "to_json" method in T's namespace - } - - static void from_json(const json& j, T& value) { - // same thing, but with the "from_json" method - } -}; -``` - -This serializer works fine when you have control over the type's namespace. However, what about `boost::optional` or `std::filesystem::path` (C++17)? Hijacking the `boost` namespace is pretty bad, and it's illegal to add something other than template specializations to `std`... - -To solve this, you need to add a specialization of `adl_serializer` to the `nlohmann` namespace, here's an example: - -```cpp -// partial specialization (full specialization works too) -namespace nlohmann { - template - struct adl_serializer> { - static void to_json(json& j, const boost::optional& opt) { - if (opt == boost::none) { - j = nullptr; - } else { - j = *opt; // this will call adl_serializer::to_json which will - // find the free function to_json in T's namespace! - } - } - - static void from_json(const json& j, boost::optional& opt) { - if (j.is_null()) { - opt = boost::none; - } else { - opt = j.get(); // same as above, but with - // adl_serializer::from_json - } - } - }; -} -``` - -#### How can I use `get()` for non-default constructible/non-copyable types? - -There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload: - -```cpp -struct move_only_type { - move_only_type() = delete; - move_only_type(int ii): i(ii) {} - move_only_type(const move_only_type&) = delete; - move_only_type(move_only_type&&) = default; - - int i; -}; - -namespace nlohmann { - template <> - struct adl_serializer { - // note: the return type is no longer 'void', and the method only takes - // one argument - static move_only_type from_json(const json& j) { - return {j.get()}; - } - - // Here's the catch! You must provide a to_json method! Otherwise you - // will not be able to convert move_only_type to json, since you fully - // specialized adl_serializer on that type - static void to_json(json& j, move_only_type t) { - j = t.i; - } - }; -} -``` - -#### Can I write my own serializer? (Advanced use) - -Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples. - -If you write your own serializer, you'll need to do a few things: - -- use a different `basic_json` alias than `nlohmann::json` (the last template parameter of `basic_json` is the `JSONSerializer`) -- use your `basic_json` alias (or a template parameter) in all your `to_json`/`from_json` methods -- use `nlohmann::to_json` and `nlohmann::from_json` when you need ADL - -Here is an example, without simplifications, that only accepts types with a size <= 32, and uses ADL. - -```cpp -// You should use void as a second template argument -// if you don't need compile-time checks on T -template::type> -struct less_than_32_serializer { - template - static void to_json(BasicJsonType& j, T value) { - // we want to use ADL, and call the correct to_json overload - using nlohmann::to_json; // this method is called by adl_serializer, - // this is where the magic happens - to_json(j, value); - } - - template - static void from_json(const BasicJsonType& j, T& value) { - // same thing here - using nlohmann::from_json; - from_json(j, value); - } -}; -``` - -Be **very** careful when reimplementing your serializer, you can stack overflow if you don't pay attention: - -```cpp -template -struct bad_serializer -{ - template - static void to_json(BasicJsonType& j, const T& value) { - // this calls BasicJsonType::json_serializer::to_json(j, value); - // if BasicJsonType::json_serializer == bad_serializer ... oops! - j = value; - } - - template - static void to_json(const BasicJsonType& j, T& value) { - // this calls BasicJsonType::json_serializer::from_json(j, value); - // if BasicJsonType::json_serializer == bad_serializer ... oops! - value = j.template get(); // oops! - } -}; -``` - -### Binary formats (CBOR, MessagePack, and UBJSON) - -Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [CBOR](http://cbor.io) (Concise Binary Object Representation), [MessagePack](http://msgpack.org), and [UBJSON](http://ubjson.org) (Universal Binary JSON Specification) to efficiently encode JSON values to byte vectors and to decode such vectors. - -```cpp -// create a JSON value -json j = R"({"compact": true, "schema": 0})"_json; - -// serialize to CBOR -std::vector v_cbor = json::to_cbor(j); - -// 0xA2, 0x67, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0xF5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00 - -// roundtrip -json j_from_cbor = json::from_cbor(v_cbor); - -// serialize to MessagePack -std::vector v_msgpack = json::to_msgpack(j); - -// 0x82, 0xA7, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0xC3, 0xA6, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00 - -// roundtrip -json j_from_msgpack = json::from_msgpack(v_msgpack); - -// serialize to UBJSON -std::vector v_ubjson = json::to_ubjson(j); - -// 0x7B, 0x69, 0x07, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x54, 0x69, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x69, 0x00, 0x7D - -// roundtrip -json j_from_ubjson = json::from_ubjson(v_ubjson); -``` - - -## Supported compilers - -Though it's 2018 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: - -- GCC 4.9 - 8.2 (and possibly later) -- Clang 3.4 - 6.1 (and possibly later) -- Intel C++ Compiler 17.0.2 (and possibly later) -- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later) -- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later) - -I would be happy to learn about other compilers/versions. - -Please note: - -- GCC 4.8 does not work because of two bugs ([55817](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55817) and [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)) in the C++11 support. Note there is a [pull request](https://github.com/nlohmann/json/pull/212) to fix some of the issues. -- Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default. - - ``` - APP_STL := c++_shared - NDK_TOOLCHAIN_VERSION := clang3.6 - APP_CPPFLAGS += -frtti -fexceptions - ``` - - The code compiles successfully with [Android NDK](https://developer.android.com/ndk/index.html?hl=ml), Revision 9 - 11 (and possibly later) and [CrystaX's Android NDK](https://www.crystax.net/en/android/ndk) version 10. - -- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod`) may occur. Note this is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](http://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219). - -- Unsupported versions of GCC and Clang are rejected by `#error` directives. This can be switched off by defining `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`. Note that you can expect no support in this case. - -The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json) and [AppVeyor](https://ci.appveyor.com/project/nlohmann/json): - -| Compiler | Operating System | Version String | -|-----------------|------------------------------|----------------| -| GCC 4.9.4 | Ubuntu 14.04.1 LTS | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4 | -| GCC 5.5.0 | Ubuntu 14.04.1 LTS | g++-5 (Ubuntu 5.5.0-12ubuntu1~14.04) 5.5.0 20171010 | -| GCC 6.4.0 | Ubuntu 14.04.1 LTS | g++-6 (Ubuntu 6.4.0-17ubuntu1~14.04) 6.4.0 20180424 | -| GCC 7.3.0 | Ubuntu 14.04.1 LTS | g++-7 (Ubuntu 7.3.0-21ubuntu1~14.04) 7.3.0 | -| GCC 7.3.0 | Windows Server 2012 R2 (x64) | g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0 | -| GCC 8.1.0 | Ubuntu 14.04.1 LTS | g++-8 (Ubuntu 8.1.0-5ubuntu1~14.04) 8.1.0 | -| Clang 3.5.0 | Ubuntu 14.04.1 LTS | clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) (based on LLVM 3.5.0) | -| Clang 3.6.2 | Ubuntu 14.04.1 LTS | clang version 3.6.2-svn240577-1~exp1 (branches/release_36) (based on LLVM 3.6.2) | -| Clang 3.7.1 | Ubuntu 14.04.1 LTS | clang version 3.7.1-svn253571-1~exp1 (branches/release_37) (based on LLVM 3.7.1) | -| Clang 3.8.0 | Ubuntu 14.04.1 LTS | clang version 3.8.0-2ubuntu3~trusty5 (tags/RELEASE_380/final) | -| Clang 3.9.1 | Ubuntu 14.04.1 LTS | clang version 3.9.1-4ubuntu3~14.04.3 (tags/RELEASE_391/rc2) | -| Clang 4.0.1 | Ubuntu 14.04.1 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) | -| Clang 5.0.2 | Ubuntu 14.04.1 LTS | clang version 5.0.2-svn328729-1~exp1~20180509123505.100 (branches/release_50) | -| Clang 6.0.1 | Ubuntu 14.04.1 LTS | clang version 6.0.1-svn334776-1~exp1~20180726133705.85 (branches/release_60) | -| Clang Xcode 6.4 | OSX 10.10.5 | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) | -| Clang Xcode 7.3 | OSX 10.11.6 | Apple LLVM version 7.3.0 (clang-703.0.31) | -| Clang Xcode 8.0 | OSX 10.11.6 | Apple LLVM version 8.0.0 (clang-800.0.38) | -| Clang Xcode 8.1 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) | -| Clang Xcode 8.2 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) | -| Clang Xcode 8.3 | OSX 10.11.6 | Apple LLVM version 8.1.0 (clang-802.0.38) | -| Clang Xcode 9.0 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.37) | -| Clang Xcode 9.1 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.38) | -| Clang Xcode 9.2 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.1) | -| Clang Xcode 9.3 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.2) | -| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25420.1, MSVC 19.0.24215.1 | -| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.7.180.61344, MSVC 19.14.26433.0 | - -## License - - - -The class is licensed under the [MIT License](http://opensource.org/licenses/MIT): - -Copyright © 2013-2018 [Niels Lohmann](http://nlohmann.me) - -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. - -* * * - -The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](http://bjoern.hoehrmann.de/) - -The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](http://florian.loitsch.com/) - -## Contact - -If you have questions regarding the library, I would like to invite you to [open an issue at GitHub](https://github.com/nlohmann/json/issues/new). Please describe your request, problem, or question as detailed as possible, and also mention the version of the library you are using as well as the version of your compiler and operating system. Opening an issue at GitHub allows other users and contributors to this library to collaborate. For instance, I have little experience with MSVC, and most issues in this regard have been solved by a growing community. If you have a look at the [closed issues](https://github.com/nlohmann/json/issues?q=is%3Aissue+is%3Aclosed), you will see that we react quite timely in most cases. - -Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). For encrypted messages, please use [this key](https://keybase.io/nlohmann/pgp_keys.asc). - -## Security - -[Commits by Niels Lohmann](https://github.com/nlohmann/json/commits) and [releases](https://github.com/nlohmann/json/releases) are signed with this [PGP Key](https://keybase.io/nlohmann/pgp_keys.asc?fingerprint=797167ae41c0a6d9232e48457f3cea63ae251b69). - -## Thanks - -I deeply appreciate the help of the following people. - -![Contributors](https://raw.githubusercontent.com/nlohmann/json/develop/doc/avatars.png) - -- [Teemperor](https://github.com/Teemperor) implemented CMake support and lcov integration, realized escape and Unicode handling in the string parser, and fixed the JSON serialization. -- [elliotgoodrich](https://github.com/elliotgoodrich) fixed an issue with double deletion in the iterator classes. -- [kirkshoop](https://github.com/kirkshoop) made the iterators of the class composable to other libraries. -- [wancw](https://github.com/wanwc) fixed a bug that hindered the class to compile with Clang. -- Tomas Åblad found a bug in the iterator implementation. -- [Joshua C. Randall](https://github.com/jrandall) fixed a bug in the floating-point serialization. -- [Aaron Burghardt](https://github.com/aburgh) implemented code to parse streams incrementally. Furthermore, he greatly improved the parser class by allowing the definition of a filter function to discard undesired elements while parsing. -- [Daniel Kopeček](https://github.com/dkopecek) fixed a bug in the compilation with GCC 5.0. -- [Florian Weber](https://github.com/Florianjw) fixed a bug in and improved the performance of the comparison operators. -- [Eric Cornelius](https://github.com/EricMCornelius) pointed out a bug in the handling with NaN and infinity values. He also improved the performance of the string escaping. -- [易思龙](https://github.com/likebeta) implemented a conversion from anonymous enums. -- [kepkin](https://github.com/kepkin) patiently pushed forward the support for Microsoft Visual studio. -- [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements. In particular, he pushed forward the implementation of user-defined types. -- [Caio Luppi](https://github.com/caiovlp) fixed a bug in the Unicode handling. -- [dariomt](https://github.com/dariomt) fixed some typos in the examples. -- [Daniel Frey](https://github.com/d-frey) cleaned up some pointers and implemented exception-safe memory allocation. -- [Colin Hirsch](https://github.com/ColinH) took care of a small namespace issue. -- [Huu Nguyen](https://github.com/whoshuu) correct a variable name in the documentation. -- [Silverweed](https://github.com/silverweed) overloaded `parse()` to accept an rvalue reference. -- [dariomt](https://github.com/dariomt) fixed a subtlety in MSVC type support and implemented the `get_ref()` function to get a reference to stored values. -- [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK. -- [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio. -- [406345](https://github.com/406345) fixed two small warnings. -- [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function. -- [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines. -- [twelsby](https://github.com/twelsby) fixed the array subscript operator, an issue that failed the MSVC build, and floating-point parsing/dumping. He further added support for unsigned integer numbers and implemented better roundtrip support for parsed numbers. -- [Volker Diels-Grabsch](https://github.com/vog) fixed a link in the README file. -- [msm-](https://github.com/msm-) added support for American Fuzzy Lop. -- [Annihil](https://github.com/Annihil) fixed an example in the README file. -- [Themercee](https://github.com/Themercee) noted a wrong URL in the README file. -- [Lv Zheng](https://github.com/lv-zheng) fixed a namespace issue with `int64_t` and `uint64_t`. -- [abc100m](https://github.com/abc100m) analyzed the issues with GCC 4.8 and proposed a [partial solution](https://github.com/nlohmann/json/pull/212). -- [zewt](https://github.com/zewt) added useful notes to the README file about Android. -- [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake. -- [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files. -- [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal). -- [Mário Feroldi](https://github.com/thelostt) fixed a small typo. -- [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release. -- [Damien](https://github.com/dtoma) fixed one of the last conversion warnings. -- [Thomas Braun](https://github.com/t-b) fixed a warning in a test case. -- [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290). He also implemented the magic behind the serialization/deserialization of user-defined types and split the single header file into smaller chunks. -- [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation. -- [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`. -- [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion. -- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix. -- [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file. -- [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function. -- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](https://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing. -- [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan. -- [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. -- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. -- [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one. -- [Daniel599](https://github.com/Daniel599) helped to get Travis execute the tests with Clang's sanitizers. -- [Jonathan Lee](https://github.com/vjon) fixed an example in the README file. -- [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types. -- [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio. -- [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types. -- [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example. -- [Martin Hořeňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite. -- [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. -- [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README. -- [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s. -- [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation. -- [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README, removed unnecessary bit arithmetic, and fixed some `-Weffc++` warnings. -- [Krzysztof Woś](https://github.com/krzysztofwos) made exceptions more visible. -- [ftillier](https://github.com/ftillier) fixed a compiler warning. -- [tinloaf](https://github.com/tinloaf) made sure all pushed warnings are properly popped. -- [Fytch](https://github.com/Fytch) found a bug in the documentation. -- [Jay Sistar](https://github.com/Type1J) implemented a Meson build description. -- [Henry Lee](https://github.com/HenryRLee) fixed a warning in ICC and improved the iterator implementation. -- [Vincent Thiery](https://github.com/vthiery) maintains a package for the Conan package manager. -- [Steffen](https://github.com/koemeet) fixed a potential issue with MSVC and `std::min`. -- [Mike Tzou](https://github.com/Chocobo1) fixed some typos. -- [amrcode](https://github.com/amrcode) noted a misleading documentation about comparison of floats. -- [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `` with ``. -- [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library. -- [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists. -- [Greg Hurrell](https://github.com/wincent) fixed a typo. -- [Dmitry Kukovinets](https://github.com/DmitryKuk) fixed a typo. -- [kbthomp1](https://github.com/kbthomp1) fixed an issue related to the Intel OSX compiler. -- [Markus Werle](https://github.com/daixtrose) fixed a typo. -- [WebProdPP](https://github.com/WebProdPP) fixed a subtle error in a precondition check. -- [Alex](https://github.com/leha-bot) noted an error in a code sample. -- [Tom de Geus](https://github.com/tdegeus) reported some warnings with ICC and helped fixing them. -- [Perry Kundert](https://github.com/pjkundert) simplified reading from input streams. -- [Sonu Lohani](https://github.com/sonulohani) fixed a small compilation error. -- [Jamie Seward](https://github.com/jseward) fixed all MSVC warnings. -- [Nate Vargas](https://github.com/eld00d) added a Doxygen tag file. -- [pvleuven](https://github.com/pvleuven) helped fixing a warning in ICC. -- [Pavel](https://github.com/crea7or) helped fixing some warnings in MSVC. -- [Jamie Seward](https://github.com/jseward) avoided unnecessary string copies in `find()` and `count()`. -- [Mitja](https://github.com/Itja) fixed some typos. -- [Jorrit Wronski](https://github.com/jowr) updated the Hunter package links. -- [Matthias Möller](https://github.com/TinyTinni) added a `.natvis` for the MSVC debug view. -- [bogemic](https://github.com/bogemic) fixed some C++17 deprecation warnings. -- [Eren Okka](https://github.com/erengy) fixed some MSVC warnings. -- [abolz](https://github.com/abolz) integrated the Grisu2 algorithm for proper floating-point formatting, allowing more roundtrip checks to succeed. -- [Vadim Evard](https://github.com/Pipeliner) fixed a Markdown issue in the README. -- [zerodefect](https://github.com/zerodefect) fixed a compiler warning. -- [Kert](https://github.com/kaidokert) allowed to template the string type in the serialization and added the possibility to override the exceptional behavior. -- [mark-99](https://github.com/mark-99) helped fixing an ICC error. -- [Patrik Huber](https://github.com/patrikhuber) fixed links in the README file. -- [johnfb](https://github.com/johnfb) found a bug in the implementation of CBOR's indefinite length strings. -- [Paul Fultz II](https://github.com/pfultz2) added a note on the cget package manager. -- [Wilson Lin](https://github.com/wla80) made the integration section of the README more concise. -- [RalfBielig](https://github.com/ralfbielig) detected and fixed a memory leak in the parser callback. -- [agrianius](https://github.com/agrianius) allowed to dump JSON to an alternative string type. -- [Kevin Tonon](https://github.com/ktonon) overworked the C++11 compiler checks in CMake. -- [Axel Huebl](https://github.com/ax3l) simplified a CMake check and added support for the [Spack package manager](https://spack.io). -- [Carlos O'Ryan](https://github.com/coryan) fixed a typo. -- [James Upjohn](https://github.com/jammehcow) fixed a version number in the compilers section. -- [Chuck Atkins](https://github.com/chuckatkins) adjusted the CMake files to the CMake packaging guidelines -- [Jan Schöppach](https://github.com/dns13) fixed a typo. -- [martin-mfg](https://github.com/martin-mfg) fixed a typo. -- [Matthias Möller](https://github.com/TinyTinni) removed the dependency from `std::stringstream`. -- [agrianius](https://github.com/agrianius) added code to use alternative string implementations. -- [Daniel599](https://github.com/Daniel599) allowed to use more algorithms with the `items()` function. -- [Julius Rakow](https://github.com/jrakow) fixed the Meson include directory and fixed the links to [cppreference.com](cppreference.com). -- [Sonu Lohani](https://github.com/sonulohani) fixed the compilation with MSVC 2015 in debug mode. -- [grembo](https://github.com/grembo) fixed the test suite and re-enabled several test cases. -- [Hyeon Kim](https://github.com/simnalamburt) introduced the macro `JSON_INTERNAL_CATCH` to control the exception handling inside the library. -- [thyu](https://github.com/thyu) fixed a compiler warning. - -Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. - - -## Used third-party tools - -The library itself consists of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of third-party tools and services. Thanks a lot! - -- [**amalgamate.py - Amalgamate C source and header files**](https://github.com/edlund/amalgamate) to create a single header file -- [**American fuzzy lop**](http://lcamtuf.coredump.cx/afl/) for fuzz testing -- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows -- [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code identation -- [**Catch**](https://github.com/philsquared/Catch) for the unit tests -- [**Clang**](http://clang.llvm.org) for compilation with code sanitizers -- [**Cmake**](https://cmake.org) for build automation -- [**Codacity**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) -- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json) -- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json) -- [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis -- [**Doxygen**](http://www.stack.nl/~dimitri/doxygen/) to generate [documentation](https://nlohmann.github.io/json/) -- [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages -- [**GitHub Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md) -- [**Google Benchmark**](https://github.com/google/benchmark) to implement the benchmarks -- [**libFuzzer**](http://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz -- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library ([project repository](https://github.com/google/oss-fuzz/tree/master/projects/json)) -- [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments. -- [**send_to_wandbox**](https://github.com/nlohmann/json/blob/develop/doc/scripts/send_to_wandbox.py) to send code examples to [Wandbox](http://melpon.org/wandbox) -- [**Travis**](https://travis-ci.org) for [continuous integration](https://travis-ci.org/nlohmann/json) on Linux and macOS -- [**Valgrind**](http://valgrind.org) to check for correct memory management -- [**Wandbox**](http://melpon.org/wandbox) for [online examples](https://wandbox.org/permlink/TarF5pPn9NtHQjhf) - - -## Projects using JSON for Modern C++ - -The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. - - -## Notes - -- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726). -- As the exact type of a number is not defined in the [JSON specification](http://rfc7159.net/rfc7159), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions. -- The library supports **Unicode input** as follows: - - Only **UTF-8** encoded input is supported which is the default encoding for JSON according to [RFC 7159](http://rfc7159.net/rfc7159#rfc.section.8.1). - - Other encodings such as Latin-1, UTF-16, or UTF-32 are not supported and will yield parse or serialization errors. - - [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. - - Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. - - The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. -- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag. -- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by an `abort()` call. -- By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc7159.html) defines objects as "an unordered collection of zero or more name/value pairs". If you do want to preserve the insertion order, you can specialize the object type with containers like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)). - - -## Execute unit tests - -To compile and run the tests, you need to execute - -```sh -$ mkdir build -$ cd build -$ cmake .. -$ cmake --build . -$ ctest --output-on-failure -``` - -For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml). diff --git a/ext/nlohmann/json.hpp b/ext/nlohmann/json.hpp deleted file mode 100644 index 8959265da..000000000 --- a/ext/nlohmann/json.hpp +++ /dev/null @@ -1,26640 +0,0 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.10.2 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Licensed under the MIT License . -SPDX-License-Identifier: MIT -Copyright (c) 2013-2019 Niels Lohmann . - -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. -*/ - -#ifndef INCLUDE_NLOHMANN_JSON_HPP_ -#define INCLUDE_NLOHMANN_JSON_HPP_ - -#define NLOHMANN_JSON_VERSION_MAJOR 3 -#define NLOHMANN_JSON_VERSION_MINOR 10 -#define NLOHMANN_JSON_VERSION_PATCH 2 - -#include // all_of, find, for_each -#include // nullptr_t, ptrdiff_t, size_t -#include // hash, less -#include // initializer_list -#ifndef JSON_NO_IO - #include // istream, ostream -#endif // JSON_NO_IO -#include // random_access_iterator_tag -#include // unique_ptr -#include // accumulate -#include // string, stoi, to_string -#include // declval, forward, move, pair, swap -#include // vector - -// #include - - -#include -#include - -// #include - - -#include // transform -#include // array -#include // forward_list -#include // inserter, front_inserter, end -#include // map -#include // string -#include // tuple, make_tuple -#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible -#include // unordered_map -#include // pair, declval -#include // valarray - -// #include - - -#include // exception -#include // runtime_error -#include // to_string -#include // vector - -// #include - - -#include // array -#include // size_t -#include // uint8_t -#include // string - -namespace nlohmann -{ -namespace detail -{ -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : std::uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - binary, ///< binary array (ordered collection of bytes) - discarded ///< discarded by the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string < binary -- furthermore, each type is not smaller than itself -- discarded values are not comparable -- binary is represented as a b"" string in python and directly comparable to a - string; however, making a binary array directly comparable with a string would - be surprising behavior in a JSON file. - -@since version 1.0.0 -*/ -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, - 6 /* binary */ - } - }; - - const auto l_index = static_cast(lhs); - const auto r_index = static_cast(rhs); - return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; -} -} // namespace detail -} // namespace nlohmann - -// #include - - -#include -// #include - - -#include // pair -// #include - - -/* Hedley - https://nemequ.github.io/hedley - * Created by Evan Nemerson - * - * To the extent possible under law, the author(s) have dedicated all - * copyright and related and neighboring rights to this software to - * the public domain worldwide. This software is distributed without - * any warranty. - * - * For details, see . - * SPDX-License-Identifier: CC0-1.0 - */ - -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) -#if defined(JSON_HEDLEY_VERSION) - #undef JSON_HEDLEY_VERSION -#endif -#define JSON_HEDLEY_VERSION 15 - -#if defined(JSON_HEDLEY_STRINGIFY_EX) - #undef JSON_HEDLEY_STRINGIFY_EX -#endif -#define JSON_HEDLEY_STRINGIFY_EX(x) #x - -#if defined(JSON_HEDLEY_STRINGIFY) - #undef JSON_HEDLEY_STRINGIFY -#endif -#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) - -#if defined(JSON_HEDLEY_CONCAT_EX) - #undef JSON_HEDLEY_CONCAT_EX -#endif -#define JSON_HEDLEY_CONCAT_EX(a,b) a##b - -#if defined(JSON_HEDLEY_CONCAT) - #undef JSON_HEDLEY_CONCAT -#endif -#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) - -#if defined(JSON_HEDLEY_CONCAT3_EX) - #undef JSON_HEDLEY_CONCAT3_EX -#endif -#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c - -#if defined(JSON_HEDLEY_CONCAT3) - #undef JSON_HEDLEY_CONCAT3 -#endif -#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) - -#if defined(JSON_HEDLEY_VERSION_ENCODE) - #undef JSON_HEDLEY_VERSION_ENCODE -#endif -#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) - #undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) - #undef JSON_HEDLEY_VERSION_DECODE_MINOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) - #undef JSON_HEDLEY_VERSION_DECODE_REVISION -#endif -#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) - -#if defined(JSON_HEDLEY_GNUC_VERSION) - #undef JSON_HEDLEY_GNUC_VERSION -#endif -#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#elif defined(__GNUC__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) -#endif - -#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) - #undef JSON_HEDLEY_GNUC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GNUC_VERSION) - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION) - #undef JSON_HEDLEY_MSVC_VERSION -#endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) - #undef JSON_HEDLEY_MSVC_VERSION_CHECK -#endif -#if !defined(JSON_HEDLEY_MSVC_VERSION) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) -#elif defined(_MSC_VER) && (_MSC_VER >= 1200) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) -#else - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION) - #undef JSON_HEDLEY_INTEL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_VERSION) - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #undef JSON_HEDLEY_INTEL_CL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) - #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION) - #undef JSON_HEDLEY_PGI_VERSION -#endif -#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) - #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) - #undef JSON_HEDLEY_PGI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #undef JSON_HEDLEY_SUNPRO_VERSION -#endif -#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) -#elif defined(__SUNPRO_C) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) -#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) -#elif defined(__SUNPRO_CC) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) - #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#endif -#if defined(__EMSCRIPTEN__) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION) - #undef JSON_HEDLEY_ARM_VERSION -#endif -#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) -#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) - #undef JSON_HEDLEY_ARM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_ARM_VERSION) - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION) - #undef JSON_HEDLEY_IBM_VERSION -#endif -#if defined(__ibmxl__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) -#elif defined(__xlC__) && defined(__xlC_ver__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) -#elif defined(__xlC__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) - #undef JSON_HEDLEY_IBM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IBM_VERSION) - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_VERSION) - #undef JSON_HEDLEY_TI_VERSION -#endif -#if \ - defined(__TI_COMPILER_VERSION__) && \ - ( \ - defined(__TMS470__) || defined(__TI_ARM__) || \ - defined(__MSP430__) || \ - defined(__TMS320C2000__) \ - ) -#if (__TI_COMPILER_VERSION__ >= 16000000) - #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif -#endif - -#if defined(JSON_HEDLEY_TI_VERSION_CHECK) - #undef JSON_HEDLEY_TI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_VERSION) - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #undef JSON_HEDLEY_TI_CL2000_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) - #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #undef JSON_HEDLEY_TI_CL430_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) - #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #undef JSON_HEDLEY_TI_ARMCL_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) - #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) - #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #undef JSON_HEDLEY_TI_CL6X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) - #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #undef JSON_HEDLEY_TI_CL7X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) - #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #undef JSON_HEDLEY_TI_CLPRU_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) - #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION) - #undef JSON_HEDLEY_CRAY_VERSION -#endif -#if defined(_CRAYC) - #if defined(_RELEASE_PATCHLEVEL) - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) - #else - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) - #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_CRAY_VERSION) - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION) - #undef JSON_HEDLEY_IAR_VERSION -#endif -#if defined(__IAR_SYSTEMS_ICC__) - #if __VER__ > 1000 - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) - #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) - #undef JSON_HEDLEY_IAR_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IAR_VERSION) - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION) - #undef JSON_HEDLEY_TINYC_VERSION -#endif -#if defined(__TINYC__) - #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) - #undef JSON_HEDLEY_TINYC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION) - #undef JSON_HEDLEY_DMC_VERSION -#endif -#if defined(__DMC__) - #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) - #undef JSON_HEDLEY_DMC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_DMC_VERSION) - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #undef JSON_HEDLEY_COMPCERT_VERSION -#endif -#if defined(__COMPCERT_VERSION__) - #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) - #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION) - #undef JSON_HEDLEY_PELLES_VERSION -#endif -#if defined(__POCC__) - #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) - #undef JSON_HEDLEY_PELLES_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PELLES_VERSION) - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #undef JSON_HEDLEY_MCST_LCC_VERSION -#endif -#if defined(__LCC__) && defined(__LCC_MINOR__) - #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) - #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION) - #undef JSON_HEDLEY_GCC_VERSION -#endif -#if \ - defined(JSON_HEDLEY_GNUC_VERSION) && \ - !defined(__clang__) && \ - !defined(JSON_HEDLEY_INTEL_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_ARM_VERSION) && \ - !defined(JSON_HEDLEY_CRAY_VERSION) && \ - !defined(JSON_HEDLEY_TI_VERSION) && \ - !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ - !defined(__COMPCERT__) && \ - !defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_ATTRIBUTE -#endif -#if \ - defined(__has_attribute) && \ - ( \ - (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ - ) -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) -#else -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#endif -#if \ - defined(__has_cpp_attribute) && \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#endif -#if !defined(__cplusplus) || !defined(__has_cpp_attribute) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#elif \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_BUILTIN) - #undef JSON_HEDLEY_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) -#else - #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) - #undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) - #undef JSON_HEDLEY_GCC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_FEATURE) - #undef JSON_HEDLEY_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) -#else - #define JSON_HEDLEY_HAS_FEATURE(feature) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) - #undef JSON_HEDLEY_GNUC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) - #undef JSON_HEDLEY_GCC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_EXTENSION) - #undef JSON_HEDLEY_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) -#else - #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) - #undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) - #undef JSON_HEDLEY_GCC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_WARNING) - #undef JSON_HEDLEY_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) -#else - #define JSON_HEDLEY_HAS_WARNING(warning) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) - #undef JSON_HEDLEY_GNUC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_WARNING) - #undef JSON_HEDLEY_GCC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) -#else - #define JSON_HEDLEY_PRAGMA(value) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP -#endif -#if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) - #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) -#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_PUSH - #define JSON_HEDLEY_DIAGNOSTIC_POP -#endif - -/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") -# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# endif -#endif -#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x -#endif - -#if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST -#endif -#if defined(__cplusplus) -# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) -#elif \ - JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) -#else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) -#else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ - ((T) (expr)) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("diag_suppress=Pe137") \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) -# endif -#else -# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif - -#if defined(JSON_HEDLEY_DEPRECATED) - #undef JSON_HEDLEY_DEPRECATED -#endif -#if defined(JSON_HEDLEY_DEPRECATED_FOR) - #undef JSON_HEDLEY_DEPRECATED_FOR -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) -#elif \ - (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) -#elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") -#else - #define JSON_HEDLEY_DEPRECATED(since) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) -#endif - -#if defined(JSON_HEDLEY_UNAVAILABLE) - #undef JSON_HEDLEY_UNAVAILABLE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) -#else - #define JSON_HEDLEY_UNAVAILABLE(available_since) -#endif - -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT -#endif -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) -#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif defined(_Check_return_) /* SAL */ - #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ -#else - #define JSON_HEDLEY_WARN_UNUSED_RESULT - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) -#endif - -#if defined(JSON_HEDLEY_SENTINEL) - #undef JSON_HEDLEY_SENTINEL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) -#else - #define JSON_HEDLEY_SENTINEL(position) -#endif - -#if defined(JSON_HEDLEY_NO_RETURN) - #undef JSON_HEDLEY_NO_RETURN -#endif -#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NO_RETURN __noreturn -#elif \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define JSON_HEDLEY_NO_RETURN _Noreturn -#elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#else - #define JSON_HEDLEY_NO_RETURN -#endif - -#if defined(JSON_HEDLEY_NO_ESCAPE) - #undef JSON_HEDLEY_NO_ESCAPE -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) - #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) -#else - #define JSON_HEDLEY_NO_ESCAPE -#endif - -#if defined(JSON_HEDLEY_UNREACHABLE) - #undef JSON_HEDLEY_UNREACHABLE -#endif -#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #undef JSON_HEDLEY_UNREACHABLE_RETURN -#endif -#if defined(JSON_HEDLEY_ASSUME) - #undef JSON_HEDLEY_ASSUME -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_ASSUME(expr) __assume(expr) -#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) - #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) -#elif \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #if defined(__cplusplus) - #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) - #else - #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) - #endif -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() -#elif defined(JSON_HEDLEY_ASSUME) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif -#if !defined(JSON_HEDLEY_ASSUME) - #if defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) - #else - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) - #endif -#endif -#if defined(JSON_HEDLEY_UNREACHABLE) - #if \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) - #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() - #endif -#else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) -#endif -#if !defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif - -JSON_HEDLEY_DIAGNOSTIC_PUSH -#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") - #pragma clang diagnostic ignored "-Wpedantic" -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) - #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if defined(__clang__) - #pragma clang diagnostic ignored "-Wvariadic-macros" - #elif defined(JSON_HEDLEY_GCC_VERSION) - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #endif -#endif -#if defined(JSON_HEDLEY_NON_NULL) - #undef JSON_HEDLEY_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#else - #define JSON_HEDLEY_NON_NULL(...) -#endif -JSON_HEDLEY_DIAGNOSTIC_POP - -#if defined(JSON_HEDLEY_PRINTF_FORMAT) - #undef JSON_HEDLEY_PRINTF_FORMAT -#endif -#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) -#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) -#else - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) -#endif - -#if defined(JSON_HEDLEY_CONSTEXPR) - #undef JSON_HEDLEY_CONSTEXPR -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) - #endif -#endif -#if !defined(JSON_HEDLEY_CONSTEXPR) - #define JSON_HEDLEY_CONSTEXPR -#endif - -#if defined(JSON_HEDLEY_PREDICT) - #undef JSON_HEDLEY_PREDICT -#endif -#if defined(JSON_HEDLEY_LIKELY) - #undef JSON_HEDLEY_LIKELY -#endif -#if defined(JSON_HEDLEY_UNLIKELY) - #undef JSON_HEDLEY_UNLIKELY -#endif -#if defined(JSON_HEDLEY_UNPREDICTABLE) - #undef JSON_HEDLEY_UNPREDICTABLE -#endif -#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) -#elif \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ - (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ - })) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ - })) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -#else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) -# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) -#endif -#if !defined(JSON_HEDLEY_UNPREDICTABLE) - #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) -#endif - -#if defined(JSON_HEDLEY_MALLOC) - #undef JSON_HEDLEY_MALLOC -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_MALLOC __declspec(restrict) -#else - #define JSON_HEDLEY_MALLOC -#endif - -#if defined(JSON_HEDLEY_PURE) - #undef JSON_HEDLEY_PURE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PURE __attribute__((__pure__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) -# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ - ) -# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") -#else -# define JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_CONST) - #undef JSON_HEDLEY_CONST -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_CONST __attribute__((__const__)) -#elif \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_CONST _Pragma("no_side_effect") -#else - #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_RESTRICT) - #undef JSON_HEDLEY_RESTRICT -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT restrict -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - defined(__clang__) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RESTRICT __restrict -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT _Restrict -#else - #define JSON_HEDLEY_RESTRICT -#endif - -#if defined(JSON_HEDLEY_INLINE) - #undef JSON_HEDLEY_INLINE -#endif -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__cplusplus) && (__cplusplus >= 199711L)) - #define JSON_HEDLEY_INLINE inline -#elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) - #define JSON_HEDLEY_INLINE __inline__ -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_INLINE __inline -#else - #define JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_ALWAYS_INLINE) - #undef JSON_HEDLEY_ALWAYS_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) -# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __forceinline -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ - ) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") -#else -# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_NEVER_INLINE) - #undef JSON_HEDLEY_NEVER_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#else - #define JSON_HEDLEY_NEVER_INLINE -#endif - -#if defined(JSON_HEDLEY_PRIVATE) - #undef JSON_HEDLEY_PRIVATE -#endif -#if defined(JSON_HEDLEY_PUBLIC) - #undef JSON_HEDLEY_PUBLIC -#endif -#if defined(JSON_HEDLEY_IMPORT) - #undef JSON_HEDLEY_IMPORT -#endif -#if defined(_WIN32) || defined(__CYGWIN__) -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC __declspec(dllexport) -# define JSON_HEDLEY_IMPORT __declspec(dllimport) -#else -# if \ - JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - ( \ - defined(__TI_EABI__) && \ - ( \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ - ) \ - ) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) -# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) -# else -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC -# endif -# define JSON_HEDLEY_IMPORT extern -#endif - -#if defined(JSON_HEDLEY_NO_THROW) - #undef JSON_HEDLEY_NO_THROW -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NO_THROW __declspec(nothrow) -#else - #define JSON_HEDLEY_NO_THROW -#endif - -#if defined(JSON_HEDLEY_FALL_THROUGH) - #undef JSON_HEDLEY_FALL_THROUGH -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) -#elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough -#else - #define JSON_HEDLEY_FALL_THROUGH -#endif - -#if defined(JSON_HEDLEY_RETURNS_NON_NULL) - #undef JSON_HEDLEY_RETURNS_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) -#elif defined(_Ret_notnull_) /* SAL */ - #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ -#else - #define JSON_HEDLEY_RETURNS_NON_NULL -#endif - -#if defined(JSON_HEDLEY_ARRAY_PARAM) - #undef JSON_HEDLEY_ARRAY_PARAM -#endif -#if \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__STDC_NO_VLA__) && \ - !defined(__cplusplus) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_ARRAY_PARAM(name) (name) -#else - #define JSON_HEDLEY_ARRAY_PARAM(name) -#endif - -#if defined(JSON_HEDLEY_IS_CONSTANT) - #undef JSON_HEDLEY_IS_CONSTANT -#endif -#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) - #undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#endif -/* JSON_HEDLEY_IS_CONSTEXPR_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #undef JSON_HEDLEY_IS_CONSTEXPR_ -#endif -#if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) -#endif -#if !defined(__cplusplus) -# if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) -#endif -# elif \ - ( \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION)) || \ - (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) -#endif -# elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - defined(JSON_HEDLEY_INTEL_VERSION) || \ - defined(JSON_HEDLEY_TINYC_VERSION) || \ - defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ - defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ - defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ - defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ - defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ - defined(__clang__) -# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ - sizeof(void) != \ - sizeof(*( \ - 1 ? \ - ((void*) ((expr) * 0L) ) : \ -((struct { char v[sizeof(void) * 2]; } *) 1) \ - ) \ - ) \ - ) -# endif -#endif -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) -#else - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) (0) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) -#endif - -#if defined(JSON_HEDLEY_BEGIN_C_DECLS) - #undef JSON_HEDLEY_BEGIN_C_DECLS -#endif -#if defined(JSON_HEDLEY_END_C_DECLS) - #undef JSON_HEDLEY_END_C_DECLS -#endif -#if defined(JSON_HEDLEY_C_DECL) - #undef JSON_HEDLEY_C_DECL -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { - #define JSON_HEDLEY_END_C_DECLS } - #define JSON_HEDLEY_C_DECL extern "C" -#else - #define JSON_HEDLEY_BEGIN_C_DECLS - #define JSON_HEDLEY_END_C_DECLS - #define JSON_HEDLEY_C_DECL -#endif - -#if defined(JSON_HEDLEY_STATIC_ASSERT) - #undef JSON_HEDLEY_STATIC_ASSERT -#endif -#if \ - !defined(__cplusplus) && ( \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - defined(_Static_assert) \ - ) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) -#elif \ - (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) -#else -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) -#endif - -#if defined(JSON_HEDLEY_NULL) - #undef JSON_HEDLEY_NULL -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) - #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL - #else - #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) - #endif -#elif defined(NULL) - #define JSON_HEDLEY_NULL NULL -#else - #define JSON_HEDLEY_NULL ((void*) 0) -#endif - -#if defined(JSON_HEDLEY_MESSAGE) - #undef JSON_HEDLEY_MESSAGE -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_MESSAGE(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(message msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) -#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_WARNING) - #undef JSON_HEDLEY_WARNING -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_WARNING(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(clang warning msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#if defined(JSON_HEDLEY_REQUIRE_MSG) - #undef JSON_HEDLEY_REQUIRE_MSG -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) -# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE(expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), #expr, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), msg, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) -# endif -#else -# define JSON_HEDLEY_REQUIRE(expr) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) -#endif - -#if defined(JSON_HEDLEY_FLAGS) - #undef JSON_HEDLEY_FLAGS -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) - #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) -#else - #define JSON_HEDLEY_FLAGS -#endif - -#if defined(JSON_HEDLEY_FLAGS_CAST) - #undef JSON_HEDLEY_FLAGS_CAST -#endif -#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) -# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("warning(disable:188)") \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) -#endif - -#if defined(JSON_HEDLEY_EMPTY_BASES) - #undef JSON_HEDLEY_EMPTY_BASES -#endif -#if \ - (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) -#else - #define JSON_HEDLEY_EMPTY_BASES -#endif - -/* Remaining macros are deprecated. */ - -#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#endif -#if defined(__clang__) - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) -#else - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) - #undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#endif -#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) - -#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) - #undef JSON_HEDLEY_CLANG_HAS_FEATURE -#endif -#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) - -#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) - #undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#endif -#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) - -#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) - #undef JSON_HEDLEY_CLANG_HAS_WARNING -#endif -#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) - -#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ - - -// This file contains all internal macro definitions -// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them - -// exclude unsupported compilers -#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif -#endif - -// C++ language standard detection -// if the user manually specified the used c++ version this is skipped -#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) - #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 - #endif - // the cpp 11 flag is always specified because it is the minimal required version - #define JSON_HAS_CPP_11 -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdocumentation" - #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" -#endif - -// allow to disable exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) -#else - #include - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) - #define JSON_INTERNAL_CATCH(exception) if(false) -#endif - -// override exception macros -#if defined(JSON_THROW_USER) - #undef JSON_THROW - #define JSON_THROW JSON_THROW_USER -#endif -#if defined(JSON_TRY_USER) - #undef JSON_TRY - #define JSON_TRY JSON_TRY_USER -#endif -#if defined(JSON_CATCH_USER) - #undef JSON_CATCH - #define JSON_CATCH JSON_CATCH_USER - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_CATCH_USER -#endif -#if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER -#endif - -// allow to override assert -#if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) -#endif - -// allow to access some private functions (needed by the test suite) -#if defined(JSON_TESTS_PRIVATE) - #define JSON_PRIVATE_UNLESS_TESTED public -#else - #define JSON_PRIVATE_UNLESS_TESTED private -#endif - -/*! -@brief macro to briefly define a mapping between an enum and JSON -@def NLOHMANN_JSON_SERIALIZE_ENUM -@since version 3.4.0 -*/ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [&j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ - } - -// Ugly macros to avoid uglier copy-paste when specializing basic_json. They -// may be removed in the future once the class is split. - -#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ - template class ObjectType, \ - template class ArrayType, \ - class StringType, class BooleanType, class NumberIntegerType, \ - class NumberUnsignedType, class NumberFloatType, \ - template class AllocatorType, \ - template class JSONSerializer, \ - class BinaryType> - -#define NLOHMANN_BASIC_JSON_TPL \ - basic_json - -// Macros to simplify conversion from/to types - -#define NLOHMANN_JSON_EXPAND( x ) x -#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME -#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - NLOHMANN_JSON_PASTE64, \ - NLOHMANN_JSON_PASTE63, \ - NLOHMANN_JSON_PASTE62, \ - NLOHMANN_JSON_PASTE61, \ - NLOHMANN_JSON_PASTE60, \ - NLOHMANN_JSON_PASTE59, \ - NLOHMANN_JSON_PASTE58, \ - NLOHMANN_JSON_PASTE57, \ - NLOHMANN_JSON_PASTE56, \ - NLOHMANN_JSON_PASTE55, \ - NLOHMANN_JSON_PASTE54, \ - NLOHMANN_JSON_PASTE53, \ - NLOHMANN_JSON_PASTE52, \ - NLOHMANN_JSON_PASTE51, \ - NLOHMANN_JSON_PASTE50, \ - NLOHMANN_JSON_PASTE49, \ - NLOHMANN_JSON_PASTE48, \ - NLOHMANN_JSON_PASTE47, \ - NLOHMANN_JSON_PASTE46, \ - NLOHMANN_JSON_PASTE45, \ - NLOHMANN_JSON_PASTE44, \ - NLOHMANN_JSON_PASTE43, \ - NLOHMANN_JSON_PASTE42, \ - NLOHMANN_JSON_PASTE41, \ - NLOHMANN_JSON_PASTE40, \ - NLOHMANN_JSON_PASTE39, \ - NLOHMANN_JSON_PASTE38, \ - NLOHMANN_JSON_PASTE37, \ - NLOHMANN_JSON_PASTE36, \ - NLOHMANN_JSON_PASTE35, \ - NLOHMANN_JSON_PASTE34, \ - NLOHMANN_JSON_PASTE33, \ - NLOHMANN_JSON_PASTE32, \ - NLOHMANN_JSON_PASTE31, \ - NLOHMANN_JSON_PASTE30, \ - NLOHMANN_JSON_PASTE29, \ - NLOHMANN_JSON_PASTE28, \ - NLOHMANN_JSON_PASTE27, \ - NLOHMANN_JSON_PASTE26, \ - NLOHMANN_JSON_PASTE25, \ - NLOHMANN_JSON_PASTE24, \ - NLOHMANN_JSON_PASTE23, \ - NLOHMANN_JSON_PASTE22, \ - NLOHMANN_JSON_PASTE21, \ - NLOHMANN_JSON_PASTE20, \ - NLOHMANN_JSON_PASTE19, \ - NLOHMANN_JSON_PASTE18, \ - NLOHMANN_JSON_PASTE17, \ - NLOHMANN_JSON_PASTE16, \ - NLOHMANN_JSON_PASTE15, \ - NLOHMANN_JSON_PASTE14, \ - NLOHMANN_JSON_PASTE13, \ - NLOHMANN_JSON_PASTE12, \ - NLOHMANN_JSON_PASTE11, \ - NLOHMANN_JSON_PASTE10, \ - NLOHMANN_JSON_PASTE9, \ - NLOHMANN_JSON_PASTE8, \ - NLOHMANN_JSON_PASTE7, \ - NLOHMANN_JSON_PASTE6, \ - NLOHMANN_JSON_PASTE5, \ - NLOHMANN_JSON_PASTE4, \ - NLOHMANN_JSON_PASTE3, \ - NLOHMANN_JSON_PASTE2, \ - NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) -#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) -#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) -#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) -#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) -#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) -#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) -#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) -#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) -#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) -#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) -#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) -#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) -#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) -#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) -#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) -#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) -#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) -#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) -#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) -#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) -#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) -#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) -#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) -#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) -#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) -#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) -#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) -#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) -#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) -#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) -#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) -#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) -#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) -#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) -#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) -#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) -#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) -#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) -#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) -#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) -#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) -#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) -#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) -#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) -#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) -#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) -#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) -#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) -#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) -#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) -#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) -#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) -#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) -#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) -#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) -#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) -#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) -#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) -#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) -#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) -#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) -#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) - -#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; -#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#ifndef JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_USE_IMPLICIT_CONVERSIONS 1 -#endif - -#if JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_EXPLICIT -#else - #define JSON_EXPLICIT explicit -#endif - -#ifndef JSON_DIAGNOSTICS - #define JSON_DIAGNOSTICS 0 -#endif - - -namespace nlohmann -{ -namespace detail -{ - -/*! -@brief replace all occurrences of a substring by another string - -@param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t -@param[in] f the substring to replace with @a t -@param[in] t the string to replace @a f - -@pre The search string @a f must not be empty. **This precondition is -enforced with an assertion.** - -@since version 2.0.0 -*/ -inline void replace_substring(std::string& s, const std::string& f, - const std::string& t) -{ - JSON_ASSERT(!f.empty()); - for (auto pos = s.find(f); // find first occurrence of f - pos != std::string::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} -} - -/*! - * @brief string escaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to escape - * @return escaped string - * - * Note the order of escaping "~" to "~0" and "/" to "~1" is important. - */ -inline std::string escape(std::string s) -{ - replace_substring(s, "~", "~0"); - replace_substring(s, "/", "~1"); - return s; -} - -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -static void unescape(std::string& s) -{ - replace_substring(s, "~1", "/"); - replace_substring(s, "~0", "~"); -} - -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // size_t - -namespace nlohmann -{ -namespace detail -{ -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -} // namespace nlohmann - -// #include - - -namespace nlohmann -{ -namespace detail -{ -//////////////// -// exceptions // -//////////////// - -/*! -@brief general exception of the @ref basic_json class - -This class is an extension of `std::exception` objects with a member @a id for -exception ids. It is used as the base class for all exceptions thrown by the -@ref basic_json class. This class can hence be used as "wildcard" to catch -exceptions. - -Subclasses: -- @ref parse_error for exceptions indicating a parse error -- @ref invalid_iterator for exceptions indicating errors with iterators -- @ref type_error for exceptions indicating executing a member function with - a wrong type -- @ref out_of_range for exceptions indicating access out of the defined range -- @ref other_error for exceptions indicating other library errors - -@internal -@note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. -@endinternal - -@liveexample{The following code shows how arbitrary library exceptions can be -caught.,exception} - -@since version 3.0.0 -*/ -class exception : public std::exception -{ - public: - /// returns the explanatory string - const char* what() const noexcept override - { - return m.what(); - } - - /// the id of the exception - const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) - - protected: - JSON_HEDLEY_NON_NULL(3) - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} - - static std::string name(const std::string& ename, int id_) - { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; - } - - template - static std::string diagnostics(const BasicJsonType& leaf_element) - { -#if JSON_DIAGNOSTICS - std::vector tokens; - for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent) - { - switch (current->m_parent->type()) - { - case value_t::array: - { - for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) - { - if (¤t->m_parent->m_value.array->operator[](i) == current) - { - tokens.emplace_back(std::to_string(i)); - break; - } - } - break; - } - - case value_t::object: - { - for (const auto& element : *current->m_parent->m_value.object) - { - if (&element.second == current) - { - tokens.emplace_back(element.first.c_str()); - break; - } - } - break; - } - - case value_t::null: // LCOV_EXCL_LINE - case value_t::string: // LCOV_EXCL_LINE - case value_t::boolean: // LCOV_EXCL_LINE - case value_t::number_integer: // LCOV_EXCL_LINE - case value_t::number_unsigned: // LCOV_EXCL_LINE - case value_t::number_float: // LCOV_EXCL_LINE - case value_t::binary: // LCOV_EXCL_LINE - case value_t::discarded: // LCOV_EXCL_LINE - default: // LCOV_EXCL_LINE - break; // LCOV_EXCL_LINE - } - } - - if (tokens.empty()) - { - return ""; - } - - return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, - [](const std::string & a, const std::string & b) - { - return a + "/" + detail::escape(b); - }) + ") "; -#else - static_cast(leaf_element); - return ""; -#endif - } - - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; - -/*! -@brief exception indicating a parse error - -This exception is thrown by the library when a parse error occurs. Parse errors -can occur during the deserialization of JSON text, CBOR, MessagePack, as well -as when using JSON Patch. - -Member @a byte holds the byte index of the last read character in the input -file. - -Exceptions have ids 1xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. -json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). -json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed. - -@note For an input with n bytes, 1 is the index of the first character and n+1 - is the index of the terminating null byte or the end of file. This also - holds true when reading a byte vector (CBOR or MessagePack). - -@liveexample{The following code shows how a `parse_error` exception can be -caught.,parse_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class parse_error : public exception -{ - public: - /*! - @brief create a parse error exception - @param[in] id_ the id of the exception - @param[in] pos the position where the error occurred (or with - chars_read_total=0 if the position cannot be - determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - template - static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + exception::diagnostics(context) + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); - } - - template - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + exception::diagnostics(context) + what_arg; - return parse_error(id_, byte_, w.c_str()); - } - - /*! - @brief byte index of the parse error - - The byte index of the last read character in the input file. - - @note For an input with n bytes, 1 is the index of the first character and - n+1 is the index of the terminating null byte or the end of file. - This also holds true when reading a byte vector (CBOR or MessagePack). - */ - const std::size_t byte; - - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} - - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } -}; - -/*! -@brief exception indicating errors with iterators - -This exception is thrown if iterators passed to a library function do not match -the expected semantics. - -Exceptions have ids 2xx. - -name / id | example message | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). - -@liveexample{The following code shows how an `invalid_iterator` exception can be -caught.,invalid_iterator} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class invalid_iterator : public exception -{ - public: - template - static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context) - { - std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg; - return invalid_iterator(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating executing a member function with a wrong type - -This exception is thrown in case of a type error; that is, a library function is -executed on a JSON value whose type does not match the expected semantics. - -Exceptions have ids 3xx. - -name / id | example message | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. -json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | -json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | - -@liveexample{The following code shows how a `type_error` exception can be -caught.,type_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class type_error : public exception -{ - public: - template - static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context) - { - std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg; - return type_error(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating access out of the defined range - -This exception is thrown in case a library function is called on an input -parameter that exceeds the expected range, for instance in case of array -indices or nonexisting object keys. - -Exceptions have ids 4xx. - -name / id | example message | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) | -json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | -json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | - -@liveexample{The following code shows how an `out_of_range` exception can be -caught.,out_of_range} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class out_of_range : public exception -{ - public: - template - static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context) - { - std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg; - return out_of_range(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating other library errors - -This exception is thrown in case of errors that cannot be classified with the -other exception types. - -Exceptions have ids 5xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range - -@liveexample{The following code shows how an `other_error` exception can be -caught.,other_error} - -@since version 3.0.0 -*/ -class other_error : public exception -{ - public: - template - static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context) - { - std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg; - return other_error(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -namespace nlohmann -{ -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; - -template -struct Gen -{ - using type = integer_sequence; -}; - -} // namespace utility_internal - -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; - -//// END OF CODE FROM GOOGLE ABSEIL - -#endif - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static constexpr T value{}; -}; - -template -constexpr T static_const::value; - -} // namespace detail -} // namespace nlohmann - -// #include - - -namespace nlohmann -{ -namespace detail -{ -// dispatching helper struct -template struct identity_tag {}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // numeric_limits -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval -#include // tuple - -// #include - - -#include // random_access_iterator_tag - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; -} // namespace detail -} // namespace nlohmann - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -struct iterator_types {}; - -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; - -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; - -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; - -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include - -// #include - - -// https://en.cppreference.com/w/cpp/experimental/is_detected -namespace nlohmann -{ -namespace detail -{ -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; - -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -template class Op, class... Args> -using is_detected = typename detector::value_t; - -template class Op, class... Args> -struct is_detected_lazy : is_detected { }; - -template class Op, class... Args> -using detected_t = typename detector::type; - -template class Op, class... Args> -using detected_or = detector; - -template class Op, class... Args> -using detected_or_t = typename detected_or::type; - -template class Op, class... Args> -using is_detected_exact = std::is_same>; - -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; -} // namespace detail -} // namespace nlohmann - -// #include -#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - -#include // int64_t, uint64_t -#include // map -#include // allocator -#include // string -#include // vector - -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ -/*! -@brief default JSONSerializer template argument - -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer; - -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector> -class basic_json; - -/*! -@brief JSON Pointer - -A JSON pointer defines a string syntax for identifying a specific value -within a JSON document. It can be used with functions `at` and -`operator[]`. Furthermore, JSON pointers are the base for JSON patches. - -@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) - -@since version 2.0.0 -*/ -template -class json_pointer; - -/*! -@brief default JSON class - -This type is the default specialization of the @ref basic_json class which -uses the standard template types. - -@since version 1.0.0 -*/ -using json = basic_json<>; - -template -struct ordered_map; - -/*! -@brief ordered JSON class - -This type preserves the insertion order of object keys. - -@since version 3.9.0 -*/ -using ordered_json = basic_json; - -} // namespace nlohmann - -#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - -namespace nlohmann -{ -/*! -@brief detail namespace with internal helper functions - -This namespace collects functions that should not be exposed, -implementations of some @ref basic_json methods, and meta-programming helpers. - -@since version 2.1.0 -*/ -namespace detail -{ -///////////// -// helpers // -///////////// - -// Note to maintainers: -// -// Every trait in this file expects a non CV-qualified type. -// The only exceptions are in the 'aliases for detected' section -// (i.e. those of the form: decltype(T::member_function(std::declval()))) -// -// In this case, T has to be properly CV-qualified to constraint the function arguments -// (e.g. to_json(BasicJsonType&, const T&)) - -template struct is_basic_json : std::false_type {}; - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; - -////////////////////// -// json_ref helpers // -////////////////////// - -template -class json_ref; - -template -struct is_json_ref : std::false_type {}; - -template -struct is_json_ref> : std::true_type {}; - -////////////////////////// -// aliases for detected // -////////////////////////// - -template -using mapped_type_t = typename T::mapped_type; - -template -using key_type_t = typename T::key_type; - -template -using value_type_t = typename T::value_type; - -template -using difference_type_t = typename T::difference_type; - -template -using pointer_t = typename T::pointer; - -template -using reference_t = typename T::reference; - -template -using iterator_category_t = typename T::iterator_category; - -template -using iterator_t = typename T::iterator; - -template -using to_json_function = decltype(T::to_json(std::declval()...)); - -template -using from_json_function = decltype(T::from_json(std::declval()...)); - -template -using get_template_function = decltype(std::declval().template get()); - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; - -// trait checking if j.get is valid -// use this trait instead of std::is_constructible or std::is_convertible, -// both rely on, or make use of implicit conversions, and thus fail when T -// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; - -template -struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; - -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; - -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - - -/////////////////// -// is_ functions // -/////////////////// - -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B1 { }; -template -struct conjunction -: std::conditional, B1>::type {}; - -// https://en.cppreference.com/w/cpp/types/negation -template struct negation : std::integral_constant < bool, !B::value > { }; - -// Reimplementation of is_constructible and is_default_constructible, due to them being broken for -// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). -// This causes compile errors in e.g. clang 3.5 or gcc 4.9. -template -struct is_default_constructible : std::is_default_constructible {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - - -template -struct is_constructible : std::is_constructible {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - - -template -struct is_iterator_traits : std::false_type {}; - -template -struct is_iterator_traits> -{ - private: - using traits = iterator_traits; - - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; -}; - -// The following implementation of is_complete_type is taken from -// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ -// and is written by Xiang Fan who agreed to using it in this library. - -template -struct is_complete_type : std::false_type {}; - -template -struct is_complete_type : std::true_type {}; - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - is_constructible::value && - is_constructible::value; -}; - -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; - -template -struct is_constructible_object_type_impl : std::false_type {}; - -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - static constexpr bool value = - (is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); -}; - -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; - -template -struct is_compatible_string_type_impl : std::false_type {}; - -template -struct is_compatible_string_type_impl < - BasicJsonType, CompatibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - is_constructible::value; -}; - -template -struct is_compatible_string_type - : is_compatible_string_type_impl {}; - -template -struct is_constructible_string_type_impl : std::false_type {}; - -template -struct is_constructible_string_type_impl < - BasicJsonType, ConstructibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - is_constructible::value; -}; - -template -struct is_constructible_string_type - : is_constructible_string_type_impl {}; - -template -struct is_compatible_array_type_impl : std::false_type {}; - -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < is_detected::value&& - is_detected::value&& -// This is needed because json_reverse_iterator has a ::iterator type... -// Therefore it is detected as a CompatibleArrayType. -// The real fix would be to have an Iterable concept. - !is_iterator_traits < - iterator_traits>::value >> -{ - static constexpr bool value = - is_constructible::value; -}; - -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; - -template -struct is_constructible_array_type_impl : std::false_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_detected::value&& -is_complete_type < -detected_t>::value >> -{ - static constexpr bool value = - // This is needed because json_reverse_iterator has a ::iterator type, - // furthermore, std::back_insert_iterator (and other iterators) have a - // base class `iterator`... Therefore it is detected as a - // ConstructibleArrayType. The real fix would be to have an Iterable - // concept. - !is_iterator_traits>::value && - - (std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, typename ConstructibleArrayType::value_type >::value); -}; - -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; - -template -struct is_compatible_type_impl: std::false_type {}; - -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> -{ - static constexpr bool value = - has_to_json::value; -}; - -template -struct is_compatible_type - : is_compatible_type_impl {}; - -template -struct is_constructible_tuple : std::false_type {}; - -template -struct is_constructible_tuple> : conjunction...> {}; - -// a naive helper to check if a type is an ordered_map (exploits the fact that -// ordered_map inherits capacity() from std::vector) -template -struct is_ordered_map -{ - using one = char; - - struct two - { - char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - }; - - template static one test( decltype(&C::capacity) ) ; - template static two test(...); - - enum { value = sizeof(test(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) -}; - -// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) -template < typename T, typename U, enable_if_t < !std::is_same::value, int > = 0 > -T conditional_static_cast(U value) -{ - return static_cast(value); -} - -template::value, int> = 0> -T conditional_static_cast(U value) -{ - return value; -} - -} // namespace detail -} // namespace nlohmann - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -void from_json(const BasicJsonType& j, typename std::nullptr_t& n) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_null())) - { - JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j)); - } - n = nullptr; -} - -// overloads for basic_json template parameters -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < std::is_arithmetic::value&& - !std::is_same::value, - int > = 0 > -void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - - case value_t::null: - case value_t::object: - case value_t::array: - case value_t::string: - case value_t::boolean: - case value_t::binary: - case value_t::discarded: - default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); - } -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) - { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j)); - } - b = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); - } - s = *j.template get_ptr(); -} - -template < - typename BasicJsonType, typename ConstructibleStringType, - enable_if_t < - is_constructible_string_type::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ConstructibleStringType& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); - } - - s = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) -{ - get_arithmetic_value(j, val); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, EnumType& e) -{ - typename std::underlying_type::type val; - get_arithmetic_value(j, val); - e = static_cast(val); -} - -// forward_list doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::forward_list& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); - } - l.clear(); - std::transform(j.rbegin(), j.rend(), - std::front_inserter(l), [](const BasicJsonType & i) - { - return i.template get(); - }); -} - -// valarray doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::valarray& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); - } - l.resize(j.size()); - std::transform(j.begin(), j.end(), std::begin(l), - [](const BasicJsonType & elem) - { - return elem.template get(); - }); -} - -template -auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) --> decltype(j.template get(), void()) -{ - for (std::size_t i = 0; i < N; ++i) - { - arr[i] = j.at(i).template get(); - } -} - -template -void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) -{ - arr = *j.template get_ptr(); -} - -template -auto from_json_array_impl(const BasicJsonType& j, std::array& arr, - priority_tag<2> /*unused*/) --> decltype(j.template get(), void()) -{ - for (std::size_t i = 0; i < N; ++i) - { - arr[i] = j.at(i).template get(); - } -} - -template::value, - int> = 0> -auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) --> decltype( - arr.reserve(std::declval()), - j.template get(), - void()) -{ - using std::end; - - ConstructibleArrayType ret; - ret.reserve(j.size()); - std::transform(j.begin(), j.end(), - std::inserter(ret, end(ret)), [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); - arr = std::move(ret); -} - -template::value, - int> = 0> -void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, - priority_tag<0> /*unused*/) -{ - using std::end; - - ConstructibleArrayType ret; - std::transform( - j.begin(), j.end(), std::inserter(ret, end(ret)), - [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); - arr = std::move(ret); -} - -template < typename BasicJsonType, typename ConstructibleArrayType, - enable_if_t < - is_constructible_array_type::value&& - !is_constructible_object_type::value&& - !is_constructible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) --> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), -j.template get(), -void()) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); - } - - from_json_array_impl(j, arr, priority_tag<3> {}); -} - -template < typename BasicJsonType, typename T, std::size_t... Idx > -std::array from_json_inplace_array_impl(BasicJsonType&& j, - identity_tag> /*unused*/, index_sequence /*unused*/) -{ - return { { std::forward(j).at(Idx).template get()... } }; -} - -template < typename BasicJsonType, typename T, std::size_t N > -auto from_json(BasicJsonType&& j, identity_tag> tag) --> decltype(from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {})) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); - } - - return from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {}); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j)); - } - - bin = *j.template get_ptr(); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j)); - } - - ConstructibleObjectType ret; - const auto* inner_object = j.template get_ptr(); - using value_type = typename ConstructibleObjectType::value_type; - std::transform( - inner_object->begin(), inner_object->end(), - std::inserter(ret, ret.begin()), - [](typename BasicJsonType::object_t::value_type const & p) - { - return value_type(p.first, p.second.template get()); - }); - obj = std::move(ret); -} - -// overload for arithmetic types, not chosen for basic_json template arguments -// (BooleanType, etc..); note: Is it really necessary to provide explicit -// overloads for boolean_t etc. in case of a custom BooleanType which is not -// an arithmetic type? -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < - std::is_arithmetic::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::boolean: - { - val = static_cast(*j.template get_ptr()); - break; - } - - case value_t::null: - case value_t::object: - case value_t::array: - case value_t::string: - case value_t::binary: - case value_t::discarded: - default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); - } -} - -template -std::tuple from_json_tuple_impl_base(BasicJsonType&& j, index_sequence /*unused*/) -{ - return std::make_tuple(std::forward(j).at(Idx).template get()...); -} - -template < typename BasicJsonType, class A1, class A2 > -std::pair from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<0> /*unused*/) -{ - return {std::forward(j).at(0).template get(), - std::forward(j).at(1).template get()}; -} - -template -void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) -{ - p = from_json_tuple_impl(std::forward(j), identity_tag> {}, priority_tag<0> {}); -} - -template -std::tuple from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<2> /*unused*/) -{ - return from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); -} - -template -void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) -{ - t = from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); -} - -template -auto from_json(BasicJsonType&& j, TupleRelated&& t) --> decltype(from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {})) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); - } - - return from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {}); -} - -template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::map& m) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); - } - m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); - } - m.emplace(p.at(0).template get(), p.at(1).template get()); - } -} - -template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::unordered_map& m) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); - } - m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); - } - m.emplace(p.at(0).template get(), p.at(1).template get()); - } -} - -struct from_json_fn -{ - template - auto operator()(const BasicJsonType& j, T&& val) const - noexcept(noexcept(from_json(j, std::forward(val)))) - -> decltype(from_json(j, std::forward(val))) - { - return from_json(j, std::forward(val)); - } -}; -} // namespace detail - -/// namespace to hold default `from_json` function -/// to see why this is required: -/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html -namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) -{ -constexpr const auto& from_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) -} // namespace -} // namespace nlohmann - -// #include - - -#include // copy -#include // begin, end -#include // string -#include // tuple, get -#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type -#include // move, forward, declval, pair -#include // valarray -#include // vector - -// #include - - -#include // size_t -#include // input_iterator_tag -#include // string, to_string -#include // tuple_size, get, tuple_element -#include // move - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -void int_to_string( string_type& target, std::size_t value ) -{ - // For ADL - using std::to_string; - target = to_string(value); -} -template class iteration_proxy_value -{ - public: - using difference_type = std::ptrdiff_t; - using value_type = iteration_proxy_value; - using pointer = value_type * ; - using reference = value_type & ; - using iterator_category = std::input_iterator_tag; - using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; - - private: - /// the iterator - IteratorType anchor; - /// an index for arrays (used to create key names) - std::size_t array_index = 0; - /// last stringified array index - mutable std::size_t array_index_last = 0; - /// a string representation of the array index - mutable string_type array_index_str = "0"; - /// an empty string (to return a reference for primitive values) - const string_type empty_str{}; - - public: - explicit iteration_proxy_value(IteratorType it) noexcept - : anchor(std::move(it)) - {} - - /// dereference operator (needed for range-based for) - iteration_proxy_value& operator*() - { - return *this; - } - - /// increment operator (needed for range-based for) - iteration_proxy_value& operator++() - { - ++anchor; - ++array_index; - - return *this; - } - - /// equality operator (needed for InputIterator) - bool operator==(const iteration_proxy_value& o) const - { - return anchor == o.anchor; - } - - /// inequality operator (needed for range-based for) - bool operator!=(const iteration_proxy_value& o) const - { - return anchor != o.anchor; - } - - /// return key of the iterator - const string_type& key() const - { - JSON_ASSERT(anchor.m_object != nullptr); - - switch (anchor.m_object->type()) - { - // use integer array index as key - case value_t::array: - { - if (array_index != array_index_last) - { - int_to_string( array_index_str, array_index ); - array_index_last = array_index; - } - return array_index_str; - } - - // use key from the object - case value_t::object: - return anchor.key(); - - // use an empty key for all primitive types - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - return empty_str; - } - } - - /// return value of the iterator - typename IteratorType::reference value() const - { - return anchor.value(); - } -}; - -/// proxy class for the items() function -template class iteration_proxy -{ - private: - /// the container to iterate - typename IteratorType::reference container; - - public: - /// construct iteration proxy from a container - explicit iteration_proxy(typename IteratorType::reference cont) noexcept - : container(cont) {} - - /// return iterator begin (needed for range-based for) - iteration_proxy_value begin() noexcept - { - return iteration_proxy_value(container.begin()); - } - - /// return iterator end (needed for range-based for) - iteration_proxy_value end() noexcept - { - return iteration_proxy_value(container.end()); - } -}; -// Structured Bindings Support -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) -{ - return i.key(); -} -// Structured Bindings Support -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) -{ - return i.value(); -} -} // namespace detail -} // namespace nlohmann - -// The Addition to the STD Namespace is required to add -// Structured Bindings Support to the iteration_proxy_value class -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -namespace std -{ -#if defined(__clang__) - // Fix: https://github.com/nlohmann/json/issues/1401 - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wmismatched-tags" -#endif -template -class tuple_size<::nlohmann::detail::iteration_proxy_value> - : public std::integral_constant {}; - -template -class tuple_element> -{ - public: - using type = decltype( - get(std::declval < - ::nlohmann::detail::iteration_proxy_value> ())); -}; -#if defined(__clang__) - #pragma clang diagnostic pop -#endif -} // namespace std - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -////////////////// -// constructors // -////////////////// - -/* - * Note all external_constructor<>::construct functions need to call - * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an - * allocated value (e.g., a string). See bug issue - * https://github.com/nlohmann/json/issues/2865 for more information. - */ - -template struct external_constructor; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::boolean; - j.m_value = b; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value = s; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value = std::move(s); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleStringType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleStringType& str) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value.string = j.template create(str); - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::binary; - j.m_value = typename BasicJsonType::binary_t(b); - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::binary; - j.m_value = typename BasicJsonType::binary_t(std::move(b)); - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_float; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_unsigned; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_integer; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = arr; - j.set_parents(); - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = std::move(arr); - j.set_parents(); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleArrayType& arr) - { - using std::begin; - using std::end; - - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value.array = j.template create(begin(arr), end(arr)); - j.set_parents(); - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, const std::vector& arr) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->reserve(arr.size()); - for (const bool x : arr) - { - j.m_value.array->push_back(x); - j.set_parent(j.m_value.array->back()); - } - j.assert_invariant(); - } - - template::value, int> = 0> - static void construct(BasicJsonType& j, const std::valarray& arr) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->resize(arr.size()); - if (arr.size() > 0) - { - std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); - } - j.set_parents(); - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value = obj; - j.set_parents(); - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) - { - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value = std::move(obj); - j.set_parents(); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < !std::is_same::value, int > = 0 > - static void construct(BasicJsonType& j, const CompatibleObjectType& obj) - { - using std::begin; - using std::end; - - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value.object = j.template create(begin(obj), end(obj)); - j.set_parents(); - j.assert_invariant(); - } -}; - -///////////// -// to_json // -///////////// - -template::value, int> = 0> -void to_json(BasicJsonType& j, T b) noexcept -{ - external_constructor::construct(j, b); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, const CompatibleString& s) -{ - external_constructor::construct(j, s); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) -{ - external_constructor::construct(j, std::move(s)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, FloatType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, EnumType e) noexcept -{ - using underlying_type = typename std::underlying_type::type; - external_constructor::construct(j, static_cast(e)); -} - -template -void to_json(BasicJsonType& j, const std::vector& e) -{ - external_constructor::construct(j, e); -} - -template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < is_compatible_array_type::value&& - !is_compatible_object_type::value&& - !is_compatible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -void to_json(BasicJsonType& j, const CompatibleArrayType& arr) -{ - external_constructor::construct(j, arr); -} - -template -void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) -{ - external_constructor::construct(j, bin); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, const std::valarray& arr) -{ - external_constructor::construct(j, std::move(arr)); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) -{ - external_constructor::construct(j, std::move(arr)); -} - -template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > -void to_json(BasicJsonType& j, const CompatibleObjectType& obj) -{ - external_constructor::construct(j, obj); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) -{ - external_constructor::construct(j, std::move(obj)); -} - -template < - typename BasicJsonType, typename T, std::size_t N, - enable_if_t < !std::is_constructible::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - int > = 0 > -void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) -{ - external_constructor::construct(j, arr); -} - -template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > -void to_json(BasicJsonType& j, const std::pair& p) -{ - j = { p.first, p.second }; -} - -// for https://github.com/nlohmann/json/pull/1134 -template>::value, int> = 0> -void to_json(BasicJsonType& j, const T& b) -{ - j = { {b.key(), b.value()} }; -} - -template -void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) -{ - j = { std::get(t)... }; -} - -template::value, int > = 0> -void to_json(BasicJsonType& j, const T& t) -{ - to_json_tuple_impl(j, t, make_index_sequence::value> {}); -} - -struct to_json_fn -{ - template - auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) - -> decltype(to_json(j, std::forward(val)), void()) - { - return to_json(j, std::forward(val)); - } -}; -} // namespace detail - -/// namespace to hold default `to_json` function -/// to see why this is required: -/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html -namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) -{ -constexpr const auto& to_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) -} // namespace -} // namespace nlohmann - -// #include - -// #include - - -namespace nlohmann -{ - -template -struct adl_serializer -{ - /*! - @brief convert a JSON value to any value type - - This function is usually called by the `get()` function of the - @ref basic_json class (either explicit or via conversion operators). - - @note This function is chosen for default-constructible value types. - - @param[in] j JSON value to read from - @param[in,out] val value to write to - */ - template - static auto from_json(BasicJsonType && j, TargetType& val) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), val))) - -> decltype(::nlohmann::from_json(std::forward(j), val), void()) - { - ::nlohmann::from_json(std::forward(j), val); - } - - /*! - @brief convert a JSON value to any value type - - This function is usually called by the `get()` function of the - @ref basic_json class (either explicit or via conversion operators). - - @note This function is chosen for value types which are not default-constructible. - - @param[in] j JSON value to read from - - @return copy of the JSON value, converted to @a ValueType - */ - template - static auto from_json(BasicJsonType && j) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), detail::identity_tag {}))) - -> decltype(::nlohmann::from_json(std::forward(j), detail::identity_tag {})) - { - return ::nlohmann::from_json(std::forward(j), detail::identity_tag {}); - } - - /*! - @brief convert any value type to a JSON value - - This function is usually called by the constructors of the @ref basic_json - class. - - @param[in,out] j JSON value to write to - @param[in] val value to read from - */ - template - static auto to_json(BasicJsonType& j, TargetType && val) noexcept( - noexcept(::nlohmann::to_json(j, std::forward(val)))) - -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) - { - ::nlohmann::to_json(j, std::forward(val)); - } -}; -} // namespace nlohmann - -// #include - - -#include // uint8_t, uint64_t -#include // tie -#include // move - -namespace nlohmann -{ - -/*! -@brief an internal type for a backed binary type - -This type extends the template parameter @a BinaryType provided to `basic_json` -with a subtype used by BSON and MessagePack. This type exists so that the user -does not have to specify a type themselves with a specific naming scheme in -order to override the binary type. - -@tparam BinaryType container to store bytes (`std::vector` by - default) - -@since version 3.8.0; changed type of subtypes to std::uint64_t in 3.10.0. -*/ -template -class byte_container_with_subtype : public BinaryType -{ - public: - /// the type of the underlying container - using container_type = BinaryType; - /// the type of the subtype - using subtype_type = std::uint64_t; - - byte_container_with_subtype() noexcept(noexcept(container_type())) - : container_type() - {} - - byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) - : container_type(b) - {} - - byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - {} - - byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) - : container_type(b) - , m_subtype(subtype_) - , m_has_subtype(true) - {} - - byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - , m_subtype(subtype_) - , m_has_subtype(true) - {} - - bool operator==(const byte_container_with_subtype& rhs) const - { - return std::tie(static_cast(*this), m_subtype, m_has_subtype) == - std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); - } - - bool operator!=(const byte_container_with_subtype& rhs) const - { - return !(rhs == *this); - } - - /*! - @brief sets the binary subtype - - Sets the binary subtype of the value, also flags a binary JSON value as - having a subtype, which has implications for serialization. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa see @ref subtype() -- return the binary subtype - @sa see @ref clear_subtype() -- clears the binary subtype - @sa see @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0 - */ - void set_subtype(subtype_type subtype_) noexcept - { - m_subtype = subtype_; - m_has_subtype = true; - } - - /*! - @brief return the binary subtype - - Returns the numerical subtype of the value if it has a subtype. If it does - not have a subtype, this function will return subtype_type(-1) as a sentinel - value. - - @return the numerical subtype of the binary value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa see @ref set_subtype() -- sets the binary subtype - @sa see @ref clear_subtype() -- clears the binary subtype - @sa see @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0; fixed return value to properly return - subtype_type(-1) as documented in version 3.10.0 - */ - constexpr subtype_type subtype() const noexcept - { - return m_has_subtype ? m_subtype : subtype_type(-1); - } - - /*! - @brief return whether the value has a subtype - - @return whether the value has a subtype - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa see @ref subtype() -- return the binary subtype - @sa see @ref set_subtype() -- sets the binary subtype - @sa see @ref clear_subtype() -- clears the binary subtype - - @since version 3.8.0 - */ - constexpr bool has_subtype() const noexcept - { - return m_has_subtype; - } - - /*! - @brief clears the binary subtype - - Clears the binary subtype and flags the value as not having a subtype, which - has implications for serialization; for instance MessagePack will prefer the - bin family over the ext family. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa see @ref subtype() -- return the binary subtype - @sa see @ref set_subtype() -- sets the binary subtype - @sa see @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0 - */ - void clear_subtype() noexcept - { - m_subtype = 0; - m_has_subtype = false; - } - - private: - subtype_type m_subtype = 0; - bool m_has_subtype = false; -}; - -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - - -#include // uint8_t -#include // size_t -#include // hash - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ - -// boost::hash_combine -inline std::size_t combine(std::size_t seed, std::size_t h) noexcept -{ - seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); - return seed; -} - -/*! -@brief hash a JSON value - -The hash function tries to rely on std::hash where possible. Furthermore, the -type of the JSON value is taken into account to have different hash values for -null, 0, 0U, and false, etc. - -@tparam BasicJsonType basic_json specialization -@param j JSON value to hash -@return hash value of j -*/ -template -std::size_t hash(const BasicJsonType& j) -{ - using string_t = typename BasicJsonType::string_t; - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - - const auto type = static_cast(j.type()); - switch (j.type()) - { - case BasicJsonType::value_t::null: - case BasicJsonType::value_t::discarded: - { - return combine(type, 0); - } - - case BasicJsonType::value_t::object: - { - auto seed = combine(type, j.size()); - for (const auto& element : j.items()) - { - const auto h = std::hash {}(element.key()); - seed = combine(seed, h); - seed = combine(seed, hash(element.value())); - } - return seed; - } - - case BasicJsonType::value_t::array: - { - auto seed = combine(type, j.size()); - for (const auto& element : j) - { - seed = combine(seed, hash(element)); - } - return seed; - } - - case BasicJsonType::value_t::string: - { - const auto h = std::hash {}(j.template get_ref()); - return combine(type, h); - } - - case BasicJsonType::value_t::boolean: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_integer: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_unsigned: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_float: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::binary: - { - auto seed = combine(type, j.get_binary().size()); - const auto h = std::hash {}(j.get_binary().has_subtype()); - seed = combine(seed, h); - seed = combine(seed, static_cast(j.get_binary().subtype())); - for (const auto byte : j.get_binary()) - { - seed = combine(seed, std::hash {}(byte)); - } - return seed; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - return 0; // LCOV_EXCL_LINE - } -} - -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // generate_n -#include // array -#include // ldexp -#include // size_t -#include // uint8_t, uint16_t, uint32_t, uint64_t -#include // snprintf -#include // memcpy -#include // back_inserter -#include // numeric_limits -#include // char_traits, string -#include // make_pair, move -#include // vector - -// #include - -// #include - - -#include // array -#include // size_t -#include // strlen -#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next -#include // shared_ptr, make_shared, addressof -#include // accumulate -#include // string, char_traits -#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer -#include // pair, declval - -#ifndef JSON_NO_IO - #include // FILE * - #include // istream -#endif // JSON_NO_IO - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/// the supported input formats -enum class input_format_t { json, cbor, msgpack, ubjson, bson }; - -//////////////////// -// input adapters // -//////////////////// - -#ifndef JSON_NO_IO -/*! -Input adapter for stdio file access. This adapter read only 1 byte and do not use any - buffer. This adapter is a very low level adapter. -*/ -class file_input_adapter -{ - public: - using char_type = char; - - JSON_HEDLEY_NON_NULL(2) - explicit file_input_adapter(std::FILE* f) noexcept - : m_file(f) - {} - - // make class move-only - file_input_adapter(const file_input_adapter&) = delete; - file_input_adapter(file_input_adapter&&) noexcept = default; - file_input_adapter& operator=(const file_input_adapter&) = delete; - file_input_adapter& operator=(file_input_adapter&&) = delete; - ~file_input_adapter() = default; - - std::char_traits::int_type get_character() noexcept - { - return std::fgetc(m_file); - } - - private: - /// the file pointer to read from - std::FILE* m_file; -}; - - -/*! -Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at -beginning of input. Does not support changing the underlying std::streambuf -in mid-input. Maintains underlying std::istream and std::streambuf to support -subsequent use of standard std::istream operations to process any input -characters following those used in parsing the JSON input. Clears the -std::istream flags; any input errors (e.g., EOF) will be detected by the first -subsequent call for input from the std::istream. -*/ -class input_stream_adapter -{ - public: - using char_type = char; - - ~input_stream_adapter() - { - // clear stream flags; we use underlying streambuf I/O, do not - // maintain ifstream flags, except eof - if (is != nullptr) - { - is->clear(is->rdstate() & std::ios::eofbit); - } - } - - explicit input_stream_adapter(std::istream& i) - : is(&i), sb(i.rdbuf()) - {} - - // delete because of pointer members - input_stream_adapter(const input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&&) = delete; - - input_stream_adapter(input_stream_adapter&& rhs) noexcept - : is(rhs.is), sb(rhs.sb) - { - rhs.is = nullptr; - rhs.sb = nullptr; - } - - // std::istream/std::streambuf use std::char_traits::to_int_type, to - // ensure that std::char_traits::eof() and the character 0xFF do not - // end up as the same value, eg. 0xFFFFFFFF. - std::char_traits::int_type get_character() - { - auto res = sb->sbumpc(); - // set eof manually, as we don't use the istream interface. - if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) - { - is->clear(is->rdstate() | std::ios::eofbit); - } - return res; - } - - private: - /// the associated input stream - std::istream* is = nullptr; - std::streambuf* sb = nullptr; -}; -#endif // JSON_NO_IO - -// General-purpose iterator-based adapter. It might not be as fast as -// theoretically possible for some containers, but it is extremely versatile. -template -class iterator_input_adapter -{ - public: - using char_type = typename std::iterator_traits::value_type; - - iterator_input_adapter(IteratorType first, IteratorType last) - : current(std::move(first)), end(std::move(last)) - {} - - typename std::char_traits::int_type get_character() - { - if (JSON_HEDLEY_LIKELY(current != end)) - { - auto result = std::char_traits::to_int_type(*current); - std::advance(current, 1); - return result; - } - - return std::char_traits::eof(); - } - - private: - IteratorType current; - IteratorType end; - - template - friend struct wide_string_input_helper; - - bool empty() const - { - return current == end; - } -}; - - -template -struct wide_string_input_helper; - -template -struct wide_string_input_helper -{ - // UTF-32 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) - { - utf8_bytes_index = 0; - - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { - utf8_bytes[0] = std::char_traits::eof(); - utf8_bytes_filled = 1; - } - else - { - // get the current character - const auto wc = input.get_character(); - - // UTF-32 to UTF-8 encoding - if (wc < 0x80) - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 2; - } - else if (wc <= 0xFFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 3; - } - else if (wc <= 0x10FFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 4; - } - else - { - // unknown character - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - } - } -}; - -template -struct wide_string_input_helper -{ - // UTF-16 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) - { - utf8_bytes_index = 0; - - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { - utf8_bytes[0] = std::char_traits::eof(); - utf8_bytes_filled = 1; - } - else - { - // get the current character - const auto wc = input.get_character(); - - // UTF-16 to UTF-8 encoding - if (wc < 0x80) - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 2; - } - else if (0xD800 > wc || wc >= 0xE000) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 3; - } - else - { - if (JSON_HEDLEY_UNLIKELY(!input.empty())) - { - const auto wc2 = static_cast(input.get_character()); - const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); - utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); - utf8_bytes_filled = 4; - } - else - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - } - } - } -}; - -// Wraps another input apdater to convert wide character types into individual bytes. -template -class wide_string_input_adapter -{ - public: - using char_type = char; - - wide_string_input_adapter(BaseInputAdapter base) - : base_adapter(base) {} - - typename std::char_traits::int_type get_character() noexcept - { - // check if buffer needs to be filled - if (utf8_bytes_index == utf8_bytes_filled) - { - fill_buffer(); - - JSON_ASSERT(utf8_bytes_filled > 0); - JSON_ASSERT(utf8_bytes_index == 0); - } - - // use buffer - JSON_ASSERT(utf8_bytes_filled > 0); - JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); - return utf8_bytes[utf8_bytes_index++]; - } - - private: - BaseInputAdapter base_adapter; - - template - void fill_buffer() - { - wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); - } - - /// a buffer for UTF-8 bytes - std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; - - /// index to the utf8_codes array for the next valid byte - std::size_t utf8_bytes_index = 0; - /// number of valid bytes in the utf8_codes array - std::size_t utf8_bytes_filled = 0; -}; - - -template -struct iterator_input_adapter_factory -{ - using iterator_type = IteratorType; - using char_type = typename std::iterator_traits::value_type; - using adapter_type = iterator_input_adapter; - - static adapter_type create(IteratorType first, IteratorType last) - { - return adapter_type(std::move(first), std::move(last)); - } -}; - -template -struct is_iterator_of_multibyte -{ - using value_type = typename std::iterator_traits::value_type; - enum - { - value = sizeof(value_type) > 1 - }; -}; - -template -struct iterator_input_adapter_factory::value>> -{ - using iterator_type = IteratorType; - using char_type = typename std::iterator_traits::value_type; - using base_adapter_type = iterator_input_adapter; - using adapter_type = wide_string_input_adapter; - - static adapter_type create(IteratorType first, IteratorType last) - { - return adapter_type(base_adapter_type(std::move(first), std::move(last))); - } -}; - -// General purpose iterator-based input -template -typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) -{ - using factory_type = iterator_input_adapter_factory; - return factory_type::create(first, last); -} - -// Convenience shorthand from container to iterator -// Enables ADL on begin(container) and end(container) -// Encloses the using declarations in namespace for not to leak them to outside scope - -namespace container_input_adapter_factory_impl -{ - -using std::begin; -using std::end; - -template -struct container_input_adapter_factory {}; - -template -struct container_input_adapter_factory< ContainerType, - void_t()), end(std::declval()))>> - { - using adapter_type = decltype(input_adapter(begin(std::declval()), end(std::declval()))); - - static adapter_type create(const ContainerType& container) -{ - return input_adapter(begin(container), end(container)); -} - }; - -} // namespace container_input_adapter_factory_impl - -template -typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) -{ - return container_input_adapter_factory_impl::container_input_adapter_factory::create(container); -} - -#ifndef JSON_NO_IO -// Special cases with fast paths -inline file_input_adapter input_adapter(std::FILE* file) -{ - return file_input_adapter(file); -} - -inline input_stream_adapter input_adapter(std::istream& stream) -{ - return input_stream_adapter(stream); -} - -inline input_stream_adapter input_adapter(std::istream&& stream) -{ - return input_stream_adapter(stream); -} -#endif // JSON_NO_IO - -using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); - -// Null-delimited strings, and the like. -template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - !std::is_array::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > -contiguous_bytes_input_adapter input_adapter(CharT b) -{ - auto length = std::strlen(reinterpret_cast(b)); - const auto* ptr = reinterpret_cast(b); - return input_adapter(ptr, ptr + length); -} - -template -auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) -{ - return input_adapter(array, array + N); -} - -// This class only handles inputs of input_buffer_adapter type. -// It's required so that expressions like {ptr, len} can be implicitely casted -// to the correct adapter. -class span_input_adapter -{ - public: - template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > - span_input_adapter(CharT b, std::size_t l) - : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} - - template::iterator_category, std::random_access_iterator_tag>::value, - int>::type = 0> - span_input_adapter(IteratorType first, IteratorType last) - : ia(input_adapter(first, last)) {} - - contiguous_bytes_input_adapter&& get() - { - return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) - } - - private: - contiguous_bytes_input_adapter ia; -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include -#include // string -#include // move -#include // vector - -// #include - -// #include - - -namespace nlohmann -{ - -/*! -@brief SAX interface - -This class describes the SAX interface used by @ref nlohmann::json::sax_parse. -Each function is called in different situations while the input is parsed. The -boolean return value informs the parser whether to continue processing the -input. -*/ -template -struct json_sax -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - /*! - @brief a null value was read - @return whether parsing should proceed - */ - virtual bool null() = 0; - - /*! - @brief a boolean value was read - @param[in] val boolean value - @return whether parsing should proceed - */ - virtual bool boolean(bool val) = 0; - - /*! - @brief an integer number was read - @param[in] val integer value - @return whether parsing should proceed - */ - virtual bool number_integer(number_integer_t val) = 0; - - /*! - @brief an unsigned integer number was read - @param[in] val unsigned integer value - @return whether parsing should proceed - */ - virtual bool number_unsigned(number_unsigned_t val) = 0; - - /*! - @brief an floating-point number was read - @param[in] val floating-point value - @param[in] s raw token value - @return whether parsing should proceed - */ - virtual bool number_float(number_float_t val, const string_t& s) = 0; - - /*! - @brief a string was read - @param[in] val string value - @return whether parsing should proceed - @note It is safe to move the passed string. - */ - virtual bool string(string_t& val) = 0; - - /*! - @brief a binary string was read - @param[in] val binary value - @return whether parsing should proceed - @note It is safe to move the passed binary. - */ - virtual bool binary(binary_t& val) = 0; - - /*! - @brief the beginning of an object was read - @param[in] elements number of object elements or -1 if unknown - @return whether parsing should proceed - @note binary formats may report the number of elements - */ - virtual bool start_object(std::size_t elements) = 0; - - /*! - @brief an object key was read - @param[in] val object key - @return whether parsing should proceed - @note It is safe to move the passed string. - */ - virtual bool key(string_t& val) = 0; - - /*! - @brief the end of an object was read - @return whether parsing should proceed - */ - virtual bool end_object() = 0; - - /*! - @brief the beginning of an array was read - @param[in] elements number of array elements or -1 if unknown - @return whether parsing should proceed - @note binary formats may report the number of elements - */ - virtual bool start_array(std::size_t elements) = 0; - - /*! - @brief the end of an array was read - @return whether parsing should proceed - */ - virtual bool end_array() = 0; - - /*! - @brief a parse error occurred - @param[in] position the position in the input where the error occurs - @param[in] last_token the last read token - @param[in] ex an exception object describing the error - @return whether parsing should proceed (must return false) - */ - virtual bool parse_error(std::size_t position, - const std::string& last_token, - const detail::exception& ex) = 0; - - json_sax() = default; - json_sax(const json_sax&) = default; - json_sax(json_sax&&) noexcept = default; - json_sax& operator=(const json_sax&) = default; - json_sax& operator=(json_sax&&) noexcept = default; - virtual ~json_sax() = default; -}; - - -namespace detail -{ -/*! -@brief SAX implementation to create a JSON value from SAX events - -This class implements the @ref json_sax interface and processes the SAX events -to create a JSON value which makes it basically a DOM parser. The structure or -hierarchy of the JSON value is managed by the stack `ref_stack` which contains -a pointer to the respective array or object for each recursion depth. - -After successful parsing, the value that is passed by reference to the -constructor contains the parsed value. - -@tparam BasicJsonType the JSON type -*/ -template -class json_sax_dom_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - /*! - @param[in,out] r reference to a JSON value that is manipulated while - parsing - @param[in] allow_exceptions_ whether parse errors yield exceptions - */ - explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) - : root(r), allow_exceptions(allow_exceptions_) - {} - - // make class move-only - json_sax_dom_parser(const json_sax_dom_parser&) = delete; - json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; - json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - ~json_sax_dom_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); - - if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); - } - - return true; - } - - bool key(string_t& val) - { - // add null at given key and store the reference for later - object_element = &(ref_stack.back()->m_value.object->operator[](val)); - return true; - } - - bool end_object() - { - ref_stack.back()->set_parents(); - ref_stack.pop_back(); - return true; - } - - bool start_array(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); - - if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); - } - - return true; - } - - bool end_array() - { - ref_stack.back()->set_parents(); - ref_stack.pop_back(); - return true; - } - - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } - - constexpr bool is_errored() const - { - return errored; - } - - private: - /*! - @invariant If the ref stack is empty, then the passed value will be the new - root. - @invariant If the ref stack contains a value, then it is an array or an - object to which we can add elements - */ - template - JSON_HEDLEY_RETURNS_NON_NULL - BasicJsonType* handle_value(Value&& v) - { - if (ref_stack.empty()) - { - root = BasicJsonType(std::forward(v)); - return &root; - } - - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->emplace_back(std::forward(v)); - return &(ref_stack.back()->m_value.array->back()); - } - - JSON_ASSERT(ref_stack.back()->is_object()); - JSON_ASSERT(object_element); - *object_element = BasicJsonType(std::forward(v)); - return object_element; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; - -template -class json_sax_dom_callback_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using parser_callback_t = typename BasicJsonType::parser_callback_t; - using parse_event_t = typename BasicJsonType::parse_event_t; - - json_sax_dom_callback_parser(BasicJsonType& r, - const parser_callback_t cb, - const bool allow_exceptions_ = true) - : root(r), callback(cb), allow_exceptions(allow_exceptions_) - { - keep_stack.push_back(true); - } - - // make class move-only - json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - ~json_sax_dom_callback_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - // check callback for object start - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::object, true); - ref_stack.push_back(val.second); - - // check object limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); - } - - return true; - } - - bool key(string_t& val) - { - BasicJsonType k = BasicJsonType(val); - - // check callback for key - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); - key_keep_stack.push_back(keep); - - // add discarded value at given key and store the reference for later - if (keep && ref_stack.back()) - { - object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); - } - - return true; - } - - bool end_object() - { - if (ref_stack.back()) - { - if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) - { - // discard object - *ref_stack.back() = discarded; - } - else - { - ref_stack.back()->set_parents(); - } - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) - { - // remove discarded value - for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) - { - if (it->is_discarded()) - { - ref_stack.back()->erase(it); - break; - } - } - } - - return true; - } - - bool start_array(std::size_t len) - { - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::array, true); - ref_stack.push_back(val.second); - - // check array limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); - } - - return true; - } - - bool end_array() - { - bool keep = true; - - if (ref_stack.back()) - { - keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); - if (keep) - { - ref_stack.back()->set_parents(); - } - else - { - // discard array - *ref_stack.back() = discarded; - } - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - // remove discarded value - if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->pop_back(); - } - - return true; - } - - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } - - constexpr bool is_errored() const - { - return errored; - } - - private: - /*! - @param[in] v value to add to the JSON value we build during parsing - @param[in] skip_callback whether we should skip calling the callback - function; this is required after start_array() and - start_object() SAX events, because otherwise we would call the - callback function with an empty array or object, respectively. - - @invariant If the ref stack is empty, then the passed value will be the new - root. - @invariant If the ref stack contains a value, then it is an array or an - object to which we can add elements - - @return pair of boolean (whether value should be kept) and pointer (to the - passed value in the ref_stack hierarchy; nullptr if not kept) - */ - template - std::pair handle_value(Value&& v, const bool skip_callback = false) - { - JSON_ASSERT(!keep_stack.empty()); - - // do not handle this value if we know it would be added to a discarded - // container - if (!keep_stack.back()) - { - return {false, nullptr}; - } - - // create value - auto value = BasicJsonType(std::forward(v)); - - // check callback - const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); - - // do not handle this value if we just learnt it shall be discarded - if (!keep) - { - return {false, nullptr}; - } - - if (ref_stack.empty()) - { - root = std::move(value); - return {true, &root}; - } - - // skip this value if we already decided to skip the parent - // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) - if (!ref_stack.back()) - { - return {false, nullptr}; - } - - // we now only expect arrays and objects - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - // array - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->emplace_back(std::move(value)); - return {true, &(ref_stack.back()->m_value.array->back())}; - } - - // object - JSON_ASSERT(ref_stack.back()->is_object()); - // check if we should store an element for the current key - JSON_ASSERT(!key_keep_stack.empty()); - const bool store_element = key_keep_stack.back(); - key_keep_stack.pop_back(); - - if (!store_element) - { - return {false, nullptr}; - } - - JSON_ASSERT(object_element); - *object_element = std::move(value); - return {true, object_element}; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// stack to manage which values to keep - std::vector keep_stack {}; - /// stack to manage which object keys to keep - std::vector key_keep_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// callback function - const parser_callback_t callback = nullptr; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; - /// a discarded value for the callback - BasicJsonType discarded = BasicJsonType::value_t::discarded; -}; - -template -class json_sax_acceptor -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - bool null() - { - return true; - } - - bool boolean(bool /*unused*/) - { - return true; - } - - bool number_integer(number_integer_t /*unused*/) - { - return true; - } - - bool number_unsigned(number_unsigned_t /*unused*/) - { - return true; - } - - bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) - { - return true; - } - - bool string(string_t& /*unused*/) - { - return true; - } - - bool binary(binary_t& /*unused*/) - { - return true; - } - - bool start_object(std::size_t /*unused*/ = std::size_t(-1)) - { - return true; - } - - bool key(string_t& /*unused*/) - { - return true; - } - - bool end_object() - { - return true; - } - - bool start_array(std::size_t /*unused*/ = std::size_t(-1)) - { - return true; - } - - bool end_array() - { - return true; - } - - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) - { - return false; - } -}; -} // namespace detail - -} // namespace nlohmann - -// #include - - -#include // array -#include // localeconv -#include // size_t -#include // snprintf -#include // strtof, strtod, strtold, strtoll, strtoull -#include // initializer_list -#include // char_traits, string -#include // move -#include // vector - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/////////// -// lexer // -/////////// - -template -class lexer_base -{ - public: - /// token types for the parser - enum class token_type - { - uninitialized, ///< indicating the scanner is uninitialized - literal_true, ///< the `true` literal - literal_false, ///< the `false` literal - literal_null, ///< the `null` literal - value_string, ///< a string -- use get_string() for actual value - value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value - value_integer, ///< a signed integer -- use get_number_integer() for actual value - value_float, ///< an floating point number -- use get_number_float() for actual value - begin_array, ///< the character for array begin `[` - begin_object, ///< the character for object begin `{` - end_array, ///< the character for array end `]` - end_object, ///< the character for object end `}` - name_separator, ///< the name separator `:` - value_separator, ///< the value separator `,` - parse_error, ///< indicating a parse error - end_of_input, ///< indicating the end of the input buffer - literal_or_value ///< a literal or the begin of a value (only for diagnostics) - }; - - /// return name of values of type token_type (only used for errors) - JSON_HEDLEY_RETURNS_NON_NULL - JSON_HEDLEY_CONST - static const char* token_type_name(const token_type t) noexcept - { - switch (t) - { - case token_type::uninitialized: - return ""; - case token_type::literal_true: - return "true literal"; - case token_type::literal_false: - return "false literal"; - case token_type::literal_null: - return "null literal"; - case token_type::value_string: - return "string literal"; - case token_type::value_unsigned: - case token_type::value_integer: - case token_type::value_float: - return "number literal"; - case token_type::begin_array: - return "'['"; - case token_type::begin_object: - return "'{'"; - case token_type::end_array: - return "']'"; - case token_type::end_object: - return "'}'"; - case token_type::name_separator: - return "':'"; - case token_type::value_separator: - return "','"; - case token_type::parse_error: - return ""; - case token_type::end_of_input: - return "end of input"; - case token_type::literal_or_value: - return "'[', '{', or a literal"; - // LCOV_EXCL_START - default: // catch non-enum values - return "unknown token"; - // LCOV_EXCL_STOP - } - } -}; -/*! -@brief lexical analysis - -This class organizes the lexical analysis during JSON deserialization. -*/ -template -class lexer : public lexer_base -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using char_type = typename InputAdapterType::char_type; - using char_int_type = typename std::char_traits::int_type; - - public: - using token_type = typename lexer_base::token_type; - - explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept - : ia(std::move(adapter)) - , ignore_comments(ignore_comments_) - , decimal_point_char(static_cast(get_decimal_point())) - {} - - // delete because of pointer members - lexer(const lexer&) = delete; - lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - lexer& operator=(lexer&) = delete; - lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - ~lexer() = default; - - private: - ///////////////////// - // locales - ///////////////////// - - /// return the locale-dependent decimal point - JSON_HEDLEY_PURE - static char get_decimal_point() noexcept - { - const auto* loc = localeconv(); - JSON_ASSERT(loc != nullptr); - return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); - } - - ///////////////////// - // scan functions - ///////////////////// - - /*! - @brief get codepoint from 4 hex characters following `\u` - - For input "\u c1 c2 c3 c4" the codepoint is: - (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 - = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) - - Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' - must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The - conversion is done by subtracting the offset (0x30, 0x37, and 0x57) - between the ASCII value of the character and the desired integer value. - - @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or - non-hex character) - */ - int get_codepoint() - { - // this function only makes sense after reading `\u` - JSON_ASSERT(current == 'u'); - int codepoint = 0; - - const auto factors = { 12u, 8u, 4u, 0u }; - for (const auto factor : factors) - { - get(); - - if (current >= '0' && current <= '9') - { - codepoint += static_cast((static_cast(current) - 0x30u) << factor); - } - else if (current >= 'A' && current <= 'F') - { - codepoint += static_cast((static_cast(current) - 0x37u) << factor); - } - else if (current >= 'a' && current <= 'f') - { - codepoint += static_cast((static_cast(current) - 0x57u) << factor); - } - else - { - return -1; - } - } - - JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); - return codepoint; - } - - /*! - @brief check if the next byte(s) are inside a given range - - Adds the current byte and, for each passed range, reads a new byte and - checks if it is inside the range. If a violation was detected, set up an - error message and return false. Otherwise, return true. - - @param[in] ranges list of integers; interpreted as list of pairs of - inclusive lower and upper bound, respectively - - @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, - 1, 2, or 3 pairs. This precondition is enforced by an assertion. - - @return true if and only if no range violation was detected - */ - bool next_byte_in_range(std::initializer_list ranges) - { - JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); - add(current); - - for (auto range = ranges.begin(); range != ranges.end(); ++range) - { - get(); - if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) - { - add(current); - } - else - { - error_message = "invalid string: ill-formed UTF-8 byte"; - return false; - } - } - - return true; - } - - /*! - @brief scan a string literal - - This function scans a string according to Sect. 7 of RFC 8259. While - scanning, bytes are escaped and copied into buffer token_buffer. Then the - function returns successfully, token_buffer is *not* null-terminated (as it - may contain \0 bytes), and token_buffer.size() is the number of bytes in the - string. - - @return token_type::value_string if string could be successfully scanned, - token_type::parse_error otherwise - - @note In case of errors, variable error_message contains a textual - description. - */ - token_type scan_string() - { - // reset token_buffer (ignore opening quote) - reset(); - - // we entered the function by reading an open quote - JSON_ASSERT(current == '\"'); - - while (true) - { - // get next character - switch (get()) - { - // end of file while parsing string - case std::char_traits::eof(): - { - error_message = "invalid string: missing closing quote"; - return token_type::parse_error; - } - - // closing quote - case '\"': - { - return token_type::value_string; - } - - // escapes - case '\\': - { - switch (get()) - { - // quotation mark - case '\"': - add('\"'); - break; - // reverse solidus - case '\\': - add('\\'); - break; - // solidus - case '/': - add('/'); - break; - // backspace - case 'b': - add('\b'); - break; - // form feed - case 'f': - add('\f'); - break; - // line feed - case 'n': - add('\n'); - break; - // carriage return - case 'r': - add('\r'); - break; - // tab - case 't': - add('\t'); - break; - - // unicode escapes - case 'u': - { - const int codepoint1 = get_codepoint(); - int codepoint = codepoint1; // start with codepoint1 - - if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } - - // check if code point is a high surrogate - if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) - { - // expect next \uxxxx entry - if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) - { - const int codepoint2 = get_codepoint(); - - if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } - - // check if codepoint2 is a low surrogate - if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) - { - // overwrite codepoint - codepoint = static_cast( - // high surrogate occupies the most significant 22 bits - (static_cast(codepoint1) << 10u) - // low surrogate occupies the least significant 15 bits - + static_cast(codepoint2) - // there is still the 0xD800, 0xDC00 and 0x10000 noise - // in the result so we have to subtract with: - // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 - - 0x35FDC00u); - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) - { - error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; - return token_type::parse_error; - } - } - - // result of the above calculation yields a proper codepoint - JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); - - // translate codepoint into bytes - if (codepoint < 0x80) - { - // 1-byte characters: 0xxxxxxx (ASCII) - add(static_cast(codepoint)); - } - else if (codepoint <= 0x7FF) - { - // 2-byte characters: 110xxxxx 10xxxxxx - add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else if (codepoint <= 0xFFFF) - { - // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx - add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else - { - // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - - break; - } - - // other characters after escape - default: - error_message = "invalid string: forbidden character after backslash"; - return token_type::parse_error; - } - - break; - } - - // invalid control characters - case 0x00: - { - error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; - return token_type::parse_error; - } - - case 0x01: - { - error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; - return token_type::parse_error; - } - - case 0x02: - { - error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; - return token_type::parse_error; - } - - case 0x03: - { - error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; - return token_type::parse_error; - } - - case 0x04: - { - error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; - return token_type::parse_error; - } - - case 0x05: - { - error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; - return token_type::parse_error; - } - - case 0x06: - { - error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; - return token_type::parse_error; - } - - case 0x07: - { - error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; - return token_type::parse_error; - } - - case 0x08: - { - error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; - return token_type::parse_error; - } - - case 0x09: - { - error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; - return token_type::parse_error; - } - - case 0x0A: - { - error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; - return token_type::parse_error; - } - - case 0x0B: - { - error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; - return token_type::parse_error; - } - - case 0x0C: - { - error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; - return token_type::parse_error; - } - - case 0x0D: - { - error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; - return token_type::parse_error; - } - - case 0x0E: - { - error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; - return token_type::parse_error; - } - - case 0x0F: - { - error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; - return token_type::parse_error; - } - - case 0x10: - { - error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; - return token_type::parse_error; - } - - case 0x11: - { - error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; - return token_type::parse_error; - } - - case 0x12: - { - error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; - return token_type::parse_error; - } - - case 0x13: - { - error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; - return token_type::parse_error; - } - - case 0x14: - { - error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; - return token_type::parse_error; - } - - case 0x15: - { - error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; - return token_type::parse_error; - } - - case 0x16: - { - error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; - return token_type::parse_error; - } - - case 0x17: - { - error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; - return token_type::parse_error; - } - - case 0x18: - { - error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; - return token_type::parse_error; - } - - case 0x19: - { - error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; - return token_type::parse_error; - } - - case 0x1A: - { - error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; - return token_type::parse_error; - } - - case 0x1B: - { - error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; - return token_type::parse_error; - } - - case 0x1C: - { - error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; - return token_type::parse_error; - } - - case 0x1D: - { - error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; - return token_type::parse_error; - } - - case 0x1E: - { - error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; - return token_type::parse_error; - } - - case 0x1F: - { - error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; - return token_type::parse_error; - } - - // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) - case 0x20: - case 0x21: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - { - add(current); - break; - } - - // U+0080..U+07FF: bytes C2..DF 80..BF - case 0xC2: - case 0xC3: - case 0xC4: - case 0xC5: - case 0xC6: - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD5: - case 0xD6: - case 0xD7: - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - { - if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) - { - return token_type::parse_error; - } - break; - } - - // U+0800..U+0FFF: bytes E0 A0..BF 80..BF - case 0xE0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF - // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xEE: - case 0xEF: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+D000..U+D7FF: bytes ED 80..9F 80..BF - case 0xED: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF - case 0xF0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF - case 0xF1: - case 0xF2: - case 0xF3: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF - case 0xF4: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // remaining bytes (80..C1 and F5..FF) are ill-formed - default: - { - error_message = "invalid string: ill-formed UTF-8 byte"; - return token_type::parse_error; - } - } - } - } - - /*! - * @brief scan a comment - * @return whether comment could be scanned successfully - */ - bool scan_comment() - { - switch (get()) - { - // single-line comments skip input until a newline or EOF is read - case '/': - { - while (true) - { - switch (get()) - { - case '\n': - case '\r': - case std::char_traits::eof(): - case '\0': - return true; - - default: - break; - } - } - } - - // multi-line comments skip input until */ is read - case '*': - { - while (true) - { - switch (get()) - { - case std::char_traits::eof(): - case '\0': - { - error_message = "invalid comment; missing closing '*/'"; - return false; - } - - case '*': - { - switch (get()) - { - case '/': - return true; - - default: - { - unget(); - continue; - } - } - } - - default: - continue; - } - } - } - - // unexpected character after reading '/' - default: - { - error_message = "invalid comment; expecting '/' or '*' after '/'"; - return false; - } - } - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(float& f, const char* str, char** endptr) noexcept - { - f = std::strtof(str, endptr); - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(double& f, const char* str, char** endptr) noexcept - { - f = std::strtod(str, endptr); - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(long double& f, const char* str, char** endptr) noexcept - { - f = std::strtold(str, endptr); - } - - /*! - @brief scan a number literal - - This function scans a string according to Sect. 6 of RFC 8259. - - The function is realized with a deterministic finite state machine derived - from the grammar described in RFC 8259. Starting in state "init", the - input is read and used to determined the next state. Only state "done" - accepts the number. State "error" is a trap state to model errors. In the - table below, "anything" means any character but the ones listed before. - - state | 0 | 1-9 | e E | + | - | . | anything - ---------|----------|----------|----------|---------|---------|----------|----------- - init | zero | any1 | [error] | [error] | minus | [error] | [error] - minus | zero | any1 | [error] | [error] | [error] | [error] | [error] - zero | done | done | exponent | done | done | decimal1 | done - any1 | any1 | any1 | exponent | done | done | decimal1 | done - decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] - decimal2 | decimal2 | decimal2 | exponent | done | done | done | done - exponent | any2 | any2 | [error] | sign | sign | [error] | [error] - sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] - any2 | any2 | any2 | done | done | done | done | done - - The state machine is realized with one label per state (prefixed with - "scan_number_") and `goto` statements between them. The state machine - contains cycles, but any cycle can be left when EOF is read. Therefore, - the function is guaranteed to terminate. - - During scanning, the read bytes are stored in token_buffer. This string is - then converted to a signed integer, an unsigned integer, or a - floating-point number. - - @return token_type::value_unsigned, token_type::value_integer, or - token_type::value_float if number could be successfully scanned, - token_type::parse_error otherwise - - @note The scanner is independent of the current locale. Internally, the - locale's decimal point is used instead of `.` to work with the - locale-dependent converters. - */ - token_type scan_number() // lgtm [cpp/use-of-goto] - { - // reset token_buffer to store the number's bytes - reset(); - - // the type of the parsed number; initially set to unsigned; will be - // changed if minus sign, decimal point or exponent is read - token_type number_type = token_type::value_unsigned; - - // state (init): we just found out we need to scan a number - switch (current) - { - case '-': - { - add(current); - goto scan_number_minus; - } - - case '0': - { - add(current); - goto scan_number_zero; - } - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - // all other characters are rejected outside scan_number() - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - } - -scan_number_minus: - // state: we just parsed a leading minus sign - number_type = token_type::value_integer; - switch (get()) - { - case '0': - { - add(current); - goto scan_number_zero; - } - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - default: - { - error_message = "invalid number; expected digit after '-'"; - return token_type::parse_error; - } - } - -scan_number_zero: - // state: we just parse a zero (maybe with a leading minus sign) - switch (get()) - { - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_any1: - // state: we just parsed a number 0-9 (maybe with a leading minus sign) - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_decimal1: - // state: we just parsed a decimal point - number_type = token_type::value_float; - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } - - default: - { - error_message = "invalid number; expected digit after '.'"; - return token_type::parse_error; - } - } - -scan_number_decimal2: - // we just parsed at least one number after a decimal point - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_exponent: - // we just parsed an exponent - number_type = token_type::value_float; - switch (get()) - { - case '+': - case '-': - { - add(current); - goto scan_number_sign; - } - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - { - error_message = - "invalid number; expected '+', '-', or digit after exponent"; - return token_type::parse_error; - } - } - -scan_number_sign: - // we just parsed an exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - { - error_message = "invalid number; expected digit after exponent sign"; - return token_type::parse_error; - } - } - -scan_number_any2: - // we just parsed a number after the exponent or exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - goto scan_number_done; - } - -scan_number_done: - // unget the character after the number (we only read it to know that - // we are done scanning a number) - unget(); - - char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - errno = 0; - - // try to parse integers first and fall back to floats - if (number_type == token_type::value_unsigned) - { - const auto x = std::strtoull(token_buffer.data(), &endptr, 10); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { - value_unsigned = static_cast(x); - if (value_unsigned == x) - { - return token_type::value_unsigned; - } - } - } - else if (number_type == token_type::value_integer) - { - const auto x = std::strtoll(token_buffer.data(), &endptr, 10); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { - value_integer = static_cast(x); - if (value_integer == x) - { - return token_type::value_integer; - } - } - } - - // this code is reached if we parse a floating-point number or if an - // integer conversion above failed - strtof(value_float, token_buffer.data(), &endptr); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - return token_type::value_float; - } - - /*! - @param[in] literal_text the literal text to expect - @param[in] length the length of the passed literal text - @param[in] return_type the token type to return on success - */ - JSON_HEDLEY_NON_NULL(2) - token_type scan_literal(const char_type* literal_text, const std::size_t length, - token_type return_type) - { - JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); - for (std::size_t i = 1; i < length; ++i) - { - if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) - { - error_message = "invalid literal"; - return token_type::parse_error; - } - } - return return_type; - } - - ///////////////////// - // input management - ///////////////////// - - /// reset token_buffer; current character is beginning of token - void reset() noexcept - { - token_buffer.clear(); - token_string.clear(); - token_string.push_back(std::char_traits::to_char_type(current)); - } - - /* - @brief get next character from the input - - This function provides the interface to the used input adapter. It does - not throw in case the input reached EOF, but returns a - `std::char_traits::eof()` in that case. Stores the scanned characters - for use in error messages. - - @return character read from the input - */ - char_int_type get() - { - ++position.chars_read_total; - ++position.chars_read_current_line; - - if (next_unget) - { - // just reset the next_unget variable and work with current - next_unget = false; - } - else - { - current = ia.get_character(); - } - - if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) - { - token_string.push_back(std::char_traits::to_char_type(current)); - } - - if (current == '\n') - { - ++position.lines_read; - position.chars_read_current_line = 0; - } - - return current; - } - - /*! - @brief unget current character (read it again on next get) - - We implement unget by setting variable next_unget to true. The input is not - changed - we just simulate ungetting by modifying chars_read_total, - chars_read_current_line, and token_string. The next call to get() will - behave as if the unget character is read again. - */ - void unget() - { - next_unget = true; - - --position.chars_read_total; - - // in case we "unget" a newline, we have to also decrement the lines_read - if (position.chars_read_current_line == 0) - { - if (position.lines_read > 0) - { - --position.lines_read; - } - } - else - { - --position.chars_read_current_line; - } - - if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) - { - JSON_ASSERT(!token_string.empty()); - token_string.pop_back(); - } - } - - /// add a character to token_buffer - void add(char_int_type c) - { - token_buffer.push_back(static_cast(c)); - } - - public: - ///////////////////// - // value getters - ///////////////////// - - /// return integer value - constexpr number_integer_t get_number_integer() const noexcept - { - return value_integer; - } - - /// return unsigned integer value - constexpr number_unsigned_t get_number_unsigned() const noexcept - { - return value_unsigned; - } - - /// return floating-point value - constexpr number_float_t get_number_float() const noexcept - { - return value_float; - } - - /// return current string value (implicitly resets the token; useful only once) - string_t& get_string() - { - return token_buffer; - } - - ///////////////////// - // diagnostics - ///////////////////// - - /// return position of last read token - constexpr position_t get_position() const noexcept - { - return position; - } - - /// return the last read token (for errors only). Will never contain EOF - /// (an arbitrary value that is not a valid char value, often -1), because - /// 255 may legitimately occur. May contain NUL, which should be escaped. - std::string get_token_string() const - { - // escape control characters - std::string result; - for (const auto c : token_string) - { - if (static_cast(c) <= '\x1F') - { - // escape control characters - std::array cs{{}}; - (std::snprintf)(cs.data(), cs.size(), "", static_cast(c)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - result += cs.data(); - } - else - { - // add character as is - result.push_back(static_cast(c)); - } - } - - return result; - } - - /// return syntax error message - JSON_HEDLEY_RETURNS_NON_NULL - constexpr const char* get_error_message() const noexcept - { - return error_message; - } - - ///////////////////// - // actual scanner - ///////////////////// - - /*! - @brief skip the UTF-8 byte order mark - @return true iff there is no BOM or the correct BOM has been skipped - */ - bool skip_bom() - { - if (get() == 0xEF) - { - // check if we completely parse the BOM - return get() == 0xBB && get() == 0xBF; - } - - // the first character is not the beginning of the BOM; unget it to - // process is later - unget(); - return true; - } - - void skip_whitespace() - { - do - { - get(); - } - while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); - } - - token_type scan() - { - // initially, skip the BOM - if (position.chars_read_total == 0 && !skip_bom()) - { - error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; - return token_type::parse_error; - } - - // read next character and ignore whitespace - skip_whitespace(); - - // ignore comments - while (ignore_comments && current == '/') - { - if (!scan_comment()) - { - return token_type::parse_error; - } - - // skip following whitespace - skip_whitespace(); - } - - switch (current) - { - // structural characters - case '[': - return token_type::begin_array; - case ']': - return token_type::end_array; - case '{': - return token_type::begin_object; - case '}': - return token_type::end_object; - case ':': - return token_type::name_separator; - case ',': - return token_type::value_separator; - - // literals - case 't': - { - std::array true_literal = {{char_type('t'), char_type('r'), char_type('u'), char_type('e')}}; - return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); - } - case 'f': - { - std::array false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), char_type('e')}}; - return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); - } - case 'n': - { - std::array null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}}; - return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); - } - - // string - case '\"': - return scan_string(); - - // number - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return scan_number(); - - // end of input (the null byte is needed when parsing from - // string literals) - case '\0': - case std::char_traits::eof(): - return token_type::end_of_input; - - // error - default: - error_message = "invalid literal"; - return token_type::parse_error; - } - } - - private: - /// input adapter - InputAdapterType ia; - - /// whether comments should be ignored (true) or signaled as errors (false) - const bool ignore_comments = false; - - /// the current character - char_int_type current = std::char_traits::eof(); - - /// whether the next get() call should just return current - bool next_unget = false; - - /// the start position of the current token - position_t position {}; - - /// raw input token string (for error messages) - std::vector token_string {}; - - /// buffer for variable-length tokens (numbers, strings) - string_t token_buffer {}; - - /// a description of occurred lexer errors - const char* error_message = ""; - - // number values - number_integer_t value_integer = 0; - number_unsigned_t value_unsigned = 0; - number_float_t value_float = 0; - - /// the decimal point - const char_int_type decimal_point_char = '.'; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // size_t -#include // declval -#include // string - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -using null_function_t = decltype(std::declval().null()); - -template -using boolean_function_t = - decltype(std::declval().boolean(std::declval())); - -template -using number_integer_function_t = - decltype(std::declval().number_integer(std::declval())); - -template -using number_unsigned_function_t = - decltype(std::declval().number_unsigned(std::declval())); - -template -using number_float_function_t = decltype(std::declval().number_float( - std::declval(), std::declval())); - -template -using string_function_t = - decltype(std::declval().string(std::declval())); - -template -using binary_function_t = - decltype(std::declval().binary(std::declval())); - -template -using start_object_function_t = - decltype(std::declval().start_object(std::declval())); - -template -using key_function_t = - decltype(std::declval().key(std::declval())); - -template -using end_object_function_t = decltype(std::declval().end_object()); - -template -using start_array_function_t = - decltype(std::declval().start_array(std::declval())); - -template -using end_array_function_t = decltype(std::declval().end_array()); - -template -using parse_error_function_t = decltype(std::declval().parse_error( - std::declval(), std::declval(), - std::declval())); - -template -struct is_sax -{ - private: - static_assert(is_basic_json::value, - "BasicJsonType must be of type basic_json<...>"); - - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using exception_t = typename BasicJsonType::exception; - - public: - static constexpr bool value = - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value; -}; - -template -struct is_sax_static_asserts -{ - private: - static_assert(is_basic_json::value, - "BasicJsonType must be of type basic_json<...>"); - - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using exception_t = typename BasicJsonType::exception; - - public: - static_assert(is_detected_exact::value, - "Missing/invalid function: bool null()"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool boolean(bool)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool boolean(bool)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool number_integer(number_integer_t)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool string(string_t&)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool binary(binary_t&)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool start_object(std::size_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool key(string_t&)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool end_object()"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool start_array(std::size_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool end_array()"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool parse_error(std::size_t, const " - "std::string&, const exception&)"); -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ - -/// how to treat CBOR tags -enum class cbor_tag_handler_t -{ - error, ///< throw a parse_error exception in case of a tag - ignore, ///< ignore tags - store ///< store tags as binary type -}; - -/*! -@brief determine system byte order - -@return true if and only if system's byte order is little endian - -@note from https://stackoverflow.com/a/1001328/266378 -*/ -static inline bool little_endianess(int num = 1) noexcept -{ - return *reinterpret_cast(&num) == 1; -} - - -/////////////////// -// binary reader // -/////////////////// - -/*! -@brief deserialization of CBOR, MessagePack, and UBJSON values -*/ -template> -class binary_reader -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using json_sax_t = SAX; - using char_type = typename InputAdapterType::char_type; - using char_int_type = typename std::char_traits::int_type; - - public: - /*! - @brief create a binary reader - - @param[in] adapter input adapter to read from - */ - explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter)) - { - (void)detail::is_sax_static_asserts {}; - } - - // make class move-only - binary_reader(const binary_reader&) = delete; - binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - binary_reader& operator=(const binary_reader&) = delete; - binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - ~binary_reader() = default; - - /*! - @param[in] format the binary format to parse - @param[in] sax_ a SAX event processor - @param[in] strict whether to expect the input to be consumed completed - @param[in] tag_handler how to treat CBOR tags - - @return whether parsing was successful - */ - JSON_HEDLEY_NON_NULL(3) - bool sax_parse(const input_format_t format, - json_sax_t* sax_, - const bool strict = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - sax = sax_; - bool result = false; - - switch (format) - { - case input_format_t::bson: - result = parse_bson_internal(); - break; - - case input_format_t::cbor: - result = parse_cbor_internal(true, tag_handler); - break; - - case input_format_t::msgpack: - result = parse_msgpack_internal(); - break; - - case input_format_t::ubjson: - result = parse_ubjson_internal(); - break; - - case input_format_t::json: // LCOV_EXCL_LINE - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - } - - // strict mode: next byte must be EOF - if (result && strict) - { - if (format == input_format_t::ubjson) - { - get_ignore_noop(); - } - else - { - get(); - } - - if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) - { - return sax->parse_error(chars_read, get_token_string(), - parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType())); - } - } - - return result; - } - - private: - ////////// - // BSON // - ////////// - - /*! - @brief Reads in a BSON-object and passes it to the SAX-parser. - @return whether a valid BSON-value was passed to the SAX parser - */ - bool parse_bson_internal() - { - std::int32_t document_size{}; - get_number(input_format_t::bson, document_size); - - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) - { - return false; - } - - return sax->end_object(); - } - - /*! - @brief Parses a C-style string from the BSON input. - @param[in,out] result A reference to the string variable where the read - string is to be stored. - @return `true` if the \x00-byte indicating the end of the string was - encountered before the EOF; false` indicates an unexpected EOF. - */ - bool get_bson_cstr(string_t& result) - { - auto out = std::back_inserter(result); - while (true) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) - { - return false; - } - if (current == 0x00) - { - return true; - } - *out++ = static_cast(current); - } - } - - /*! - @brief Parses a zero-terminated string of length @a len from the BSON - input. - @param[in] len The length (including the zero-byte at the end) of the - string to be read. - @param[in,out] result A reference to the string variable where the read - string is to be stored. - @tparam NumberType The type of the length @a len - @pre len >= 1 - @return `true` if the string was successfully parsed - */ - template - bool get_bson_string(const NumberType len, string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(len < 1)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType())); - } - - return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); - } - - /*! - @brief Parses a byte array input of length @a len from the BSON input. - @param[in] len The length of the byte array to be read. - @param[in,out] result A reference to the binary variable where the read - array is to be stored. - @tparam NumberType The type of the length @a len - @pre len >= 0 - @return `true` if the byte array was successfully parsed - */ - template - bool get_bson_binary(const NumberType len, binary_t& result) - { - if (JSON_HEDLEY_UNLIKELY(len < 0)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType())); - } - - // All BSON binary values have a subtype - std::uint8_t subtype{}; - get_number(input_format_t::bson, subtype); - result.set_subtype(subtype); - - return get_binary(input_format_t::bson, len, result); - } - - /*! - @brief Read a BSON document element of the given @a element_type. - @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html - @param[in] element_type_parse_position The position in the input stream, - where the `element_type` was read. - @warning Not all BSON element types are supported yet. An unsupported - @a element_type will give rise to a parse_error.114: - Unsupported BSON record type 0x... - @return whether a valid BSON-object/array was passed to the SAX parser - */ - bool parse_bson_element_internal(const char_int_type element_type, - const std::size_t element_type_parse_position) - { - switch (element_type) - { - case 0x01: // double - { - double number{}; - return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); - } - - case 0x02: // string - { - std::int32_t len{}; - string_t value; - return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); - } - - case 0x03: // object - { - return parse_bson_internal(); - } - - case 0x04: // array - { - return parse_bson_array(); - } - - case 0x05: // binary - { - std::int32_t len{}; - binary_t value; - return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); - } - - case 0x08: // boolean - { - return sax->boolean(get() != 0); - } - - case 0x0A: // null - { - return sax->null(); - } - - case 0x10: // int32 - { - std::int32_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } - - case 0x12: // int64 - { - std::int64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } - - default: // anything else not supported (yet) - { - std::array cr{{}}; - (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType())); - } - } - } - - /*! - @brief Read a BSON element list (as specified in the BSON-spec) - - The same binary layout is used for objects and arrays, hence it must be - indicated with the argument @a is_array which one is expected - (true --> array, false --> object). - - @param[in] is_array Determines if the element list being read is to be - treated as an object (@a is_array == false), or as an - array (@a is_array == true). - @return whether a valid BSON-object/array was passed to the SAX parser - */ - bool parse_bson_element_list(const bool is_array) - { - string_t key; - - while (auto element_type = get()) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) - { - return false; - } - - const std::size_t element_type_parse_position = chars_read; - if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) - { - return false; - } - - if (!is_array && !sax->key(key)) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) - { - return false; - } - - // get_bson_cstr only appends - key.clear(); - } - - return true; - } - - /*! - @brief Reads an array from the BSON input and passes it to the SAX-parser. - @return whether a valid BSON-array was passed to the SAX parser - */ - bool parse_bson_array() - { - std::int32_t document_size{}; - get_number(input_format_t::bson, document_size); - - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) - { - return false; - } - - return sax->end_array(); - } - - ////////// - // CBOR // - ////////// - - /*! - @param[in] get_char whether a new character should be retrieved from the - input (true) or whether the last read character should - be considered instead (false) - @param[in] tag_handler how CBOR tags should be treated - - @return whether a valid CBOR value was passed to the SAX parser - */ - bool parse_cbor_internal(const bool get_char, - const cbor_tag_handler_t tag_handler) - { - switch (get_char ? get() : current) - { - // EOF - case std::char_traits::eof(): - return unexpect_eof(input_format_t::cbor, "value"); - - // Integer 0x00..0x17 (0..23) - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - return sax->number_unsigned(static_cast(current)); - - case 0x18: // Unsigned integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x19: // Unsigned integer (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x1A: // Unsigned integer (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x1B: // Unsigned integer (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - // Negative integer -1-0x00..-1-0x17 (-1..-24) - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - return sax->number_integer(static_cast(0x20 - 1 - current)); - - case 0x38: // Negative integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x39: // Negative integer -1-n (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - - static_cast(number)); - } - - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: // Binary data (one-byte uint8_t for n follows) - case 0x59: // Binary data (two-byte uint16_t for n follow) - case 0x5A: // Binary data (four-byte uint32_t for n follow) - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - case 0x5F: // Binary data (indefinite length) - { - binary_t b; - return get_cbor_binary(b) && sax->binary(b); - } - - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - case 0x7F: // UTF-8 string (indefinite length) - { - string_t s; - return get_cbor_string(s) && sax->string(s); - } - - // array (0x00..0x17 data items follow) - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); - - case 0x98: // array (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x99: // array (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x9A: // array (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x9B: // array (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast(len), tag_handler); - } - - case 0x9F: // array (indefinite length) - return get_cbor_array(std::size_t(-1), tag_handler); - - // map (0x00..0x17 pairs of data items follow) - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); - - case 0xB8: // map (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xB9: // map (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xBA: // map (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xBB: // map (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast(len), tag_handler); - } - - case 0xBF: // map (indefinite length) - return get_cbor_object(std::size_t(-1), tag_handler); - - case 0xC6: // tagged item - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD8: // tagged item (1 bytes follow) - case 0xD9: // tagged item (2 bytes follow) - case 0xDA: // tagged item (4 bytes follow) - case 0xDB: // tagged item (8 bytes follow) - { - switch (tag_handler) - { - case cbor_tag_handler_t::error: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); - } - - case cbor_tag_handler_t::ignore: - { - // ignore binary subtype - switch (current) - { - case 0xD8: - { - std::uint8_t subtype_to_ignore{}; - get_number(input_format_t::cbor, subtype_to_ignore); - break; - } - case 0xD9: - { - std::uint16_t subtype_to_ignore{}; - get_number(input_format_t::cbor, subtype_to_ignore); - break; - } - case 0xDA: - { - std::uint32_t subtype_to_ignore{}; - get_number(input_format_t::cbor, subtype_to_ignore); - break; - } - case 0xDB: - { - std::uint64_t subtype_to_ignore{}; - get_number(input_format_t::cbor, subtype_to_ignore); - break; - } - default: - break; - } - return parse_cbor_internal(true, tag_handler); - } - - case cbor_tag_handler_t::store: - { - binary_t b; - // use binary subtype and store in binary container - switch (current) - { - case 0xD8: - { - std::uint8_t subtype{}; - get_number(input_format_t::cbor, subtype); - b.set_subtype(detail::conditional_static_cast(subtype)); - break; - } - case 0xD9: - { - std::uint16_t subtype{}; - get_number(input_format_t::cbor, subtype); - b.set_subtype(detail::conditional_static_cast(subtype)); - break; - } - case 0xDA: - { - std::uint32_t subtype{}; - get_number(input_format_t::cbor, subtype); - b.set_subtype(detail::conditional_static_cast(subtype)); - break; - } - case 0xDB: - { - std::uint64_t subtype{}; - get_number(input_format_t::cbor, subtype); - b.set_subtype(detail::conditional_static_cast(subtype)); - break; - } - default: - return parse_cbor_internal(true, tag_handler); - } - get(); - return get_cbor_binary(b) && sax->binary(b); - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE - } - } - - case 0xF4: // false - return sax->boolean(false); - - case 0xF5: // true - return sax->boolean(true); - - case 0xF6: // null - return sax->null(); - - case 0xF9: // Half-Precision Float (two-byte IEEE 754) - { - const auto byte1_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; - } - const auto byte2_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; - } - - const auto byte1 = static_cast(byte1_raw); - const auto byte2 = static_cast(byte2_raw); - - // code from RFC 7049, Appendix D, Figure 3: - // As half-precision floating-point numbers were only added - // to IEEE 754 in 2008, today's programming platforms often - // still only have limited support for them. It is very - // easy to include at least decoding support for them even - // without such support. An example of a small decoder for - // half-precision floating-point numbers in the C language - // is shown in Fig. 3. - const auto half = static_cast((byte1 << 8u) + byte2); - const double val = [&half] - { - const int exp = (half >> 10u) & 0x1Fu; - const unsigned int mant = half & 0x3FFu; - JSON_ASSERT(0 <= exp&& exp <= 32); - JSON_ASSERT(mant <= 1024); - switch (exp) - { - case 0: - return std::ldexp(mant, -24); - case 31: - return (mant == 0) - ? std::numeric_limits::infinity() - : std::numeric_limits::quiet_NaN(); - default: - return std::ldexp(mant + 1024, exp - 25); - } - }(); - return sax->number_float((half & 0x8000u) != 0 - ? static_cast(-val) - : static_cast(val), ""); - } - - case 0xFA: // Single-Precision Float (four-byte IEEE 754) - { - float number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); - } - - case 0xFB: // Double-Precision Float (eight-byte IEEE 754) - { - double number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); - } - - default: // anything else (0xFF is handled inside the other types) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); - } - } - } - - /*! - @brief reads a CBOR string - - This function first reads starting bytes to determine the expected - string length and then copies this number of bytes into a string. - Additionally, CBOR's strings with indefinite lengths are supported. - - @param[out] result created string - - @return whether string creation completed - */ - bool get_cbor_string(string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) - { - return false; - } - - switch (current) - { - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - { - return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } - - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7F: // UTF-8 string (indefinite length) - { - while (get() != 0xFF) - { - string_t chunk; - if (!get_cbor_string(chunk)) - { - return false; - } - result.append(chunk); - } - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType())); - } - } - } - - /*! - @brief reads a CBOR byte array - - This function first reads starting bytes to determine the expected - byte array length and then copies this number of bytes into the byte array. - Additionally, CBOR's byte arrays with indefinite lengths are supported. - - @param[out] result created byte array - - @return whether byte array creation completed - */ - bool get_cbor_binary(binary_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) - { - return false; - } - - switch (current) - { - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - { - return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } - - case 0x58: // Binary data (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x59: // Binary data (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5A: // Binary data (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5F: // Binary data (indefinite length) - { - while (get() != 0xFF) - { - binary_t chunk; - if (!get_cbor_binary(chunk)) - { - return false; - } - result.insert(result.end(), chunk.begin(), chunk.end()); - } - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType())); - } - } - } - - /*! - @param[in] len the length of the array or std::size_t(-1) for an - array of indefinite size - @param[in] tag_handler how CBOR tags should be treated - @return whether array creation completed - */ - bool get_cbor_array(const std::size_t len, - const cbor_tag_handler_t tag_handler) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { - return false; - } - - if (len != std::size_t(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) - { - return false; - } - } - } - - return sax->end_array(); - } - - /*! - @param[in] len the length of the object or std::size_t(-1) for an - object of indefinite size - @param[in] tag_handler how CBOR tags should be treated - @return whether object creation completed - */ - bool get_cbor_object(const std::size_t len, - const cbor_tag_handler_t tag_handler) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { - return false; - } - - if (len != 0) - { - string_t key; - if (len != std::size_t(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - key.clear(); - } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - key.clear(); - } - } - } - - return sax->end_object(); - } - - ///////////// - // MsgPack // - ///////////// - - /*! - @return whether a valid MessagePack value was passed to the SAX parser - */ - bool parse_msgpack_internal() - { - switch (get()) - { - // EOF - case std::char_traits::eof(): - return unexpect_eof(input_format_t::msgpack, "value"); - - // positive fixint - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5C: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - return sax->number_unsigned(static_cast(current)); - - // fixmap - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); - - // fixarray - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9A: - case 0x9B: - case 0x9C: - case 0x9D: - case 0x9E: - case 0x9F: - return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); - - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - case 0xD9: // str 8 - case 0xDA: // str 16 - case 0xDB: // str 32 - { - string_t s; - return get_msgpack_string(s) && sax->string(s); - } - - case 0xC0: // nil - return sax->null(); - - case 0xC2: // false - return sax->boolean(false); - - case 0xC3: // true - return sax->boolean(true); - - case 0xC4: // bin 8 - case 0xC5: // bin 16 - case 0xC6: // bin 32 - case 0xC7: // ext 8 - case 0xC8: // ext 16 - case 0xC9: // ext 32 - case 0xD4: // fixext 1 - case 0xD5: // fixext 2 - case 0xD6: // fixext 4 - case 0xD7: // fixext 8 - case 0xD8: // fixext 16 - { - binary_t b; - return get_msgpack_binary(b) && sax->binary(b); - } - - case 0xCA: // float 32 - { - float number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } - - case 0xCB: // float 64 - { - double number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } - - case 0xCC: // uint 8 - { - std::uint8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCD: // uint 16 - { - std::uint16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCE: // uint 32 - { - std::uint32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCF: // uint 64 - { - std::uint64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xD0: // int 8 - { - std::int8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD1: // int 16 - { - std::int16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD2: // int 32 - { - std::int32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD3: // int 64 - { - std::int64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xDC: // array 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } - - case 0xDD: // array 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } - - case 0xDE: // map 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } - - case 0xDF: // map 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } - - // negative fixint - case 0xE0: - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xED: - case 0xEE: - case 0xEF: - case 0xF0: - case 0xF1: - case 0xF2: - case 0xF3: - case 0xF4: - case 0xF5: - case 0xF6: - case 0xF7: - case 0xF8: - case 0xF9: - case 0xFA: - case 0xFB: - case 0xFC: - case 0xFD: - case 0xFE: - case 0xFF: - return sax->number_integer(static_cast(current)); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); - } - } - } - - /*! - @brief reads a MessagePack string - - This function first reads starting bytes to determine the expected - string length and then copies this number of bytes into a string. - - @param[out] result created string - - @return whether string creation completed - */ - bool get_msgpack_string(string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) - { - return false; - } - - switch (current) - { - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - { - return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); - } - - case 0xD9: // str 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - case 0xDA: // str 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - case 0xDB: // str 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType())); - } - } - } - - /*! - @brief reads a MessagePack byte array - - This function first reads starting bytes to determine the expected - byte array length and then copies this number of bytes into a byte array. - - @param[out] result created byte array - - @return whether byte array creation completed - */ - bool get_msgpack_binary(binary_t& result) - { - // helper function to set the subtype - auto assign_and_return_true = [&result](std::int8_t subtype) - { - result.set_subtype(static_cast(subtype)); - return true; - }; - - switch (current) - { - case 0xC4: // bin 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC5: // bin 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC6: // bin 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC7: // ext 8 - { - std::uint8_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xC8: // ext 16 - { - std::uint16_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xC9: // ext 32 - { - std::uint32_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xD4: // fixext 1 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 1, result) && - assign_and_return_true(subtype); - } - - case 0xD5: // fixext 2 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 2, result) && - assign_and_return_true(subtype); - } - - case 0xD6: // fixext 4 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 4, result) && - assign_and_return_true(subtype); - } - - case 0xD7: // fixext 8 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 8, result) && - assign_and_return_true(subtype); - } - - case 0xD8: // fixext 16 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 16, result) && - assign_and_return_true(subtype); - } - - default: // LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE - } - } - - /*! - @param[in] len the length of the array - @return whether array creation completed - */ - bool get_msgpack_array(const std::size_t len) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { - return false; - } - - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { - return false; - } - } - - return sax->end_array(); - } - - /*! - @param[in] len the length of the object - @return whether object creation completed - */ - bool get_msgpack_object(const std::size_t len) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { - return false; - } - - string_t key; - for (std::size_t i = 0; i < len; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { - return false; - } - key.clear(); - } - - return sax->end_object(); - } - - //////////// - // UBJSON // - //////////// - - /*! - @param[in] get_char whether a new character should be retrieved from the - input (true, default) or whether the last read - character should be considered instead - - @return whether a valid UBJSON value was passed to the SAX parser - */ - bool parse_ubjson_internal(const bool get_char = true) - { - return get_ubjson_value(get_char ? get_ignore_noop() : current); - } - - /*! - @brief reads a UBJSON string - - This function is either called after reading the 'S' byte explicitly - indicating a string, or in case of an object key where the 'S' byte can be - left out. - - @param[out] result created string - @param[in] get_char whether a new character should be retrieved from the - input (true, default) or whether the last read - character should be considered instead - - @return whether string creation completed - */ - bool get_ubjson_string(string_t& result, const bool get_char = true) - { - if (get_char) - { - get(); // TODO(niels): may we ignore N here? - } - - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) - { - return false; - } - - switch (current) - { - case 'U': - { - std::uint8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'i': - { - std::int8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'I': - { - std::int16_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'l': - { - std::int32_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'L': - { - std::int64_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - default: - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType())); - } - } - - /*! - @param[out] result determined size - @return whether size determination completed - */ - bool get_ubjson_size_value(std::size_t& result) - { - switch (get_ignore_noop()) - { - case 'U': - { - std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'i': - { - std::int8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char - return true; - } - - case 'I': - { - std::int16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'l': - { - std::int32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'L': - { - std::int64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType())); - } - } - } - - /*! - @brief determine the type and size for a container - - In the optimized UBJSON format, a type and a size can be provided to allow - for a more compact representation. - - @param[out] result pair of the size and the type - - @return whether pair creation completed - */ - bool get_ubjson_size_type(std::pair& result) - { - result.first = string_t::npos; // size - result.second = 0; // type - - get_ignore_noop(); - - if (current == '$') - { - result.second = get(); // must not ignore 'N', because 'N' maybe the type - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) - { - return false; - } - - get_ignore_noop(); - if (JSON_HEDLEY_UNLIKELY(current != '#')) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) - { - return false; - } - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType())); - } - - return get_ubjson_size_value(result.first); - } - - if (current == '#') - { - return get_ubjson_size_value(result.first); - } - - return true; - } - - /*! - @param prefix the previously read or set type prefix - @return whether value creation completed - */ - bool get_ubjson_value(const char_int_type prefix) - { - switch (prefix) - { - case std::char_traits::eof(): // EOF - return unexpect_eof(input_format_t::ubjson, "value"); - - case 'T': // true - return sax->boolean(true); - case 'F': // false - return sax->boolean(false); - - case 'Z': // null - return sax->null(); - - case 'U': - { - std::uint8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); - } - - case 'i': - { - std::int8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'I': - { - std::int16_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'l': - { - std::int32_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'L': - { - std::int64_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'd': - { - float number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); - } - - case 'D': - { - double number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); - } - - case 'H': - { - return get_ubjson_high_precision_number(); - } - - case 'C': // char - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(current > 127)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType())); - } - string_t s(1, static_cast(current)); - return sax->string(s); - } - - case 'S': // string - { - string_t s; - return get_ubjson_string(s) && sax->string(s); - } - - case '[': // array - return get_ubjson_array(); - - case '{': // object - return get_ubjson_object(); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); - } - } - } - - /*! - @return whether array creation completed - */ - bool get_ubjson_array() - { - std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { - return false; - } - - if (size_and_type.first != string_t::npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) - { - return false; - } - - if (size_and_type.second != 0) - { - if (size_and_type.second != 'N') - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { - return false; - } - } - } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - } - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - while (current != ']') - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) - { - return false; - } - get_ignore_noop(); - } - } - - return sax->end_array(); - } - - /*! - @return whether object creation completed - */ - bool get_ubjson_object() - { - std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { - return false; - } - - string_t key; - if (size_and_type.first != string_t::npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) - { - return false; - } - - if (size_and_type.second != 0) - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { - return false; - } - key.clear(); - } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - key.clear(); - } - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - while (current != '}') - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - get_ignore_noop(); - key.clear(); - } - } - - return sax->end_object(); - } - - // Note, no reader for UBJSON binary types is implemented because they do - // not exist - - bool get_ubjson_high_precision_number() - { - // get size of following number string - std::size_t size{}; - auto res = get_ubjson_size_value(size); - if (JSON_HEDLEY_UNLIKELY(!res)) - { - return res; - } - - // get number string - std::vector number_vector; - for (std::size_t i = 0; i < size; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) - { - return false; - } - number_vector.push_back(static_cast(current)); - } - - // parse number string - using ia_type = decltype(detail::input_adapter(number_vector)); - auto number_lexer = detail::lexer(detail::input_adapter(number_vector), false); - const auto result_number = number_lexer.scan(); - const auto number_string = number_lexer.get_token_string(); - const auto result_remainder = number_lexer.scan(); - - using token_type = typename detail::lexer_base::token_type; - - if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) - { - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); - } - - switch (result_number) - { - case token_type::value_integer: - return sax->number_integer(number_lexer.get_number_integer()); - case token_type::value_unsigned: - return sax->number_unsigned(number_lexer.get_number_unsigned()); - case token_type::value_float: - return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); - case token_type::uninitialized: - case token_type::literal_true: - case token_type::literal_false: - case token_type::literal_null: - case token_type::value_string: - case token_type::begin_array: - case token_type::begin_object: - case token_type::end_array: - case token_type::end_object: - case token_type::name_separator: - case token_type::value_separator: - case token_type::parse_error: - case token_type::end_of_input: - case token_type::literal_or_value: - default: - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); - } - } - - /////////////////////// - // Utility functions // - /////////////////////// - - /*! - @brief get next character from the input - - This function provides the interface to the used input adapter. It does - not throw in case the input reached EOF, but returns a -'ve valued - `std::char_traits::eof()` in that case. - - @return character read from the input - */ - char_int_type get() - { - ++chars_read; - return current = ia.get_character(); - } - - /*! - @return character read from the input after ignoring all 'N' entries - */ - char_int_type get_ignore_noop() - { - do - { - get(); - } - while (current == 'N'); - - return current; - } - - /* - @brief read a number from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[out] result number of type @a NumberType - - @return whether conversion completed - - @note This function needs to respect the system's endianess, because - bytes in CBOR, MessagePack, and UBJSON are stored in network order - (big endian) and therefore need reordering on little endian systems. - */ - template - bool get_number(const input_format_t format, NumberType& result) - { - // step 1: read input into array with system's byte order - std::array vec{}; - for (std::size_t i = 0; i < sizeof(NumberType); ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) - { - return false; - } - - // reverse byte order prior to conversion if necessary - if (is_little_endian != InputIsLittleEndian) - { - vec[sizeof(NumberType) - i - 1] = static_cast(current); - } - else - { - vec[i] = static_cast(current); // LCOV_EXCL_LINE - } - } - - // step 2: convert array into number of type T and return - std::memcpy(&result, vec.data(), sizeof(NumberType)); - return true; - } - - /*! - @brief create a string by reading characters from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[in] len number of characters to read - @param[out] result string created by reading @a len bytes - - @return whether string creation completed - - @note We can not reserve @a len bytes for the result, because @a len - may be too large. Usually, @ref unexpect_eof() detects the end of - the input before we run out of string memory. - */ - template - bool get_string(const input_format_t format, - const NumberType len, - string_t& result) - { - bool success = true; - for (NumberType i = 0; i < len; i++) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) - { - success = false; - break; - } - result.push_back(static_cast(current)); - } - return success; - } - - /*! - @brief create a byte array by reading bytes from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[in] len number of bytes to read - @param[out] result byte array created by reading @a len bytes - - @return whether byte array creation completed - - @note We can not reserve @a len bytes for the result, because @a len - may be too large. Usually, @ref unexpect_eof() detects the end of - the input before we run out of memory. - */ - template - bool get_binary(const input_format_t format, - const NumberType len, - binary_t& result) - { - bool success = true; - for (NumberType i = 0; i < len; i++) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) - { - success = false; - break; - } - result.push_back(static_cast(current)); - } - return success; - } - - /*! - @param[in] format the current format (for diagnostics) - @param[in] context further context information (for diagnostics) - @return whether the last read character is not EOF - */ - JSON_HEDLEY_NON_NULL(3) - bool unexpect_eof(const input_format_t format, const char* context) const - { - if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) - { - return sax->parse_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType())); - } - return true; - } - - /*! - @return a string representation of the last read byte - */ - std::string get_token_string() const - { - std::array cr{{}}; - (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - return std::string{cr.data()}; - } - - /*! - @param[in] format the current format - @param[in] detail a detailed error message - @param[in] context further context information - @return a message string to use in the parse_error exceptions - */ - std::string exception_message(const input_format_t format, - const std::string& detail, - const std::string& context) const - { - std::string error_msg = "syntax error while parsing "; - - switch (format) - { - case input_format_t::cbor: - error_msg += "CBOR"; - break; - - case input_format_t::msgpack: - error_msg += "MessagePack"; - break; - - case input_format_t::ubjson: - error_msg += "UBJSON"; - break; - - case input_format_t::bson: - error_msg += "BSON"; - break; - - case input_format_t::json: // LCOV_EXCL_LINE - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - } - - return error_msg + " " + context + ": " + detail; - } - - private: - /// input adapter - InputAdapterType ia; - - /// the current character - char_int_type current = std::char_traits::eof(); - - /// the number of characters read - std::size_t chars_read = 0; - - /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); - - /// the SAX parser - json_sax_t* sax = nullptr; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include // isfinite -#include // uint8_t -#include // function -#include // string -#include // move -#include // vector - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -//////////// -// parser // -//////////// - -enum class parse_event_t : std::uint8_t -{ - /// the parser read `{` and started to process a JSON object - object_start, - /// the parser read `}` and finished processing a JSON object - object_end, - /// the parser read `[` and started to process a JSON array - array_start, - /// the parser read `]` and finished processing a JSON array - array_end, - /// the parser read a key of a value in an object - key, - /// the parser finished reading a JSON value - value -}; - -template -using parser_callback_t = - std::function; - -/*! -@brief syntax analysis - -This class implements a recursive descent parser. -*/ -template -class parser -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using lexer_t = lexer; - using token_type = typename lexer_t::token_type; - - public: - /// a parser reading from an input adapter - explicit parser(InputAdapterType&& adapter, - const parser_callback_t cb = nullptr, - const bool allow_exceptions_ = true, - const bool skip_comments = false) - : callback(cb) - , m_lexer(std::move(adapter), skip_comments) - , allow_exceptions(allow_exceptions_) - { - // read first token - get_token(); - } - - /*! - @brief public parser interface - - @param[in] strict whether to expect the last token to be EOF - @param[in,out] result parsed JSON value - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - void parse(const bool strict, BasicJsonType& result) - { - if (callback) - { - json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); - sax_parse_internal(&sdp); - - // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"), BasicJsonType())); - } - - // in case of an error, return discarded value - if (sdp.is_errored()) - { - result = value_t::discarded; - return; - } - - // set top-level value to null if it was discarded by the callback - // function - if (result.is_discarded()) - { - result = nullptr; - } - } - else - { - json_sax_dom_parser sdp(result, allow_exceptions); - sax_parse_internal(&sdp); - - // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); - } - - // in case of an error, return discarded value - if (sdp.is_errored()) - { - result = value_t::discarded; - return; - } - } - - result.assert_invariant(); - } - - /*! - @brief public accept interface - - @param[in] strict whether to expect the last token to be EOF - @return whether the input is a proper JSON text - */ - bool accept(const bool strict = true) - { - json_sax_acceptor sax_acceptor; - return sax_parse(&sax_acceptor, strict); - } - - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse(SAX* sax, const bool strict = true) - { - (void)detail::is_sax_static_asserts {}; - const bool result = sax_parse_internal(sax); - - // strict mode: next byte must be EOF - if (result && strict && (get_token() != token_type::end_of_input)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); - } - - return result; - } - - private: - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse_internal(SAX* sax) - { - // stack to remember the hierarchy of structured values we are parsing - // true = array; false = object - std::vector states; - // value to avoid a goto (see comment where set to true) - bool skip_to_state_evaluation = false; - - while (true) - { - if (!skip_to_state_evaluation) - { - // invariant: get_token() was called before each iteration - switch (last_token) - { - case token_type::begin_object: - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - // closing } -> we are done - if (get_token() == token_type::end_object) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { - return false; - } - break; - } - - // parse key - if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); - } - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } - - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); - } - - // remember we are now inside an object - states.push_back(false); - - // parse values - get_token(); - continue; - } - - case token_type::begin_array: - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - // closing ] -> we are done - if (get_token() == token_type::end_array) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { - return false; - } - break; - } - - // remember we are now inside an array - states.push_back(true); - - // parse values (no need to call get_token) - continue; - } - - case token_type::value_float: - { - const auto res = m_lexer.get_number_float(); - - if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType())); - } - - if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) - { - return false; - } - - break; - } - - case token_type::literal_false: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) - { - return false; - } - break; - } - - case token_type::literal_null: - { - if (JSON_HEDLEY_UNLIKELY(!sax->null())) - { - return false; - } - break; - } - - case token_type::literal_true: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) - { - return false; - } - break; - } - - case token_type::value_integer: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) - { - return false; - } - break; - } - - case token_type::value_string: - { - if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) - { - return false; - } - break; - } - - case token_type::value_unsigned: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) - { - return false; - } - break; - } - - case token_type::parse_error: - { - // using "uninitialized" to avoid "expected" message - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType())); - } - - case token_type::uninitialized: - case token_type::end_array: - case token_type::end_object: - case token_type::name_separator: - case token_type::value_separator: - case token_type::end_of_input: - case token_type::literal_or_value: - default: // the last token was unexpected - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType())); - } - } - } - else - { - skip_to_state_evaluation = false; - } - - // we reached this line after we successfully parsed a value - if (states.empty()) - { - // empty stack: we reached the end of the hierarchy: done - return true; - } - - if (states.back()) // array - { - // comma -> next value - if (get_token() == token_type::value_separator) - { - // parse a new value - get_token(); - continue; - } - - // closing ] - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { - return false; - } - - // We are done with this array. Before we can parse a - // new value, we need to evaluate the new state first. - // By setting skip_to_state_evaluation to false, we - // are effectively jumping to the beginning of this if. - JSON_ASSERT(!states.empty()); - states.pop_back(); - skip_to_state_evaluation = true; - continue; - } - - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType())); - } - - // states.back() is false -> object - - // comma -> next value - if (get_token() == token_type::value_separator) - { - // parse key - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); - } - - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } - - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); - } - - // parse values - get_token(); - continue; - } - - // closing } - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { - return false; - } - - // We are done with this object. Before we can parse a - // new value, we need to evaluate the new state first. - // By setting skip_to_state_evaluation to false, we - // are effectively jumping to the beginning of this if. - JSON_ASSERT(!states.empty()); - states.pop_back(); - skip_to_state_evaluation = true; - continue; - } - - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType())); - } - } - - /// get next token from lexer - token_type get_token() - { - return last_token = m_lexer.scan(); - } - - std::string exception_message(const token_type expected, const std::string& context) - { - std::string error_msg = "syntax error "; - - if (!context.empty()) - { - error_msg += "while parsing " + context + " "; - } - - error_msg += "- "; - - if (last_token == token_type::parse_error) - { - error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + - m_lexer.get_token_string() + "'"; - } - else - { - error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); - } - - if (expected != token_type::uninitialized) - { - error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); - } - - return error_msg; - } - - private: - /// callback function - const parser_callback_t callback = nullptr; - /// the type of the last read token - token_type last_token = token_type::uninitialized; - /// the lexer - lexer_t m_lexer; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; - -} // namespace detail -} // namespace nlohmann - -// #include - - -// #include - - -#include // ptrdiff_t -#include // numeric_limits - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/* -@brief an iterator for primitive JSON types - -This class models an iterator for primitive JSON types (boolean, number, -string). It's only purpose is to allow the iterator/const_iterator classes -to "iterate" over primitive values. Internally, the iterator is modeled by -a `difference_type` variable. Value begin_value (`0`) models the begin, -end_value (`1`) models past the end. -*/ -class primitive_iterator_t -{ - private: - using difference_type = std::ptrdiff_t; - static constexpr difference_type begin_value = 0; - static constexpr difference_type end_value = begin_value + 1; - - JSON_PRIVATE_UNLESS_TESTED: - /// iterator as signed integer type - difference_type m_it = (std::numeric_limits::min)(); - - public: - constexpr difference_type get_value() const noexcept - { - return m_it; - } - - /// set iterator to a defined beginning - void set_begin() noexcept - { - m_it = begin_value; - } - - /// set iterator to a defined past the end - void set_end() noexcept - { - m_it = end_value; - } - - /// return whether the iterator can be dereferenced - constexpr bool is_begin() const noexcept - { - return m_it == begin_value; - } - - /// return whether the iterator is at end - constexpr bool is_end() const noexcept - { - return m_it == end_value; - } - - friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it == rhs.m_it; - } - - friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it < rhs.m_it; - } - - primitive_iterator_t operator+(difference_type n) noexcept - { - auto result = *this; - result += n; - return result; - } - - friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it - rhs.m_it; - } - - primitive_iterator_t& operator++() noexcept - { - ++m_it; - return *this; - } - - primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type) - { - auto result = *this; - ++m_it; - return result; - } - - primitive_iterator_t& operator--() noexcept - { - --m_it; - return *this; - } - - primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type) - { - auto result = *this; - --m_it; - return result; - } - - primitive_iterator_t& operator+=(difference_type n) noexcept - { - m_it += n; - return *this; - } - - primitive_iterator_t& operator-=(difference_type n) noexcept - { - m_it -= n; - return *this; - } -}; -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -/*! -@brief an iterator value - -@note This structure could easily be a union, but MSVC currently does not allow -unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. -*/ -template struct internal_iterator -{ - /// iterator for JSON objects - typename BasicJsonType::object_t::iterator object_iterator {}; - /// iterator for JSON arrays - typename BasicJsonType::array_t::iterator array_iterator {}; - /// generic iterator for all other types - primitive_iterator_t primitive_iterator {}; -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next -#include // conditional, is_const, remove_const - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -// forward declare, to be able to friend it later on -template class iteration_proxy; -template class iteration_proxy_value; - -/*! -@brief a template for a bidirectional iterator for the @ref basic_json class -This class implements a both iterators (iterator and const_iterator) for the -@ref basic_json class. -@note An iterator is called *initialized* when a pointer to a JSON value has - been set (e.g., by a constructor or a copy assignment). If the iterator is - default-constructed, it is *uninitialized* and most methods are undefined. - **The library uses assertions to detect calls on uninitialized iterators.** -@requirement The class satisfies the following concept requirements: -- -[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): - The iterator that can be moved can be moved in both directions (i.e. - incremented and decremented). -@since version 1.0.0, simplified in version 2.0.9, change to bidirectional - iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) -*/ -template -class iter_impl -{ - /// the iterator with BasicJsonType of different const-ness - using other_iter_impl = iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; - /// allow basic_json to access private members - friend other_iter_impl; - friend BasicJsonType; - friend iteration_proxy; - friend iteration_proxy_value; - - using object_t = typename BasicJsonType::object_t; - using array_t = typename BasicJsonType::array_t; - // make sure BasicJsonType is basic_json or const basic_json - static_assert(is_basic_json::type>::value, - "iter_impl only accepts (const) basic_json"); - - public: - - /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. - /// The C++ Standard has never required user-defined iterators to derive from std::iterator. - /// A user-defined iterator should provide publicly accessible typedefs named - /// iterator_category, value_type, difference_type, pointer, and reference. - /// Note that value_type is required to be non-const, even for constant iterators. - using iterator_category = std::bidirectional_iterator_tag; - - /// the type of the values when the iterator is dereferenced - using value_type = typename BasicJsonType::value_type; - /// a type to represent differences between iterators - using difference_type = typename BasicJsonType::difference_type; - /// defines a pointer to the type iterated over (value_type) - using pointer = typename std::conditional::value, - typename BasicJsonType::const_pointer, - typename BasicJsonType::pointer>::type; - /// defines a reference to the type iterated over (value_type) - using reference = - typename std::conditional::value, - typename BasicJsonType::const_reference, - typename BasicJsonType::reference>::type; - - iter_impl() = default; - ~iter_impl() = default; - iter_impl(iter_impl&&) noexcept = default; - iter_impl& operator=(iter_impl&&) noexcept = default; - - /*! - @brief constructor for a given JSON instance - @param[in] object pointer to a JSON object for this iterator - @pre object != nullptr - @post The iterator is initialized; i.e. `m_object != nullptr`. - */ - explicit iter_impl(pointer object) noexcept : m_object(object) - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = typename object_t::iterator(); - break; - } - - case value_t::array: - { - m_it.array_iterator = typename array_t::iterator(); - break; - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } - } - } - - /*! - @note The conventional copy constructor and copy assignment are implicitly - defined. Combined with the following converting constructor and - assignment, they support: (1) copy from iterator to iterator, (2) - copy from const iterator to const iterator, and (3) conversion from - iterator to const iterator. However conversion from const iterator - to iterator is not defined. - */ - - /*! - @brief const copy constructor - @param[in] other const iterator to copy from - @note This copy constructor had to be defined explicitly to circumvent a bug - occurring on msvc v19.0 compiler (VS 2015) debug build. For more - information refer to: https://github.com/nlohmann/json/issues/1608 - */ - iter_impl(const iter_impl& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /*! - @brief converting assignment - @param[in] other const iterator to copy from - @return const/non-const iterator - @note It is not checked whether @a other is initialized. - */ - iter_impl& operator=(const iter_impl& other) noexcept - { - if (&other != this) - { - m_object = other.m_object; - m_it = other.m_it; - } - return *this; - } - - /*! - @brief converting constructor - @param[in] other non-const iterator to copy from - @note It is not checked whether @a other is initialized. - */ - iter_impl(const iter_impl::type>& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /*! - @brief converting assignment - @param[in] other non-const iterator to copy from - @return const/non-const iterator - @note It is not checked whether @a other is initialized. - */ - iter_impl& operator=(const iter_impl::type>& other) noexcept // NOLINT(cert-oop54-cpp) - { - m_object = other.m_object; - m_it = other.m_it; - return *this; - } - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief set the iterator to the first value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_begin() noexcept - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } - - case value_t::array: - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } - - case value_t::null: - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } - - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } - } - - /*! - @brief set the iterator past the last value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_end() noexcept - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } - - case value_t::array: - { - m_it.array_iterator = m_object->m_value.array->end(); - break; - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - m_it.primitive_iterator.set_end(); - break; - } - } - } - - public: - /*! - @brief return a reference to the value pointed to by the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator*() const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); - return m_it.object_iterator->second; - } - - case value_t::array: - { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); - return *m_it.array_iterator; - } - - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); - - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); - } - } - } - - /*! - @brief dereference the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - pointer operator->() const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); - return &(m_it.object_iterator->second); - } - - case value_t::array: - { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); - return &*m_it.array_iterator; - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); - } - } - } - - /*! - @brief post-increment (it++) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl const operator++(int) // NOLINT(readability-const-return-type) - { - auto result = *this; - ++(*this); - return result; - } - - /*! - @brief pre-increment (++it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator++() - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, 1); - break; - } - - case value_t::array: - { - std::advance(m_it.array_iterator, 1); - break; - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - ++m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief post-decrement (it--) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl const operator--(int) // NOLINT(readability-const-return-type) - { - auto result = *this; - --(*this); - return result; - } - - /*! - @brief pre-decrement (--it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator--() - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, -1); - break; - } - - case value_t::array: - { - std::advance(m_it.array_iterator, -1); - break; - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - --m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief comparison: equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > - bool operator==(const IterImpl& other) const - { - // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); - } - - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - return (m_it.object_iterator == other.m_it.object_iterator); - - case value_t::array: - return (m_it.array_iterator == other.m_it.array_iterator); - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - return (m_it.primitive_iterator == other.m_it.primitive_iterator); - } - } - - /*! - @brief comparison: not equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > - bool operator!=(const IterImpl& other) const - { - return !operator==(other); - } - - /*! - @brief comparison: smaller - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); - } - - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object)); - - case value_t::array: - return (m_it.array_iterator < other.m_it.array_iterator); - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - return (m_it.primitive_iterator < other.m_it.primitive_iterator); - } - } - - /*! - @brief comparison: less than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<=(const iter_impl& other) const - { - return !other.operator < (*this); - } - - /*! - @brief comparison: greater than - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>(const iter_impl& other) const - { - return !operator<=(other); - } - - /*! - @brief comparison: greater than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>=(const iter_impl& other) const - { - return !operator<(other); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator+=(difference_type i) - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); - - case value_t::array: - { - std::advance(m_it.array_iterator, i); - break; - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - m_it.primitive_iterator += i; - break; - } - } - - return *this; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator-=(difference_type i) - { - return operator+=(-i); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator+(difference_type i) const - { - auto result = *this; - result += i; - return result; - } - - /*! - @brief addition of distance and iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - friend iter_impl operator+(difference_type i, const iter_impl& it) - { - auto result = it; - result += i; - return result; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator-(difference_type i) const - { - auto result = *this; - result -= i; - return result; - } - - /*! - @brief return difference - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - difference_type operator-(const iter_impl& other) const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); - - case value_t::array: - return m_it.array_iterator - other.m_it.array_iterator; - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - return m_it.primitive_iterator - other.m_it.primitive_iterator; - } - } - - /*! - @brief access to successor - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator[](difference_type n) const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object)); - - case value_t::array: - return *std::next(m_it.array_iterator, n); - - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); - - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); - } - } - } - - /*! - @brief return the key of an object iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - const typename object_t::key_type& key() const - { - JSON_ASSERT(m_object != nullptr); - - if (JSON_HEDLEY_LIKELY(m_object->is_object())) - { - return m_it.object_iterator->first; - } - - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object)); - } - - /*! - @brief return the value of an iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference value() const - { - return operator*(); - } - - JSON_PRIVATE_UNLESS_TESTED: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - internal_iterator::type> m_it {}; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // ptrdiff_t -#include // reverse_iterator -#include // declval - -namespace nlohmann -{ -namespace detail -{ -////////////////////// -// reverse_iterator // -////////////////////// - -/*! -@brief a template for a reverse iterator class - -@tparam Base the base iterator type to reverse. Valid types are @ref -iterator (to create @ref reverse_iterator) and @ref const_iterator (to -create @ref const_reverse_iterator). - -@requirement The class satisfies the following concept requirements: -- -[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): - The iterator that can be moved can be moved in both directions (i.e. - incremented and decremented). -- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): - It is possible to write to the pointed-to element (only if @a Base is - @ref iterator). - -@since version 1.0.0 -*/ -template -class json_reverse_iterator : public std::reverse_iterator -{ - public: - using difference_type = std::ptrdiff_t; - /// shortcut to the reverse iterator adapter - using base_iterator = std::reverse_iterator; - /// the reference type for the pointed-to element - using reference = typename Base::reference; - - /// create reverse iterator from iterator - explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept - : base_iterator(it) {} - - /// create reverse iterator from base class - explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} - - /// post-increment (it++) - json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type) - { - return static_cast(base_iterator::operator++(1)); - } - - /// pre-increment (++it) - json_reverse_iterator& operator++() - { - return static_cast(base_iterator::operator++()); - } - - /// post-decrement (it--) - json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type) - { - return static_cast(base_iterator::operator--(1)); - } - - /// pre-decrement (--it) - json_reverse_iterator& operator--() - { - return static_cast(base_iterator::operator--()); - } - - /// add to iterator - json_reverse_iterator& operator+=(difference_type i) - { - return static_cast(base_iterator::operator+=(i)); - } - - /// add to iterator - json_reverse_iterator operator+(difference_type i) const - { - return static_cast(base_iterator::operator+(i)); - } - - /// subtract from iterator - json_reverse_iterator operator-(difference_type i) const - { - return static_cast(base_iterator::operator-(i)); - } - - /// return difference - difference_type operator-(const json_reverse_iterator& other) const - { - return base_iterator(*this) - base_iterator(other); - } - - /// access to successor - reference operator[](difference_type n) const - { - return *(this->operator+(n)); - } - - /// return the key of an object iterator - auto key() const -> decltype(std::declval().key()) - { - auto it = --this->base(); - return it.key(); - } - - /// return the value of an iterator - reference value() const - { - auto it = --this->base(); - return it.operator * (); - } -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // all_of -#include // isdigit -#include // max -#include // accumulate -#include // string -#include // move -#include // vector - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -template -class json_pointer -{ - // allow basic_json to access private members - NLOHMANN_BASIC_JSON_TPL_DECLARATION - friend class basic_json; - - public: - /*! - @brief create JSON pointer - - Create a JSON pointer according to the syntax described in - [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). - - @param[in] s string representing the JSON pointer; if omitted, the empty - string is assumed which references the whole JSON value - - @throw parse_error.107 if the given JSON pointer @a s is nonempty and does - not begin with a slash (`/`); see example below - - @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is - not followed by `0` (representing `~`) or `1` (representing `/`); see - example below - - @liveexample{The example shows the construction several valid JSON pointers - as well as the exceptional behavior.,json_pointer} - - @since version 2.0.0 - */ - explicit json_pointer(const std::string& s = "") - : reference_tokens(split(s)) - {} - - /*! - @brief return a string representation of the JSON pointer - - @invariant For each JSON pointer `ptr`, it holds: - @code {.cpp} - ptr == json_pointer(ptr.to_string()); - @endcode - - @return a string representation of the JSON pointer - - @liveexample{The example shows the result of `to_string`.,json_pointer__to_string} - - @since version 2.0.0 - */ - std::string to_string() const - { - return std::accumulate(reference_tokens.begin(), reference_tokens.end(), - std::string{}, - [](const std::string & a, const std::string & b) - { - return a + "/" + detail::escape(b); - }); - } - - /// @copydoc to_string() - operator std::string() const - { - return to_string(); - } - - /*! - @brief append another JSON pointer at the end of this JSON pointer - - @param[in] ptr JSON pointer to append - @return JSON pointer with @a ptr appended - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Linear in the length of @a ptr. - - @sa see @ref operator/=(std::string) to append a reference token - @sa see @ref operator/=(std::size_t) to append an array index - @sa see @ref operator/(const json_pointer&, const json_pointer&) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(const json_pointer& ptr) - { - reference_tokens.insert(reference_tokens.end(), - ptr.reference_tokens.begin(), - ptr.reference_tokens.end()); - return *this; - } - - /*! - @brief append an unescaped reference token at the end of this JSON pointer - - @param[in] token reference token to append - @return JSON pointer with @a token appended without escaping @a token - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Amortized constant. - - @sa see @ref operator/=(const json_pointer&) to append a JSON pointer - @sa see @ref operator/=(std::size_t) to append an array index - @sa see @ref operator/(const json_pointer&, std::size_t) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(std::string token) - { - push_back(std::move(token)); - return *this; - } - - /*! - @brief append an array index at the end of this JSON pointer - - @param[in] array_idx array index to append - @return JSON pointer with @a array_idx appended - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Amortized constant. - - @sa see @ref operator/=(const json_pointer&) to append a JSON pointer - @sa see @ref operator/=(std::string) to append a reference token - @sa see @ref operator/(const json_pointer&, std::string) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(std::size_t array_idx) - { - return *this /= std::to_string(array_idx); - } - - /*! - @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer - - @param[in] lhs JSON pointer - @param[in] rhs JSON pointer - @return a new JSON pointer with @a rhs appended to @a lhs - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a lhs and @a rhs. - - @sa see @ref operator/=(const json_pointer&) to append a JSON pointer - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& lhs, - const json_pointer& rhs) - { - return json_pointer(lhs) /= rhs; - } - - /*! - @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer - - @param[in] ptr JSON pointer - @param[in] token reference token - @return a new JSON pointer with unescaped @a token appended to @a ptr - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a ptr. - - @sa see @ref operator/=(std::string) to append a reference token - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& ptr, std::string token) // NOLINT(performance-unnecessary-value-param) - { - return json_pointer(ptr) /= std::move(token); - } - - /*! - @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer - - @param[in] ptr JSON pointer - @param[in] array_idx array index - @return a new JSON pointer with @a array_idx appended to @a ptr - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a ptr. - - @sa see @ref operator/=(std::size_t) to append an array index - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx) - { - return json_pointer(ptr) /= array_idx; - } - - /*! - @brief returns the parent of this JSON pointer - - @return parent of this JSON pointer; in case this JSON pointer is the root, - the root itself is returned - - @complexity Linear in the length of the JSON pointer. - - @liveexample{The example shows the result of `parent_pointer` for different - JSON Pointers.,json_pointer__parent_pointer} - - @since version 3.6.0 - */ - json_pointer parent_pointer() const - { - if (empty()) - { - return *this; - } - - json_pointer res = *this; - res.pop_back(); - return res; - } - - /*! - @brief remove last reference token - - @pre not `empty()` - - @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back} - - @complexity Constant. - - @throw out_of_range.405 if JSON pointer has no parent - - @since version 3.6.0 - */ - void pop_back() - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); - } - - reference_tokens.pop_back(); - } - - /*! - @brief return last reference token - - @pre not `empty()` - @return last reference token - - @liveexample{The example shows the usage of `back`.,json_pointer__back} - - @complexity Constant. - - @throw out_of_range.405 if JSON pointer has no parent - - @since version 3.6.0 - */ - const std::string& back() const - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); - } - - return reference_tokens.back(); - } - - /*! - @brief append an unescaped token at the end of the reference pointer - - @param[in] token token to add - - @complexity Amortized constant. - - @liveexample{The example shows the result of `push_back` for different - JSON Pointers.,json_pointer__push_back} - - @since version 3.6.0 - */ - void push_back(const std::string& token) - { - reference_tokens.push_back(token); - } - - /// @copydoc push_back(const std::string&) - void push_back(std::string&& token) - { - reference_tokens.push_back(std::move(token)); - } - - /*! - @brief return whether pointer points to the root document - - @return true iff the JSON pointer points to the root document - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example shows the result of `empty` for different JSON - Pointers.,json_pointer__empty} - - @since version 3.6.0 - */ - bool empty() const noexcept - { - return reference_tokens.empty(); - } - - private: - /*! - @param[in] s reference token to be converted into an array index - - @return integer representation of @a s - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index begins not with a digit - @throw out_of_range.404 if string @a s could not be converted to an integer - @throw out_of_range.410 if an array index exceeds size_type - */ - static typename BasicJsonType::size_type array_index(const std::string& s) - { - using size_type = typename BasicJsonType::size_type; - - // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) - { - JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType())); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) - { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType())); - } - - std::size_t processed_chars = 0; - unsigned long long res = 0; // NOLINT(runtime/int) - JSON_TRY - { - res = std::stoull(s, &processed_chars); - } - JSON_CATCH(std::out_of_range&) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); - } - - // check if the string was completely read - if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); - } - - // only triggered on special platforms (like 32bit), see also - // https://github.com/nlohmann/json/pull/2203 - if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) - { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE - } - - return static_cast(res); - } - - JSON_PRIVATE_UNLESS_TESTED: - json_pointer top() const - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); - } - - json_pointer result = *this; - result.reference_tokens = {reference_tokens[0]}; - return result; - } - - private: - /*! - @brief create and return a reference to the pointed to value - - @complexity Linear in the number of reference tokens. - - @throw parse_error.109 if array index is not a number - @throw type_error.313 if value cannot be unflattened - */ - BasicJsonType& get_and_create(BasicJsonType& j) const - { - auto* result = &j; - - // in case no reference tokens exist, return a reference to the JSON value - // j which will be overwritten by a primitive value - for (const auto& reference_token : reference_tokens) - { - switch (result->type()) - { - case detail::value_t::null: - { - if (reference_token == "0") - { - // start a new array if reference token is 0 - result = &result->operator[](0); - } - else - { - // start a new object otherwise - result = &result->operator[](reference_token); - } - break; - } - - case detail::value_t::object: - { - // create an entry in the object - result = &result->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - // create an entry in the array - result = &result->operator[](array_index(reference_token)); - break; - } - - /* - The following code is only reached if there exists a reference - token _and_ the current value is primitive. In this case, we have - an error situation, because primitive values may only occur as - single value; that is, with an empty list of reference tokens. - */ - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); - } - } - - return *result; - } - - /*! - @brief return a reference to the pointed to value - - @note This version does not throw if a value is not present, but tries to - create nested values instead. For instance, calling this function - with pointer `"/this/that"` on a null value is equivalent to calling - `operator[]("this").operator[]("that")` on that value, effectively - changing the null value to an object. - - @param[in] ptr a JSON value - - @return reference to the JSON value pointed to by the JSON pointer - - @complexity Linear in the length of the JSON pointer. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - BasicJsonType& get_unchecked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - // convert null values to arrays or objects before continuing - if (ptr->is_null()) - { - // check if reference token is a number - const bool nums = - std::all_of(reference_token.begin(), reference_token.end(), - [](const unsigned char x) - { - return std::isdigit(x); - }); - - // change value to array for numbers or "-" or to object otherwise - *ptr = (nums || reference_token == "-") - ? detail::value_t::array - : detail::value_t::object; - } - - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (reference_token == "-") - { - // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_value.array->size()); - } - else - { - // convert array index to number; unchecked access - ptr = &ptr->operator[](array_index(reference_token)); - } - break; - } - - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - BasicJsonType& get_checked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range", *ptr)); - } - - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; - } - - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); - } - } - - return *ptr; - } - - /*! - @brief return a const reference to the pointed to value - - @param[in] ptr a JSON value - - @return const reference to the JSON value pointed to by the JSON - pointer - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr)); - } - - // use unchecked array access - ptr = &ptr->operator[](array_index(reference_token)); - break; - } - - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const BasicJsonType& get_checked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range", *ptr)); - } - - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; - } - - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - */ - bool contains(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - if (!ptr->contains(reference_token)) - { - // we did not find the key in the object - return false; - } - - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) - { - // invalid char - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) - { - if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) - { - // first char should be between '1' and '9' - return false; - } - for (std::size_t i = 1; i < reference_token.size(); i++) - { - if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) - { - // other char should be between '0' and '9' - return false; - } - } - } - - const auto idx = array_index(reference_token); - if (idx >= ptr->size()) - { - // index out of range - return false; - } - - ptr = &ptr->operator[](idx); - break; - } - - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - { - // we do not expect primitive values if there is still a - // reference token to process - return false; - } - } - } - - // no reference token left means we found a primitive value - return true; - } - - /*! - @brief split the string input to reference tokens - - @note This function is only called by the json_pointer constructor. - All exceptions below are documented there. - - @throw parse_error.107 if the pointer is not empty or begins with '/' - @throw parse_error.108 if character '~' is not followed by '0' or '1' - */ - static std::vector split(const std::string& reference_string) - { - std::vector result; - - // special case: empty reference string -> no reference tokens - if (reference_string.empty()) - { - return result; - } - - // check if nonempty reference string begins with slash - if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) - { - JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType())); - } - - // extract the reference tokens: - // - slash: position of the last read slash (or end of string) - // - start: position after the previous slash - for ( - // search for the first slash after the first character - std::size_t slash = reference_string.find_first_of('/', 1), - // set the beginning of the first reference token - start = 1; - // we can stop if start == 0 (if slash == std::string::npos) - start != 0; - // set the beginning of the next reference token - // (will eventually be 0 if slash == std::string::npos) - start = (slash == std::string::npos) ? 0 : slash + 1, - // find next slash - slash = reference_string.find_first_of('/', start)) - { - // use the text between the beginning of the reference token - // (start) and the last slash (slash). - auto reference_token = reference_string.substr(start, slash - start); - - // check reference tokens are properly escaped - for (std::size_t pos = reference_token.find_first_of('~'); - pos != std::string::npos; - pos = reference_token.find_first_of('~', pos + 1)) - { - JSON_ASSERT(reference_token[pos] == '~'); - - // ~ must be followed by 0 or 1 - if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || - (reference_token[pos + 1] != '0' && - reference_token[pos + 1] != '1'))) - { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType())); - } - } - - // finally, store the reference token - detail::unescape(reference_token); - result.push_back(reference_token); - } - - return result; - } - - private: - /*! - @param[in] reference_string the reference string to the current value - @param[in] value the value to consider - @param[in,out] result the result object to insert values to - - @note Empty objects or arrays are flattened to `null`. - */ - static void flatten(const std::string& reference_string, - const BasicJsonType& value, - BasicJsonType& result) - { - switch (value.type()) - { - case detail::value_t::array: - { - if (value.m_value.array->empty()) - { - // flatten empty array as null - result[reference_string] = nullptr; - } - else - { - // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_value.array->size(); ++i) - { - flatten(reference_string + "/" + std::to_string(i), - value.m_value.array->operator[](i), result); - } - } - break; - } - - case detail::value_t::object: - { - if (value.m_value.object->empty()) - { - // flatten empty object as null - result[reference_string] = nullptr; - } - else - { - // iterate object and use keys as reference string - for (const auto& element : *value.m_value.object) - { - flatten(reference_string + "/" + detail::escape(element.first), element.second, result); - } - } - break; - } - - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - { - // add primitive value with its reference string - result[reference_string] = value; - break; - } - } - } - - /*! - @param[in] value flattened JSON - - @return unflattened JSON - - @throw parse_error.109 if array index is not a number - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitive - @throw type_error.313 if value cannot be unflattened - */ - static BasicJsonType - unflatten(const BasicJsonType& value) - { - if (JSON_HEDLEY_UNLIKELY(!value.is_object())) - { - JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value)); - } - - BasicJsonType result; - - // iterate the JSON object values - for (const auto& element : *value.m_value.object) - { - if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) - { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second)); - } - - // assign value to reference pointed to by JSON pointer; Note that if - // the JSON pointer is "" (i.e., points to the whole value), function - // get_and_create returns a reference to result itself. An assignment - // will then create a primitive value. - json_pointer(element.first).get_and_create(result) = element.second; - } - - return result; - } - - /*! - @brief compares two JSON pointers for equality - - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is equal to @a rhs - - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return lhs.reference_tokens == rhs.reference_tokens; - } - - /*! - @brief compares two JSON pointers for inequality - - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is not equal @a rhs - - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return !(lhs == rhs); - } - - /// the reference tokens - std::vector reference_tokens; -}; -} // namespace nlohmann - -// #include - - -#include -#include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -class json_ref -{ - public: - using value_type = BasicJsonType; - - json_ref(value_type&& value) - : owned_value(std::move(value)) - {} - - json_ref(const value_type& value) - : value_ref(&value) - {} - - json_ref(std::initializer_list init) - : owned_value(init) - {} - - template < - class... Args, - enable_if_t::value, int> = 0 > - json_ref(Args && ... args) - : owned_value(std::forward(args)...) - {} - - // class should be movable only - json_ref(json_ref&&) noexcept = default; - json_ref(const json_ref&) = delete; - json_ref& operator=(const json_ref&) = delete; - json_ref& operator=(json_ref&&) = delete; - ~json_ref() = default; - - value_type moved_or_copied() const - { - if (value_ref == nullptr) - { - return std::move(owned_value); - } - return *value_ref; - } - - value_type const& operator*() const - { - return value_ref ? *value_ref : owned_value; - } - - value_type const* operator->() const - { - return &** this; - } - - private: - mutable value_type owned_value = nullptr; - value_type const* value_ref = nullptr; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - -// #include - - -#include // reverse -#include // array -#include // isnan, isinf -#include // uint8_t, uint16_t, uint32_t, uint64_t -#include // memcpy -#include // numeric_limits -#include // string -#include // move - -// #include - -// #include - -// #include - - -#include // copy -#include // size_t -#include // back_inserter -#include // shared_ptr, make_shared -#include // basic_string -#include // vector - -#ifndef JSON_NO_IO - #include // streamsize - #include // basic_ostream -#endif // JSON_NO_IO - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/// abstract output adapter interface -template struct output_adapter_protocol -{ - virtual void write_character(CharType c) = 0; - virtual void write_characters(const CharType* s, std::size_t length) = 0; - virtual ~output_adapter_protocol() = default; - - output_adapter_protocol() = default; - output_adapter_protocol(const output_adapter_protocol&) = default; - output_adapter_protocol(output_adapter_protocol&&) noexcept = default; - output_adapter_protocol& operator=(const output_adapter_protocol&) = default; - output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; -}; - -/// a type to simplify interfaces -template -using output_adapter_t = std::shared_ptr>; - -/// output adapter for byte vectors -template -class output_vector_adapter : public output_adapter_protocol -{ - public: - explicit output_vector_adapter(std::vector& vec) noexcept - : v(vec) - {} - - void write_character(CharType c) override - { - v.push_back(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - std::copy(s, s + length, std::back_inserter(v)); - } - - private: - std::vector& v; -}; - -#ifndef JSON_NO_IO -/// output adapter for output streams -template -class output_stream_adapter : public output_adapter_protocol -{ - public: - explicit output_stream_adapter(std::basic_ostream& s) noexcept - : stream(s) - {} - - void write_character(CharType c) override - { - stream.put(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - stream.write(s, static_cast(length)); - } - - private: - std::basic_ostream& stream; -}; -#endif // JSON_NO_IO - -/// output adapter for basic_string -template> -class output_string_adapter : public output_adapter_protocol -{ - public: - explicit output_string_adapter(StringType& s) noexcept - : str(s) - {} - - void write_character(CharType c) override - { - str.push_back(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - str.append(s, length); - } - - private: - StringType& str; -}; - -template> -class output_adapter -{ - public: - output_adapter(std::vector& vec) - : oa(std::make_shared>(vec)) {} - -#ifndef JSON_NO_IO - output_adapter(std::basic_ostream& s) - : oa(std::make_shared>(s)) {} -#endif // JSON_NO_IO - - output_adapter(StringType& s) - : oa(std::make_shared>(s)) {} - - operator output_adapter_t() - { - return oa; - } - - private: - output_adapter_t oa = nullptr; -}; -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -/////////////////// -// binary writer // -/////////////////// - -/*! -@brief serialization to CBOR and MessagePack values -*/ -template -class binary_writer -{ - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using number_float_t = typename BasicJsonType::number_float_t; - - public: - /*! - @brief create a binary writer - - @param[in] adapter output adapter to write to - */ - explicit binary_writer(output_adapter_t adapter) : oa(std::move(adapter)) - { - JSON_ASSERT(oa); - } - - /*! - @param[in] j JSON value to serialize - @pre j.type() == value_t::object - */ - void write_bson(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::object: - { - write_bson_object(*j.m_value.object); - break; - } - - case value_t::null: - case value_t::array: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j)); - } - } - } - - /*! - @param[in] j JSON value to serialize - */ - void write_cbor(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::null: - { - oa->write_character(to_char_type(0xF6)); - break; - } - - case value_t::boolean: - { - oa->write_character(j.m_value.boolean - ? to_char_type(0xF5) - : to_char_type(0xF4)); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // CBOR does not differentiate between positive signed - // integers and unsigned integers. Therefore, we used the - // code from the value_t::number_unsigned case here. - if (j.m_value.number_integer <= 0x17) - { - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_integer)); - } - else - { - oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_integer)); - } - } - else - { - // The conversions below encode the sign in the first - // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_value.number_integer; - if (j.m_value.number_integer >= -24) - { - write_number(static_cast(0x20 + positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x38)); - write_number(static_cast(positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x39)); - write_number(static_cast(positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x3A)); - write_number(static_cast(positive_number)); - } - else - { - oa->write_character(to_char_type(0x3B)); - write_number(static_cast(positive_number)); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= 0x17) - { - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else - { - oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_unsigned)); - } - break; - } - - case value_t::number_float: - { - if (std::isnan(j.m_value.number_float)) - { - // NaN is 0xf97e00 in CBOR - oa->write_character(to_char_type(0xF9)); - oa->write_character(to_char_type(0x7E)); - oa->write_character(to_char_type(0x00)); - } - else if (std::isinf(j.m_value.number_float)) - { - // Infinity is 0xf97c00, -Infinity is 0xf9fc00 - oa->write_character(to_char_type(0xf9)); - oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); - oa->write_character(to_char_type(0x00)); - } - else - { - write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); - } - break; - } - - case value_t::string: - { - // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); - if (N <= 0x17) - { - write_number(static_cast(0x60 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x78)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x79)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x7A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x7B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write the string - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); - if (N <= 0x17) - { - write_number(static_cast(0x80 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x98)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x99)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x9A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x9B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - for (const auto& el : *j.m_value.array) - { - write_cbor(el); - } - break; - } - - case value_t::binary: - { - if (j.m_value.binary->has_subtype()) - { - if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) - { - write_number(static_cast(0xd8)); - write_number(static_cast(j.m_value.binary->subtype())); - } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) - { - write_number(static_cast(0xd9)); - write_number(static_cast(j.m_value.binary->subtype())); - } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) - { - write_number(static_cast(0xda)); - write_number(static_cast(j.m_value.binary->subtype())); - } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) - { - write_number(static_cast(0xdb)); - write_number(static_cast(j.m_value.binary->subtype())); - } - } - - // step 1: write control byte and the binary array size - const auto N = j.m_value.binary->size(); - if (N <= 0x17) - { - write_number(static_cast(0x40 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x58)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x59)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x5A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x5B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - N); - - break; - } - - case value_t::object: - { - // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); - if (N <= 0x17) - { - write_number(static_cast(0xA0 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xB8)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xB9)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xBA)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xBB)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - for (const auto& el : *j.m_value.object) - { - write_cbor(el.first); - write_cbor(el.second); - } - break; - } - - case value_t::discarded: - default: - break; - } - } - - /*! - @param[in] j JSON value to serialize - */ - void write_msgpack(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::null: // nil - { - oa->write_character(to_char_type(0xC0)); - break; - } - - case value_t::boolean: // true and false - { - oa->write_character(j.m_value.boolean - ? to_char_type(0xC3) - : to_char_type(0xC2)); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); - } - } - else - { - if (j.m_value.number_integer >= -32) - { - // negative fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 8 - oa->write_character(to_char_type(0xD0)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 16 - oa->write_character(to_char_type(0xD1)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 32 - oa->write_character(to_char_type(0xD2)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 64 - oa->write_character(to_char_type(0xD3)); - write_number(static_cast(j.m_value.number_integer)); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); - } - break; - } - - case value_t::number_float: - { - write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); - break; - } - - case value_t::string: - { - // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); - if (N <= 31) - { - // fixstr - write_number(static_cast(0xA0 | N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 8 - oa->write_character(to_char_type(0xD9)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 16 - oa->write_character(to_char_type(0xDA)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 32 - oa->write_character(to_char_type(0xDB)); - write_number(static_cast(N)); - } - - // step 2: write the string - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); - if (N <= 15) - { - // fixarray - write_number(static_cast(0x90 | N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // array 16 - oa->write_character(to_char_type(0xDC)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // array 32 - oa->write_character(to_char_type(0xDD)); - write_number(static_cast(N)); - } - - // step 2: write each element - for (const auto& el : *j.m_value.array) - { - write_msgpack(el); - } - break; - } - - case value_t::binary: - { - // step 0: determine if the binary type has a set subtype to - // determine whether or not to use the ext or fixext types - const bool use_ext = j.m_value.binary->has_subtype(); - - // step 1: write control byte and the byte string length - const auto N = j.m_value.binary->size(); - if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type{}; - bool fixed = true; - if (use_ext) - { - switch (N) - { - case 1: - output_type = 0xD4; // fixext 1 - break; - case 2: - output_type = 0xD5; // fixext 2 - break; - case 4: - output_type = 0xD6; // fixext 4 - break; - case 8: - output_type = 0xD7; // fixext 8 - break; - case 16: - output_type = 0xD8; // fixext 16 - break; - default: - output_type = 0xC7; // ext 8 - fixed = false; - break; - } - - } - else - { - output_type = 0xC4; // bin 8 - fixed = false; - } - - oa->write_character(to_char_type(output_type)); - if (!fixed) - { - write_number(static_cast(N)); - } - } - else if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type = use_ext - ? 0xC8 // ext 16 - : 0xC5; // bin 16 - - oa->write_character(to_char_type(output_type)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type = use_ext - ? 0xC9 // ext 32 - : 0xC6; // bin 32 - - oa->write_character(to_char_type(output_type)); - write_number(static_cast(N)); - } - - // step 1.5: if this is an ext type, write the subtype - if (use_ext) - { - write_number(static_cast(j.m_value.binary->subtype())); - } - - // step 2: write the byte string - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - N); - - break; - } - - case value_t::object: - { - // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); - if (N <= 15) - { - // fixmap - write_number(static_cast(0x80 | (N & 0xF))); - } - else if (N <= (std::numeric_limits::max)()) - { - // map 16 - oa->write_character(to_char_type(0xDE)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // map 32 - oa->write_character(to_char_type(0xDF)); - write_number(static_cast(N)); - } - - // step 2: write each element - for (const auto& el : *j.m_value.object) - { - write_msgpack(el.first); - write_msgpack(el.second); - } - break; - } - - case value_t::discarded: - default: - break; - } - } - - /*! - @param[in] j JSON value to serialize - @param[in] use_count whether to use '#' prefixes (optimized format) - @param[in] use_type whether to use '$' prefixes (optimized format) - @param[in] add_prefix whether prefixes need to be used for this value - */ - void write_ubjson(const BasicJsonType& j, const bool use_count, - const bool use_type, const bool add_prefix = true) - { - switch (j.type()) - { - case value_t::null: - { - if (add_prefix) - { - oa->write_character(to_char_type('Z')); - } - break; - } - - case value_t::boolean: - { - if (add_prefix) - { - oa->write_character(j.m_value.boolean - ? to_char_type('T') - : to_char_type('F')); - } - break; - } - - case value_t::number_integer: - { - write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); - break; - } - - case value_t::number_unsigned: - { - write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); - break; - } - - case value_t::number_float: - { - write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); - break; - } - - case value_t::string: - { - if (add_prefix) - { - oa->write_character(to_char_type('S')); - } - write_number_with_ubjson_prefix(j.m_value.string->size(), true); - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - if (add_prefix) - { - oa->write_character(to_char_type('[')); - } - - bool prefix_required = true; - if (use_type && !j.m_value.array->empty()) - { - JSON_ASSERT(use_count); - const CharType first_prefix = ubjson_prefix(j.front()); - const bool same_prefix = std::all_of(j.begin() + 1, j.end(), - [this, first_prefix](const BasicJsonType & v) - { - return ubjson_prefix(v) == first_prefix; - }); - - if (same_prefix) - { - prefix_required = false; - oa->write_character(to_char_type('$')); - oa->write_character(first_prefix); - } - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.array->size(), true); - } - - for (const auto& el : *j.m_value.array) - { - write_ubjson(el, use_count, use_type, prefix_required); - } - - if (!use_count) - { - oa->write_character(to_char_type(']')); - } - - break; - } - - case value_t::binary: - { - if (add_prefix) - { - oa->write_character(to_char_type('[')); - } - - if (use_type && !j.m_value.binary->empty()) - { - JSON_ASSERT(use_count); - oa->write_character(to_char_type('$')); - oa->write_character('U'); - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.binary->size(), true); - } - - if (use_type) - { - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - j.m_value.binary->size()); - } - else - { - for (size_t i = 0; i < j.m_value.binary->size(); ++i) - { - oa->write_character(to_char_type('U')); - oa->write_character(j.m_value.binary->data()[i]); - } - } - - if (!use_count) - { - oa->write_character(to_char_type(']')); - } - - break; - } - - case value_t::object: - { - if (add_prefix) - { - oa->write_character(to_char_type('{')); - } - - bool prefix_required = true; - if (use_type && !j.m_value.object->empty()) - { - JSON_ASSERT(use_count); - const CharType first_prefix = ubjson_prefix(j.front()); - const bool same_prefix = std::all_of(j.begin(), j.end(), - [this, first_prefix](const BasicJsonType & v) - { - return ubjson_prefix(v) == first_prefix; - }); - - if (same_prefix) - { - prefix_required = false; - oa->write_character(to_char_type('$')); - oa->write_character(first_prefix); - } - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.object->size(), true); - } - - for (const auto& el : *j.m_value.object) - { - write_number_with_ubjson_prefix(el.first.size(), true); - oa->write_characters( - reinterpret_cast(el.first.c_str()), - el.first.size()); - write_ubjson(el.second, use_count, use_type, prefix_required); - } - - if (!use_count) - { - oa->write_character(to_char_type('}')); - } - - break; - } - - case value_t::discarded: - default: - break; - } - } - - private: - ////////// - // BSON // - ////////// - - /*! - @return The size of a BSON document entry header, including the id marker - and the entry name size (and its null-terminator). - */ - static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) - { - const auto it = name.find(static_cast(0)); - if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) - { - JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j)); - static_cast(j); - } - - return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; - } - - /*! - @brief Writes the given @a element_type and @a name to the output adapter - */ - void write_bson_entry_header(const string_t& name, - const std::uint8_t element_type) - { - oa->write_character(to_char_type(element_type)); // boolean - oa->write_characters( - reinterpret_cast(name.c_str()), - name.size() + 1u); - } - - /*! - @brief Writes a BSON element with key @a name and boolean value @a value - */ - void write_bson_boolean(const string_t& name, - const bool value) - { - write_bson_entry_header(name, 0x08); - oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); - } - - /*! - @brief Writes a BSON element with key @a name and double value @a value - */ - void write_bson_double(const string_t& name, - const double value) - { - write_bson_entry_header(name, 0x01); - write_number(value); - } - - /*! - @return The size of the BSON-encoded string in @a value - */ - static std::size_t calc_bson_string_size(const string_t& value) - { - return sizeof(std::int32_t) + value.size() + 1ul; - } - - /*! - @brief Writes a BSON element with key @a name and string value @a value - */ - void write_bson_string(const string_t& name, - const string_t& value) - { - write_bson_entry_header(name, 0x02); - - write_number(static_cast(value.size() + 1ul)); - oa->write_characters( - reinterpret_cast(value.c_str()), - value.size() + 1); - } - - /*! - @brief Writes a BSON element with key @a name and null value - */ - void write_bson_null(const string_t& name) - { - write_bson_entry_header(name, 0x0A); - } - - /*! - @return The size of the BSON-encoded integer @a value - */ - static std::size_t calc_bson_integer_size(const std::int64_t value) - { - return (std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)() - ? sizeof(std::int32_t) - : sizeof(std::int64_t); - } - - /*! - @brief Writes a BSON element with key @a name and integer @a value - */ - void write_bson_integer(const string_t& name, - const std::int64_t value) - { - if ((std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)()) - { - write_bson_entry_header(name, 0x10); // int32 - write_number(static_cast(value)); - } - else - { - write_bson_entry_header(name, 0x12); // int64 - write_number(static_cast(value)); - } - } - - /*! - @return The size of the BSON-encoded unsigned integer in @a j - */ - static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept - { - return (value <= static_cast((std::numeric_limits::max)())) - ? sizeof(std::int32_t) - : sizeof(std::int64_t); - } - - /*! - @brief Writes a BSON element with key @a name and unsigned @a value - */ - void write_bson_unsigned(const string_t& name, - const BasicJsonType& j) - { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - write_bson_entry_header(name, 0x10 /* int32 */); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - write_bson_entry_header(name, 0x12 /* int64 */); - write_number(static_cast(j.m_value.number_unsigned)); - } - else - { - JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j)); - } - } - - /*! - @brief Writes a BSON element with key @a name and object @a value - */ - void write_bson_object_entry(const string_t& name, - const typename BasicJsonType::object_t& value) - { - write_bson_entry_header(name, 0x03); // object - write_bson_object(value); - } - - /*! - @return The size of the BSON-encoded array @a value - */ - static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) - { - std::size_t array_index = 0ul; - - const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) - { - return result + calc_bson_element_size(std::to_string(array_index++), el); - }); - - return sizeof(std::int32_t) + embedded_document_size + 1ul; - } - - /*! - @return The size of the BSON-encoded binary array @a value - */ - static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) - { - return sizeof(std::int32_t) + value.size() + 1ul; - } - - /*! - @brief Writes a BSON element with key @a name and array @a value - */ - void write_bson_array(const string_t& name, - const typename BasicJsonType::array_t& value) - { - write_bson_entry_header(name, 0x04); // array - write_number(static_cast(calc_bson_array_size(value))); - - std::size_t array_index = 0ul; - - for (const auto& el : value) - { - write_bson_element(std::to_string(array_index++), el); - } - - oa->write_character(to_char_type(0x00)); - } - - /*! - @brief Writes a BSON element with key @a name and binary value @a value - */ - void write_bson_binary(const string_t& name, - const binary_t& value) - { - write_bson_entry_header(name, 0x05); - - write_number(static_cast(value.size())); - write_number(value.has_subtype() ? static_cast(value.subtype()) : std::uint8_t(0x00)); - - oa->write_characters(reinterpret_cast(value.data()), value.size()); - } - - /*! - @brief Calculates the size necessary to serialize the JSON value @a j with its @a name - @return The calculated size for the BSON document entry for @a j with the given @a name. - */ - static std::size_t calc_bson_element_size(const string_t& name, - const BasicJsonType& j) - { - const auto header_size = calc_bson_entry_header_size(name, j); - switch (j.type()) - { - case value_t::object: - return header_size + calc_bson_object_size(*j.m_value.object); - - case value_t::array: - return header_size + calc_bson_array_size(*j.m_value.array); - - case value_t::binary: - return header_size + calc_bson_binary_size(*j.m_value.binary); - - case value_t::boolean: - return header_size + 1ul; - - case value_t::number_float: - return header_size + 8ul; - - case value_t::number_integer: - return header_size + calc_bson_integer_size(j.m_value.number_integer); - - case value_t::number_unsigned: - return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); - - case value_t::string: - return header_size + calc_bson_string_size(*j.m_value.string); - - case value_t::null: - return header_size + 0ul; - - // LCOV_EXCL_START - case value_t::discarded: - default: - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) - return 0ul; - // LCOV_EXCL_STOP - } - } - - /*! - @brief Serializes the JSON value @a j to BSON and associates it with the - key @a name. - @param name The name to associate with the JSON entity @a j within the - current BSON document - */ - void write_bson_element(const string_t& name, - const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::object: - return write_bson_object_entry(name, *j.m_value.object); - - case value_t::array: - return write_bson_array(name, *j.m_value.array); - - case value_t::binary: - return write_bson_binary(name, *j.m_value.binary); - - case value_t::boolean: - return write_bson_boolean(name, j.m_value.boolean); - - case value_t::number_float: - return write_bson_double(name, j.m_value.number_float); - - case value_t::number_integer: - return write_bson_integer(name, j.m_value.number_integer); - - case value_t::number_unsigned: - return write_bson_unsigned(name, j); - - case value_t::string: - return write_bson_string(name, *j.m_value.string); - - case value_t::null: - return write_bson_null(name); - - // LCOV_EXCL_START - case value_t::discarded: - default: - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) - return; - // LCOV_EXCL_STOP - } - } - - /*! - @brief Calculates the size of the BSON serialization of the given - JSON-object @a j. - @param[in] value JSON value to serialize - @pre value.type() == value_t::object - */ - static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) - { - std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0), - [](size_t result, const typename BasicJsonType::object_t::value_type & el) - { - return result += calc_bson_element_size(el.first, el.second); - }); - - return sizeof(std::int32_t) + document_size + 1ul; - } - - /*! - @param[in] value JSON value to serialize - @pre value.type() == value_t::object - */ - void write_bson_object(const typename BasicJsonType::object_t& value) - { - write_number(static_cast(calc_bson_object_size(value))); - - for (const auto& el : value) - { - write_bson_element(el.first, el.second); - } - - oa->write_character(to_char_type(0x00)); - } - - ////////// - // CBOR // - ////////// - - static constexpr CharType get_cbor_float_prefix(float /*unused*/) - { - return to_char_type(0xFA); // Single-Precision Float - } - - static constexpr CharType get_cbor_float_prefix(double /*unused*/) - { - return to_char_type(0xFB); // Double-Precision Float - } - - ///////////// - // MsgPack // - ///////////// - - static constexpr CharType get_msgpack_float_prefix(float /*unused*/) - { - return to_char_type(0xCA); // float 32 - } - - static constexpr CharType get_msgpack_float_prefix(double /*unused*/) - { - return to_char_type(0xCB); // float 64 - } - - //////////// - // UBJSON // - //////////// - - // UBJSON: write number (floating point) - template::value, int>::type = 0> - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if (add_prefix) - { - oa->write_character(get_ubjson_float_prefix(n)); - } - write_number(n); - } - - // UBJSON: write number (unsigned integer) - template::value, int>::type = 0> - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('i')); // int8 - } - write_number(static_cast(n)); - } - else if (n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('U')); // uint8 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('I')); // int16 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('l')); // int32 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('L')); // int64 - } - write_number(static_cast(n)); - } - else - { - if (add_prefix) - { - oa->write_character(to_char_type('H')); // high-precision number - } - - const auto number = BasicJsonType(n).dump(); - write_number_with_ubjson_prefix(number.size(), true); - for (std::size_t i = 0; i < number.size(); ++i) - { - oa->write_character(to_char_type(static_cast(number[i]))); - } - } - } - - // UBJSON: write number (signed integer) - template < typename NumberType, typename std::enable_if < - std::is_signed::value&& - !std::is_floating_point::value, int >::type = 0 > - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('i')); // int8 - } - write_number(static_cast(n)); - } - else if (static_cast((std::numeric_limits::min)()) <= n && n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('U')); // uint8 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('I')); // int16 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('l')); // int32 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('L')); // int64 - } - write_number(static_cast(n)); - } - // LCOV_EXCL_START - else - { - if (add_prefix) - { - oa->write_character(to_char_type('H')); // high-precision number - } - - const auto number = BasicJsonType(n).dump(); - write_number_with_ubjson_prefix(number.size(), true); - for (std::size_t i = 0; i < number.size(); ++i) - { - oa->write_character(to_char_type(static_cast(number[i]))); - } - } - // LCOV_EXCL_STOP - } - - /*! - @brief determine the type prefix of container values - */ - CharType ubjson_prefix(const BasicJsonType& j) const noexcept - { - switch (j.type()) - { - case value_t::null: - return 'Z'; - - case value_t::boolean: - return j.m_value.boolean ? 'T' : 'F'; - - case value_t::number_integer: - { - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'i'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'U'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'I'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'l'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'L'; - } - // anything else is treated as high-precision number - return 'H'; // LCOV_EXCL_LINE - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'i'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'U'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'I'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'l'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'L'; - } - // anything else is treated as high-precision number - return 'H'; // LCOV_EXCL_LINE - } - - case value_t::number_float: - return get_ubjson_float_prefix(j.m_value.number_float); - - case value_t::string: - return 'S'; - - case value_t::array: // fallthrough - case value_t::binary: - return '['; - - case value_t::object: - return '{'; - - case value_t::discarded: - default: // discarded values - return 'N'; - } - } - - static constexpr CharType get_ubjson_float_prefix(float /*unused*/) - { - return 'd'; // float 32 - } - - static constexpr CharType get_ubjson_float_prefix(double /*unused*/) - { - return 'D'; // float 64 - } - - /////////////////////// - // Utility functions // - /////////////////////// - - /* - @brief write a number to output input - @param[in] n number of type @a NumberType - @tparam NumberType the type of the number - @tparam OutputIsLittleEndian Set to true if output data is - required to be little endian - - @note This function needs to respect the system's endianess, because bytes - in CBOR, MessagePack, and UBJSON are stored in network order (big - endian) and therefore need reordering on little endian systems. - */ - template - void write_number(const NumberType n) - { - // step 1: write number to array of length NumberType - std::array vec{}; - std::memcpy(vec.data(), &n, sizeof(NumberType)); - - // step 2: write array to output (with possible reordering) - if (is_little_endian != OutputIsLittleEndian) - { - // reverse byte order prior to conversion if necessary - std::reverse(vec.begin(), vec.end()); - } - - oa->write_characters(vec.data(), sizeof(NumberType)); - } - - void write_compact_float(const number_float_t n, detail::input_format_t format) - { -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && - static_cast(n) <= static_cast((std::numeric_limits::max)()) && - static_cast(static_cast(n)) == static_cast(n)) - { - oa->write_character(format == detail::input_format_t::cbor - ? get_cbor_float_prefix(static_cast(n)) - : get_msgpack_float_prefix(static_cast(n))); - write_number(static_cast(n)); - } - else - { - oa->write_character(format == detail::input_format_t::cbor - ? get_cbor_float_prefix(n) - : get_msgpack_float_prefix(n)); - write_number(n); - } -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - } - - public: - // The following to_char_type functions are implement the conversion - // between uint8_t and CharType. In case CharType is not unsigned, - // such a conversion is required to allow values greater than 128. - // See for a discussion. - template < typename C = CharType, - enable_if_t < std::is_signed::value && std::is_signed::value > * = nullptr > - static constexpr CharType to_char_type(std::uint8_t x) noexcept - { - return *reinterpret_cast(&x); - } - - template < typename C = CharType, - enable_if_t < std::is_signed::value && std::is_unsigned::value > * = nullptr > - static CharType to_char_type(std::uint8_t x) noexcept - { - static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); - static_assert(std::is_trivial::value, "CharType must be trivial"); - CharType result; - std::memcpy(&result, &x, sizeof(x)); - return result; - } - - template::value>* = nullptr> - static constexpr CharType to_char_type(std::uint8_t x) noexcept - { - return x; - } - - template < typename InputCharType, typename C = CharType, - enable_if_t < - std::is_signed::value && - std::is_signed::value && - std::is_same::type>::value - > * = nullptr > - static constexpr CharType to_char_type(InputCharType x) noexcept - { - return x; - } - - private: - /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); - - /// the output - output_adapter_t oa = nullptr; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // reverse, remove, fill, find, none_of -#include // array -#include // localeconv, lconv -#include // labs, isfinite, isnan, signbit -#include // size_t, ptrdiff_t -#include // uint8_t -#include // snprintf -#include // numeric_limits -#include // string, char_traits -#include // is_same -#include // move - -// #include - - -#include // array -#include // signbit, isfinite -#include // intN_t, uintN_t -#include // memcpy, memmove -#include // numeric_limits -#include // conditional - -// #include - - -namespace nlohmann -{ -namespace detail -{ - -/*! -@brief implements the Grisu2 algorithm for binary to decimal floating-point -conversion. - -This implementation is a slightly modified version of the reference -implementation which may be obtained from -http://florian.loitsch.com/publications (bench.tar.gz). - -The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. - -For a detailed description of the algorithm see: - -[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with - Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming - Language Design and Implementation, PLDI 2010 -[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", - Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language - Design and Implementation, PLDI 1996 -*/ -namespace dtoa_impl -{ - -template -Target reinterpret_bits(const Source source) -{ - static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); - - Target target; - std::memcpy(&target, &source, sizeof(Source)); - return target; -} - -struct diyfp // f * 2^e -{ - static constexpr int kPrecision = 64; // = q - - std::uint64_t f = 0; - int e = 0; - - constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} - - /*! - @brief returns x - y - @pre x.e == y.e and x.f >= y.f - */ - static diyfp sub(const diyfp& x, const diyfp& y) noexcept - { - JSON_ASSERT(x.e == y.e); - JSON_ASSERT(x.f >= y.f); - - return {x.f - y.f, x.e}; - } - - /*! - @brief returns x * y - @note The result is rounded. (Only the upper q bits are returned.) - */ - static diyfp mul(const diyfp& x, const diyfp& y) noexcept - { - static_assert(kPrecision == 64, "internal error"); - - // Computes: - // f = round((x.f * y.f) / 2^q) - // e = x.e + y.e + q - - // Emulate the 64-bit * 64-bit multiplication: - // - // p = u * v - // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) - // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) - // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) - // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) - // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) - // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) - // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) - // - // (Since Q might be larger than 2^32 - 1) - // - // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) - // - // (Q_hi + H does not overflow a 64-bit int) - // - // = p_lo + 2^64 p_hi - - const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; - const std::uint64_t u_hi = x.f >> 32u; - const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; - const std::uint64_t v_hi = y.f >> 32u; - - const std::uint64_t p0 = u_lo * v_lo; - const std::uint64_t p1 = u_lo * v_hi; - const std::uint64_t p2 = u_hi * v_lo; - const std::uint64_t p3 = u_hi * v_hi; - - const std::uint64_t p0_hi = p0 >> 32u; - const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; - const std::uint64_t p1_hi = p1 >> 32u; - const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; - const std::uint64_t p2_hi = p2 >> 32u; - - std::uint64_t Q = p0_hi + p1_lo + p2_lo; - - // The full product might now be computed as - // - // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) - // p_lo = p0_lo + (Q << 32) - // - // But in this particular case here, the full p_lo is not required. - // Effectively we only need to add the highest bit in p_lo to p_hi (and - // Q_hi + 1 does not overflow). - - Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up - - const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); - - return {h, x.e + y.e + 64}; - } - - /*! - @brief normalize x such that the significand is >= 2^(q-1) - @pre x.f != 0 - */ - static diyfp normalize(diyfp x) noexcept - { - JSON_ASSERT(x.f != 0); - - while ((x.f >> 63u) == 0) - { - x.f <<= 1u; - x.e--; - } - - return x; - } - - /*! - @brief normalize x such that the result has the exponent E - @pre e >= x.e and the upper e - x.e bits of x.f must be zero. - */ - static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept - { - const int delta = x.e - target_exponent; - - JSON_ASSERT(delta >= 0); - JSON_ASSERT(((x.f << delta) >> delta) == x.f); - - return {x.f << delta, target_exponent}; - } -}; - -struct boundaries -{ - diyfp w; - diyfp minus; - diyfp plus; -}; - -/*! -Compute the (normalized) diyfp representing the input number 'value' and its -boundaries. - -@pre value must be finite and positive -*/ -template -boundaries compute_boundaries(FloatType value) -{ - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); - - // Convert the IEEE representation into a diyfp. - // - // If v is denormal: - // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) - // If v is normalized: - // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) - - static_assert(std::numeric_limits::is_iec559, - "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); - - constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) - constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); - constexpr int kMinExp = 1 - kBias; - constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) - - using bits_type = typename std::conditional::type; - - const auto bits = static_cast(reinterpret_bits(value)); - const std::uint64_t E = bits >> (kPrecision - 1); - const std::uint64_t F = bits & (kHiddenBit - 1); - - const bool is_denormal = E == 0; - const diyfp v = is_denormal - ? diyfp(F, kMinExp) - : diyfp(F + kHiddenBit, static_cast(E) - kBias); - - // Compute the boundaries m- and m+ of the floating-point value - // v = f * 2^e. - // - // Determine v- and v+, the floating-point predecessor and successor if v, - // respectively. - // - // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) - // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) - // - // v+ = v + 2^e - // - // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ - // between m- and m+ round to v, regardless of how the input rounding - // algorithm breaks ties. - // - // ---+-------------+-------------+-------------+-------------+--- (A) - // v- m- v m+ v+ - // - // -----------------+------+------+-------------+-------------+--- (B) - // v- m- v m+ v+ - - const bool lower_boundary_is_closer = F == 0 && E > 1; - const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); - const diyfp m_minus = lower_boundary_is_closer - ? diyfp(4 * v.f - 1, v.e - 2) // (B) - : diyfp(2 * v.f - 1, v.e - 1); // (A) - - // Determine the normalized w+ = m+. - const diyfp w_plus = diyfp::normalize(m_plus); - - // Determine w- = m- such that e_(w-) = e_(w+). - const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); - - return {diyfp::normalize(v), w_minus, w_plus}; -} - -// Given normalized diyfp w, Grisu needs to find a (normalized) cached -// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies -// within a certain range [alpha, gamma] (Definition 3.2 from [1]) -// -// alpha <= e = e_c + e_w + q <= gamma -// -// or -// -// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q -// <= f_c * f_w * 2^gamma -// -// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies -// -// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma -// -// or -// -// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) -// -// The choice of (alpha,gamma) determines the size of the table and the form of -// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well -// in practice: -// -// The idea is to cut the number c * w = f * 2^e into two parts, which can be -// processed independently: An integral part p1, and a fractional part p2: -// -// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e -// = (f div 2^-e) + (f mod 2^-e) * 2^e -// = p1 + p2 * 2^e -// -// The conversion of p1 into decimal form requires a series of divisions and -// modulos by (a power of) 10. These operations are faster for 32-bit than for -// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be -// achieved by choosing -// -// -e >= 32 or e <= -32 := gamma -// -// In order to convert the fractional part -// -// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... -// -// into decimal form, the fraction is repeatedly multiplied by 10 and the digits -// d[-i] are extracted in order: -// -// (10 * p2) div 2^-e = d[-1] -// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... -// -// The multiplication by 10 must not overflow. It is sufficient to choose -// -// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. -// -// Since p2 = f mod 2^-e < 2^-e, -// -// -e <= 60 or e >= -60 := alpha - -constexpr int kAlpha = -60; -constexpr int kGamma = -32; - -struct cached_power // c = f * 2^e ~= 10^k -{ - std::uint64_t f; - int e; - int k; -}; - -/*! -For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached -power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c -satisfies (Definition 3.2 from [1]) - - alpha <= e_c + e + q <= gamma. -*/ -inline cached_power get_cached_power_for_binary_exponent(int e) -{ - // Now - // - // alpha <= e_c + e + q <= gamma (1) - // ==> f_c * 2^alpha <= c * 2^e * 2^q - // - // and since the c's are normalized, 2^(q-1) <= f_c, - // - // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) - // ==> 2^(alpha - e - 1) <= c - // - // If c were an exact power of ten, i.e. c = 10^k, one may determine k as - // - // k = ceil( log_10( 2^(alpha - e - 1) ) ) - // = ceil( (alpha - e - 1) * log_10(2) ) - // - // From the paper: - // "In theory the result of the procedure could be wrong since c is rounded, - // and the computation itself is approximated [...]. In practice, however, - // this simple function is sufficient." - // - // For IEEE double precision floating-point numbers converted into - // normalized diyfp's w = f * 2^e, with q = 64, - // - // e >= -1022 (min IEEE exponent) - // -52 (p - 1) - // -52 (p - 1, possibly normalize denormal IEEE numbers) - // -11 (normalize the diyfp) - // = -1137 - // - // and - // - // e <= +1023 (max IEEE exponent) - // -52 (p - 1) - // -11 (normalize the diyfp) - // = 960 - // - // This binary exponent range [-1137,960] results in a decimal exponent - // range [-307,324]. One does not need to store a cached power for each - // k in this range. For each such k it suffices to find a cached power - // such that the exponent of the product lies in [alpha,gamma]. - // This implies that the difference of the decimal exponents of adjacent - // table entries must be less than or equal to - // - // floor( (gamma - alpha) * log_10(2) ) = 8. - // - // (A smaller distance gamma-alpha would require a larger table.) - - // NB: - // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. - - constexpr int kCachedPowersMinDecExp = -300; - constexpr int kCachedPowersDecStep = 8; - - static constexpr std::array kCachedPowers = - { - { - { 0xAB70FE17C79AC6CA, -1060, -300 }, - { 0xFF77B1FCBEBCDC4F, -1034, -292 }, - { 0xBE5691EF416BD60C, -1007, -284 }, - { 0x8DD01FAD907FFC3C, -980, -276 }, - { 0xD3515C2831559A83, -954, -268 }, - { 0x9D71AC8FADA6C9B5, -927, -260 }, - { 0xEA9C227723EE8BCB, -901, -252 }, - { 0xAECC49914078536D, -874, -244 }, - { 0x823C12795DB6CE57, -847, -236 }, - { 0xC21094364DFB5637, -821, -228 }, - { 0x9096EA6F3848984F, -794, -220 }, - { 0xD77485CB25823AC7, -768, -212 }, - { 0xA086CFCD97BF97F4, -741, -204 }, - { 0xEF340A98172AACE5, -715, -196 }, - { 0xB23867FB2A35B28E, -688, -188 }, - { 0x84C8D4DFD2C63F3B, -661, -180 }, - { 0xC5DD44271AD3CDBA, -635, -172 }, - { 0x936B9FCEBB25C996, -608, -164 }, - { 0xDBAC6C247D62A584, -582, -156 }, - { 0xA3AB66580D5FDAF6, -555, -148 }, - { 0xF3E2F893DEC3F126, -529, -140 }, - { 0xB5B5ADA8AAFF80B8, -502, -132 }, - { 0x87625F056C7C4A8B, -475, -124 }, - { 0xC9BCFF6034C13053, -449, -116 }, - { 0x964E858C91BA2655, -422, -108 }, - { 0xDFF9772470297EBD, -396, -100 }, - { 0xA6DFBD9FB8E5B88F, -369, -92 }, - { 0xF8A95FCF88747D94, -343, -84 }, - { 0xB94470938FA89BCF, -316, -76 }, - { 0x8A08F0F8BF0F156B, -289, -68 }, - { 0xCDB02555653131B6, -263, -60 }, - { 0x993FE2C6D07B7FAC, -236, -52 }, - { 0xE45C10C42A2B3B06, -210, -44 }, - { 0xAA242499697392D3, -183, -36 }, - { 0xFD87B5F28300CA0E, -157, -28 }, - { 0xBCE5086492111AEB, -130, -20 }, - { 0x8CBCCC096F5088CC, -103, -12 }, - { 0xD1B71758E219652C, -77, -4 }, - { 0x9C40000000000000, -50, 4 }, - { 0xE8D4A51000000000, -24, 12 }, - { 0xAD78EBC5AC620000, 3, 20 }, - { 0x813F3978F8940984, 30, 28 }, - { 0xC097CE7BC90715B3, 56, 36 }, - { 0x8F7E32CE7BEA5C70, 83, 44 }, - { 0xD5D238A4ABE98068, 109, 52 }, - { 0x9F4F2726179A2245, 136, 60 }, - { 0xED63A231D4C4FB27, 162, 68 }, - { 0xB0DE65388CC8ADA8, 189, 76 }, - { 0x83C7088E1AAB65DB, 216, 84 }, - { 0xC45D1DF942711D9A, 242, 92 }, - { 0x924D692CA61BE758, 269, 100 }, - { 0xDA01EE641A708DEA, 295, 108 }, - { 0xA26DA3999AEF774A, 322, 116 }, - { 0xF209787BB47D6B85, 348, 124 }, - { 0xB454E4A179DD1877, 375, 132 }, - { 0x865B86925B9BC5C2, 402, 140 }, - { 0xC83553C5C8965D3D, 428, 148 }, - { 0x952AB45CFA97A0B3, 455, 156 }, - { 0xDE469FBD99A05FE3, 481, 164 }, - { 0xA59BC234DB398C25, 508, 172 }, - { 0xF6C69A72A3989F5C, 534, 180 }, - { 0xB7DCBF5354E9BECE, 561, 188 }, - { 0x88FCF317F22241E2, 588, 196 }, - { 0xCC20CE9BD35C78A5, 614, 204 }, - { 0x98165AF37B2153DF, 641, 212 }, - { 0xE2A0B5DC971F303A, 667, 220 }, - { 0xA8D9D1535CE3B396, 694, 228 }, - { 0xFB9B7CD9A4A7443C, 720, 236 }, - { 0xBB764C4CA7A44410, 747, 244 }, - { 0x8BAB8EEFB6409C1A, 774, 252 }, - { 0xD01FEF10A657842C, 800, 260 }, - { 0x9B10A4E5E9913129, 827, 268 }, - { 0xE7109BFBA19C0C9D, 853, 276 }, - { 0xAC2820D9623BF429, 880, 284 }, - { 0x80444B5E7AA7CF85, 907, 292 }, - { 0xBF21E44003ACDD2D, 933, 300 }, - { 0x8E679C2F5E44FF8F, 960, 308 }, - { 0xD433179D9C8CB841, 986, 316 }, - { 0x9E19DB92B4E31BA9, 1013, 324 }, - } - }; - - // This computation gives exactly the same results for k as - // k = ceil((kAlpha - e - 1) * 0.30102999566398114) - // for |e| <= 1500, but doesn't require floating-point operations. - // NB: log_10(2) ~= 78913 / 2^18 - JSON_ASSERT(e >= -1500); - JSON_ASSERT(e <= 1500); - const int f = kAlpha - e - 1; - const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); - - const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; - JSON_ASSERT(index >= 0); - JSON_ASSERT(static_cast(index) < kCachedPowers.size()); - - const cached_power cached = kCachedPowers[static_cast(index)]; - JSON_ASSERT(kAlpha <= cached.e + e + 64); - JSON_ASSERT(kGamma >= cached.e + e + 64); - - return cached; -} - -/*! -For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. -For n == 0, returns 1 and sets pow10 := 1. -*/ -inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) -{ - // LCOV_EXCL_START - if (n >= 1000000000) - { - pow10 = 1000000000; - return 10; - } - // LCOV_EXCL_STOP - if (n >= 100000000) - { - pow10 = 100000000; - return 9; - } - if (n >= 10000000) - { - pow10 = 10000000; - return 8; - } - if (n >= 1000000) - { - pow10 = 1000000; - return 7; - } - if (n >= 100000) - { - pow10 = 100000; - return 6; - } - if (n >= 10000) - { - pow10 = 10000; - return 5; - } - if (n >= 1000) - { - pow10 = 1000; - return 4; - } - if (n >= 100) - { - pow10 = 100; - return 3; - } - if (n >= 10) - { - pow10 = 10; - return 2; - } - - pow10 = 1; - return 1; -} - -inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, - std::uint64_t rest, std::uint64_t ten_k) -{ - JSON_ASSERT(len >= 1); - JSON_ASSERT(dist <= delta); - JSON_ASSERT(rest <= delta); - JSON_ASSERT(ten_k > 0); - - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // ten_k - // <------> - // <---- rest ----> - // --------------[------------------+----+--------------]-------------- - // w V - // = buf * 10^k - // - // ten_k represents a unit-in-the-last-place in the decimal representation - // stored in buf. - // Decrement buf by ten_k while this takes buf closer to w. - - // The tests are written in this order to avoid overflow in unsigned - // integer arithmetic. - - while (rest < dist - && delta - rest >= ten_k - && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) - { - JSON_ASSERT(buf[len - 1] != '0'); - buf[len - 1]--; - rest += ten_k; - } -} - -/*! -Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. -M- and M+ must be normalized and share the same exponent -60 <= e <= -32. -*/ -inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, - diyfp M_minus, diyfp w, diyfp M_plus) -{ - static_assert(kAlpha >= -60, "internal error"); - static_assert(kGamma <= -32, "internal error"); - - // Generates the digits (and the exponent) of a decimal floating-point - // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's - // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. - // - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // Grisu2 generates the digits of M+ from left to right and stops as soon as - // V is in [M-,M+]. - - JSON_ASSERT(M_plus.e >= kAlpha); - JSON_ASSERT(M_plus.e <= kGamma); - - std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) - std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) - - // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): - // - // M+ = f * 2^e - // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e - // = ((p1 ) * 2^-e + (p2 )) * 2^e - // = p1 + p2 * 2^e - - const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); - - auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) - std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e - - // 1) - // - // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] - - JSON_ASSERT(p1 > 0); - - std::uint32_t pow10{}; - const int k = find_largest_pow10(p1, pow10); - - // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) - // - // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) - // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) - // - // M+ = p1 + p2 * 2^e - // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e - // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e - // = d[k-1] * 10^(k-1) + ( rest) * 2^e - // - // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) - // - // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] - // - // but stop as soon as - // - // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e - - int n = k; - while (n > 0) - { - // Invariants: - // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) - // pow10 = 10^(n-1) <= p1 < 10^n - // - const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) - const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) - // - // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e - // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) - // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d - // - // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) - // - p1 = r; - n--; - // - // M+ = buffer * 10^n + (p1 + p2 * 2^e) - // pow10 = 10^n - // - - // Now check if enough digits have been generated. - // Compute - // - // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e - // - // Note: - // Since rest and delta share the same exponent e, it suffices to - // compare the significands. - const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; - if (rest <= delta) - { - // V = buffer * 10^n, with M- <= V <= M+. - - decimal_exponent += n; - - // We may now just stop. But instead look if the buffer could be - // decremented to bring V closer to w. - // - // pow10 = 10^n is now 1 ulp in the decimal representation V. - // The rounding procedure works with diyfp's with an implicit - // exponent of e. - // - // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e - // - const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; - grisu2_round(buffer, length, dist, delta, rest, ten_n); - - return; - } - - pow10 /= 10; - // - // pow10 = 10^(n-1) <= p1 < 10^n - // Invariants restored. - } - - // 2) - // - // The digits of the integral part have been generated: - // - // M+ = d[k-1]...d[1]d[0] + p2 * 2^e - // = buffer + p2 * 2^e - // - // Now generate the digits of the fractional part p2 * 2^e. - // - // Note: - // No decimal point is generated: the exponent is adjusted instead. - // - // p2 actually represents the fraction - // - // p2 * 2^e - // = p2 / 2^-e - // = d[-1] / 10^1 + d[-2] / 10^2 + ... - // - // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) - // - // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m - // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) - // - // using - // - // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) - // = ( d) * 2^-e + ( r) - // - // or - // 10^m * p2 * 2^e = d + r * 2^e - // - // i.e. - // - // M+ = buffer + p2 * 2^e - // = buffer + 10^-m * (d + r * 2^e) - // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e - // - // and stop as soon as 10^-m * r * 2^e <= delta * 2^e - - JSON_ASSERT(p2 > delta); - - int m = 0; - for (;;) - { - // Invariant: - // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e - // = buffer * 10^-m + 10^-m * (p2 ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e - // - JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); - p2 *= 10; - const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e - const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e - // - // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) - // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e - // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d - // - // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e - // - p2 = r; - m++; - // - // M+ = buffer * 10^-m + 10^-m * p2 * 2^e - // Invariant restored. - - // Check if enough digits have been generated. - // - // 10^-m * p2 * 2^e <= delta * 2^e - // p2 * 2^e <= 10^m * delta * 2^e - // p2 <= 10^m * delta - delta *= 10; - dist *= 10; - if (p2 <= delta) - { - break; - } - } - - // V = buffer * 10^-m, with M- <= V <= M+. - - decimal_exponent -= m; - - // 1 ulp in the decimal representation is now 10^-m. - // Since delta and dist are now scaled by 10^m, we need to do the - // same with ulp in order to keep the units in sync. - // - // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e - // - const std::uint64_t ten_m = one.f; - grisu2_round(buffer, length, dist, delta, p2, ten_m); - - // By construction this algorithm generates the shortest possible decimal - // number (Loitsch, Theorem 6.2) which rounds back to w. - // For an input number of precision p, at least - // - // N = 1 + ceil(p * log_10(2)) - // - // decimal digits are sufficient to identify all binary floating-point - // numbers (Matula, "In-and-Out conversions"). - // This implies that the algorithm does not produce more than N decimal - // digits. - // - // N = 17 for p = 53 (IEEE double precision) - // N = 9 for p = 24 (IEEE single precision) -} - -/*! -v = buf * 10^decimal_exponent -len is the length of the buffer (number of decimal digits) -The buffer must be large enough, i.e. >= max_digits10. -*/ -JSON_HEDLEY_NON_NULL(1) -inline void grisu2(char* buf, int& len, int& decimal_exponent, - diyfp m_minus, diyfp v, diyfp m_plus) -{ - JSON_ASSERT(m_plus.e == m_minus.e); - JSON_ASSERT(m_plus.e == v.e); - - // --------(-----------------------+-----------------------)-------- (A) - // m- v m+ - // - // --------------------(-----------+-----------------------)-------- (B) - // m- v m+ - // - // First scale v (and m- and m+) such that the exponent is in the range - // [alpha, gamma]. - - const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); - - const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k - - // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] - const diyfp w = diyfp::mul(v, c_minus_k); - const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); - const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); - - // ----(---+---)---------------(---+---)---------------(---+---)---- - // w- w w+ - // = c*m- = c*v = c*m+ - // - // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and - // w+ are now off by a small amount. - // In fact: - // - // w - v * 10^k < 1 ulp - // - // To account for this inaccuracy, add resp. subtract 1 ulp. - // - // --------+---[---------------(---+---)---------------]---+-------- - // w- M- w M+ w+ - // - // Now any number in [M-, M+] (bounds included) will round to w when input, - // regardless of how the input rounding algorithm breaks ties. - // - // And digit_gen generates the shortest possible such number in [M-, M+]. - // Note that this does not mean that Grisu2 always generates the shortest - // possible number in the interval (m-, m+). - const diyfp M_minus(w_minus.f + 1, w_minus.e); - const diyfp M_plus (w_plus.f - 1, w_plus.e ); - - decimal_exponent = -cached.k; // = -(-k) = k - - grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); -} - -/*! -v = buf * 10^decimal_exponent -len is the length of the buffer (number of decimal digits) -The buffer must be large enough, i.e. >= max_digits10. -*/ -template -JSON_HEDLEY_NON_NULL(1) -void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) -{ - static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, - "internal error: not enough precision"); - - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); - - // If the neighbors (and boundaries) of 'value' are always computed for double-precision - // numbers, all float's can be recovered using strtod (and strtof). However, the resulting - // decimal representations are not exactly "short". - // - // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) - // says "value is converted to a string as if by std::sprintf in the default ("C") locale" - // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' - // does. - // On the other hand, the documentation for 'std::to_chars' requires that "parsing the - // representation using the corresponding std::from_chars function recovers value exactly". That - // indicates that single precision floating-point numbers should be recovered using - // 'std::strtof'. - // - // NB: If the neighbors are computed for single-precision numbers, there is a single float - // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision - // value is off by 1 ulp. -#if 0 - const boundaries w = compute_boundaries(static_cast(value)); -#else - const boundaries w = compute_boundaries(value); -#endif - - grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); -} - -/*! -@brief appends a decimal representation of e to buf -@return a pointer to the element following the exponent. -@pre -1000 < e < 1000 -*/ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* append_exponent(char* buf, int e) -{ - JSON_ASSERT(e > -1000); - JSON_ASSERT(e < 1000); - - if (e < 0) - { - e = -e; - *buf++ = '-'; - } - else - { - *buf++ = '+'; - } - - auto k = static_cast(e); - if (k < 10) - { - // Always print at least two digits in the exponent. - // This is for compatibility with printf("%g"). - *buf++ = '0'; - *buf++ = static_cast('0' + k); - } - else if (k < 100) - { - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } - else - { - *buf++ = static_cast('0' + k / 100); - k %= 100; - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } - - return buf; -} - -/*! -@brief prettify v = buf * 10^decimal_exponent - -If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point -notation. Otherwise it will be printed in exponential notation. - -@pre min_exp < 0 -@pre max_exp > 0 -*/ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* format_buffer(char* buf, int len, int decimal_exponent, - int min_exp, int max_exp) -{ - JSON_ASSERT(min_exp < 0); - JSON_ASSERT(max_exp > 0); - - const int k = len; - const int n = len + decimal_exponent; - - // v = buf * 10^(n-k) - // k is the length of the buffer (number of decimal digits) - // n is the position of the decimal point relative to the start of the buffer. - - if (k <= n && n <= max_exp) - { - // digits[000] - // len <= max_exp + 2 - - std::memset(buf + k, '0', static_cast(n) - static_cast(k)); - // Make it look like a floating-point number (#362, #378) - buf[n + 0] = '.'; - buf[n + 1] = '0'; - return buf + (static_cast(n) + 2); - } - - if (0 < n && n <= max_exp) - { - // dig.its - // len <= max_digits10 + 1 - - JSON_ASSERT(k > n); - - std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); - buf[n] = '.'; - return buf + (static_cast(k) + 1U); - } - - if (min_exp < n && n <= 0) - { - // 0.[000]digits - // len <= 2 + (-min_exp - 1) + max_digits10 - - std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); - buf[0] = '0'; - buf[1] = '.'; - std::memset(buf + 2, '0', static_cast(-n)); - return buf + (2U + static_cast(-n) + static_cast(k)); - } - - if (k == 1) - { - // dE+123 - // len <= 1 + 5 - - buf += 1; - } - else - { - // d.igitsE+123 - // len <= max_digits10 + 1 + 5 - - std::memmove(buf + 2, buf + 1, static_cast(k) - 1); - buf[1] = '.'; - buf += 1 + static_cast(k); - } - - *buf++ = 'e'; - return append_exponent(buf, n - 1); -} - -} // namespace dtoa_impl - -/*! -@brief generates a decimal representation of the floating-point number value in [first, last). - -The format of the resulting decimal representation is similar to printf's %g -format. Returns an iterator pointing past-the-end of the decimal representation. - -@note The input number must be finite, i.e. NaN's and Inf's are not supported. -@note The buffer must be large enough. -@note The result is NOT null-terminated. -*/ -template -JSON_HEDLEY_NON_NULL(1, 2) -JSON_HEDLEY_RETURNS_NON_NULL -char* to_chars(char* first, const char* last, FloatType value) -{ - static_cast(last); // maybe unused - fix warning - JSON_ASSERT(std::isfinite(value)); - - // Use signbit(value) instead of (value < 0) since signbit works for -0. - if (std::signbit(value)) - { - value = -value; - *first++ = '-'; - } - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - if (value == 0) // +-0 - { - *first++ = '0'; - // Make it look like a floating-point number (#362, #378) - *first++ = '.'; - *first++ = '0'; - return first; - } -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - - JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); - - // Compute v = buffer * 10^decimal_exponent. - // The decimal digits are stored in the buffer, which needs to be interpreted - // as an unsigned decimal integer. - // len is the length of the buffer, i.e. the number of decimal digits. - int len = 0; - int decimal_exponent = 0; - dtoa_impl::grisu2(first, len, decimal_exponent, value); - - JSON_ASSERT(len <= std::numeric_limits::max_digits10); - - // Format the buffer like printf("%.*g", prec, value) - constexpr int kMinExp = -4; - // Use digits10 here to increase compatibility with version 2. - constexpr int kMaxExp = std::numeric_limits::digits10; - - JSON_ASSERT(last - first >= kMaxExp + 2); - JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); - JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); - - return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); -} - -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/////////////////// -// serialization // -/////////////////// - -/// how to treat decoding errors -enum class error_handler_t -{ - strict, ///< throw a type_error exception in case of invalid UTF-8 - replace, ///< replace invalid UTF-8 sequences with U+FFFD - ignore ///< ignore invalid UTF-8 sequences -}; - -template -class serializer -{ - using string_t = typename BasicJsonType::string_t; - using number_float_t = typename BasicJsonType::number_float_t; - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using binary_char_t = typename BasicJsonType::binary_t::value_type; - static constexpr std::uint8_t UTF8_ACCEPT = 0; - static constexpr std::uint8_t UTF8_REJECT = 1; - - public: - /*! - @param[in] s output stream to serialize to - @param[in] ichar indentation character to use - @param[in] error_handler_ how to react on decoding errors - */ - serializer(output_adapter_t s, const char ichar, - error_handler_t error_handler_ = error_handler_t::strict) - : o(std::move(s)) - , loc(std::localeconv()) - , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))) - , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))) - , indent_char(ichar) - , indent_string(512, indent_char) - , error_handler(error_handler_) - {} - - // delete because of pointer members - serializer(const serializer&) = delete; - serializer& operator=(const serializer&) = delete; - serializer(serializer&&) = delete; - serializer& operator=(serializer&&) = delete; - ~serializer() = default; - - /*! - @brief internal implementation of the serialization function - - This function is called by the public member function dump and organizes - the serialization internally. The indentation level is propagated as - additional parameter. In case of arrays and objects, the function is - called recursively. - - - strings and object keys are escaped using `escape_string()` - - integer numbers are converted implicitly via `operator<<` - - floating-point numbers are converted to a string using `"%g"` format - - binary values are serialized as objects containing the subtype and the - byte array - - @param[in] val value to serialize - @param[in] pretty_print whether the output shall be pretty-printed - @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters - in the output are escaped with `\uXXXX` sequences, and the result consists - of ASCII characters only. - @param[in] indent_step the indent level - @param[in] current_indent the current indent level (only used internally) - */ - void dump(const BasicJsonType& val, - const bool pretty_print, - const bool ensure_ascii, - const unsigned int indent_step, - const unsigned int current_indent = 0) - { - switch (val.m_type) - { - case value_t::object: - { - if (val.m_value.object->empty()) - { - o->write_characters("{}", 2); - return; - } - - if (pretty_print) - { - o->write_characters("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o->write_characters(indent_string.c_str(), new_indent); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); - o->write_characters(",\n", 2); - } - - // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); - o->write_characters(indent_string.c_str(), new_indent); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); - - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character('}'); - } - else - { - o->write_character('{'); - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); - o->write_character(','); - } - - // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); - - o->write_character('}'); - } - - return; - } - - case value_t::array: - { - if (val.m_value.array->empty()) - { - o->write_characters("[]", 2); - return; - } - - if (pretty_print) - { - o->write_characters("[\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) - { - o->write_characters(indent_string.c_str(), new_indent); - dump(*i, true, ensure_ascii, indent_step, new_indent); - o->write_characters(",\n", 2); - } - - // last element - JSON_ASSERT(!val.m_value.array->empty()); - o->write_characters(indent_string.c_str(), new_indent); - dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); - - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character(']'); - } - else - { - o->write_character('['); - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) - { - dump(*i, false, ensure_ascii, indent_step, current_indent); - o->write_character(','); - } - - // last element - JSON_ASSERT(!val.m_value.array->empty()); - dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); - - o->write_character(']'); - } - - return; - } - - case value_t::string: - { - o->write_character('\"'); - dump_escaped(*val.m_value.string, ensure_ascii); - o->write_character('\"'); - return; - } - - case value_t::binary: - { - if (pretty_print) - { - o->write_characters("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - o->write_characters(indent_string.c_str(), new_indent); - - o->write_characters("\"bytes\": [", 10); - - if (!val.m_value.binary->empty()) - { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) - { - dump_integer(*i); - o->write_characters(", ", 2); - } - dump_integer(val.m_value.binary->back()); - } - - o->write_characters("],\n", 3); - o->write_characters(indent_string.c_str(), new_indent); - - o->write_characters("\"subtype\": ", 11); - if (val.m_value.binary->has_subtype()) - { - dump_integer(val.m_value.binary->subtype()); - } - else - { - o->write_characters("null", 4); - } - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character('}'); - } - else - { - o->write_characters("{\"bytes\":[", 10); - - if (!val.m_value.binary->empty()) - { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) - { - dump_integer(*i); - o->write_character(','); - } - dump_integer(val.m_value.binary->back()); - } - - o->write_characters("],\"subtype\":", 12); - if (val.m_value.binary->has_subtype()) - { - dump_integer(val.m_value.binary->subtype()); - o->write_character('}'); - } - else - { - o->write_characters("null}", 5); - } - } - return; - } - - case value_t::boolean: - { - if (val.m_value.boolean) - { - o->write_characters("true", 4); - } - else - { - o->write_characters("false", 5); - } - return; - } - - case value_t::number_integer: - { - dump_integer(val.m_value.number_integer); - return; - } - - case value_t::number_unsigned: - { - dump_integer(val.m_value.number_unsigned); - return; - } - - case value_t::number_float: - { - dump_float(val.m_value.number_float); - return; - } - - case value_t::discarded: - { - o->write_characters("", 11); - return; - } - - case value_t::null: - { - o->write_characters("null", 4); - return; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - } - } - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief dump escaped string - - Escape a string by replacing certain special characters by a sequence of an - escape character (backslash) and another character and other control - characters by a sequence of "\u" followed by a four-digit hex - representation. The escaped string is written to output stream @a o. - - @param[in] s the string to escape - @param[in] ensure_ascii whether to escape non-ASCII characters with - \uXXXX sequences - - @complexity Linear in the length of string @a s. - */ - void dump_escaped(const string_t& s, const bool ensure_ascii) - { - std::uint32_t codepoint{}; - std::uint8_t state = UTF8_ACCEPT; - std::size_t bytes = 0; // number of bytes written to string_buffer - - // number of bytes written at the point of the last valid byte - std::size_t bytes_after_last_accept = 0; - std::size_t undumped_chars = 0; - - for (std::size_t i = 0; i < s.size(); ++i) - { - const auto byte = static_cast(s[i]); - - switch (decode(state, codepoint, byte)) - { - case UTF8_ACCEPT: // decode found a new code point - { - switch (codepoint) - { - case 0x08: // backspace - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'b'; - break; - } - - case 0x09: // horizontal tab - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 't'; - break; - } - - case 0x0A: // newline - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'n'; - break; - } - - case 0x0C: // formfeed - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'f'; - break; - } - - case 0x0D: // carriage return - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'r'; - break; - } - - case 0x22: // quotation mark - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = '\"'; - break; - } - - case 0x5C: // reverse solidus - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = '\\'; - break; - } - - default: - { - // escape control characters (0x00..0x1F) or, if - // ensure_ascii parameter is used, non-ASCII characters - if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) - { - if (codepoint <= 0xFFFF) - { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", - static_cast(codepoint)); - bytes += 6; - } - else - { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", - static_cast(0xD7C0u + (codepoint >> 10u)), - static_cast(0xDC00u + (codepoint & 0x3FFu))); - bytes += 12; - } - } - else - { - // copy byte to buffer (all previous bytes - // been copied have in default case above) - string_buffer[bytes++] = s[i]; - } - break; - } - } - - // write buffer and reset index; there must be 13 bytes - // left, as this is the maximal number of bytes to be - // written ("\uxxxx\uxxxx\0") for one code point - if (string_buffer.size() - bytes < 13) - { - o->write_characters(string_buffer.data(), bytes); - bytes = 0; - } - - // remember the byte position of this accept - bytes_after_last_accept = bytes; - undumped_chars = 0; - break; - } - - case UTF8_REJECT: // decode found invalid UTF-8 byte - { - switch (error_handler) - { - case error_handler_t::strict: - { - std::string sn(9, '\0'); - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn, BasicJsonType())); - } - - case error_handler_t::ignore: - case error_handler_t::replace: - { - // in case we saw this character the first time, we - // would like to read it again, because the byte - // may be OK for itself, but just not OK for the - // previous sequence - if (undumped_chars > 0) - { - --i; - } - - // reset length buffer to the last accepted index; - // thus removing/ignoring the invalid characters - bytes = bytes_after_last_accept; - - if (error_handler == error_handler_t::replace) - { - // add a replacement character - if (ensure_ascii) - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'u'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'd'; - } - else - { - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xEF'); - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBF'); - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBD'); - } - - // write buffer and reset index; there must be 13 bytes - // left, as this is the maximal number of bytes to be - // written ("\uxxxx\uxxxx\0") for one code point - if (string_buffer.size() - bytes < 13) - { - o->write_characters(string_buffer.data(), bytes); - bytes = 0; - } - - bytes_after_last_accept = bytes; - } - - undumped_chars = 0; - - // continue processing the string - state = UTF8_ACCEPT; - break; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - } - break; - } - - default: // decode found yet incomplete multi-byte code point - { - if (!ensure_ascii) - { - // code point will not be escaped - copy byte to buffer - string_buffer[bytes++] = s[i]; - } - ++undumped_chars; - break; - } - } - } - - // we finished processing the string - if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) - { - // write buffer - if (bytes > 0) - { - o->write_characters(string_buffer.data(), bytes); - } - } - else - { - // we finish reading, but do not accept: string was incomplete - switch (error_handler) - { - case error_handler_t::strict: - { - std::string sn(9, '\0'); - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn, BasicJsonType())); - } - - case error_handler_t::ignore: - { - // write all accepted bytes - o->write_characters(string_buffer.data(), bytes_after_last_accept); - break; - } - - case error_handler_t::replace: - { - // write all accepted bytes - o->write_characters(string_buffer.data(), bytes_after_last_accept); - // add a replacement character - if (ensure_ascii) - { - o->write_characters("\\ufffd", 6); - } - else - { - o->write_characters("\xEF\xBF\xBD", 3); - } - break; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - } - } - } - - private: - /*! - @brief count digits - - Count the number of decimal (base 10) digits for an input unsigned integer. - - @param[in] x unsigned integer number to count its digits - @return number of decimal digits - */ - inline unsigned int count_digits(number_unsigned_t x) noexcept - { - unsigned int n_digits = 1; - for (;;) - { - if (x < 10) - { - return n_digits; - } - if (x < 100) - { - return n_digits + 1; - } - if (x < 1000) - { - return n_digits + 2; - } - if (x < 10000) - { - return n_digits + 3; - } - x = x / 10000u; - n_digits += 4; - } - } - - /*! - @brief dump an integer - - Dump a given integer to output stream @a o. Works internally with - @a number_buffer. - - @param[in] x integer number (signed or unsigned) to dump - @tparam NumberType either @a number_integer_t or @a number_unsigned_t - */ - template < typename NumberType, detail::enable_if_t < - std::is_integral::value || - std::is_same::value || - std::is_same::value || - std::is_same::value, - int > = 0 > - void dump_integer(NumberType x) - { - static constexpr std::array, 100> digits_to_99 - { - { - {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, - {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, - {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, - {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, - {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, - {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, - {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, - {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, - {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, - {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, - } - }; - - // special case for "0" - if (x == 0) - { - o->write_character('0'); - return; - } - - // use a pointer to fill the buffer - auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) - - const bool is_negative = std::is_signed::value && !(x >= 0); // see issue #755 - number_unsigned_t abs_value; - - unsigned int n_chars{}; - - if (is_negative) - { - *buffer_ptr = '-'; - abs_value = remove_sign(static_cast(x)); - - // account one more byte for the minus sign - n_chars = 1 + count_digits(abs_value); - } - else - { - abs_value = static_cast(x); - n_chars = count_digits(abs_value); - } - - // spare 1 byte for '\0' - JSON_ASSERT(n_chars < number_buffer.size() - 1); - - // jump to the end to generate the string from backward - // so we later avoid reversing the result - buffer_ptr += n_chars; - - // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu - // See: https://www.youtube.com/watch?v=o4-CwDo2zpg - while (abs_value >= 100) - { - const auto digits_index = static_cast((abs_value % 100)); - abs_value /= 100; - *(--buffer_ptr) = digits_to_99[digits_index][1]; - *(--buffer_ptr) = digits_to_99[digits_index][0]; - } - - if (abs_value >= 10) - { - const auto digits_index = static_cast(abs_value); - *(--buffer_ptr) = digits_to_99[digits_index][1]; - *(--buffer_ptr) = digits_to_99[digits_index][0]; - } - else - { - *(--buffer_ptr) = static_cast('0' + abs_value); - } - - o->write_characters(number_buffer.data(), n_chars); - } - - /*! - @brief dump a floating-point number - - Dump a given floating-point number to output stream @a o. Works internally - with @a number_buffer. - - @param[in] x floating-point number to dump - */ - void dump_float(number_float_t x) - { - // NaN / inf - if (!std::isfinite(x)) - { - o->write_characters("null", 4); - return; - } - - // If number_float_t is an IEEE-754 single or double precision number, - // use the Grisu2 algorithm to produce short numbers which are - // guaranteed to round-trip, using strtof and strtod, resp. - // - // NB: The test below works if == . - static constexpr bool is_ieee_single_or_double - = (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 24 && std::numeric_limits::max_exponent == 128) || - (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 53 && std::numeric_limits::max_exponent == 1024); - - dump_float(x, std::integral_constant()); - } - - void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) - { - auto* begin = number_buffer.data(); - auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); - - o->write_characters(begin, static_cast(end - begin)); - } - - void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) - { - // get number of digits for a float -> text -> float round-trip - static constexpr auto d = std::numeric_limits::max_digits10; - - // the actual conversion - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); - - // negative value indicates an error - JSON_ASSERT(len > 0); - // check if buffer was large enough - JSON_ASSERT(static_cast(len) < number_buffer.size()); - - // erase thousands separator - if (thousands_sep != '\0') - { - auto* const end = std::remove(number_buffer.begin(), - number_buffer.begin() + len, thousands_sep); - std::fill(end, number_buffer.end(), '\0'); - JSON_ASSERT((end - number_buffer.begin()) <= len); - len = (end - number_buffer.begin()); - } - - // convert decimal point to '.' - if (decimal_point != '\0' && decimal_point != '.') - { - auto* const dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); - if (dec_pos != number_buffer.end()) - { - *dec_pos = '.'; - } - } - - o->write_characters(number_buffer.data(), static_cast(len)); - - // determine if need to append ".0" - const bool value_is_int_like = - std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, - [](char c) - { - return c == '.' || c == 'e'; - }); - - if (value_is_int_like) - { - o->write_characters(".0", 2); - } - } - - /*! - @brief check whether a string is UTF-8 encoded - - The function checks each byte of a string whether it is UTF-8 encoded. The - result of the check is stored in the @a state parameter. The function must - be called initially with state 0 (accept). State 1 means the string must - be rejected, because the current byte is not allowed. If the string is - completely processed, but the state is non-zero, the string ended - prematurely; that is, the last byte indicated more bytes should have - followed. - - @param[in,out] state the state of the decoding - @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) - @param[in] byte next byte to decode - @return new state - - @note The function has been edited: a std::array is used. - - @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann - @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ - */ - static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept - { - static const std::array utf8d = - { - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF - 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF - 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF - 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF - 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 - 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 - 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 - 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 - } - }; - - JSON_ASSERT(byte < utf8d.size()); - const std::uint8_t type = utf8d[byte]; - - codep = (state != UTF8_ACCEPT) - ? (byte & 0x3fu) | (codep << 6u) - : (0xFFu >> type) & (byte); - - std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); - JSON_ASSERT(index < 400); - state = utf8d[index]; - return state; - } - - /* - * Overload to make the compiler happy while it is instantiating - * dump_integer for number_unsigned_t. - * Must never be called. - */ - number_unsigned_t remove_sign(number_unsigned_t x) - { - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - return x; // LCOV_EXCL_LINE - } - - /* - * Helper function for dump_integer - * - * This function takes a negative signed integer and returns its absolute - * value as unsigned integer. The plus/minus shuffling is necessary as we can - * not directly remove the sign of an arbitrary signed integer as the - * absolute values of INT_MIN and INT_MAX are usually not the same. See - * #1708 for details. - */ - inline number_unsigned_t remove_sign(number_integer_t x) noexcept - { - JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) - return static_cast(-(x + 1)) + 1; - } - - private: - /// the output of the serializer - output_adapter_t o = nullptr; - - /// a (hopefully) large enough character buffer - std::array number_buffer{{}}; - - /// the locale - const std::lconv* loc = nullptr; - /// the locale's thousand separator character - const char thousands_sep = '\0'; - /// the locale's decimal point character - const char decimal_point = '\0'; - - /// string buffer - std::array string_buffer{{}}; - - /// the indentation character - const char indent_char; - /// the indentation string - string_t indent_string; - - /// error_handler how to react on decoding errors - const error_handler_t error_handler; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include // less -#include // initializer_list -#include // input_iterator_tag, iterator_traits -#include // allocator -#include // for out_of_range -#include // enable_if, is_convertible -#include // pair -#include // vector - -// #include - - -namespace nlohmann -{ - -/// ordered_map: a minimal map-like container that preserves insertion order -/// for use within nlohmann::basic_json -template , - class Allocator = std::allocator>> - struct ordered_map : std::vector, Allocator> -{ - using key_type = Key; - using mapped_type = T; - using Container = std::vector, Allocator>; - using typename Container::iterator; - using typename Container::const_iterator; - using typename Container::size_type; - using typename Container::value_type; - - // Explicit constructors instead of `using Container::Container` - // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) - ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {} - template - ordered_map(It first, It last, const Allocator& alloc = Allocator()) - : Container{first, last, alloc} {} - ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) - : Container{init, alloc} {} - - std::pair emplace(const key_type& key, T&& t) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return {it, false}; - } - } - Container::emplace_back(key, t); - return {--this->end(), true}; - } - - T& operator[](const Key& key) - { - return emplace(key, T{}).first->second; - } - - const T& operator[](const Key& key) const - { - return at(key); - } - - T& at(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it->second; - } - } - - JSON_THROW(std::out_of_range("key not found")); - } - - const T& at(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it->second; - } - } - - JSON_THROW(std::out_of_range("key not found")); - } - - size_type erase(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - // Since we cannot move const Keys, re-construct them in place - for (auto next = it; ++next != this->end(); ++it) - { - it->~value_type(); // Destroy but keep allocation - new (&*it) value_type{std::move(*next)}; - } - Container::pop_back(); - return 1; - } - } - return 0; - } - - iterator erase(iterator pos) - { - auto it = pos; - - // Since we cannot move const Keys, re-construct them in place - for (auto next = it; ++next != this->end(); ++it) - { - it->~value_type(); // Destroy but keep allocation - new (&*it) value_type{std::move(*next)}; - } - Container::pop_back(); - return pos; - } - - size_type count(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return 1; - } - } - return 0; - } - - iterator find(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it; - } - } - return Container::end(); - } - - const_iterator find(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it; - } - } - return Container::end(); - } - - std::pair insert( value_type&& value ) - { - return emplace(value.first, std::move(value.second)); - } - - std::pair insert( const value_type& value ) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == value.first) - { - return {it, false}; - } - } - Container::push_back(value); - return {--this->end(), true}; - } - - template - using require_input_iter = typename std::enable_if::iterator_category, - std::input_iterator_tag>::value>::type; - - template> - void insert(InputIt first, InputIt last) - { - for (auto it = first; it != last; ++it) - { - insert(*it); - } - } -}; - -} // namespace nlohmann - - -#if defined(JSON_HAS_CPP_17) - #include -#endif - -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ - -/*! -@brief a class to store JSON values - -@tparam ObjectType type for JSON objects (`std::map` by default; will be used -in @ref object_t) -@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used -in @ref array_t) -@tparam StringType type for JSON strings and object keys (`std::string` by -default; will be used in @ref string_t) -@tparam BooleanType type for JSON booleans (`bool` by default; will be used -in @ref boolean_t) -@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by -default; will be used in @ref number_integer_t) -@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c -`uint64_t` by default; will be used in @ref number_unsigned_t) -@tparam NumberFloatType type for JSON floating-point numbers (`double` by -default; will be used in @ref number_float_t) -@tparam BinaryType type for packed binary data for compatibility with binary -serialization formats (`std::vector` by default; will be used in -@ref binary_t) -@tparam AllocatorType type of the allocator to use (`std::allocator` by -default) -@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` -and `from_json()` (@ref adl_serializer by default) - -@requirement The class satisfies the following concept requirements: -- Basic - - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null - value. - - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible): - A JSON value can be constructed from an rvalue argument. - - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible): - A JSON value can be copy-constructed from an lvalue expression. - - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable): - A JSON value van be assigned from an rvalue argument. - - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable): - A JSON value can be copy-assigned from an lvalue expression. - - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible): - JSON values can be destructed. -- Layout - - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType): - JSON values have - [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the - class has no virtual functions or (virtual) base classes. -- Library-wide - - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable): - JSON values can be compared with `==`, see @ref - operator==(const_reference,const_reference). - - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable): - JSON values can be compared with `<`, see @ref - operator<(const_reference,const_reference). - - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable): - Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of - other compatible types, using unqualified function call @ref swap(). - - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer): - JSON values can be compared against `std::nullptr_t` objects which are used - to model the `null` value. -- Container - - [Container](https://en.cppreference.com/w/cpp/named_req/Container): - JSON values can be used like STL containers and provide iterator access. - - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer); - JSON values can be used like STL containers and provide reverse iterator - access. - -@invariant The member variables @a m_value and @a m_type have the following -relationship: -- If `m_type == value_t::object`, then `m_value.object != nullptr`. -- If `m_type == value_t::array`, then `m_value.array != nullptr`. -- If `m_type == value_t::string`, then `m_value.string != nullptr`. -The invariants are checked by member function assert_invariant(). - -@internal -@note ObjectType trick from https://stackoverflow.com/a/9860911 -@endinternal - -@see [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange -Format](https://tools.ietf.org/html/rfc8259) - -@since version 1.0.0 - -@nosubgrouping -*/ -NLOHMANN_BASIC_JSON_TPL_DECLARATION -class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) -{ - private: - template friend struct detail::external_constructor; - friend ::nlohmann::json_pointer; - - template - friend class ::nlohmann::detail::parser; - friend ::nlohmann::detail::serializer; - template - friend class ::nlohmann::detail::iter_impl; - template - friend class ::nlohmann::detail::binary_writer; - template - friend class ::nlohmann::detail::binary_reader; - template - friend class ::nlohmann::detail::json_sax_dom_parser; - template - friend class ::nlohmann::detail::json_sax_dom_callback_parser; - friend class ::nlohmann::detail::exception; - - /// workaround type for MSVC - using basic_json_t = NLOHMANN_BASIC_JSON_TPL; - - JSON_PRIVATE_UNLESS_TESTED: - // convenience aliases for types residing in namespace detail; - using lexer = ::nlohmann::detail::lexer_base; - - template - static ::nlohmann::detail::parser parser( - InputAdapterType adapter, - detail::parser_callback_tcb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false - ) - { - return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments); - } - - private: - using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; - template - using internal_iterator = ::nlohmann::detail::internal_iterator; - template - using iter_impl = ::nlohmann::detail::iter_impl; - template - using iteration_proxy = ::nlohmann::detail::iteration_proxy; - template using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator; - - template - using output_adapter_t = ::nlohmann::detail::output_adapter_t; - - template - using binary_reader = ::nlohmann::detail::binary_reader; - template using binary_writer = ::nlohmann::detail::binary_writer; - - JSON_PRIVATE_UNLESS_TESTED: - using serializer = ::nlohmann::detail::serializer; - - public: - using value_t = detail::value_t; - /// JSON Pointer, see @ref nlohmann::json_pointer - using json_pointer = ::nlohmann::json_pointer; - template - using json_serializer = JSONSerializer; - /// how to treat decoding errors - using error_handler_t = detail::error_handler_t; - /// how to treat CBOR tags - using cbor_tag_handler_t = detail::cbor_tag_handler_t; - /// helper type for initializer lists of basic_json values - using initializer_list_t = std::initializer_list>; - - using input_format_t = detail::input_format_t; - /// SAX interface type, see @ref nlohmann::json_sax - using json_sax_t = json_sax; - - //////////////// - // exceptions // - //////////////// - - /// @name exceptions - /// Classes to implement user-defined exceptions. - /// @{ - - /// @copydoc detail::exception - using exception = detail::exception; - /// @copydoc detail::parse_error - using parse_error = detail::parse_error; - /// @copydoc detail::invalid_iterator - using invalid_iterator = detail::invalid_iterator; - /// @copydoc detail::type_error - using type_error = detail::type_error; - /// @copydoc detail::out_of_range - using out_of_range = detail::out_of_range; - /// @copydoc detail::other_error - using other_error = detail::other_error; - - /// @} - - - ///////////////////// - // container types // - ///////////////////// - - /// @name container types - /// The canonic container types to use @ref basic_json like any other STL - /// container. - /// @{ - - /// the type of elements in a basic_json container - using value_type = basic_json; - - /// the type of an element reference - using reference = value_type&; - /// the type of an element const reference - using const_reference = const value_type&; - - /// a type to represent differences between iterators - using difference_type = std::ptrdiff_t; - /// a type to represent container sizes - using size_type = std::size_t; - - /// the allocator type - using allocator_type = AllocatorType; - - /// the type of an element pointer - using pointer = typename std::allocator_traits::pointer; - /// the type of an element const pointer - using const_pointer = typename std::allocator_traits::const_pointer; - - /// an iterator for a basic_json container - using iterator = iter_impl; - /// a const iterator for a basic_json container - using const_iterator = iter_impl; - /// a reverse iterator for a basic_json container - using reverse_iterator = json_reverse_iterator; - /// a const reverse iterator for a basic_json container - using const_reverse_iterator = json_reverse_iterator; - - /// @} - - - /*! - @brief returns the allocator associated with the container - */ - static allocator_type get_allocator() - { - return allocator_type(); - } - - /*! - @brief returns version information on the library - - This function returns a JSON object with information about the library, - including the version number and information on the platform and compiler. - - @return JSON object holding version information - key | description - ----------- | --------------- - `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). - `copyright` | The copyright line for the library as string. - `name` | The name of the library as string. - `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. - `url` | The URL of the project as string. - `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). - - @liveexample{The following code shows an example output of the `meta()` - function.,meta} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @complexity Constant. - - @since 2.1.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json meta() - { - basic_json result; - - result["copyright"] = "(C) 2013-2021 Niels Lohmann"; - result["name"] = "JSON for Modern C++"; - result["url"] = "https://github.com/nlohmann/json"; - result["version"]["string"] = - std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + - std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + - std::to_string(NLOHMANN_JSON_VERSION_PATCH); - result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; - result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; - result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; - -#ifdef _WIN32 - result["platform"] = "win32"; -#elif defined __linux__ - result["platform"] = "linux"; -#elif defined __APPLE__ - result["platform"] = "apple"; -#elif defined __unix__ - result["platform"] = "unix"; -#else - result["platform"] = "unknown"; -#endif - -#if defined(__ICC) || defined(__INTEL_COMPILER) - result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; -#elif defined(__clang__) - result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; -#elif defined(__GNUC__) || defined(__GNUG__) - result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; -#elif defined(__HP_cc) || defined(__HP_aCC) - result["compiler"] = "hp" -#elif defined(__IBMCPP__) - result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; -#elif defined(_MSC_VER) - result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; -#elif defined(__PGI) - result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; -#elif defined(__SUNPRO_CC) - result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; -#else - result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; -#endif - -#ifdef __cplusplus - result["compiler"]["c++"] = std::to_string(__cplusplus); -#else - result["compiler"]["c++"] = "unknown"; -#endif - return result; - } - - - /////////////////////////// - // JSON value data types // - /////////////////////////// - - /// @name JSON value data types - /// The data types to store a JSON value. These types are derived from - /// the template arguments passed to class @ref basic_json. - /// @{ - -#if defined(JSON_HAS_CPP_14) - // Use transparent comparator if possible, combined with perfect forwarding - // on find() and count() calls prevents unnecessary string construction. - using object_comparator_t = std::less<>; -#else - using object_comparator_t = std::less; -#endif - - /*! - @brief a type for an object - - [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON objects as follows: - > An object is an unordered collection of zero or more name/value pairs, - > where a name is a string and a value is a string, number, boolean, null, - > object, or array. - - To store objects in C++, a type is defined by the template parameters - described below. - - @tparam ObjectType the container to store objects (e.g., `std::map` or - `std::unordered_map`) - @tparam StringType the type of the keys or names (e.g., `std::string`). - The comparison function `std::less` is used to order elements - inside the container. - @tparam AllocatorType the allocator to use for objects (e.g., - `std::allocator`) - - #### Default type - - With the default values for @a ObjectType (`std::map`), @a StringType - (`std::string`), and @a AllocatorType (`std::allocator`), the default - value for @a object_t is: - - @code {.cpp} - std::map< - std::string, // key_type - basic_json, // value_type - std::less, // key_compare - std::allocator> // allocator_type - > - @endcode - - #### Behavior - - The choice of @a object_t influences the behavior of the JSON class. With - the default type, objects have the following behavior: - - - When all names are unique, objects will be interoperable in the sense - that all software implementations receiving that object will agree on - the name-value mappings. - - When the names within an object are not unique, it is unspecified which - one of the values for a given key will be chosen. For instance, - `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or - `{"key": 2}`. - - Internally, name/value pairs are stored in lexicographical order of the - names. Objects will also be serialized (see @ref dump) in this order. - For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored - and serialized as `{"a": 2, "b": 1}`. - - When comparing objects, the order of the name/value pairs is irrelevant. - This makes objects interoperable in the sense that they will not be - affected by these differences. For instance, `{"b": 1, "a": 2}` and - `{"a": 2, "b": 1}` will be treated as equal. - - #### Limits - - [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the object's limit of nesting is not explicitly constrained. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON object. - - #### Storage - - Objects are stored as pointers in a @ref basic_json type. That is, for any - access to object values, a pointer of type `object_t*` must be - dereferenced. - - @sa see @ref array_t -- type for an array value - - @since version 1.0.0 - - @note The order name/value pairs are added to the object is *not* - preserved by the library. Therefore, iterating an object may return - name/value pairs in a different order than they were originally stored. In - fact, keys will be traversed in alphabetical order as `std::map` with - `std::less` is used by default. Please note this behavior conforms to [RFC - 8259](https://tools.ietf.org/html/rfc8259), because any order implements the - specified "unordered" nature of JSON objects. - */ - using object_t = ObjectType>>; - - /*! - @brief a type for an array - - [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON arrays as follows: - > An array is an ordered sequence of zero or more values. - - To store objects in C++, a type is defined by the template parameters - explained below. - - @tparam ArrayType container type to store arrays (e.g., `std::vector` or - `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) - - #### Default type - - With the default values for @a ArrayType (`std::vector`) and @a - AllocatorType (`std::allocator`), the default value for @a array_t is: - - @code {.cpp} - std::vector< - basic_json, // value_type - std::allocator // allocator_type - > - @endcode - - #### Limits - - [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the array's limit of nesting is not explicitly constrained. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON array. - - #### Storage - - Arrays are stored as pointers in a @ref basic_json type. That is, for any - access to array values, a pointer of type `array_t*` must be dereferenced. - - @sa see @ref object_t -- type for an object value - - @since version 1.0.0 - */ - using array_t = ArrayType>; - - /*! - @brief a type for a string - - [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON strings as follows: - > A string is a sequence of zero or more Unicode characters. - - To store objects in C++, a type is defined by the template parameter - described below. Unicode values are split by the JSON class into - byte-sized characters during deserialization. - - @tparam StringType the container to store strings (e.g., `std::string`). - Note this container is used for keys/names in objects, see @ref object_t. - - #### Default type - - With the default values for @a StringType (`std::string`), the default - value for @a string_t is: - - @code {.cpp} - std::string - @endcode - - #### Encoding - - Strings are stored in UTF-8 encoding. Therefore, functions like - `std::string::size()` or `std::string::length()` return the number of - bytes in the string rather than the number of characters or glyphs. - - #### String comparison - - [RFC 8259](https://tools.ietf.org/html/rfc8259) states: - > Software implementations are typically required to test names of object - > members for equality. Implementations that transform the textual - > representation into sequences of Unicode code units and then perform the - > comparison numerically, code unit by code unit, are interoperable in the - > sense that implementations will agree in all cases on equality or - > inequality of two strings. For example, implementations that compare - > strings with escaped characters unconverted may incorrectly find that - > `"a\\b"` and `"a\u005Cb"` are not equal. - - This implementation is interoperable as it does compare strings code unit - by code unit. - - #### Storage - - String values are stored as pointers in a @ref basic_json type. That is, - for any access to string values, a pointer of type `string_t*` must be - dereferenced. - - @since version 1.0.0 - */ - using string_t = StringType; - - /*! - @brief a type for a boolean - - [RFC 8259](https://tools.ietf.org/html/rfc8259) implicitly describes a boolean as a - type which differentiates the two literals `true` and `false`. - - To store objects in C++, a type is defined by the template parameter @a - BooleanType which chooses the type to use. - - #### Default type - - With the default values for @a BooleanType (`bool`), the default value for - @a boolean_t is: - - @code {.cpp} - bool - @endcode - - #### Storage - - Boolean values are stored directly inside a @ref basic_json type. - - @since version 1.0.0 - */ - using boolean_t = BooleanType; - - /*! - @brief a type for a number (integer) - - [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store integer numbers in C++, a type is defined by the template - parameter @a NumberIntegerType which chooses the type to use. - - #### Default type - - With the default values for @a NumberIntegerType (`int64_t`), the default - value for @a number_integer_t is: - - @code {.cpp} - int64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `9223372036854775807` (INT64_MAX) and the minimal integer number - that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers - that are out of range will yield over/underflow when used in a - constructor. During deserialization, too large or small integer numbers - will be automatically be stored as @ref number_unsigned_t or @ref - number_float_t. - - [RFC 8259](https://tools.ietf.org/html/rfc8259) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange of the exactly supported range [INT64_MIN, - INT64_MAX], this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa see @ref number_float_t -- type for number values (floating-point) - - @sa see @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_integer_t = NumberIntegerType; - - /*! - @brief a type for a number (unsigned) - - [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store unsigned integer numbers in C++, a type is defined by the - template parameter @a NumberUnsignedType which chooses the type to use. - - #### Default type - - With the default values for @a NumberUnsignedType (`uint64_t`), the - default value for @a number_unsigned_t is: - - @code {.cpp} - uint64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `18446744073709551615` (UINT64_MAX) and the minimal integer - number that can be stored is `0`. Integer numbers that are out of range - will yield over/underflow when used in a constructor. During - deserialization, too large or small integer numbers will be automatically - be stored as @ref number_integer_t or @ref number_float_t. - - [RFC 8259](https://tools.ietf.org/html/rfc8259) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], - this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa see @ref number_float_t -- type for number values (floating-point) - @sa see @ref number_integer_t -- type for number values (integer) - - @since version 2.0.0 - */ - using number_unsigned_t = NumberUnsignedType; - - /*! - @brief a type for a number (floating-point) - - [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store floating-point numbers in C++, a type is defined by the template - parameter @a NumberFloatType which chooses the type to use. - - #### Default type - - With the default values for @a NumberFloatType (`double`), the default - value for @a number_float_t is: - - @code {.cpp} - double - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in floating-point literals will be ignored. Internally, - the value will be stored as decimal number. For instance, the C++ - floating-point literal `01.2` will be serialized to `1.2`. During - deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 8259](https://tools.ietf.org/html/rfc8259) states: - > This specification allows implementations to set limits on the range and - > precision of numbers accepted. Since software that implements IEEE - > 754-2008 binary64 (double precision) numbers is generally available and - > widely used, good interoperability can be achieved by implementations - > that expect no more precision or range than these provide, in the sense - > that implementations will approximate JSON numbers within the expected - > precision. - - This implementation does exactly follow this approach, as it uses double - precision floating-point numbers. Note values smaller than - `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` - will be stored as NaN internally and be serialized to `null`. - - #### Storage - - Floating-point number values are stored directly inside a @ref basic_json - type. - - @sa see @ref number_integer_t -- type for number values (integer) - - @sa see @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_float_t = NumberFloatType; - - /*! - @brief a type for a packed binary type - - This type is a type designed to carry binary data that appears in various - serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and - BSON's generic binary subtype. This type is NOT a part of standard JSON and - exists solely for compatibility with these binary types. As such, it is - simply defined as an ordered sequence of zero or more byte values. - - Additionally, as an implementation detail, the subtype of the binary data is - carried around as a `std::uint8_t`, which is compatible with both of the - binary data formats that use binary subtyping, (though the specific - numbering is incompatible with each other, and it is up to the user to - translate between them). - - [CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type - as: - > Major type 2: a byte string. The string's length in bytes is represented - > following the rules for positive integers (major type 0). - - [MessagePack's documentation on the bin type - family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family) - describes this type as: - > Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes - > in addition to the size of the byte array. - - [BSON's specifications](http://bsonspec.org/spec.html) describe several - binary types; however, this type is intended to represent the generic binary - type which has the description: - > Generic binary subtype - This is the most commonly used binary subtype and - > should be the 'default' for drivers and tools. - - None of these impose any limitations on the internal representation other - than the basic unit of storage be some type of array whose parts are - decomposable into bytes. - - The default representation of this binary format is a - `std::vector`, which is a very common way to represent a byte - array in modern C++. - - #### Default type - - The default values for @a BinaryType is `std::vector` - - #### Storage - - Binary Arrays are stored as pointers in a @ref basic_json type. That is, - for any access to array values, a pointer of the type `binary_t*` must be - dereferenced. - - #### Notes on subtypes - - - CBOR - - Binary values are represented as byte strings. Subtypes are serialized - as tagged values. - - MessagePack - - If a subtype is given and the binary array contains exactly 1, 2, 4, 8, - or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8) - is used. For other sizes, the ext family (ext8, ext16, ext32) is used. - The subtype is then added as singed 8-bit integer. - - If no subtype is given, the bin family (bin8, bin16, bin32) is used. - - BSON - - If a subtype is given, it is used and added as unsigned 8-bit integer. - - If no subtype is given, the generic binary subtype 0x00 is used. - - @sa see @ref binary -- create a binary array - - @since version 3.8.0 - */ - using binary_t = nlohmann::byte_container_with_subtype; - /// @} - - private: - - /// helper for exception-safe object creation - template - JSON_HEDLEY_RETURNS_NON_NULL - static T* create(Args&& ... args) - { - AllocatorType alloc; - using AllocatorTraits = std::allocator_traits>; - - auto deleter = [&](T * obj) - { - AllocatorTraits::deallocate(alloc, obj, 1); - }; - std::unique_ptr obj(AllocatorTraits::allocate(alloc, 1), deleter); - AllocatorTraits::construct(alloc, obj.get(), std::forward(args)...); - JSON_ASSERT(obj != nullptr); - return obj.release(); - } - - //////////////////////// - // JSON value storage // - //////////////////////// - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief a JSON value - - The actual storage for a JSON value of the @ref basic_json class. This - union combines the different storage types for the JSON value types - defined in @ref value_t. - - JSON type | value_t type | used type - --------- | --------------- | ------------------------ - object | object | pointer to @ref object_t - array | array | pointer to @ref array_t - string | string | pointer to @ref string_t - boolean | boolean | @ref boolean_t - number | number_integer | @ref number_integer_t - number | number_unsigned | @ref number_unsigned_t - number | number_float | @ref number_float_t - binary | binary | pointer to @ref binary_t - null | null | *no value is stored* - - @note Variable-length types (objects, arrays, and strings) are stored as - pointers. The size of the union should not exceed 64 bits if the default - value types are used. - - @since version 1.0.0 - */ - union json_value - { - /// object (stored with pointer to save storage) - object_t* object; - /// array (stored with pointer to save storage) - array_t* array; - /// string (stored with pointer to save storage) - string_t* string; - /// binary (stored with pointer to save storage) - binary_t* binary; - /// boolean - boolean_t boolean; - /// number (integer) - number_integer_t number_integer; - /// number (unsigned integer) - number_unsigned_t number_unsigned; - /// number (floating-point) - number_float_t number_float; - - /// default constructor (for null values) - json_value() = default; - /// constructor for booleans - json_value(boolean_t v) noexcept : boolean(v) {} - /// constructor for numbers (integer) - json_value(number_integer_t v) noexcept : number_integer(v) {} - /// constructor for numbers (unsigned) - json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} - /// constructor for numbers (floating-point) - json_value(number_float_t v) noexcept : number_float(v) {} - /// constructor for empty values of a given type - json_value(value_t t) - { - switch (t) - { - case value_t::object: - { - object = create(); - break; - } - - case value_t::array: - { - array = create(); - break; - } - - case value_t::string: - { - string = create(""); - break; - } - - case value_t::binary: - { - binary = create(); - break; - } - - case value_t::boolean: - { - boolean = boolean_t(false); - break; - } - - case value_t::number_integer: - { - number_integer = number_integer_t(0); - break; - } - - case value_t::number_unsigned: - { - number_unsigned = number_unsigned_t(0); - break; - } - - case value_t::number_float: - { - number_float = number_float_t(0.0); - break; - } - - case value_t::null: - { - object = nullptr; // silence warning, see #821 - break; - } - - case value_t::discarded: - default: - { - object = nullptr; // silence warning, see #821 - if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) - { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.2", basic_json())); // LCOV_EXCL_LINE - } - break; - } - } - } - - /// constructor for strings - json_value(const string_t& value) - { - string = create(value); - } - - /// constructor for rvalue strings - json_value(string_t&& value) - { - string = create(std::move(value)); - } - - /// constructor for objects - json_value(const object_t& value) - { - object = create(value); - } - - /// constructor for rvalue objects - json_value(object_t&& value) - { - object = create(std::move(value)); - } - - /// constructor for arrays - json_value(const array_t& value) - { - array = create(value); - } - - /// constructor for rvalue arrays - json_value(array_t&& value) - { - array = create(std::move(value)); - } - - /// constructor for binary arrays - json_value(const typename binary_t::container_type& value) - { - binary = create(value); - } - - /// constructor for rvalue binary arrays - json_value(typename binary_t::container_type&& value) - { - binary = create(std::move(value)); - } - - /// constructor for binary arrays (internal type) - json_value(const binary_t& value) - { - binary = create(value); - } - - /// constructor for rvalue binary arrays (internal type) - json_value(binary_t&& value) - { - binary = create(std::move(value)); - } - - void destroy(value_t t) - { - if (t == value_t::array || t == value_t::object) - { - // flatten the current json_value to a heap-allocated stack - std::vector stack; - - // move the top-level items to stack - if (t == value_t::array) - { - stack.reserve(array->size()); - std::move(array->begin(), array->end(), std::back_inserter(stack)); - } - else - { - stack.reserve(object->size()); - for (auto&& it : *object) - { - stack.push_back(std::move(it.second)); - } - } - - while (!stack.empty()) - { - // move the last item to local variable to be processed - basic_json current_item(std::move(stack.back())); - stack.pop_back(); - - // if current_item is array/object, move - // its children to the stack to be processed later - if (current_item.is_array()) - { - std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); - - current_item.m_value.array->clear(); - } - else if (current_item.is_object()) - { - for (auto&& it : *current_item.m_value.object) - { - stack.push_back(std::move(it.second)); - } - - current_item.m_value.object->clear(); - } - - // it's now safe that current_item get destructed - // since it doesn't have any children - } - } - - switch (t) - { - case value_t::object: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, object); - std::allocator_traits::deallocate(alloc, object, 1); - break; - } - - case value_t::array: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, array); - std::allocator_traits::deallocate(alloc, array, 1); - break; - } - - case value_t::string: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, string); - std::allocator_traits::deallocate(alloc, string, 1); - break; - } - - case value_t::binary: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, binary); - std::allocator_traits::deallocate(alloc, binary, 1); - break; - } - - case value_t::null: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::discarded: - default: - { - break; - } - } - } - }; - - private: - /*! - @brief checks the class invariants - - This function asserts the class invariants. It needs to be called at the - end of every constructor to make sure that created objects respect the - invariant. Furthermore, it has to be called each time the type of a JSON - value is changed, because the invariant expresses a relationship between - @a m_type and @a m_value. - - Furthermore, the parent relation is checked for arrays and objects: If - @a check_parents true and the value is an array or object, then the - container's elements must have the current value as parent. - - @param[in] check_parents whether the parent relation should be checked. - The value is true by default and should only be set to false - during destruction of objects when the invariant does not - need to hold. - */ - void assert_invariant(bool check_parents = true) const noexcept - { - JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); - JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); - JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); - JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); - -#if JSON_DIAGNOSTICS - JSON_TRY - { - // cppcheck-suppress assertWithSideEffect - JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) - { - return j.m_parent == this; - })); - } - JSON_CATCH(...) {} // LCOV_EXCL_LINE -#endif - static_cast(check_parents); - } - - void set_parents() - { -#if JSON_DIAGNOSTICS - switch (m_type) - { - case value_t::array: - { - for (auto& element : *m_value.array) - { - element.m_parent = this; - } - break; - } - - case value_t::object: - { - for (auto& element : *m_value.object) - { - element.second.m_parent = this; - } - break; - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - break; - } -#endif - } - - iterator set_parents(iterator it, typename iterator::difference_type count) - { -#if JSON_DIAGNOSTICS - for (typename iterator::difference_type i = 0; i < count; ++i) - { - (it + i)->m_parent = this; - } -#else - static_cast(count); -#endif - return it; - } - - reference set_parent(reference j, std::size_t old_capacity = std::size_t(-1)) - { -#if JSON_DIAGNOSTICS - if (old_capacity != std::size_t(-1)) - { - // see https://github.com/nlohmann/json/issues/2838 - JSON_ASSERT(type() == value_t::array); - if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) - { - // capacity has changed: update all parents - set_parents(); - return j; - } - } - - // ordered_json uses a vector internally, so pointers could have - // been invalidated; see https://github.com/nlohmann/json/issues/2962 -#ifdef JSON_HEDLEY_MSVC_VERSION -#pragma warning(push ) -#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr -#endif - if (detail::is_ordered_map::value) - { - set_parents(); - return j; - } -#ifdef JSON_HEDLEY_MSVC_VERSION -#pragma warning( pop ) -#endif - - j.m_parent = this; -#else - static_cast(j); - static_cast(old_capacity); -#endif - return j; - } - - public: - ////////////////////////// - // JSON parser callback // - ////////////////////////// - - /*! - @brief parser event types - - The parser callback distinguishes the following events: - - `object_start`: the parser read `{` and started to process a JSON object - - `key`: the parser read a key of a value in an object - - `object_end`: the parser read `}` and finished processing a JSON object - - `array_start`: the parser read `[` and started to process a JSON array - - `array_end`: the parser read `]` and finished processing a JSON array - - `value`: the parser finished reading a JSON value - - @image html callback_events.png "Example when certain parse events are triggered" - - @sa see @ref parser_callback_t for more information and examples - */ - using parse_event_t = detail::parse_event_t; - - /*! - @brief per-element parser callback type - - With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse, it is called on certain events - (passed as @ref parse_event_t via parameter @a event) with a set recursion - depth @a depth and context JSON value @a parsed. The return value of the - callback function is a boolean indicating whether the element that emitted - the callback shall be kept or not. - - We distinguish six scenarios (determined by the event type) in which the - callback function can be called. The following table describes the values - of the parameters @a depth, @a event, and @a parsed. - - parameter @a event | description | parameter @a depth | parameter @a parsed - ------------------ | ----------- | ------------------ | ------------------- - parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded - parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key - parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object - parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded - parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array - parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value - - @image html callback_events.png "Example when certain parse events are triggered" - - Discarding a value (i.e., returning `false`) has different effects - depending on the context in which function was called: - - - Discarded values in structured types are skipped. That is, the parser - will behave as if the discarded value was never read. - - In case a value outside a structured type is skipped, it is replaced - with `null`. This case happens if the top-level element is skipped. - - @param[in] depth the depth of the recursion during parsing - - @param[in] event an event of type parse_event_t indicating the context in - the callback function has been called - - @param[in,out] parsed the current intermediate parse result; note that - writing to this value has no effect for parse_event_t::key events - - @return Whether the JSON value which called the function during parsing - should be kept (`true`) or not (`false`). In the latter case, it is either - skipped completely or replaced by an empty discarded object. - - @sa see @ref parse for examples - - @since version 1.0.0 - */ - using parser_callback_t = detail::parser_callback_t; - - ////////////////// - // constructors // - ////////////////// - - /// @name constructors and destructors - /// Constructors of class @ref basic_json, copy/move constructor, copy - /// assignment, static functions creating objects, and the destructor. - /// @{ - - /*! - @brief create an empty value with a given type - - Create an empty JSON value with a given type. The value will be default - initialized with an empty value which depends on the type: - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - object | `{}` - array | `[]` - binary | empty array - - @param[in] v the type of the value to create - - @complexity Constant. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows the constructor for different @ref - value_t values,basic_json__value_t} - - @sa see @ref clear() -- restores the postcondition of this constructor - - @since version 1.0.0 - */ - basic_json(const value_t v) - : m_type(v), m_value(v) - { - assert_invariant(); - } - - /*! - @brief create a null object - - Create a `null` JSON value. It either takes a null pointer as parameter - (explicitly creating `null`) or no parameter (implicitly creating `null`). - The passed null pointer itself is not read -- it is only used to choose - the right constructor. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. - - @liveexample{The following code shows the constructor with and without a - null pointer parameter.,basic_json__nullptr_t} - - @since version 1.0.0 - */ - basic_json(std::nullptr_t = nullptr) noexcept - : basic_json(value_t::null) - { - assert_invariant(); - } - - /*! - @brief create a JSON value - - This is a "catch all" constructor for all compatible JSON types; that is, - types for which a `to_json()` method exists. The constructor forwards the - parameter @a val to that method (to `json_serializer::to_json` method - with `U = uncvref_t`, to be exact). - - Template type @a CompatibleType includes, but is not limited to, the - following types: - - **arrays**: @ref array_t and all kinds of compatible containers such as - `std::vector`, `std::deque`, `std::list`, `std::forward_list`, - `std::array`, `std::valarray`, `std::set`, `std::unordered_set`, - `std::multiset`, and `std::unordered_multiset` with a `value_type` from - which a @ref basic_json value can be constructed. - - **objects**: @ref object_t and all kinds of compatible associative - containers such as `std::map`, `std::unordered_map`, `std::multimap`, - and `std::unordered_multimap` with a `key_type` compatible to - @ref string_t and a `value_type` from which a @ref basic_json value can - be constructed. - - **strings**: @ref string_t, string literals, and all compatible string - containers can be used. - - **numbers**: @ref number_integer_t, @ref number_unsigned_t, - @ref number_float_t, and all convertible number types such as `int`, - `size_t`, `int64_t`, `float` or `double` can be used. - - **boolean**: @ref boolean_t / `bool` can be used. - - **binary**: @ref binary_t / `std::vector` may be used, - unfortunately because string literals cannot be distinguished from binary - character arrays by the C++ type system, all types compatible with `const - char*` will be directed to the string constructor instead. This is both - for backwards compatibility, and due to the fact that a binary type is not - a standard JSON type. - - See the examples below. - - @tparam CompatibleType a type such that: - - @a CompatibleType is not derived from `std::istream`, - - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move - constructors), - - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments) - - @a CompatibleType is not a @ref basic_json nested type (e.g., - @ref json_pointer, @ref iterator, etc ...) - - `json_serializer` has a `to_json(basic_json_t&, CompatibleType&&)` method - - @tparam U = `uncvref_t` - - @param[in] val the value to be forwarded to the respective constructor - - @complexity Usually linear in the size of the passed @a val, also - depending on the implementation of the called `to_json()` - method. - - @exceptionsafety Depends on the called constructor. For types directly - supported by the library (i.e., all types for which no `to_json()` function - was provided), strong guarantee holds: if an exception is thrown, there are - no changes to any JSON value. - - @liveexample{The following code shows the constructor with several - compatible types.,basic_json__CompatibleType} - - @since version 2.1.0 - */ - template < typename CompatibleType, - typename U = detail::uncvref_t, - detail::enable_if_t < - !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > - basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) - JSONSerializer::to_json(std::declval(), - std::forward(val)))) - { - JSONSerializer::to_json(*this, std::forward(val)); - set_parents(); - assert_invariant(); - } - - /*! - @brief create a JSON value from an existing one - - This is a constructor for existing @ref basic_json types. - It does not hijack copy/move constructors, since the parameter has different - template arguments than the current ones. - - The constructor tries to convert the internal @ref m_value of the parameter. - - @tparam BasicJsonType a type such that: - - @a BasicJsonType is a @ref basic_json type. - - @a BasicJsonType has different template arguments than @ref basic_json_t. - - @param[in] val the @ref basic_json value to be converted. - - @complexity Usually linear in the size of the passed @a val, also - depending on the implementation of the called `to_json()` - method. - - @exceptionsafety Depends on the called constructor. For types directly - supported by the library (i.e., all types for which no `to_json()` function - was provided), strong guarantee holds: if an exception is thrown, there are - no changes to any JSON value. - - @since version 3.2.0 - */ - template < typename BasicJsonType, - detail::enable_if_t < - detail::is_basic_json::value&& !std::is_same::value, int > = 0 > - basic_json(const BasicJsonType& val) - { - using other_boolean_t = typename BasicJsonType::boolean_t; - using other_number_float_t = typename BasicJsonType::number_float_t; - using other_number_integer_t = typename BasicJsonType::number_integer_t; - using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using other_string_t = typename BasicJsonType::string_t; - using other_object_t = typename BasicJsonType::object_t; - using other_array_t = typename BasicJsonType::array_t; - using other_binary_t = typename BasicJsonType::binary_t; - - switch (val.type()) - { - case value_t::boolean: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_float: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_integer: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_unsigned: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::string: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::object: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::array: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::binary: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::null: - *this = nullptr; - break; - case value_t::discarded: - m_type = value_t::discarded; - break; - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - } - set_parents(); - assert_invariant(); - } - - /*! - @brief create a container (array or object) from an initializer list - - Creates a JSON value of type array or object from the passed initializer - list @a init. In case @a type_deduction is `true` (default), the type of - the JSON value to be created is deducted from the initializer list @a init - according to the following rules: - - 1. If the list is empty, an empty JSON object value `{}` is created. - 2. If the list consists of pairs whose first element is a string, a JSON - object value is created where the first elements of the pairs are - treated as keys and the second elements are as values. - 3. In all other cases, an array is created. - - The rules aim to create the best fit between a C++ initializer list and - JSON values. The rationale is as follows: - - 1. The empty initializer list is written as `{}` which is exactly an empty - JSON object. - 2. C++ has no way of describing mapped types other than to list a list of - pairs. As JSON requires that keys must be of type string, rule 2 is the - weakest constraint one can pose on initializer lists to interpret them - as an object. - 3. In all other cases, the initializer list could not be interpreted as - JSON object type, so interpreting it as JSON array type is safe. - - With the rules described above, the following JSON values cannot be - expressed by an initializer list: - - - the empty array (`[]`): use @ref array(initializer_list_t) - with an empty initializer list in this case - - arrays whose elements satisfy rule 2: use @ref - array(initializer_list_t) with the same initializer list - in this case - - @note When used without parentheses around an empty initializer list, @ref - basic_json() is called instead of this function, yielding the JSON null - value. - - @param[in] init initializer list with JSON values - - @param[in] type_deduction internal parameter; when set to `true`, the type - of the JSON value is deducted from the initializer list @a init; when set - to `false`, the type provided via @a manual_type is forced. This mode is - used by the functions @ref array(initializer_list_t) and - @ref object(initializer_list_t). - - @param[in] manual_type internal parameter; when @a type_deduction is set - to `false`, the created JSON value will use the provided type (only @ref - value_t::array and @ref value_t::object are valid); when @a type_deduction - is set to `true`, this parameter has no effect - - @throw type_error.301 if @a type_deduction is `false`, @a manual_type is - `value_t::object`, but @a init contains an element which is not a pair - whose first element is a string. In this case, the constructor could not - create an object. If @a type_deduction would have be `true`, an array - would have been created. See @ref object(initializer_list_t) - for an example. - - @complexity Linear in the size of the initializer list @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The example below shows how JSON values are created from - initializer lists.,basic_json__list_init_t} - - @sa see @ref array(initializer_list_t) -- create a JSON array - value from an initializer list - @sa see @ref object(initializer_list_t) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - basic_json(initializer_list_t init, - bool type_deduction = true, - value_t manual_type = value_t::array) - { - // check if each element is an array with two elements whose first - // element is a string - bool is_an_object = std::all_of(init.begin(), init.end(), - [](const detail::json_ref& element_ref) - { - return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); - }); - - // adjust type if type deduction is not wanted - if (!type_deduction) - { - // if array is wanted, do not create an object though possible - if (manual_type == value_t::array) - { - is_an_object = false; - } - - // if object is wanted but impossible, throw an exception - if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) - { - JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json())); - } - } - - if (is_an_object) - { - // the initializer list is a list of pairs -> create object - m_type = value_t::object; - m_value = value_t::object; - - for (auto& element_ref : init) - { - auto element = element_ref.moved_or_copied(); - m_value.object->emplace( - std::move(*((*element.m_value.array)[0].m_value.string)), - std::move((*element.m_value.array)[1])); - } - } - else - { - // the initializer list describes an array -> create array - m_type = value_t::array; - m_value.array = create(init.begin(), init.end()); - } - - set_parents(); - assert_invariant(); - } - - /*! - @brief explicitly create a binary array (without subtype) - - Creates a JSON binary array value from a given binary container. Binary - values are part of various binary formats, such as CBOR, MessagePack, and - BSON. This constructor is used to create a value for serialization to those - formats. - - @note Note, this function exists because of the difficulty in correctly - specifying the correct template overload in the standard value ctor, as both - JSON arrays and JSON binary arrays are backed with some form of a - `std::vector`. Because JSON binary arrays are a non-standard extension it - was decided that it would be best to prevent automatic initialization of a - binary array type, for backwards compatibility and so it does not happen on - accident. - - @param[in] init container containing bytes to use as binary type - - @return JSON binary array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @since version 3.8.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(const typename binary_t::container_type& init) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = init; - return res; - } - - /*! - @brief explicitly create a binary array (with subtype) - - Creates a JSON binary array value from a given binary container. Binary - values are part of various binary formats, such as CBOR, MessagePack, and - BSON. This constructor is used to create a value for serialization to those - formats. - - @note Note, this function exists because of the difficulty in correctly - specifying the correct template overload in the standard value ctor, as both - JSON arrays and JSON binary arrays are backed with some form of a - `std::vector`. Because JSON binary arrays are a non-standard extension it - was decided that it would be best to prevent automatic initialization of a - binary array type, for backwards compatibility and so it does not happen on - accident. - - @param[in] init container containing bytes to use as binary type - @param[in] subtype subtype to use in MessagePack and BSON - - @return JSON binary array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @since version 3.8.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(init, subtype); - return res; - } - - /// @copydoc binary(const typename binary_t::container_type&) - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(typename binary_t::container_type&& init) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = std::move(init); - return res; - } - - /// @copydoc binary(const typename binary_t::container_type&, typename binary_t::subtype_type) - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(std::move(init), subtype); - return res; - } - - /*! - @brief explicitly create an array from an initializer list - - Creates a JSON array value from a given initializer list. That is, given a - list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the - initializer list is empty, the empty array `[]` is created. - - @note This function is only needed to express two edge cases that cannot - be realized with the initializer list constructor (@ref - basic_json(initializer_list_t, bool, value_t)). These cases - are: - 1. creating an array whose elements are all pairs whose first element is a - string -- in this case, the initializer list constructor would create an - object, taking the first elements as keys - 2. creating an empty array -- passing the empty initializer list to the - initializer list constructor yields an empty object - - @param[in] init initializer list with JSON values to create an array from - (optional) - - @return JSON array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows an example for the `array` - function.,array} - - @sa see @ref basic_json(initializer_list_t, bool, value_t) -- - create a JSON value from an initializer list - @sa see @ref object(initializer_list_t) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json array(initializer_list_t init = {}) - { - return basic_json(init, false, value_t::array); - } - - /*! - @brief explicitly create an object from an initializer list - - Creates a JSON object value from a given initializer list. The initializer - lists elements must be pairs, and their first elements must be strings. If - the initializer list is empty, the empty object `{}` is created. - - @note This function is only added for symmetry reasons. In contrast to the - related function @ref array(initializer_list_t), there are - no cases which can only be expressed by this function. That is, any - initializer list @a init can also be passed to the initializer list - constructor @ref basic_json(initializer_list_t, bool, value_t). - - @param[in] init initializer list to create an object from (optional) - - @return JSON object value - - @throw type_error.301 if @a init is not a list of pairs whose first - elements are strings. In this case, no object can be created. When such a - value is passed to @ref basic_json(initializer_list_t, bool, value_t), - an array would have been created from the passed initializer list @a init. - See example below. - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows an example for the `object` - function.,object} - - @sa see @ref basic_json(initializer_list_t, bool, value_t) -- - create a JSON value from an initializer list - @sa see @ref array(initializer_list_t) -- create a JSON array - value from an initializer list - - @since version 1.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json object(initializer_list_t init = {}) - { - return basic_json(init, false, value_t::object); - } - - /*! - @brief construct an array with count copies of given value - - Constructs a JSON array value by creating @a cnt copies of a passed value. - In case @a cnt is `0`, an empty array is created. - - @param[in] cnt the number of JSON copies of @a val to create - @param[in] val the JSON value to copy - - @post `std::distance(begin(),end()) == cnt` holds. - - @complexity Linear in @a cnt. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows examples for the @ref - basic_json(size_type\, const basic_json&) - constructor.,basic_json__size_type_basic_json} - - @since version 1.0.0 - */ - basic_json(size_type cnt, const basic_json& val) - : m_type(value_t::array) - { - m_value.array = create(cnt, val); - set_parents(); - assert_invariant(); - } - - /*! - @brief construct a JSON container given an iterator range - - Constructs the JSON value with the contents of the range `[first, last)`. - The semantics depends on the different types a JSON value can have: - - In case of a null type, invalid_iterator.206 is thrown. - - In case of other primitive types (number, boolean, or string), @a first - must be `begin()` and @a last must be `end()`. In this case, the value is - copied. Otherwise, invalid_iterator.204 is thrown. - - In case of structured types (array, object), the constructor behaves as - similar versions for `std::vector` or `std::map`; that is, a JSON array - or object is constructed from the values in the range. - - @tparam InputIT an input iterator type (@ref iterator or @ref - const_iterator) - - @param[in] first begin of the range to copy from (included) - @param[in] last end of the range to copy from (excluded) - - @pre Iterators @a first and @a last must be initialized. **This - precondition is enforced with an assertion (see warning).** If - assertions are switched off, a violation of this precondition yields - undefined behavior. - - @pre Range `[first, last)` is valid. Usually, this precondition cannot be - checked efficiently. Only certain edge cases are detected; see the - description of the exceptions below. A violation of this precondition - yields undefined behavior. - - @warning A precondition is enforced with a runtime assertion that will - result in calling `std::abort` if this precondition is not met. - Assertions can be disabled by defining `NDEBUG` at compile time. - See https://en.cppreference.com/w/cpp/error/assert for more - information. - - @throw invalid_iterator.201 if iterators @a first and @a last are not - compatible (i.e., do not belong to the same JSON value). In this case, - the range `[first, last)` is undefined. - @throw invalid_iterator.204 if iterators @a first and @a last belong to a - primitive type (number, boolean, or string), but @a first does not point - to the first element any more. In this case, the range `[first, last)` is - undefined. See example code below. - @throw invalid_iterator.206 if iterators @a first and @a last belong to a - null value. In this case, the range `[first, last)` is undefined. - - @complexity Linear in distance between @a first and @a last. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The example below shows several ways to create JSON values by - specifying a subrange with iterators.,basic_json__InputIt_InputIt} - - @since version 1.0.0 - */ - template < class InputIT, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type = 0 > - basic_json(InputIT first, InputIT last) - { - JSON_ASSERT(first.m_object != nullptr); - JSON_ASSERT(last.m_object != nullptr); - - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json())); - } - - // copy type from first iterator - m_type = first.m_object->m_type; - - // check if iterator range is complete for primitive values - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() - || !last.m_it.primitive_iterator.is_end())) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object)); - } - break; - } - - case value_t::null: - case value_t::object: - case value_t::array: - case value_t::binary: - case value_t::discarded: - default: - break; - } - - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = first.m_object->m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = first.m_object->m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value.number_float = first.m_object->m_value.number_float; - break; - } - - case value_t::boolean: - { - m_value.boolean = first.m_object->m_value.boolean; - break; - } - - case value_t::string: - { - m_value = *first.m_object->m_value.string; - break; - } - - case value_t::object: - { - m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - case value_t::binary: - { - m_value = *first.m_object->m_value.binary; - break; - } - - case value_t::null: - case value_t::discarded: - default: - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object)); - } - - set_parents(); - assert_invariant(); - } - - - /////////////////////////////////////// - // other constructors and destructor // - /////////////////////////////////////// - - template, - std::is_same>::value, int> = 0 > - basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} - - /*! - @brief copy constructor - - Creates a copy of a given JSON value. - - @param[in] other the JSON value to copy - - @post `*this == other` - - @complexity Linear in the size of @a other. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - As postcondition, it holds: `other == basic_json(other)`. - - @liveexample{The following code shows an example for the copy - constructor.,basic_json__basic_json} - - @since version 1.0.0 - */ - basic_json(const basic_json& other) - : m_type(other.m_type) - { - // check of passed value is valid - other.assert_invariant(); - - switch (m_type) - { - case value_t::object: - { - m_value = *other.m_value.object; - break; - } - - case value_t::array: - { - m_value = *other.m_value.array; - break; - } - - case value_t::string: - { - m_value = *other.m_value.string; - break; - } - - case value_t::boolean: - { - m_value = other.m_value.boolean; - break; - } - - case value_t::number_integer: - { - m_value = other.m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value = other.m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value = other.m_value.number_float; - break; - } - - case value_t::binary: - { - m_value = *other.m_value.binary; - break; - } - - case value_t::null: - case value_t::discarded: - default: - break; - } - - set_parents(); - assert_invariant(); - } - - /*! - @brief move constructor - - Move constructor. Constructs a JSON value with the contents of the given - value @a other using move semantics. It "steals" the resources from @a - other and leaves it as JSON null value. - - @param[in,out] other value to move to this object - - @post `*this` has the same value as @a other before the call. - @post @a other is a JSON null value. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. - - @requirement This function helps `basic_json` satisfying the - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible) - requirements. - - @liveexample{The code below shows the move constructor explicitly called - via std::move.,basic_json__moveconstructor} - - @since version 1.0.0 - */ - basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) - { - // check that passed value is valid - other.assert_invariant(false); - - // invalidate payload - other.m_type = value_t::null; - other.m_value = {}; - - set_parents(); - assert_invariant(); - } - - /*! - @brief copy assignment - - Copy assignment operator. Copies a JSON value via the "copy and swap" - strategy: It is expressed in terms of the copy constructor, destructor, - and the `swap()` member function. - - @param[in] other value to copy from - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - @liveexample{The code below shows and example for the copy assignment. It - creates a copy of value `a` which is then swapped with `b`. Finally\, the - copy of `a` (which is the null value after the swap) is - destroyed.,basic_json__copyassignment} - - @since version 1.0.0 - */ - basic_json& operator=(basic_json other) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - // check that passed value is valid - other.assert_invariant(); - - using std::swap; - swap(m_type, other.m_type); - swap(m_value, other.m_value); - - set_parents(); - assert_invariant(); - return *this; - } - - /*! - @brief destructor - - Destroys the JSON value and frees all allocated memory. - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - All stored elements are destroyed and all memory is freed. - - @since version 1.0.0 - */ - ~basic_json() noexcept - { - assert_invariant(false); - m_value.destroy(m_type); - } - - /// @} - - public: - /////////////////////// - // object inspection // - /////////////////////// - - /// @name object inspection - /// Functions to inspect the type of a JSON value. - /// @{ - - /*! - @brief serialization - - Serialization function for JSON values. The function tries to mimic - Python's `json.dumps()` function, and currently supports its @a indent - and @a ensure_ascii parameters. - - @param[in] indent If indent is nonnegative, then array elements and object - members will be pretty-printed with that indent level. An indent level of - `0` will only insert newlines. `-1` (the default) selects the most compact - representation. - @param[in] indent_char The character to use for indentation if @a indent is - greater than `0`. The default is ` ` (space). - @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters - in the output are escaped with `\uXXXX` sequences, and the result consists - of ASCII characters only. - @param[in] error_handler how to react on decoding errors; there are three - possible values: `strict` (throws and exception in case a decoding error - occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD), - and `ignore` (ignore invalid UTF-8 sequences during serialization; all - bytes are copied to the output unchanged). - - @return string containing the serialization of the JSON value - - @throw type_error.316 if a string stored inside the JSON value is not - UTF-8 encoded and @a error_handler is set to strict - - @note Binary values are serialized as object containing two keys: - - "bytes": an array of bytes as integers - - "subtype": the subtype as integer or "null" if the binary has no subtype - - @complexity Linear. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @liveexample{The following example shows the effect of different @a indent\, - @a indent_char\, and @a ensure_ascii parameters to the result of the - serialization.,dump} - - @see https://docs.python.org/2/library/json.html#json.dump - - @since version 1.0.0; indentation character @a indent_char, option - @a ensure_ascii and exceptions added in version 3.0.0; error - handlers added in version 3.4.0; serialization of binary values added - in version 3.8.0. - */ - string_t dump(const int indent = -1, - const char indent_char = ' ', - const bool ensure_ascii = false, - const error_handler_t error_handler = error_handler_t::strict) const - { - string_t result; - serializer s(detail::output_adapter(result), indent_char, error_handler); - - if (indent >= 0) - { - s.dump(*this, true, ensure_ascii, static_cast(indent)); - } - else - { - s.dump(*this, false, ensure_ascii, 0); - } - - return result; - } - - /*! - @brief return the type of the JSON value (explicit) - - Return the type of the JSON value as a value from the @ref value_t - enumeration. - - @return the type of the JSON value - Value type | return value - ------------------------- | ------------------------- - null | value_t::null - boolean | value_t::boolean - string | value_t::string - number (integer) | value_t::number_integer - number (unsigned integer) | value_t::number_unsigned - number (floating-point) | value_t::number_float - object | value_t::object - array | value_t::array - binary | value_t::binary - discarded | value_t::discarded - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `type()` for all JSON - types.,type} - - @sa see @ref operator value_t() -- return the type of the JSON value (implicit) - @sa see @ref type_name() -- return the type as string - - @since version 1.0.0 - */ - constexpr value_t type() const noexcept - { - return m_type; - } - - /*! - @brief return whether type is primitive - - This function returns true if and only if the JSON type is primitive - (string, number, boolean, or null). - - @return `true` if type is primitive (string, number, boolean, or null), - `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_primitive()` for all JSON - types.,is_primitive} - - @sa see @ref is_structured() -- returns whether JSON value is structured - @sa see @ref is_null() -- returns whether JSON value is `null` - @sa see @ref is_string() -- returns whether JSON value is a string - @sa see @ref is_boolean() -- returns whether JSON value is a boolean - @sa see @ref is_number() -- returns whether JSON value is a number - @sa see @ref is_binary() -- returns whether JSON value is a binary array - - @since version 1.0.0 - */ - constexpr bool is_primitive() const noexcept - { - return is_null() || is_string() || is_boolean() || is_number() || is_binary(); - } - - /*! - @brief return whether type is structured - - This function returns true if and only if the JSON type is structured - (array or object). - - @return `true` if type is structured (array or object), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_structured()` for all JSON - types.,is_structured} - - @sa see @ref is_primitive() -- returns whether value is primitive - @sa see @ref is_array() -- returns whether value is an array - @sa see @ref is_object() -- returns whether value is an object - - @since version 1.0.0 - */ - constexpr bool is_structured() const noexcept - { - return is_array() || is_object(); - } - - /*! - @brief return whether value is null - - This function returns true if and only if the JSON value is null. - - @return `true` if type is null, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_null()` for all JSON - types.,is_null} - - @since version 1.0.0 - */ - constexpr bool is_null() const noexcept - { - return m_type == value_t::null; - } - - /*! - @brief return whether value is a boolean - - This function returns true if and only if the JSON value is a boolean. - - @return `true` if type is boolean, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_boolean()` for all JSON - types.,is_boolean} - - @since version 1.0.0 - */ - constexpr bool is_boolean() const noexcept - { - return m_type == value_t::boolean; - } - - /*! - @brief return whether value is a number - - This function returns true if and only if the JSON value is a number. This - includes both integer (signed and unsigned) and floating-point values. - - @return `true` if type is number (regardless whether integer, unsigned - integer or floating-type), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number()` for all JSON - types.,is_number} - - @sa see @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa see @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa see @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number() const noexcept - { - return is_number_integer() || is_number_float(); - } - - /*! - @brief return whether value is an integer number - - This function returns true if and only if the JSON value is a signed or - unsigned integer number. This excludes floating-point values. - - @return `true` if type is an integer or unsigned integer number, `false` - otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_integer()` for all - JSON types.,is_number_integer} - - @sa see @ref is_number() -- check if value is a number - @sa see @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa see @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number_integer() const noexcept - { - return m_type == value_t::number_integer || m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is an unsigned integer number - - This function returns true if and only if the JSON value is an unsigned - integer number. This excludes floating-point and signed integer values. - - @return `true` if type is an unsigned integer number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_unsigned()` for all - JSON types.,is_number_unsigned} - - @sa see @ref is_number() -- check if value is a number - @sa see @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa see @ref is_number_float() -- check if value is a floating-point number - - @since version 2.0.0 - */ - constexpr bool is_number_unsigned() const noexcept - { - return m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is a floating-point number - - This function returns true if and only if the JSON value is a - floating-point number. This excludes signed and unsigned integer values. - - @return `true` if type is a floating-point number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_float()` for all - JSON types.,is_number_float} - - @sa see @ref is_number() -- check if value is number - @sa see @ref is_number_integer() -- check if value is an integer number - @sa see @ref is_number_unsigned() -- check if value is an unsigned integer - number - - @since version 1.0.0 - */ - constexpr bool is_number_float() const noexcept - { - return m_type == value_t::number_float; - } - - /*! - @brief return whether value is an object - - This function returns true if and only if the JSON value is an object. - - @return `true` if type is object, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_object()` for all JSON - types.,is_object} - - @since version 1.0.0 - */ - constexpr bool is_object() const noexcept - { - return m_type == value_t::object; - } - - /*! - @brief return whether value is an array - - This function returns true if and only if the JSON value is an array. - - @return `true` if type is array, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_array()` for all JSON - types.,is_array} - - @since version 1.0.0 - */ - constexpr bool is_array() const noexcept - { - return m_type == value_t::array; - } - - /*! - @brief return whether value is a string - - This function returns true if and only if the JSON value is a string. - - @return `true` if type is string, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_string()` for all JSON - types.,is_string} - - @since version 1.0.0 - */ - constexpr bool is_string() const noexcept - { - return m_type == value_t::string; - } - - /*! - @brief return whether value is a binary array - - This function returns true if and only if the JSON value is a binary array. - - @return `true` if type is binary array, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_binary()` for all JSON - types.,is_binary} - - @since version 3.8.0 - */ - constexpr bool is_binary() const noexcept - { - return m_type == value_t::binary; - } - - /*! - @brief return whether value is discarded - - This function returns true if and only if the JSON value was discarded - during parsing with a callback function (see @ref parser_callback_t). - - @note This function will always be `false` for JSON values after parsing. - That is, discarded values can only occur during parsing, but will be - removed when inside a structured value or replaced by null in other cases. - - @return `true` if type is discarded, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_discarded()` for all JSON - types.,is_discarded} - - @since version 1.0.0 - */ - constexpr bool is_discarded() const noexcept - { - return m_type == value_t::discarded; - } - - /*! - @brief return the type of the JSON value (implicit) - - Implicitly return the type of the JSON value as a value from the @ref - value_t enumeration. - - @return the type of the JSON value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies the @ref value_t operator for - all JSON types.,operator__value_t} - - @sa see @ref type() -- return the type of the JSON value (explicit) - @sa see @ref type_name() -- return the type as string - - @since version 1.0.0 - */ - constexpr operator value_t() const noexcept - { - return m_type; - } - - /// @} - - private: - ////////////////// - // value access // - ////////////////// - - /// get a boolean (explicit) - boolean_t get_impl(boolean_t* /*unused*/) const - { - if (JSON_HEDLEY_LIKELY(is_boolean())) - { - return m_value.boolean; - } - - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this)); - } - - /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t* /*unused*/) noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t* /*unused*/) noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t* /*unused*/) noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /// get a pointer to the value (floating-point number) - constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /// get a pointer to the value (binary) - binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept - { - return is_binary() ? m_value.binary : nullptr; - } - - /// get a pointer to the value (binary) - constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept - { - return is_binary() ? m_value.binary : nullptr; - } - - /*! - @brief helper function to implement get_ref() - - This function helps to implement get_ref() without code duplication for - const and non-const overloads - - @tparam ThisType will be deduced as `basic_json` or `const basic_json` - - @throw type_error.303 if ReferenceType does not match underlying value - type of the current JSON - */ - template - static ReferenceType get_ref_impl(ThisType& obj) - { - // delegate the call to get_ptr<>() - auto* ptr = obj.template get_ptr::type>(); - - if (JSON_HEDLEY_LIKELY(ptr != nullptr)) - { - return *ptr; - } - - JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj)); - } - - public: - /// @name value access - /// Direct access to the stored value of a JSON value. - /// @{ - - /*! - @brief get a pointer value (implicit) - - Implicit pointer access to the internally stored JSON value. No copies are - made. - - @warning Writing data to the pointee of the result yields an undefined - state. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. Enforced by a static - assertion. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get_ptr} - - @since version 1.0.0 - */ - template::value, int>::type = 0> - auto get_ptr() noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) - { - // delegate the call to get_impl_ptr<>() - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a pointer value (implicit) - @copydoc get_ptr() - */ - template < typename PointerType, typename std::enable_if < - std::is_pointer::value&& - std::is_const::type>::value, int >::type = 0 > - constexpr auto get_ptr() const noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) - { - // delegate the call to get_impl_ptr<>() const - return get_impl_ptr(static_cast(nullptr)); - } - - private: - /*! - @brief get a value (explicit) - - Explicit type conversion between the JSON value and a compatible value - which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) - and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json, - - @ref json_serializer has a `from_json()` method of the form - `void from_json(const basic_json&, ValueType&)`, and - - @ref json_serializer does not have a `from_json()` method of - the form `ValueType from_json(const basic_json&)` - - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,get__ValueType_const} - - @since version 2.1.0 - */ - template < typename ValueType, - detail::enable_if_t < - detail::is_default_constructible::value&& - detail::has_from_json::value, - int > = 0 > - ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) - { - ValueType ret{}; - JSONSerializer::from_json(*this, ret); - return ret; - } - - /*! - @brief get a value (explicit); special case - - Explicit type conversion between the JSON value and a compatible value - which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) - and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - return JSONSerializer::from_json(*this); - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json and - - @ref json_serializer has a `from_json()` method of the form - `ValueType from_json(const basic_json&)` - - @note If @ref json_serializer has both overloads of - `from_json()`, this one is chosen. - - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @since version 2.1.0 - */ - template < typename ValueType, - detail::enable_if_t < - detail::has_non_default_from_json::value, - int > = 0 > - ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) - { - return JSONSerializer::from_json(*this); - } - - /*! - @brief get special-case overload - - This overloads converts the current @ref basic_json in a different - @ref basic_json type - - @tparam BasicJsonType == @ref basic_json - - @return a copy of *this, converted into @a BasicJsonType - - @complexity Depending on the implementation of the called `from_json()` - method. - - @since version 3.2.0 - */ - template < typename BasicJsonType, - detail::enable_if_t < - detail::is_basic_json::value, - int > = 0 > - BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const - { - return *this; - } - - /*! - @brief get special-case overload - - This overloads avoids a lot of template boilerplate, it can be seen as the - identity method - - @tparam BasicJsonType == @ref basic_json - - @return a copy of *this - - @complexity Constant. - - @since version 2.1.0 - */ - template::value, - int> = 0> - basic_json get_impl(detail::priority_tag<3> /*unused*/) const - { - return *this; - } - - /*! - @brief get a pointer value (explicit) - @copydoc get() - */ - template::value, - int> = 0> - constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept - -> decltype(std::declval().template get_ptr()) - { - // delegate the call to get_ptr - return get_ptr(); - } - - public: - /*! - @brief get a (pointer) value (explicit) - - Performs explicit type conversion between the JSON value and a compatible value if required. - - - If the requested type is a pointer to the internally stored JSON value that pointer is returned. - No copies are made. - - - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible - from the current @ref basic_json. - - - Otherwise the value is converted by calling the @ref json_serializer `from_json()` - method. - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @tparam ValueType if necessary - - @throw what @ref json_serializer `from_json()` method throws if conversion is required - - @since version 2.1.0 - */ - template < typename ValueTypeCV, typename ValueType = detail::uncvref_t> -#if defined(JSON_HAS_CPP_14) - constexpr -#endif - auto get() const noexcept( - noexcept(std::declval().template get_impl(detail::priority_tag<4> {}))) - -> decltype(std::declval().template get_impl(detail::priority_tag<4> {})) - { - // we cannot static_assert on ValueTypeCV being non-const, because - // there is support for get(), which is why we - // still need the uncvref - static_assert(!std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - return get_impl(detail::priority_tag<4> {}); - } - - /*! - @brief get a pointer value (explicit) - - Explicit pointer access to the internally stored JSON value. No copies are - made. - - @warning The pointer becomes invalid if the underlying JSON object - changes. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get__PointerType} - - @sa see @ref get_ptr() for explicit pointer-member access - - @since version 1.0.0 - */ - template::value, int>::type = 0> - auto get() noexcept -> decltype(std::declval().template get_ptr()) - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a value (explicit) - - Explicit type conversion between the JSON value and a compatible value. - The value is filled into the input parameter by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - ValueType v; - JSONSerializer::from_json(*this, v); - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json, - - @ref json_serializer has a `from_json()` method of the form - `void from_json(const basic_json&, ValueType&)`, and - - @tparam ValueType the input parameter type. - - @return the input parameter, allowing chaining calls. - - @throw what @ref json_serializer `from_json()` method throws - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,get_to} - - @since version 3.3.0 - */ - template < typename ValueType, - detail::enable_if_t < - !detail::is_basic_json::value&& - detail::has_from_json::value, - int > = 0 > - ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) - { - JSONSerializer::from_json(*this, v); - return v; - } - - // specialization to allow to call get_to with a basic_json value - // see https://github.com/nlohmann/json/issues/2175 - template::value, - int> = 0> - ValueType & get_to(ValueType& v) const - { - v = *this; - return v; - } - - template < - typename T, std::size_t N, - typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - detail::enable_if_t < - detail::has_from_json::value, int > = 0 > - Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - noexcept(noexcept(JSONSerializer::from_json( - std::declval(), v))) - { - JSONSerializer::from_json(*this, v); - return v; - } - - /*! - @brief get a reference value (implicit) - - Implicit reference access to the internally stored JSON value. No copies - are made. - - @warning Writing data to the referee of the result yields an undefined - state. - - @tparam ReferenceType reference type; must be a reference to @ref array_t, - @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or - @ref number_float_t. Enforced by static assertion. - - @return reference to the internally stored JSON value if the requested - reference type @a ReferenceType fits to the JSON value; throws - type_error.303 otherwise - - @throw type_error.303 in case passed type @a ReferenceType is incompatible - with the stored JSON value; see example below - - @complexity Constant. - - @liveexample{The example shows several calls to `get_ref()`.,get_ref} - - @since version 1.1.0 - */ - template::value, int>::type = 0> - ReferenceType get_ref() - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a reference value (implicit) - @copydoc get_ref() - */ - template < typename ReferenceType, typename std::enable_if < - std::is_reference::value&& - std::is_const::type>::value, int >::type = 0 > - ReferenceType get_ref() const - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a value (implicit) - - Implicit type conversion between the JSON value and a compatible value. - The call is realized by calling @ref get() const. - - @tparam ValueType non-pointer type compatible to the JSON value, for - instance `int` for JSON integer numbers, `bool` for JSON booleans, or - `std::vector` types for JSON arrays. The character type of @ref string_t - as well as an initializer list of this type is excluded to avoid - ambiguities as these types implicitly convert to `std::string`. - - @return copy of the JSON value, converted to type @a ValueType - - @throw type_error.302 in case passed type @a ValueType is incompatible - to the JSON value type (e.g., the JSON value is of type boolean, but a - string is requested); see example below - - @complexity Linear in the size of the JSON value. - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,operator__ValueType} - - @since version 1.0.0 - */ - template < typename ValueType, typename std::enable_if < - detail::conjunction < - detail::negation>, - detail::negation>>, - detail::negation>, - detail::negation>, - detail::negation>>, - -#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) - detail::negation>, -#endif - detail::is_detected_lazy - >::value, int >::type = 0 > - JSON_EXPLICIT operator ValueType() const - { - // delegate the call to get<>() const - return get(); - } - - /*! - @return reference to the binary value - - @throw type_error.302 if the value is not binary - - @sa see @ref is_binary() to check if the value is binary - - @since version 3.8.0 - */ - binary_t& get_binary() - { - if (!is_binary()) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); - } - - return *get_ptr(); - } - - /// @copydoc get_binary() - const binary_t& get_binary() const - { - if (!is_binary()) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); - } - - return *get_ptr(); - } - - /// @} - - - //////////////////// - // element access // - //////////////////// - - /// @name element access - /// Access to the JSON value. - /// @{ - - /*! - @brief access specified array element with bounds checking - - Returns a reference to the element at specified location @a idx, with - bounds checking. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__size_type} - */ - reference at(size_type idx) - { - // at only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - JSON_TRY - { - return set_parent(m_value.array->at(idx)); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); - } - } - - /*! - @brief access specified array element with bounds checking - - Returns a const reference to the element at specified location @a idx, - with bounds checking. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__size_type_const} - */ - const_reference at(size_type idx) const - { - // at only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a reference to the element at with specified key @a key, with - bounds checking. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa see @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa see @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__object_t_key_type} - */ - reference at(const typename object_t::key_type& key) - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return set_parent(m_value.object->at(key)); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a const reference to the element at with specified key @a key, - with bounds checking. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa see @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa see @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__object_t_key_type_const} - */ - const_reference at(const typename object_t::key_type& key) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); - } - } - - /*! - @brief access specified array element - - Returns a reference to the element at specified location @a idx. - - @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), - then the array is silently filled up with `null` values to make `idx` a - valid reference to the last stored element. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array or null; in that - cases, using the [] operator with an index makes no sense. - - @complexity Constant if @a idx is in the range of the array. Otherwise - linear in `idx - size()`. - - @liveexample{The example below shows how array elements can be read and - written using `[]` operator. Note the addition of `null` - values.,operatorarray__size_type} - - @since version 1.0.0 - */ - reference operator[](size_type idx) - { - // implicitly convert null value to an empty array - if (is_null()) - { - m_type = value_t::array; - m_value.array = create(); - assert_invariant(); - } - - // operator[] only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // fill up array with null values if given idx is outside range - if (idx >= m_value.array->size()) - { -#if JSON_DIAGNOSTICS - // remember array size before resizing - const auto previous_size = m_value.array->size(); -#endif - m_value.array->resize(idx + 1); - -#if JSON_DIAGNOSTICS - // set parent for values added above - set_parents(begin() + static_cast(previous_size), static_cast(idx + 1 - previous_size)); -#endif - } - - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); - } - - /*! - @brief access specified array element - - Returns a const reference to the element at specified location @a idx. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array; in that case, - using the [] operator with an index makes no sense. - - @complexity Constant. - - @liveexample{The example below shows how array elements can be read using - the `[]` operator.,operatorarray__size_type_const} - - @since version 1.0.0 - */ - const_reference operator[](size_type idx) const - { - // const operator[] only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa see @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa see @ref value() for access by value with a default value - - @since version 1.0.0 - */ - reference operator[](const typename object_t::key_type& key) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - // operator[] only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return set_parent(m_value.object->operator[](key)); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that case, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa see @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa see @ref value() for access by value with a default value - - @since version 1.0.0 - */ - const_reference operator[](const typename object_t::key_type& key) const - { - // const operator[] only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa see @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa see @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - reference operator[](T* key) - { - // implicitly convert null to object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return set_parent(m_value.object->operator[](key)); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that case, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa see @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa see @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - const_reference operator[](T* key) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); - } - - /*! - @brief access specified object element with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(key); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const typename object_t::key_type&), this function - does not throw if the given key @a key was not found. - - @note Unlike @ref operator[](const typename object_t::key_type& key), this - function does not implicitly add an element to the position defined by @a - key. This function is furthermore also applicable to const objects. - - @param[in] key key of the element to access - @param[in] default_value the value to return if @a key is not found - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.302 if @a default_value does not match the type of the - value at @a key - @throw type_error.306 if the JSON value is not an object; in that case, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value} - - @sa see @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa see @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - - @since version 1.0.0 - */ - // using std::is_convertible in a std::enable_if will fail when using explicit conversions - template < class ValueType, typename std::enable_if < - detail::is_getable::value - && !std::is_same::value, int >::type = 0 > - ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if key is found, return value and given default value otherwise - const auto it = find(key); - if (it != end()) - { - return it->template get(); - } - - return default_value; - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const - */ - string_t value(const typename object_t::key_type& key, const char* default_value) const - { - return value(key, string_t(default_value)); - } - - /*! - @brief access specified object element via JSON Pointer with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(ptr); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const json_pointer&), this function does not throw - if the given key @a key was not found. - - @param[in] ptr a JSON pointer to the element to access - @param[in] default_value the value to return if @a ptr found no value - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.302 if @a default_value does not match the type of the - value at @a ptr - @throw type_error.306 if the JSON value is not an object; in that case, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value_ptr} - - @sa see @ref operator[](const json_pointer&) for unchecked access by reference - - @since version 2.0.2 - */ - template::value, int>::type = 0> - ValueType value(const json_pointer& ptr, const ValueType& default_value) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if pointer resolves a value, return it or use default value - JSON_TRY - { - return ptr.get_checked(this).template get(); - } - JSON_INTERNAL_CATCH (out_of_range&) - { - return default_value; - } - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const json_pointer&, ValueType) const - */ - JSON_HEDLEY_NON_NULL(3) - string_t value(const json_pointer& ptr, const char* default_value) const - { - return value(ptr, string_t(default_value)); - } - - /*! - @brief access the first element - - Returns a reference to the first element in the container. For a JSON - container `c`, the expression `c.front()` is equivalent to `*c.begin()`. - - @return In case of a structured type (array or object), a reference to the - first element is returned. In case of number, string, boolean, or binary - values, a reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on `null` value - - @liveexample{The following code shows an example for `front()`.,front} - - @sa see @ref back() -- access the last element - - @since version 1.0.0 - */ - reference front() - { - return *begin(); - } - - /*! - @copydoc basic_json::front() - */ - const_reference front() const - { - return *cbegin(); - } - - /*! - @brief access the last element - - Returns a reference to the last element in the container. For a JSON - container `c`, the expression `c.back()` is equivalent to - @code {.cpp} - auto tmp = c.end(); - --tmp; - return *tmp; - @endcode - - @return In case of a structured type (array or object), a reference to the - last element is returned. In case of number, string, boolean, or binary - values, a reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on a `null` value. See example - below. - - @liveexample{The following code shows an example for `back()`.,back} - - @sa see @ref front() -- access the first element - - @since version 1.0.0 - */ - reference back() - { - auto tmp = end(); - --tmp; - return *tmp; - } - - /*! - @copydoc basic_json::back() - */ - const_reference back() const - { - auto tmp = cend(); - --tmp; - return *tmp; - } - - /*! - @brief remove element given an iterator - - Removes the element specified by iterator @a pos. The iterator @a pos must - be valid and dereferenceable. Thus the `end()` iterator (which is valid, - but is not dereferenceable) cannot be used as a value for @a pos. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] pos iterator to the element to remove - @return Iterator following the last removed element. If the iterator @a - pos refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.202 if called on an iterator which does not belong - to the current JSON value; example: `"iterator does not fit current - value"` - @throw invalid_iterator.205 if called on a primitive type with invalid - iterator (i.e., any iterator which is not `begin()`); example: `"iterator - out of range"` - - @complexity The complexity depends on the type: - - objects: amortized constant - - arrays: linear in distance between @a pos and the end of the container - - strings and binary: linear in the length of the member - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType} - - @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa see @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa see @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template < class IteratorType, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type - = 0 > - IteratorType erase(IteratorType pos) - { - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - case value_t::binary: - { - if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) - { - JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this)); - } - - if (is_string()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; - } - else if (is_binary()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); - break; - } - - case value_t::null: - case value_t::discarded: - default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); - } - - return result; - } - - /*! - @brief remove elements given an iterator range - - Removes the element specified by the range `[first; last)`. The iterator - @a first does not need to be dereferenceable if `first == last`: erasing - an empty range is a no-op. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] first iterator to the beginning of the range to remove - @param[in] last iterator past the end of the range to remove - @return Iterator following the last removed element. If the iterator @a - second refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.203 if called on iterators which does not belong - to the current JSON value; example: `"iterators do not fit current value"` - @throw invalid_iterator.204 if called on a primitive type with invalid - iterators (i.e., if `first != begin()` and `last != end()`); example: - `"iterators out of range"` - - @complexity The complexity depends on the type: - - objects: `log(size()) + std::distance(first, last)` - - arrays: linear in the distance between @a first and @a last, plus linear - in the distance between @a last and end of the container - - strings and binary: linear in the length of the member - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType_IteratorType} - - @sa see @ref erase(IteratorType) -- removes the element at a given position - @sa see @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa see @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template < class IteratorType, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type - = 0 > - IteratorType erase(IteratorType first, IteratorType last) - { - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) - { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this)); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - case value_t::binary: - { - if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() - || !last.m_it.primitive_iterator.is_end())) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this)); - } - - if (is_string()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; - } - else if (is_binary()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - case value_t::null: - case value_t::discarded: - default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); - } - - return result; - } - - /*! - @brief remove element from a JSON object given a key - - Removes elements from a JSON object with the key value @a key. - - @param[in] key value of the elements to remove - - @return Number of elements removed. If @a ObjectType is the default - `std::map` type, the return value will always be `0` (@a key was not - found) or `1` (@a key was found). - - @post References and iterators to the erased elements are invalidated. - Other references and iterators are not affected. - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - - @complexity `log(size()) + count(key)` - - @liveexample{The example shows the effect of `erase()`.,erase__key_type} - - @sa see @ref erase(IteratorType) -- removes the element at a given position - @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa see @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - size_type erase(const typename object_t::key_type& key) - { - // this erase only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->erase(key); - } - - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); - } - - /*! - @brief remove element from a JSON array given an index - - Removes element from a JSON array at the index @a idx. - - @param[in] idx index of the element to remove - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 - is out of range"` - - @complexity Linear in distance between @a idx and the end of the container. - - @liveexample{The example shows the effect of `erase()`.,erase__size_type} - - @sa see @ref erase(IteratorType) -- removes the element at a given position - @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa see @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - - @since version 1.0.0 - */ - void erase(const size_type idx) - { - // this erase only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - if (JSON_HEDLEY_UNLIKELY(idx >= size())) - { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); - } - - m_value.array->erase(m_value.array->begin() + static_cast(idx)); - } - else - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); - } - } - - /// @} - - - //////////// - // lookup // - //////////// - - /// @name lookup - /// @{ - - /*! - @brief find an element in a JSON object - - Finds an element in a JSON object with key equivalent to @a key. If the - element is not found or the JSON value is not an object, end() is - returned. - - @note This method always returns @ref end() when executed on a JSON type - that is not an object. - - @param[in] key key value of the element to search for. - - @return Iterator to an element with key equivalent to @a key. If no such - element is found or the JSON value is not an object, past-the-end (see - @ref end()) iterator is returned. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `find()` is used.,find__key_type} - - @sa see @ref contains(KeyT&&) const -- checks whether a key exists - - @since version 1.0.0 - */ - template - iterator find(KeyT&& key) - { - auto result = end(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); - } - - return result; - } - - /*! - @brief find an element in a JSON object - @copydoc find(KeyT&&) - */ - template - const_iterator find(KeyT&& key) const - { - auto result = cend(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); - } - - return result; - } - - /*! - @brief returns the number of occurrences of a key in a JSON object - - Returns the number of elements with key @a key. If ObjectType is the - default `std::map` type, the return value will always be `0` (@a key was - not found) or `1` (@a key was found). - - @note This method always returns `0` when executed on a JSON type that is - not an object. - - @param[in] key key value of the element to count - - @return Number of elements with key @a key. If the JSON value is not an - object, the return value will be `0`. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `count()` is used.,count} - - @since version 1.0.0 - */ - template - size_type count(KeyT&& key) const - { - // return 0 for all nonobject types - return is_object() ? m_value.object->count(std::forward(key)) : 0; - } - - /*! - @brief check the existence of an element in a JSON object - - Check whether an element exists in a JSON object with key equivalent to - @a key. If the element is not found or the JSON value is not an object, - false is returned. - - @note This method always returns false when executed on a JSON type - that is not an object. - - @param[in] key key value to check its existence. - - @return true if an element with specified @a key exists. If no such - element with such key is found or the JSON value is not an object, - false is returned. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The following code shows an example for `contains()`.,contains} - - @sa see @ref find(KeyT&&) -- returns an iterator to an object element - @sa see @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer - - @since version 3.6.0 - */ - template < typename KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value, int >::type = 0 > - bool contains(KeyT && key) const - { - return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); - } - - /*! - @brief check the existence of an element in a JSON object given a JSON pointer - - Check whether the given JSON pointer @a ptr can be resolved in the current - JSON value. - - @note This method can be executed on any JSON value type. - - @param[in] ptr JSON pointer to check its existence. - - @return true if the JSON pointer can be resolved to a stored value, false - otherwise. - - @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The following code shows an example for `contains()`.,contains_json_pointer} - - @sa see @ref contains(KeyT &&) const -- checks the existence of a key - - @since version 3.7.0 - */ - bool contains(const json_pointer& ptr) const - { - return ptr.contains(this); - } - - /// @} - - - /////////////// - // iterators // - /////////////// - - /// @name iterators - /// @{ - - /*! - @brief returns an iterator to the first element - - Returns an iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `begin()`.,begin} - - @sa see @ref cbegin() -- returns a const iterator to the beginning - @sa see @ref end() -- returns an iterator to the end - @sa see @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - iterator begin() noexcept - { - iterator result(this); - result.set_begin(); - return result; - } - - /*! - @copydoc basic_json::cbegin() - */ - const_iterator begin() const noexcept - { - return cbegin(); - } - - /*! - @brief returns a const iterator to the first element - - Returns a const iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).begin()`. - - @liveexample{The following code shows an example for `cbegin()`.,cbegin} - - @sa see @ref begin() -- returns an iterator to the beginning - @sa see @ref end() -- returns an iterator to the end - @sa see @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - const_iterator cbegin() const noexcept - { - const_iterator result(this); - result.set_begin(); - return result; - } - - /*! - @brief returns an iterator to one past the last element - - Returns an iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `end()`.,end} - - @sa see @ref cend() -- returns a const iterator to the end - @sa see @ref begin() -- returns an iterator to the beginning - @sa see @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - iterator end() noexcept - { - iterator result(this); - result.set_end(); - return result; - } - - /*! - @copydoc basic_json::cend() - */ - const_iterator end() const noexcept - { - return cend(); - } - - /*! - @brief returns a const iterator to one past the last element - - Returns a const iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).end()`. - - @liveexample{The following code shows an example for `cend()`.,cend} - - @sa see @ref end() -- returns an iterator to the end - @sa see @ref begin() -- returns an iterator to the beginning - @sa see @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - const_iterator cend() const noexcept - { - const_iterator result(this); - result.set_end(); - return result; - } - - /*! - @brief returns an iterator to the reverse-beginning - - Returns an iterator to the reverse-beginning; that is, the last element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(end())`. - - @liveexample{The following code shows an example for `rbegin()`.,rbegin} - - @sa see @ref crbegin() -- returns a const reverse iterator to the beginning - @sa see @ref rend() -- returns a reverse iterator to the end - @sa see @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - reverse_iterator rbegin() noexcept - { - return reverse_iterator(end()); - } - - /*! - @copydoc basic_json::crbegin() - */ - const_reverse_iterator rbegin() const noexcept - { - return crbegin(); - } - - /*! - @brief returns an iterator to the reverse-end - - Returns an iterator to the reverse-end; that is, one before the first - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(begin())`. - - @liveexample{The following code shows an example for `rend()`.,rend} - - @sa see @ref crend() -- returns a const reverse iterator to the end - @sa see @ref rbegin() -- returns a reverse iterator to the beginning - @sa see @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - reverse_iterator rend() noexcept - { - return reverse_iterator(begin()); - } - - /*! - @copydoc basic_json::crend() - */ - const_reverse_iterator rend() const noexcept - { - return crend(); - } - - /*! - @brief returns a const reverse iterator to the last element - - Returns a const iterator to the reverse-beginning; that is, the last - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rbegin()`. - - @liveexample{The following code shows an example for `crbegin()`.,crbegin} - - @sa see @ref rbegin() -- returns a reverse iterator to the beginning - @sa see @ref rend() -- returns a reverse iterator to the end - @sa see @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator(cend()); - } - - /*! - @brief returns a const reverse iterator to one before the first - - Returns a const reverse iterator to the reverse-end; that is, one before - the first element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rend()`. - - @liveexample{The following code shows an example for `crend()`.,crend} - - @sa see @ref rend() -- returns a reverse iterator to the end - @sa see @ref rbegin() -- returns a reverse iterator to the beginning - @sa see @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator(cbegin()); - } - - public: - /*! - @brief wrapper to access iterator member functions in range-based for - - This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a - reference to the JSON values is returned, so there is no access to the - underlying iterator. - - For loop without iterator_wrapper: - - @code{cpp} - for (auto it = j_object.begin(); it != j_object.end(); ++it) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - Range-based for loop without iterator proxy: - - @code{cpp} - for (auto it : j_object) - { - // "it" is of type json::reference and has no key() member - std::cout << "value: " << it << '\n'; - } - @endcode - - Range-based for loop with iterator proxy: - - @code{cpp} - for (auto it : json::iterator_wrapper(j_object)) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - @note When iterating over an array, `key()` will return the index of the - element as string (see example). - - @param[in] ref reference to a JSON value - @return iteration proxy object wrapping @a ref with an interface to use in - range-based for loops - - @liveexample{The following code shows how the wrapper is used,iterator_wrapper} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @note The name of this function is not yet final and may change in the - future. - - @deprecated This stream operator is deprecated and will be removed in - future 4.0.0 of the library. Please use @ref items() instead; - that is, replace `json::iterator_wrapper(j)` with `j.items()`. - */ - JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) - static iteration_proxy iterator_wrapper(reference ref) noexcept - { - return ref.items(); - } - - /*! - @copydoc iterator_wrapper(reference) - */ - JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) - static iteration_proxy iterator_wrapper(const_reference ref) noexcept - { - return ref.items(); - } - - /*! - @brief helper to access iterator member functions in range-based for - - This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a - reference to the JSON values is returned, so there is no access to the - underlying iterator. - - For loop without `items()` function: - - @code{cpp} - for (auto it = j_object.begin(); it != j_object.end(); ++it) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - Range-based for loop without `items()` function: - - @code{cpp} - for (auto it : j_object) - { - // "it" is of type json::reference and has no key() member - std::cout << "value: " << it << '\n'; - } - @endcode - - Range-based for loop with `items()` function: - - @code{cpp} - for (auto& el : j_object.items()) - { - std::cout << "key: " << el.key() << ", value:" << el.value() << '\n'; - } - @endcode - - The `items()` function also allows to use - [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding) - (C++17): - - @code{cpp} - for (auto& [key, val] : j_object.items()) - { - std::cout << "key: " << key << ", value:" << val << '\n'; - } - @endcode - - @note When iterating over an array, `key()` will return the index of the - element as string (see example). For primitive types (e.g., numbers), - `key()` returns an empty string. - - @warning Using `items()` on temporary objects is dangerous. Make sure the - object's lifetime exeeds the iteration. See - for more - information. - - @return iteration proxy object wrapping @a ref with an interface to use in - range-based for loops - - @liveexample{The following code shows how the function is used.,items} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 3.1.0, structured bindings support since 3.5.0. - */ - iteration_proxy items() noexcept - { - return iteration_proxy(*this); - } - - /*! - @copydoc items() - */ - iteration_proxy items() const noexcept - { - return iteration_proxy(*this); - } - - /// @} - - - ////////////// - // capacity // - ////////////// - - /// @name capacity - /// @{ - - /*! - @brief checks whether the container is empty. - - Checks if a JSON value has no elements (i.e. whether its @ref size is `0`). - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `true` - boolean | `false` - string | `false` - number | `false` - binary | `false` - object | result of function `object_t::empty()` - array | result of function `array_t::empty()` - - @liveexample{The following code uses `empty()` to check if a JSON - object contains any elements.,empty} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `empty()` functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @note This function does not return whether a string stored as JSON value - is empty - it returns whether the JSON container itself is empty which is - false in the case of a string. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `begin() == end()`. - - @sa see @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - bool empty() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return true; - } - - case value_t::array: - { - // delegate call to array_t::empty() - return m_value.array->empty(); - } - - case value_t::object: - { - // delegate call to object_t::empty() - return m_value.object->empty(); - } - - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - // all other types are nonempty - return false; - } - } - } - - /*! - @brief returns the number of elements - - Returns the number of elements in a JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` - boolean | `1` - string | `1` - number | `1` - binary | `1` - object | result of function object_t::size() - array | result of function array_t::size() - - @liveexample{The following code calls `size()` on the different value - types.,size} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their size() functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @note This function does not return the length of a string stored as JSON - value - it returns the number of elements in the JSON value which is 1 in - the case of a string. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `std::distance(begin(), end())`. - - @sa see @ref empty() -- checks whether the container is empty - @sa see @ref max_size() -- returns the maximal number of elements - - @since version 1.0.0 - */ - size_type size() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return 0; - } - - case value_t::array: - { - // delegate call to array_t::size() - return m_value.array->size(); - } - - case value_t::object: - { - // delegate call to object_t::size() - return m_value.object->size(); - } - - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - // all other types have size 1 - return 1; - } - } - } - - /*! - @brief returns the maximum possible number of elements - - Returns the maximum number of elements a JSON value is able to hold due to - system or library implementation limitations, i.e. `std::distance(begin(), - end())` for the JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` (same as `size()`) - boolean | `1` (same as `size()`) - string | `1` (same as `size()`) - number | `1` (same as `size()`) - binary | `1` (same as `size()`) - object | result of function `object_t::max_size()` - array | result of function `array_t::max_size()` - - @liveexample{The following code calls `max_size()` on the different value - types. Note the output is implementation specific.,max_size} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `max_size()` functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of returning `b.size()` where `b` is the largest - possible JSON value. - - @sa see @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - size_type max_size() const noexcept - { - switch (m_type) - { - case value_t::array: - { - // delegate call to array_t::max_size() - return m_value.array->max_size(); - } - - case value_t::object: - { - // delegate call to object_t::max_size() - return m_value.object->max_size(); - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - // all other types have max_size() == size() - return size(); - } - } - } - - /// @} - - - /////////////// - // modifiers // - /////////////// - - /// @name modifiers - /// @{ - - /*! - @brief clears the contents - - Clears the content of a JSON value and resets it to the default value as - if @ref basic_json(value_t) would have been called with the current value - type from @ref type(): - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - binary | An empty byte vector - object | `{}` - array | `[]` - - @post Has the same effect as calling - @code {.cpp} - *this = basic_json(type()); - @endcode - - @liveexample{The example below shows the effect of `clear()` to different - JSON types.,clear} - - @complexity Linear in the size of the JSON value. - - @iterators All iterators, pointers and references related to this container - are invalidated. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @sa see @ref basic_json(value_t) -- constructor that creates an object with the - same value than calling `clear()` - - @since version 1.0.0 - */ - void clear() noexcept - { - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = 0; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = 0; - break; - } - - case value_t::number_float: - { - m_value.number_float = 0.0; - break; - } - - case value_t::boolean: - { - m_value.boolean = false; - break; - } - - case value_t::string: - { - m_value.string->clear(); - break; - } - - case value_t::binary: - { - m_value.binary->clear(); - break; - } - - case value_t::array: - { - m_value.array->clear(); - break; - } - - case value_t::object: - { - m_value.object->clear(); - break; - } - - case value_t::null: - case value_t::discarded: - default: - break; - } - } - - /*! - @brief add an object to an array - - Appends the given element @a val to the end of the JSON value. If the - function is called on a JSON null value, an empty array is created before - appending @a val. - - @param[in] val the value to add to the JSON array - - @throw type_error.308 when called on a type other than JSON array or - null; example: `"cannot use push_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON array. Note how the `null` value was silently - converted to a JSON array.,push_back} - - @since version 1.0.0 - */ - void push_back(basic_json&& val) - { - // push_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (move semantics) - const auto old_capacity = m_value.array->capacity(); - m_value.array->push_back(std::move(val)); - set_parent(m_value.array->back(), old_capacity); - // if val is moved from, basic_json move constructor marks it null so we do not call the destructor - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(basic_json&& val) - { - push_back(std::move(val)); - return *this; - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - void push_back(const basic_json& val) - { - // push_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array - const auto old_capacity = m_value.array->capacity(); - m_value.array->push_back(val); - set_parent(m_value.array->back(), old_capacity); - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(const basic_json& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - Inserts the given element @a val to the JSON object. If the function is - called on a JSON null value, an empty object is created before inserting - @a val. - - @param[in] val the value to add to the JSON object - - @throw type_error.308 when called on a type other than JSON object or - null; example: `"cannot use push_back() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON object. Note how the `null` value was silently - converted to a JSON object.,push_back__object_t__value} - - @since version 1.0.0 - */ - void push_back(const typename object_t::value_type& val) - { - // push_back only works for null objects or objects - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to object - auto res = m_value.object->insert(val); - set_parent(res.first->second); - } - - /*! - @brief add an object to an object - @copydoc push_back(const typename object_t::value_type&) - */ - reference operator+=(const typename object_t::value_type& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - This function allows to use `push_back` with an initializer list. In case - - 1. the current value is an object, - 2. the initializer list @a init contains only two elements, and - 3. the first element of @a init is a string, - - @a init is converted into an object element and added using - @ref push_back(const typename object_t::value_type&). Otherwise, @a init - is converted to a JSON value and added using @ref push_back(basic_json&&). - - @param[in] init an initializer list - - @complexity Linear in the size of the initializer list @a init. - - @note This function is required to resolve an ambiguous overload error, - because pairs like `{"key", "value"}` can be both interpreted as - `object_t::value_type` or `std::initializer_list`, see - https://github.com/nlohmann/json/issues/235 for more information. - - @liveexample{The example shows how initializer lists are treated as - objects when possible.,push_back__initializer_list} - */ - void push_back(initializer_list_t init) - { - if (is_object() && init.size() == 2 && (*init.begin())->is_string()) - { - basic_json&& key = init.begin()->moved_or_copied(); - push_back(typename object_t::value_type( - std::move(key.get_ref()), (init.begin() + 1)->moved_or_copied())); - } - else - { - push_back(basic_json(init)); - } - } - - /*! - @brief add an object to an object - @copydoc push_back(initializer_list_t) - */ - reference operator+=(initializer_list_t init) - { - push_back(init); - return *this; - } - - /*! - @brief add an object to an array - - Creates a JSON value from the passed parameters @a args to the end of the - JSON value. If the function is called on a JSON null value, an empty array - is created before appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @return reference to the inserted element - - @throw type_error.311 when called on a type other than JSON array or - null; example: `"cannot use emplace_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` can be used to add - elements to a JSON array. Note how the `null` value was silently converted - to a JSON array.,emplace_back} - - @since version 2.0.8, returns reference since 3.7.0 - */ - template - reference emplace_back(Args&& ... args) - { - // emplace_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this)); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (perfect forwarding) - const auto old_capacity = m_value.array->capacity(); - m_value.array->emplace_back(std::forward(args)...); - return set_parent(m_value.array->back(), old_capacity); - } - - /*! - @brief add an object to an object if key does not exist - - Inserts a new element into a JSON object constructed in-place with the - given @a args if there is no element with the key in the container. If the - function is called on a JSON null value, an empty object is created before - appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @return a pair consisting of an iterator to the inserted element, or the - already-existing element if no insertion happened, and a bool - denoting whether the insertion took place. - - @throw type_error.311 when called on a type other than JSON object or - null; example: `"cannot use emplace() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `emplace()` can be used to add elements - to a JSON object. Note how the `null` value was silently converted to a - JSON object. Further note how no value is added if there was already one - value stored with the same key.,emplace} - - @since version 2.0.8 - */ - template - std::pair emplace(Args&& ... args) - { - // emplace only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) - { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this)); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array (perfect forwarding) - auto res = m_value.object->emplace(std::forward(args)...); - set_parent(res.first->second); - - // create result iterator and set iterator to the result of emplace - auto it = begin(); - it.m_it.object_iterator = res.first; - - // return pair of iterator and boolean - return {it, res.second}; - } - - /// Helper for insertion of an iterator - /// @note: This uses std::distance to support GCC 4.8, - /// see https://github.com/nlohmann/json/pull/1257 - template - iterator insert_iterator(const_iterator pos, Args&& ... args) - { - iterator result(this); - JSON_ASSERT(m_value.array != nullptr); - - auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); - m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); - result.m_it.array_iterator = m_value.array->begin() + insert_pos; - - // This could have been written as: - // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); - // but the return value of insert is missing in GCC 4.8, so it is written this way instead. - - set_parents(); - return result; - } - - /*! - @brief inserts element - - Inserts element @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] val element to insert - @return iterator pointing to the inserted @a val. - - @throw type_error.309 if called on JSON values other than arrays; - example: `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Constant plus linear in the distance between @a pos and end of - the container. - - @liveexample{The example shows how `insert()` is used.,insert} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const basic_json& val) - { - // insert only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); - } - - // insert to array and return iterator - return insert_iterator(pos, val); - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); - } - - /*! - @brief inserts element - @copydoc insert(const_iterator, const basic_json&) - */ - iterator insert(const_iterator pos, basic_json&& val) - { - return insert(pos, val); - } - - /*! - @brief inserts elements - - Inserts @a cnt copies of @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] cnt number of copies of @a val to insert - @param[in] val element to insert - @return iterator pointing to the first element inserted, or @a pos if - `cnt==0` - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Linear in @a cnt plus linear in the distance between @a pos - and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__count} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, size_type cnt, const basic_json& val) - { - // insert only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); - } - - // insert to array and return iterator - return insert_iterator(pos, cnt, val); - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)` before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - @throw invalid_iterator.211 if @a first or @a last are iterators into - container for which insert is called; example: `"passed iterators may not - belong to container"` - - @return iterator pointing to the first element inserted, or @a pos if - `first==last` - - @complexity Linear in `std::distance(first, last)` plus linear in the - distance between @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__range} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const_iterator first, const_iterator last) - { - // insert only works for arrays - if (JSON_HEDLEY_UNLIKELY(!is_array())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); - } - - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); - } - - if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) - { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this)); - } - - // insert to array and return iterator - return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); - } - - /*! - @brief inserts elements - - Inserts elements from initializer list @a ilist before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] ilist initializer list to insert the values from - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @return iterator pointing to the first element inserted, or @a pos if - `ilist` is empty - - @complexity Linear in `ilist.size()` plus linear in the distance between - @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__ilist} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, initializer_list_t ilist) - { - // insert only works for arrays - if (JSON_HEDLEY_UNLIKELY(!is_array())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); - } - - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); - } - - // insert to array and return iterator - return insert_iterator(pos, ilist.begin(), ilist.end()); - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)`. - - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than objects; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if iterator @a first or @a last does does not - point to an object; example: `"iterators first and last must point to - objects"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - - @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number - of elements to insert. - - @liveexample{The example shows how `insert()` is used.,insert__range_object} - - @since version 3.0.0 - */ - void insert(const_iterator first, const_iterator last) - { - // insert only works for objects - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); - } - - // passed iterators must belong to objects - if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); - } - - m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); - } - - /*! - @brief updates a JSON object from another object, overwriting existing keys - - Inserts all values from JSON object @a j and overwrites existing keys. - - @param[in] j JSON object to read values from - - @throw type_error.312 if called on JSON values other than objects; example: - `"cannot use update() with string"` - - @complexity O(N*log(size() + N)), where N is the number of elements to - insert. - - @liveexample{The example shows how `update()` is used.,update} - - @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update - - @since version 3.0.0 - */ - void update(const_reference j) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); - } - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()), *this)); - } - - for (auto it = j.cbegin(); it != j.cend(); ++it) - { - m_value.object->operator[](it.key()) = it.value(); - } - } - - /*! - @brief updates a JSON object from another object, overwriting existing keys - - Inserts all values from from range `[first, last)` and overwrites existing - keys. - - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.312 if called on JSON values other than objects; example: - `"cannot use update() with string"` - @throw invalid_iterator.202 if iterator @a first or @a last does does not - point to an object; example: `"iterators first and last must point to - objects"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - - @complexity O(N*log(size() + N)), where N is the number of elements to - insert. - - @liveexample{The example shows how `update()` is used__range.,update} - - @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update - - @since version 3.0.0 - */ - void update(const_iterator first, const_iterator last) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); - } - - // passed iterators must belong to objects - if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object() - || !last.m_object->is_object())) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); - } - - for (auto it = first; it != last; ++it) - { - m_value.object->operator[](it.key()) = it.value(); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of the JSON value with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other JSON value to exchange the contents with - - @complexity Constant. - - @liveexample{The example below shows how JSON values can be swapped with - `swap()`.,swap__reference} - - @since version 1.0.0 - */ - void swap(reference other) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); - - set_parents(); - other.set_parents(); - assert_invariant(); - } - - /*! - @brief exchanges the values - - Exchanges the contents of the JSON value from @a left with those of @a right. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. implemented as a friend function callable via ADL. - - @param[in,out] left JSON value to exchange the contents with - @param[in,out] right JSON value to exchange the contents with - - @complexity Constant. - - @liveexample{The example below shows how JSON values can be swapped with - `swap()`.,swap__reference} - - @since version 1.0.0 - */ - friend void swap(reference left, reference right) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - left.swap(right); - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON array with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other array to exchange the contents with - - @throw type_error.310 when JSON value is not an array; example: `"cannot - use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how arrays can be swapped with - `swap()`.,swap__array_t} - - @since version 1.0.0 - */ - void swap(array_t& other) // NOLINT(bugprone-exception-escape) - { - // swap only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - std::swap(*(m_value.array), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON object with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other object to exchange the contents with - - @throw type_error.310 when JSON value is not an object; example: - `"cannot use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how objects can be swapped with - `swap()`.,swap__object_t} - - @since version 1.0.0 - */ - void swap(object_t& other) // NOLINT(bugprone-exception-escape) - { - // swap only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - std::swap(*(m_value.object), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON string with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other string to exchange the contents with - - @throw type_error.310 when JSON value is not a string; example: `"cannot - use swap() with boolean"` - - @complexity Constant. - - @liveexample{The example below shows how strings can be swapped with - `swap()`.,swap__string_t} - - @since version 1.0.0 - */ - void swap(string_t& other) // NOLINT(bugprone-exception-escape) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_string())) - { - std::swap(*(m_value.string), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON string with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other binary to exchange the contents with - - @throw type_error.310 when JSON value is not a string; example: `"cannot - use swap() with boolean"` - - @complexity Constant. - - @liveexample{The example below shows how strings can be swapped with - `swap()`.,swap__binary_t} - - @since version 3.8.0 - */ - void swap(binary_t& other) // NOLINT(bugprone-exception-escape) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_binary())) - { - std::swap(*(m_value.binary), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); - } - } - - /// @copydoc swap(binary_t&) - void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_binary())) - { - std::swap(*(m_value.binary), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); - } - } - - /// @} - - public: - ////////////////////////////////////////// - // lexicographical comparison operators // - ////////////////////////////////////////// - - /// @name lexicographical comparison operators - /// @{ - - /*! - @brief comparison: equal - - Compares two JSON values for equality according to the following rules: - - Two JSON values are equal if (1) they are from the same type and (2) - their stored values are the same according to their respective - `operator==`. - - Integer and floating-point numbers are automatically converted before - comparison. Note that two NaN values are always treated as unequal. - - Two JSON null values are equal. - - @note Floating-point inside JSON values numbers are compared with - `json::number_float_t::operator==` which is `double::operator==` by - default. To compare floating-point while respecting an epsilon, an alternative - [comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39) - could be used, for instance - @code {.cpp} - template::value, T>::type> - inline bool is_same(T a, T b, T epsilon = std::numeric_limits::epsilon()) noexcept - { - return std::abs(a - b) <= epsilon; - } - @endcode - Or you can self-defined operator equal function like this: - @code {.cpp} - bool my_equal(const_reference lhs, const_reference rhs) { - const auto lhs_type lhs.type(); - const auto rhs_type rhs.type(); - if (lhs_type == rhs_type) { - switch(lhs_type) - // self_defined case - case value_t::number_float: - return std::abs(lhs - rhs) <= std::numeric_limits::epsilon(); - // other cases remain the same with the original - ... - } - ... - } - @endcode - - @note NaN values never compare equal to themselves or to other NaN values. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are equal - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__equal} - - @since version 1.0.0 - */ - friend bool operator==(const_reference lhs, const_reference rhs) noexcept - { -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - return *lhs.m_value.array == *rhs.m_value.array; - - case value_t::object: - return *lhs.m_value.object == *rhs.m_value.object; - - case value_t::null: - return true; - - case value_t::string: - return *lhs.m_value.string == *rhs.m_value.string; - - case value_t::boolean: - return lhs.m_value.boolean == rhs.m_value.boolean; - - case value_t::number_integer: - return lhs.m_value.number_integer == rhs.m_value.number_integer; - - case value_t::number_unsigned: - return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; - - case value_t::number_float: - return lhs.m_value.number_float == rhs.m_value.number_float; - - case value_t::binary: - return *lhs.m_value.binary == *rhs.m_value.binary; - - case value_t::discarded: - default: - return false; - } - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); - } - - return false; -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const_reference lhs, ScalarType rhs) noexcept - { - return lhs == basic_json(rhs); - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) == rhs; - } - - /*! - @brief comparison: not equal - - Compares two JSON values for inequality by calculating `not (lhs == rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are not equal - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__notequal} - - @since version 1.0.0 - */ - friend bool operator!=(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs == rhs); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept - { - return lhs != basic_json(rhs); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) != rhs; - } - - /*! - @brief comparison: less than - - Compares whether one JSON value @a lhs is less than another JSON value @a - rhs according to the following rules: - - If @a lhs and @a rhs have the same type, the values are compared using - the default `<` operator. - - Integer and floating-point numbers are automatically converted before - comparison - - In case @a lhs and @a rhs have different types, the values are ignored - and the order of the types is considered, see - @ref operator<(const value_t, const value_t). - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__less} - - @since version 1.0.0 - */ - friend bool operator<(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - // note parentheses are necessary, see - // https://github.com/nlohmann/json/issues/1530 - return (*lhs.m_value.array) < (*rhs.m_value.array); - - case value_t::object: - return (*lhs.m_value.object) < (*rhs.m_value.object); - - case value_t::null: - return false; - - case value_t::string: - return (*lhs.m_value.string) < (*rhs.m_value.string); - - case value_t::boolean: - return (lhs.m_value.boolean) < (rhs.m_value.boolean); - - case value_t::number_integer: - return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); - - case value_t::number_unsigned: - return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); - - case value_t::number_float: - return (lhs.m_value.number_float) < (rhs.m_value.number_float); - - case value_t::binary: - return (*lhs.m_value.binary) < (*rhs.m_value.binary); - - case value_t::discarded: - default: - return false; - } - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; - } - - // We only reach this line if we cannot compare values. In that case, - // we compare types. Note we have to call the operator explicitly, - // because MSVC has problems otherwise. - return operator<(lhs_type, rhs_type); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const_reference lhs, ScalarType rhs) noexcept - { - return lhs < basic_json(rhs); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) < rhs; - } - - /*! - @brief comparison: less than or equal - - Compares whether one JSON value @a lhs is less than or equal to another - JSON value by calculating `not (rhs < lhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than or equal to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greater} - - @since version 1.0.0 - */ - friend bool operator<=(const_reference lhs, const_reference rhs) noexcept - { - return !(rhs < lhs); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept - { - return lhs <= basic_json(rhs); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) <= rhs; - } - - /*! - @brief comparison: greater than - - Compares whether one JSON value @a lhs is greater than another - JSON value by calculating `not (lhs <= rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__lessequal} - - @since version 1.0.0 - */ - friend bool operator>(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs <= rhs); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const_reference lhs, ScalarType rhs) noexcept - { - return lhs > basic_json(rhs); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) > rhs; - } - - /*! - @brief comparison: greater than or equal - - Compares whether one JSON value @a lhs is greater than or equal to another - JSON value by calculating `not (lhs < rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than or equal to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greaterequal} - - @since version 1.0.0 - */ - friend bool operator>=(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs < rhs); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept - { - return lhs >= basic_json(rhs); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) >= rhs; - } - - /// @} - - /////////////////// - // serialization // - /////////////////// - - /// @name serialization - /// @{ -#ifndef JSON_NO_IO - /*! - @brief serialize to stream - - Serialize the given JSON value @a j to the output stream @a o. The JSON - value will be serialized using the @ref dump member function. - - - The indentation of the output can be controlled with the member variable - `width` of the output stream @a o. For instance, using the manipulator - `std::setw(4)` on @a o sets the indentation level to `4` and the - serialization result is the same as calling `dump(4)`. - - - The indentation character can be controlled with the member variable - `fill` of the output stream @a o. For instance, the manipulator - `std::setfill('\\t')` sets indentation to use a tab character rather than - the default space character. - - @param[in,out] o stream to serialize to - @param[in] j JSON value to serialize - - @return the stream @a o - - @throw type_error.316 if a string stored inside the JSON value is not - UTF-8 encoded - - @complexity Linear. - - @liveexample{The example below shows the serialization with different - parameters to `width` to adjust the indentation level.,operator_serialize} - - @since version 1.0.0; indentation character added in version 3.0.0 - */ - friend std::ostream& operator<<(std::ostream& o, const basic_json& j) - { - // read width member and use it as indentation parameter if nonzero - const bool pretty_print = o.width() > 0; - const auto indentation = pretty_print ? o.width() : 0; - - // reset width to 0 for subsequent calls to this stream - o.width(0); - - // do the actual serialization - serializer s(detail::output_adapter(o), o.fill()); - s.dump(j, pretty_print, false, static_cast(indentation)); - return o; - } - - /*! - @brief serialize to stream - @deprecated This stream operator is deprecated and will be removed in - future 4.0.0 of the library. Please use - @ref operator<<(std::ostream&, const basic_json&) - instead; that is, replace calls like `j >> o;` with `o << j;`. - @since version 1.0.0; deprecated since version 3.0.0 - */ - JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) - friend std::ostream& operator>>(const basic_json& j, std::ostream& o) - { - return o << j; - } -#endif // JSON_NO_IO - /// @} - - - ///////////////////// - // deserialization // - ///////////////////// - - /// @name deserialization - /// @{ - - /*! - @brief deserialize from a compatible input - - @tparam InputType A compatible input, for instance - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb or reading from the input @a i has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from an array.,parse__array__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__string__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__istream__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function reading - from a contiguous container.,parse__contiguouscontainer__parser_callback_t} - - @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to - ignore comments. - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json parse(InputType&& i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - /*! - @brief deserialize from a pair of character iterators - - The value_type of the iterator must be a integral type with size of 1, 2 or - 4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32. - - @param[in] first iterator to start of character range - @param[in] last iterator to end of character range - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json parse(IteratorType first, - IteratorType last, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) - static basic_json parse(detail::span_input_adapter&& i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - /*! - @brief check if the input is valid JSON - - Unlike the @ref parse(InputType&&, const parser_callback_t,const bool) - function, this function neither throws an exception in case of invalid JSON - input (i.e., a parse error) nor creates diagnostic information. - - @tparam InputType A compatible input, for instance - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return Whether the input read from @a i is valid JSON. - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `accept()` function reading - from a string.,accept__string} - */ - template - static bool accept(InputType&& i, - const bool ignore_comments = false) - { - return parser(detail::input_adapter(std::forward(i)), nullptr, false, ignore_comments).accept(true); - } - - template - static bool accept(IteratorType first, IteratorType last, - const bool ignore_comments = false) - { - return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) - static bool accept(detail::span_input_adapter&& i, - const bool ignore_comments = false) - { - return parser(i.get(), nullptr, false, ignore_comments).accept(true); - } - - /*! - @brief generate SAX events - - The SAX event lister must follow the interface of @ref json_sax. - - This function reads from a compatible input. Examples are: - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in,out] sax SAX event listener - @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON) - @param[in] strict whether the input has to be consumed completely - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default); only applies to the JSON file format. - - @return return value of the last processed SAX event - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the SAX consumer @a sax has - a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `sax_parse()` function - reading from string and processing the events with a user-defined SAX - event consumer.,sax_parse} - - @since version 3.2.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - static bool sax_parse(InputType&& i, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = detail::input_adapter(std::forward(i)); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } - - template - JSON_HEDLEY_NON_NULL(3) - static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = detail::input_adapter(std::move(first), std::move(last)); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } - - template - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) - JSON_HEDLEY_NON_NULL(2) - static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = i.get(); - return format == input_format_t::json - // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } -#ifndef JSON_NO_IO - /*! - @brief deserialize from stream - @deprecated This stream operator is deprecated and will be removed in - version 4.0.0 of the library. Please use - @ref operator>>(std::istream&, basic_json&) - instead; that is, replace calls like `j << i;` with `i >> j;`. - @since version 1.0.0; deprecated since version 3.0.0 - */ - JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) - friend std::istream& operator<<(basic_json& j, std::istream& i) - { - return operator>>(i, j); - } - - /*! - @brief deserialize from stream - - Deserializes an input stream to a JSON value. - - @param[in,out] i input stream to read a serialized JSON value from - @param[in,out] j JSON value to write the deserialized input to - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below shows how a JSON value is constructed by - reading a serialization from a stream.,operator_deserialize} - - @sa parse(std::istream&, const parser_callback_t) for a variant with a - parser callback function to filter values while parsing - - @since version 1.0.0 - */ - friend std::istream& operator>>(std::istream& i, basic_json& j) - { - parser(detail::input_adapter(i)).parse(false, j); - return i; - } -#endif // JSON_NO_IO - /// @} - - /////////////////////////// - // convenience functions // - /////////////////////////// - - /*! - @brief return the type as string - - Returns the type name as string to be used in error messages - usually to - indicate that a function was called on a wrong JSON type. - - @return a string representation of a the @a m_type member: - Value type | return value - ----------- | ------------- - null | `"null"` - boolean | `"boolean"` - string | `"string"` - number | `"number"` (for all number types) - object | `"object"` - array | `"array"` - binary | `"binary"` - discarded | `"discarded"` - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @complexity Constant. - - @liveexample{The following code exemplifies `type_name()` for all JSON - types.,type_name} - - @sa see @ref type() -- return the type of the JSON value - @sa see @ref operator value_t() -- return the type of the JSON value (implicit) - - @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept` - since 3.0.0 - */ - JSON_HEDLEY_RETURNS_NON_NULL - const char* type_name() const noexcept - { - { - switch (m_type) - { - case value_t::null: - return "null"; - case value_t::object: - return "object"; - case value_t::array: - return "array"; - case value_t::string: - return "string"; - case value_t::boolean: - return "boolean"; - case value_t::binary: - return "binary"; - case value_t::discarded: - return "discarded"; - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - default: - return "number"; - } - } - } - - - JSON_PRIVATE_UNLESS_TESTED: - ////////////////////// - // member variables // - ////////////////////// - - /// the type of the current element - value_t m_type = value_t::null; - - /// the value of the current element - json_value m_value = {}; - -#if JSON_DIAGNOSTICS - /// a pointer to a parent value (for debugging purposes) - basic_json* m_parent = nullptr; -#endif - - ////////////////////////////////////////// - // binary serialization/deserialization // - ////////////////////////////////////////// - - /// @name binary serialization/deserialization support - /// @{ - - public: - /*! - @brief create a CBOR serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the CBOR (Concise - Binary Object Representation) serialization format. CBOR is a binary - serialization format which aims to be more compact than JSON itself, yet - more efficient to parse. - - The library uses the following mapping from JSON values types to - CBOR types according to the CBOR specification (RFC 7049): - - JSON value type | value/range | CBOR type | first byte - --------------- | ------------------------------------------ | ---------------------------------- | --------------- - null | `null` | Null | 0xF6 - boolean | `true` | True | 0xF5 - boolean | `false` | False | 0xF4 - number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B - number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A - number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 - number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 - number_integer | -24..-1 | Negative integer | 0x20..0x37 - number_integer | 0..23 | Integer | 0x00..0x17 - number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A - number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B - number_unsigned | 0..23 | Integer | 0x00..0x17 - number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A - number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B - number_float | *any value representable by a float* | Single-Precision Float | 0xFA - number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB - string | *length*: 0..23 | UTF-8 string | 0x60..0x77 - string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 - string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 - string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A - string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B - array | *size*: 0..23 | array | 0x80..0x97 - array | *size*: 23..255 | array (1 byte follow) | 0x98 - array | *size*: 256..65535 | array (2 bytes follow) | 0x99 - array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A - array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B - object | *size*: 0..23 | map | 0xA0..0xB7 - object | *size*: 23..255 | map (1 byte follow) | 0xB8 - object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 - object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA - object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB - binary | *size*: 0..23 | byte string | 0x40..0x57 - binary | *size*: 23..255 | byte string (1 byte follow) | 0x58 - binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59 - binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A - binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B - - Binary values with subtype are mapped to tagged values (0xD8..0xDB) - depending on the subtype, followed by a byte string, see "binary" cells - in the table above. - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a CBOR value. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @note The following CBOR types are not used in the conversion: - - UTF-8 strings terminated by "break" (0x7F) - - arrays terminated by "break" (0x9F) - - maps terminated by "break" (0xBF) - - byte strings terminated by "break" (0x5F) - - date/time (0xC0..0xC1) - - bignum (0xC2..0xC3) - - decimal fraction (0xC4) - - bigfloat (0xC5) - - expected conversions (0xD5..0xD7) - - simple values (0xE0..0xF3, 0xF8) - - undefined (0xF7) - - half-precision floats (0xF9) - - break (0xFF) - - @param[in] j JSON value to serialize - @return CBOR serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in CBOR format.,to_cbor} - - @sa http://cbor.io - @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the - analogous deserialization - @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format - @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9; compact representation of floating-point numbers - since version 3.8.0 - */ - static std::vector to_cbor(const basic_json& j) - { - std::vector result; - to_cbor(j, result); - return result; - } - - static void to_cbor(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_cbor(j); - } - - static void to_cbor(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_cbor(j); - } - - /*! - @brief create a MessagePack serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the MessagePack - serialization format. MessagePack is a binary serialization format which - aims to be more compact than JSON itself, yet more efficient to parse. - - The library uses the following mapping from JSON values types to - MessagePack types according to the MessagePack specification: - - JSON value type | value/range | MessagePack type | first byte - --------------- | --------------------------------- | ---------------- | ---------- - null | `null` | nil | 0xC0 - boolean | `true` | true | 0xC3 - boolean | `false` | false | 0xC2 - number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 - number_integer | -2147483648..-32769 | int32 | 0xD2 - number_integer | -32768..-129 | int16 | 0xD1 - number_integer | -128..-33 | int8 | 0xD0 - number_integer | -32..-1 | negative fixint | 0xE0..0xFF - number_integer | 0..127 | positive fixint | 0x00..0x7F - number_integer | 128..255 | uint 8 | 0xCC - number_integer | 256..65535 | uint 16 | 0xCD - number_integer | 65536..4294967295 | uint 32 | 0xCE - number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF - number_unsigned | 0..127 | positive fixint | 0x00..0x7F - number_unsigned | 128..255 | uint 8 | 0xCC - number_unsigned | 256..65535 | uint 16 | 0xCD - number_unsigned | 65536..4294967295 | uint 32 | 0xCE - number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF - number_float | *any value representable by a float* | float 32 | 0xCA - number_float | *any value NOT representable by a float* | float 64 | 0xCB - string | *length*: 0..31 | fixstr | 0xA0..0xBF - string | *length*: 32..255 | str 8 | 0xD9 - string | *length*: 256..65535 | str 16 | 0xDA - string | *length*: 65536..4294967295 | str 32 | 0xDB - array | *size*: 0..15 | fixarray | 0x90..0x9F - array | *size*: 16..65535 | array 16 | 0xDC - array | *size*: 65536..4294967295 | array 32 | 0xDD - object | *size*: 0..15 | fix map | 0x80..0x8F - object | *size*: 16..65535 | map 16 | 0xDE - object | *size*: 65536..4294967295 | map 32 | 0xDF - binary | *size*: 0..255 | bin 8 | 0xC4 - binary | *size*: 256..65535 | bin 16 | 0xC5 - binary | *size*: 65536..4294967295 | bin 32 | 0xC6 - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a MessagePack value. - - @note The following values can **not** be converted to a MessagePack value: - - strings with more than 4294967295 bytes - - byte strings with more than 4294967295 bytes - - arrays with more than 4294967295 elements - - objects with more than 4294967295 elements - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @param[in] j JSON value to serialize - @return MessagePack serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in MessagePack format.,to_msgpack} - - @sa http://msgpack.org - @sa see @ref from_msgpack for the analogous deserialization - @sa see @ref to_cbor(const basic_json& for the related CBOR format - @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9 - */ - static std::vector to_msgpack(const basic_json& j) - { - std::vector result; - to_msgpack(j, result); - return result; - } - - static void to_msgpack(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_msgpack(j); - } - - static void to_msgpack(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_msgpack(j); - } - - /*! - @brief create a UBJSON serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the UBJSON - (Universal Binary JSON) serialization format. UBJSON aims to be more compact - than JSON itself, yet more efficient to parse. - - The library uses the following mapping from JSON values types to - UBJSON types according to the UBJSON specification: - - JSON value type | value/range | UBJSON type | marker - --------------- | --------------------------------- | ----------- | ------ - null | `null` | null | `Z` - boolean | `true` | true | `T` - boolean | `false` | false | `F` - number_integer | -9223372036854775808..-2147483649 | int64 | `L` - number_integer | -2147483648..-32769 | int32 | `l` - number_integer | -32768..-129 | int16 | `I` - number_integer | -128..127 | int8 | `i` - number_integer | 128..255 | uint8 | `U` - number_integer | 256..32767 | int16 | `I` - number_integer | 32768..2147483647 | int32 | `l` - number_integer | 2147483648..9223372036854775807 | int64 | `L` - number_unsigned | 0..127 | int8 | `i` - number_unsigned | 128..255 | uint8 | `U` - number_unsigned | 256..32767 | int16 | `I` - number_unsigned | 32768..2147483647 | int32 | `l` - number_unsigned | 2147483648..9223372036854775807 | int64 | `L` - number_unsigned | 2147483649..18446744073709551615 | high-precision | `H` - number_float | *any value* | float64 | `D` - string | *with shortest length indicator* | string | `S` - array | *see notes on optimized format* | array | `[` - object | *see notes on optimized format* | map | `{` - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a UBJSON value. - - @note The following values can **not** be converted to a UBJSON value: - - strings with more than 9223372036854775807 bytes (theoretical) - - @note The following markers are not used in the conversion: - - `Z`: no-op values are not created. - - `C`: single-byte strings are serialized with `S` markers. - - @note Any UBJSON output created @ref to_ubjson can be successfully parsed - by @ref from_ubjson. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @note The optimized formats for containers are supported: Parameter - @a use_size adds size information to the beginning of a container and - removes the closing marker. Parameter @a use_type further checks - whether all elements of a container have the same type and adds the - type marker to the beginning of the container. The @a use_type - parameter must only be used together with @a use_size = true. Note - that @a use_size = true alone may result in larger representations - - the benefit of this parameter is that the receiving side is - immediately informed on the number of elements of the container. - - @note If the JSON data contains the binary type, the value stored is a list - of integers, as suggested by the UBJSON documentation. In particular, - this means that serialization and the deserialization of a JSON - containing binary values into UBJSON and back will result in a - different JSON object. - - @param[in] j JSON value to serialize - @param[in] use_size whether to add size annotations to container types - @param[in] use_type whether to add type annotations to container types - (must be combined with @a use_size = true) - @return UBJSON serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in UBJSON format.,to_ubjson} - - @sa http://ubjson.org - @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the - analogous deserialization - @sa see @ref to_cbor(const basic_json& for the related CBOR format - @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format - - @since version 3.1.0 - */ - static std::vector to_ubjson(const basic_json& j, - const bool use_size = false, - const bool use_type = false) - { - std::vector result; - to_ubjson(j, result, use_size, use_type); - return result; - } - - static void to_ubjson(const basic_json& j, detail::output_adapter o, - const bool use_size = false, const bool use_type = false) - { - binary_writer(o).write_ubjson(j, use_size, use_type); - } - - static void to_ubjson(const basic_json& j, detail::output_adapter o, - const bool use_size = false, const bool use_type = false) - { - binary_writer(o).write_ubjson(j, use_size, use_type); - } - - - /*! - @brief Serializes the given JSON object `j` to BSON and returns a vector - containing the corresponding BSON-representation. - - BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are - stored as a single entity (a so-called document). - - The library uses the following mapping from JSON values types to BSON types: - - JSON value type | value/range | BSON type | marker - --------------- | --------------------------------- | ----------- | ------ - null | `null` | null | 0x0A - boolean | `true`, `false` | boolean | 0x08 - number_integer | -9223372036854775808..-2147483649 | int64 | 0x12 - number_integer | -2147483648..2147483647 | int32 | 0x10 - number_integer | 2147483648..9223372036854775807 | int64 | 0x12 - number_unsigned | 0..2147483647 | int32 | 0x10 - number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12 - number_unsigned | 9223372036854775808..18446744073709551615| -- | -- - number_float | *any value* | double | 0x01 - string | *any value* | string | 0x02 - array | *any value* | document | 0x04 - object | *any value* | document | 0x03 - binary | *any value* | binary | 0x05 - - @warning The mapping is **incomplete**, since only JSON-objects (and things - contained therein) can be serialized to BSON. - Also, integers larger than 9223372036854775807 cannot be serialized to BSON, - and the keys may not contain U+0000, since they are serialized a - zero-terminated c-strings. - - @throw out_of_range.407 if `j.is_number_unsigned() && j.get() > 9223372036854775807` - @throw out_of_range.409 if a key in `j` contains a NULL (U+0000) - @throw type_error.317 if `!j.is_object()` - - @pre The input `j` is required to be an object: `j.is_object() == true`. - - @note Any BSON output created via @ref to_bson can be successfully parsed - by @ref from_bson. - - @param[in] j JSON value to serialize - @return BSON serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in BSON format.,to_bson} - - @sa http://bsonspec.org/spec.html - @sa see @ref from_bson(detail::input_adapter&&, const bool strict) for the - analogous deserialization - @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - @sa see @ref to_cbor(const basic_json&) for the related CBOR format - @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format - */ - static std::vector to_bson(const basic_json& j) - { - std::vector result; - to_bson(j, result); - return result; - } - - /*! - @brief Serializes the given JSON object `j` to BSON and forwards the - corresponding BSON-representation to the given output_adapter `o`. - @param j The JSON object to convert to BSON. - @param o The output adapter that receives the binary BSON representation. - @pre The input `j` shall be an object: `j.is_object() == true` - @sa see @ref to_bson(const basic_json&) - */ - static void to_bson(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_bson(j); - } - - /*! - @copydoc to_bson(const basic_json&, detail::output_adapter) - */ - static void to_bson(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_bson(j); - } - - - /*! - @brief create a JSON value from an input in CBOR format - - Deserializes a given input @a i to a JSON value using the CBOR (Concise - Binary Object Representation) serialization format. - - The library maps CBOR types to JSON value types as follows: - - CBOR type | JSON value type | first byte - ---------------------- | --------------- | ---------- - Integer | number_unsigned | 0x00..0x17 - Unsigned integer | number_unsigned | 0x18 - Unsigned integer | number_unsigned | 0x19 - Unsigned integer | number_unsigned | 0x1A - Unsigned integer | number_unsigned | 0x1B - Negative integer | number_integer | 0x20..0x37 - Negative integer | number_integer | 0x38 - Negative integer | number_integer | 0x39 - Negative integer | number_integer | 0x3A - Negative integer | number_integer | 0x3B - Byte string | binary | 0x40..0x57 - Byte string | binary | 0x58 - Byte string | binary | 0x59 - Byte string | binary | 0x5A - Byte string | binary | 0x5B - UTF-8 string | string | 0x60..0x77 - UTF-8 string | string | 0x78 - UTF-8 string | string | 0x79 - UTF-8 string | string | 0x7A - UTF-8 string | string | 0x7B - UTF-8 string | string | 0x7F - array | array | 0x80..0x97 - array | array | 0x98 - array | array | 0x99 - array | array | 0x9A - array | array | 0x9B - array | array | 0x9F - map | object | 0xA0..0xB7 - map | object | 0xB8 - map | object | 0xB9 - map | object | 0xBA - map | object | 0xBB - map | object | 0xBF - False | `false` | 0xF4 - True | `true` | 0xF5 - Null | `null` | 0xF6 - Half-Precision Float | number_float | 0xF9 - Single-Precision Float | number_float | 0xFA - Double-Precision Float | number_float | 0xFB - - @warning The mapping is **incomplete** in the sense that not all CBOR - types can be converted to a JSON value. The following CBOR types - are not supported and will yield parse errors (parse_error.112): - - date/time (0xC0..0xC1) - - bignum (0xC2..0xC3) - - decimal fraction (0xC4) - - bigfloat (0xC5) - - expected conversions (0xD5..0xD7) - - simple values (0xE0..0xF3, 0xF8) - - undefined (0xF7) - - @warning CBOR allows map keys of any type, whereas JSON only allows - strings as keys in object values. Therefore, CBOR maps with keys - other than UTF-8 strings are rejected (parse_error.113). - - @note Any CBOR output created @ref to_cbor can be successfully parsed by - @ref from_cbor. - - @param[in] i an input in CBOR format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] tag_handler how to treat CBOR tags (optional, error by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if unsupported features from CBOR were - used in the given input @a v or if the input is not valid CBOR - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in CBOR - format to a JSON value.,from_cbor} - - @sa http://cbor.io - @sa see @ref to_cbor(const basic_json&) for the analogous serialization - @sa see @ref from_msgpack(InputType&&, const bool, const bool) for the - related MessagePack format - @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9; parameter @a start_index since 2.1.1; changed to - consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @a allow_exceptions parameter - since 3.2.0; added @a tag_handler parameter since 3.9.0. - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_cbor(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_cbor(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) - static basic_json from_cbor(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); - } - - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) - static basic_json from_cbor(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @brief create a JSON value from an input in MessagePack format - - Deserializes a given input @a i to a JSON value using the MessagePack - serialization format. - - The library maps MessagePack types to JSON value types as follows: - - MessagePack type | JSON value type | first byte - ---------------- | --------------- | ---------- - positive fixint | number_unsigned | 0x00..0x7F - fixmap | object | 0x80..0x8F - fixarray | array | 0x90..0x9F - fixstr | string | 0xA0..0xBF - nil | `null` | 0xC0 - false | `false` | 0xC2 - true | `true` | 0xC3 - float 32 | number_float | 0xCA - float 64 | number_float | 0xCB - uint 8 | number_unsigned | 0xCC - uint 16 | number_unsigned | 0xCD - uint 32 | number_unsigned | 0xCE - uint 64 | number_unsigned | 0xCF - int 8 | number_integer | 0xD0 - int 16 | number_integer | 0xD1 - int 32 | number_integer | 0xD2 - int 64 | number_integer | 0xD3 - str 8 | string | 0xD9 - str 16 | string | 0xDA - str 32 | string | 0xDB - array 16 | array | 0xDC - array 32 | array | 0xDD - map 16 | object | 0xDE - map 32 | object | 0xDF - bin 8 | binary | 0xC4 - bin 16 | binary | 0xC5 - bin 32 | binary | 0xC6 - ext 8 | binary | 0xC7 - ext 16 | binary | 0xC8 - ext 32 | binary | 0xC9 - fixext 1 | binary | 0xD4 - fixext 2 | binary | 0xD5 - fixext 4 | binary | 0xD6 - fixext 8 | binary | 0xD7 - fixext 16 | binary | 0xD8 - negative fixint | number_integer | 0xE0-0xFF - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @param[in] i an input in MessagePack format convertible to an input - adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if unsupported features from MessagePack were - used in the given input @a i or if the input is not valid MessagePack - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - MessagePack format to a JSON value.,from_msgpack} - - @sa http://msgpack.org - @sa see @ref to_msgpack(const basic_json&) for the analogous serialization - @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa see @ref from_ubjson(InputType&&, const bool, const bool) for - the related UBJSON format - @sa see @ref from_bson(InputType&&, const bool, const bool) for - the related BSON format - - @since version 2.0.9; parameter @a start_index since 2.1.1; changed to - consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @a allow_exceptions parameter - since 3.2.0 - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_msgpack(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_msgpack(InputType&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_msgpack(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) - static basic_json from_msgpack(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_msgpack(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) - static basic_json from_msgpack(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - /*! - @brief create a JSON value from an input in UBJSON format - - Deserializes a given input @a i to a JSON value using the UBJSON (Universal - Binary JSON) serialization format. - - The library maps UBJSON types to JSON value types as follows: - - UBJSON type | JSON value type | marker - ----------- | --------------------------------------- | ------ - no-op | *no value, next value is read* | `N` - null | `null` | `Z` - false | `false` | `F` - true | `true` | `T` - float32 | number_float | `d` - float64 | number_float | `D` - uint8 | number_unsigned | `U` - int8 | number_integer | `i` - int16 | number_integer | `I` - int32 | number_integer | `l` - int64 | number_integer | `L` - high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H' - string | string | `S` - char | string | `C` - array | array (optimized values are supported) | `[` - object | object (optimized values are supported) | `{` - - @note The mapping is **complete** in the sense that any UBJSON value can - be converted to a JSON value. - - @param[in] i an input in UBJSON format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if a parse error occurs - @throw parse_error.113 if a string could not be parsed successfully - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - UBJSON format to a JSON value.,from_ubjson} - - @sa http://ubjson.org - @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the - analogous serialization - @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa see @ref from_msgpack(InputType&&, const bool, const bool) for - the related MessagePack format - @sa see @ref from_bson(InputType&&, const bool, const bool) for - the related BSON format - - @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0 - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_ubjson(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_ubjson(InputType&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_ubjson(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) - static basic_json from_ubjson(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_ubjson(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) - static basic_json from_ubjson(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - /*! - @brief Create a JSON value from an input in BSON format - - Deserializes a given input @a i to a JSON value using the BSON (Binary JSON) - serialization format. - - The library maps BSON record types to JSON value types as follows: - - BSON type | BSON marker byte | JSON value type - --------------- | ---------------- | --------------------------- - double | 0x01 | number_float - string | 0x02 | string - document | 0x03 | object - array | 0x04 | array - binary | 0x05 | binary - undefined | 0x06 | still unsupported - ObjectId | 0x07 | still unsupported - boolean | 0x08 | boolean - UTC Date-Time | 0x09 | still unsupported - null | 0x0A | null - Regular Expr. | 0x0B | still unsupported - DB Pointer | 0x0C | still unsupported - JavaScript Code | 0x0D | still unsupported - Symbol | 0x0E | still unsupported - JavaScript Code | 0x0F | still unsupported - int32 | 0x10 | number_integer - Timestamp | 0x11 | still unsupported - 128-bit decimal float | 0x13 | still unsupported - Max Key | 0x7F | still unsupported - Min Key | 0xFF | still unsupported - - @warning The mapping is **incomplete**. The unsupported mappings - are indicated in the table above. - - @param[in] i an input in BSON format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.114 if an unsupported BSON record type is encountered - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - BSON format to a JSON value.,from_bson} - - @sa http://bsonspec.org/spec.html - @sa see @ref to_bson(const basic_json&) for the analogous serialization - @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa see @ref from_msgpack(InputType&&, const bool, const bool) for - the related MessagePack format - @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the - related UBJSON format - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bson(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_bson(InputType&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bson(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) - static basic_json from_bson(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_bson(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) - static basic_json from_bson(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - /// @} - - ////////////////////////// - // JSON Pointer support // - ////////////////////////// - - /// @name JSON Pointer functions - /// @{ - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. Similar to @ref operator[](const typename - object_t::key_type&), `null` values are created in arrays and objects if - necessary. - - In particular: - - If the JSON pointer points to an object key that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. - - If the JSON pointer points to an array index that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. All indices between the current maximum and the given - index are also filled with `null`. - - The special value `-` is treated as a synonym for the index past the - end. - - @param[in] ptr a JSON pointer - - @return reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer} - - @since version 2.0.0 - */ - reference operator[](const json_pointer& ptr) - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. The function does not change the JSON - value; no `null` values are created. In particular, the special value - `-` yields an exception. - - @param[in] ptr JSON pointer to the desired element - - @return const reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} - - @since version 2.0.0 - */ - const_reference operator[](const json_pointer& ptr) const - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a reference to the element at with specified JSON pointer @a ptr, - with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.403 if the JSON pointer describes a key of an object - which cannot be found. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer} - */ - reference at(const json_pointer& ptr) - { - return ptr.get_checked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a const reference to the element at with specified JSON pointer @a - ptr, with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.403 if the JSON pointer describes a key of an object - which cannot be found. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer_const} - */ - const_reference at(const json_pointer& ptr) const - { - return ptr.get_checked(this); - } - - /*! - @brief return flattened JSON value - - The function creates a JSON object whose keys are JSON pointers (see [RFC - 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all - primitive. The original JSON value can be restored using the @ref - unflatten() function. - - @return an object that maps JSON pointers to primitive values - - @note Empty objects and arrays are flattened to `null` and will not be - reconstructed correctly by the @ref unflatten() function. - - @complexity Linear in the size the JSON value. - - @liveexample{The following code shows how a JSON object is flattened to an - object whose keys consist of JSON pointers.,flatten} - - @sa see @ref unflatten() for the reverse function - - @since version 2.0.0 - */ - basic_json flatten() const - { - basic_json result(value_t::object); - json_pointer::flatten("", *this, result); - return result; - } - - /*! - @brief unflatten a previously flattened JSON value - - The function restores the arbitrary nesting of a JSON value that has been - flattened before using the @ref flatten() function. The JSON value must - meet certain constraints: - 1. The value must be an object. - 2. The keys must be JSON pointers (see - [RFC 6901](https://tools.ietf.org/html/rfc6901)) - 3. The mapped values must be primitive JSON types. - - @return the original JSON from a flattened version - - @note Empty objects and arrays are flattened by @ref flatten() to `null` - values and can not unflattened to their original type. Apart from - this example, for a JSON value `j`, the following is always true: - `j == j.flatten().unflatten()`. - - @complexity Linear in the size the JSON value. - - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitive - - @liveexample{The following code shows how a flattened JSON object is - unflattened into the original nested JSON object.,unflatten} - - @sa see @ref flatten() for the reverse function - - @since version 2.0.0 - */ - basic_json unflatten() const - { - return json_pointer::unflatten(*this); - } - - /// @} - - ////////////////////////// - // JSON Patch functions // - ////////////////////////// - - /// @name JSON Patch functions - /// @{ - - /*! - @brief applies a JSON patch - - [JSON Patch](http://jsonpatch.com) defines a JSON document structure for - expressing a sequence of operations to apply to a JSON) document. With - this function, a JSON Patch is applied to the current JSON value by - executing all operations from the patch. - - @param[in] json_patch JSON patch document - @return patched document - - @note The application of a patch is atomic: Either all operations succeed - and the patched document is returned or an exception is thrown. In - any case, the original value is not changed: the patch is applied - to a copy of the value. - - @throw parse_error.104 if the JSON patch does not consist of an array of - objects - - @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory - attributes are missing); example: `"operation add must have member path"` - - @throw out_of_range.401 if an array index is out of range. - - @throw out_of_range.403 if a JSON pointer inside the patch could not be - resolved successfully in the current JSON value; example: `"key baz not - found"` - - @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", - "move") - - @throw other_error.501 if "test" operation was unsuccessful - - @complexity Linear in the size of the JSON value and the length of the - JSON patch. As usually only a fraction of the JSON value is affected by - the patch, the complexity can usually be neglected. - - @liveexample{The following code shows how a JSON patch is applied to a - value.,patch} - - @sa see @ref diff -- create a JSON patch by comparing two JSON values - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) - - @since version 2.0.0 - */ - basic_json patch(const basic_json& json_patch) const - { - // make a working copy to apply the patch to - basic_json result = *this; - - // the valid JSON Patch operations - enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - - const auto get_op = [](const std::string & op) - { - if (op == "add") - { - return patch_operations::add; - } - if (op == "remove") - { - return patch_operations::remove; - } - if (op == "replace") - { - return patch_operations::replace; - } - if (op == "move") - { - return patch_operations::move; - } - if (op == "copy") - { - return patch_operations::copy; - } - if (op == "test") - { - return patch_operations::test; - } - - return patch_operations::invalid; - }; - - // wrapper for "add" operation; add value at ptr - const auto operation_add = [&result](json_pointer & ptr, basic_json val) - { - // adding to the root of the target document means replacing it - if (ptr.empty()) - { - result = val; - return; - } - - // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); - if (top_pointer != ptr) - { - result.at(top_pointer); - } - - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.back(); - ptr.pop_back(); - basic_json& parent = result[ptr]; - - switch (parent.m_type) - { - case value_t::null: - case value_t::object: - { - // use operator[] to add value - parent[last_path] = val; - break; - } - - case value_t::array: - { - if (last_path == "-") - { - // special case: append to back - parent.push_back(val); - } - else - { - const auto idx = json_pointer::array_index(last_path); - if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) - { - // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent)); - } - - // default case: insert add offset - parent.insert(parent.begin() + static_cast(idx), val); - } - break; - } - - // if there exists a parent it cannot be primitive - case value_t::string: // LCOV_EXCL_LINE - case value_t::boolean: // LCOV_EXCL_LINE - case value_t::number_integer: // LCOV_EXCL_LINE - case value_t::number_unsigned: // LCOV_EXCL_LINE - case value_t::number_float: // LCOV_EXCL_LINE - case value_t::binary: // LCOV_EXCL_LINE - case value_t::discarded: // LCOV_EXCL_LINE - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - } - }; - - // wrapper for "remove" operation; remove value at ptr - const auto operation_remove = [this, &result](json_pointer & ptr) - { - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.back(); - ptr.pop_back(); - basic_json& parent = result.at(ptr); - - // remove child - if (parent.is_object()) - { - // perform range check - auto it = parent.find(last_path); - if (JSON_HEDLEY_LIKELY(it != parent.end())) - { - parent.erase(it); - } - else - { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this)); - } - } - else if (parent.is_array()) - { - // note erase performs range check - parent.erase(json_pointer::array_index(last_path)); - } - }; - - // type check: top level value must be an array - if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch)); - } - - // iterate and apply the operations - for (const auto& val : json_patch) - { - // wrapper to get a value for an operation - const auto get_value = [&val](const std::string & op, - const std::string & member, - bool string_type) -> basic_json & - { - // find value - auto it = val.m_value.object->find(member); - - // context-sensitive error message - const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; - - // check if desired value is present - if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) - { - // NOLINTNEXTLINE(performance-inefficient-string-concatenation) - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val)); - } - - // check if result is of type string - if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) - { - // NOLINTNEXTLINE(performance-inefficient-string-concatenation) - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val)); - } - - // no error: return value - return it->second; - }; - - // type check: every element of the array must be an object - if (JSON_HEDLEY_UNLIKELY(!val.is_object())) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val)); - } - - // collect mandatory members - const auto op = get_value("op", "op", true).template get(); - const auto path = get_value(op, "path", true).template get(); - json_pointer ptr(path); - - switch (get_op(op)) - { - case patch_operations::add: - { - operation_add(ptr, get_value("add", "value", false)); - break; - } - - case patch_operations::remove: - { - operation_remove(ptr); - break; - } - - case patch_operations::replace: - { - // the "path" location must exist - use at() - result.at(ptr) = get_value("replace", "value", false); - break; - } - - case patch_operations::move: - { - const auto from_path = get_value("move", "from", true).template get(); - json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The move operation is functionally identical to a - // "remove" operation on the "from" location, followed - // immediately by an "add" operation at the target - // location with the value that was just removed. - operation_remove(from_ptr); - operation_add(ptr, v); - break; - } - - case patch_operations::copy: - { - const auto from_path = get_value("copy", "from", true).template get(); - const json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The copy is functionally identical to an "add" - // operation at the target location using the value - // specified in the "from" member. - operation_add(ptr, v); - break; - } - - case patch_operations::test: - { - bool success = false; - JSON_TRY - { - // check if "value" matches the one at "path" - // the "path" location must exist - use at() - success = (result.at(ptr) == get_value("test", "value", false)); - } - JSON_INTERNAL_CATCH (out_of_range&) - { - // ignore out of range errors: success remains false - } - - // throw an exception if test fails - if (JSON_HEDLEY_UNLIKELY(!success)) - { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val)); - } - - break; - } - - case patch_operations::invalid: - default: - { - // op must be "add", "remove", "replace", "move", "copy", or - // "test" - JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val)); - } - } - } - - return result; - } - - /*! - @brief creates a diff as a JSON patch - - Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can - be changed into the value @a target by calling @ref patch function. - - @invariant For two JSON values @a source and @a target, the following code - yields always `true`: - @code {.cpp} - source.patch(diff(source, target)) == target; - @endcode - - @note Currently, only `remove`, `add`, and `replace` operations are - generated. - - @param[in] source JSON value to compare from - @param[in] target JSON value to compare against - @param[in] path helper value to create JSON pointers - - @return a JSON patch to convert the @a source to @a target - - @complexity Linear in the lengths of @a source and @a target. - - @liveexample{The following code shows how a JSON patch is created as a - diff for two JSON values.,diff} - - @sa see @ref patch -- apply a JSON patch - @sa see @ref merge_patch -- apply a JSON Merge Patch - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - - @since version 2.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json diff(const basic_json& source, const basic_json& target, - const std::string& path = "") - { - // the patch - basic_json result(value_t::array); - - // if the values are the same, return empty patch - if (source == target) - { - return result; - } - - if (source.type() != target.type()) - { - // different types: replace value - result.push_back( - { - {"op", "replace"}, {"path", path}, {"value", target} - }); - return result; - } - - switch (source.type()) - { - case value_t::array: - { - // first pass: traverse common elements - std::size_t i = 0; - while (i < source.size() && i < target.size()) - { - // recursive call to compare array values at index i - auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - ++i; - } - - // i now reached the end of at least one array - // in a second pass, traverse the remaining elements - - // remove my remaining elements - const auto end_index = static_cast(result.size()); - while (i < source.size()) - { - // add operations in reverse order to avoid invalid - // indices - result.insert(result.begin() + end_index, object( - { - {"op", "remove"}, - {"path", path + "/" + std::to_string(i)} - })); - ++i; - } - - // add other remaining elements - while (i < target.size()) - { - result.push_back( - { - {"op", "add"}, - {"path", path + "/-"}, - {"value", target[i]} - }); - ++i; - } - - break; - } - - case value_t::object: - { - // first pass: traverse this object's elements - for (auto it = source.cbegin(); it != source.cend(); ++it) - { - // escape the key name to be used in a JSON patch - const auto path_key = path + "/" + detail::escape(it.key()); - - if (target.find(it.key()) != target.end()) - { - // recursive call to compare object values at key it - auto temp_diff = diff(it.value(), target[it.key()], path_key); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - } - else - { - // found a key that is not in o -> remove it - result.push_back(object( - { - {"op", "remove"}, {"path", path_key} - })); - } - } - - // second pass: traverse other object's elements - for (auto it = target.cbegin(); it != target.cend(); ++it) - { - if (source.find(it.key()) == source.end()) - { - // found a key that is not in this -> add it - const auto path_key = path + "/" + detail::escape(it.key()); - result.push_back( - { - {"op", "add"}, {"path", path_key}, - {"value", it.value()} - }); - } - } - - break; - } - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - // both primitive type: replace value - result.push_back( - { - {"op", "replace"}, {"path", path}, {"value", target} - }); - break; - } - } - - return result; - } - - /// @} - - //////////////////////////////// - // JSON Merge Patch functions // - //////////////////////////////// - - /// @name JSON Merge Patch functions - /// @{ - - /*! - @brief applies a JSON Merge Patch - - The merge patch format is primarily intended for use with the HTTP PATCH - method as a means of describing a set of modifications to a target - resource's content. This function applies a merge patch to the current - JSON value. - - The function implements the following algorithm from Section 2 of - [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396): - - ``` - define MergePatch(Target, Patch): - if Patch is an Object: - if Target is not an Object: - Target = {} // Ignore the contents and set it to an empty Object - for each Name/Value pair in Patch: - if Value is null: - if Name exists in Target: - remove the Name/Value pair from Target - else: - Target[Name] = MergePatch(Target[Name], Value) - return Target - else: - return Patch - ``` - - Thereby, `Target` is the current object; that is, the patch is applied to - the current value. - - @param[in] apply_patch the patch to apply - - @complexity Linear in the lengths of @a patch. - - @liveexample{The following code shows how a JSON Merge Patch is applied to - a JSON document.,merge_patch} - - @sa see @ref patch -- apply a JSON patch - @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) - - @since version 3.0.0 - */ - void merge_patch(const basic_json& apply_patch) - { - if (apply_patch.is_object()) - { - if (!is_object()) - { - *this = object(); - } - for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) - { - if (it.value().is_null()) - { - erase(it.key()); - } - else - { - operator[](it.key()).merge_patch(it.value()); - } - } - } - else - { - *this = apply_patch; - } - } - - /// @} -}; - -/*! -@brief user-defined to_string function for JSON values - -This function implements a user-defined to_string for JSON objects. - -@param[in] j a JSON object -@return a std::string object -*/ - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) -{ - return j.dump(); -} -} // namespace nlohmann - -/////////////////////// -// nonmember support // -/////////////////////// - -// specialization of std::swap, and std::hash -namespace std -{ - -/// hash value for JSON objects -template<> -struct hash -{ - /*! - @brief return a hash value for a JSON object - - @since version 1.0.0 - */ - std::size_t operator()(const nlohmann::json& j) const - { - return nlohmann::detail::hash(j); - } -}; - -/// specialization for std::less -/// @note: do not remove the space after '<', -/// see https://github.com/nlohmann/json/pull/679 -template<> -struct less<::nlohmann::detail::value_t> -{ - /*! - @brief compare two value_t enum values - @since version 3.0.0 - */ - bool operator()(nlohmann::detail::value_t lhs, - nlohmann::detail::value_t rhs) const noexcept - { - return nlohmann::detail::operator<(lhs, rhs); - } -}; - -// C++20 prohibit function specialization in the std namespace. -#ifndef JSON_HAS_CPP_20 - -/*! -@brief exchanges the values of two JSON objects - -@since version 1.0.0 -*/ -template<> -inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name) - is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression) - is_nothrow_move_assignable::value - ) -{ - j1.swap(j2); -} - -#endif - -} // namespace std - -/*! -@brief user-defined string literal for JSON values - -This operator implements a user-defined string literal for JSON objects. It -can be used by adding `"_json"` to a string literal and returns a JSON object -if no parse error occurred. - -@param[in] s a string representation of a JSON object -@param[in] n the length of string @a s -@return a JSON object - -@since version 1.0.0 -*/ -JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json operator "" _json(const char* s, std::size_t n) -{ - return nlohmann::json::parse(s, s + n); -} - -/*! -@brief user-defined string literal for JSON pointer - -This operator implements a user-defined string literal for JSON Pointers. It -can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer -object if no parse error occurred. - -@param[in] s a string representation of a JSON Pointer -@param[in] n the length of string @a s -@return a JSON pointer object - -@since version 2.0.0 -*/ -JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -{ - return nlohmann::json::json_pointer(std::string(s, n)); -} - -// #include - - -// restore clang diagnostic settings -#if defined(__clang__) - #pragma clang diagnostic pop -#endif - -// clean up -#undef JSON_ASSERT -#undef JSON_INTERNAL_CATCH -#undef JSON_CATCH -#undef JSON_THROW -#undef JSON_TRY -#undef JSON_PRIVATE_UNLESS_TESTED -#undef JSON_HAS_CPP_11 -#undef JSON_HAS_CPP_14 -#undef JSON_HAS_CPP_17 -#undef JSON_HAS_CPP_20 -#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION -#undef NLOHMANN_BASIC_JSON_TPL -#undef JSON_EXPLICIT - -// #include - - -#undef JSON_HEDLEY_ALWAYS_INLINE -#undef JSON_HEDLEY_ARM_VERSION -#undef JSON_HEDLEY_ARM_VERSION_CHECK -#undef JSON_HEDLEY_ARRAY_PARAM -#undef JSON_HEDLEY_ASSUME -#undef JSON_HEDLEY_BEGIN_C_DECLS -#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#undef JSON_HEDLEY_CLANG_HAS_FEATURE -#undef JSON_HEDLEY_CLANG_HAS_WARNING -#undef JSON_HEDLEY_COMPCERT_VERSION -#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#undef JSON_HEDLEY_CONCAT -#undef JSON_HEDLEY_CONCAT3 -#undef JSON_HEDLEY_CONCAT3_EX -#undef JSON_HEDLEY_CONCAT_EX -#undef JSON_HEDLEY_CONST -#undef JSON_HEDLEY_CONSTEXPR -#undef JSON_HEDLEY_CONST_CAST -#undef JSON_HEDLEY_CPP_CAST -#undef JSON_HEDLEY_CRAY_VERSION -#undef JSON_HEDLEY_CRAY_VERSION_CHECK -#undef JSON_HEDLEY_C_DECL -#undef JSON_HEDLEY_DEPRECATED -#undef JSON_HEDLEY_DEPRECATED_FOR -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#undef JSON_HEDLEY_DIAGNOSTIC_POP -#undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#undef JSON_HEDLEY_DMC_VERSION -#undef JSON_HEDLEY_DMC_VERSION_CHECK -#undef JSON_HEDLEY_EMPTY_BASES -#undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#undef JSON_HEDLEY_END_C_DECLS -#undef JSON_HEDLEY_FLAGS -#undef JSON_HEDLEY_FLAGS_CAST -#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_BUILTIN -#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_EXTENSION -#undef JSON_HEDLEY_GCC_HAS_FEATURE -#undef JSON_HEDLEY_GCC_HAS_WARNING -#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#undef JSON_HEDLEY_GCC_VERSION -#undef JSON_HEDLEY_GCC_VERSION_CHECK -#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#undef JSON_HEDLEY_GNUC_HAS_FEATURE -#undef JSON_HEDLEY_GNUC_HAS_WARNING -#undef JSON_HEDLEY_GNUC_VERSION -#undef JSON_HEDLEY_GNUC_VERSION_CHECK -#undef JSON_HEDLEY_HAS_ATTRIBUTE -#undef JSON_HEDLEY_HAS_BUILTIN -#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_HAS_EXTENSION -#undef JSON_HEDLEY_HAS_FEATURE -#undef JSON_HEDLEY_HAS_WARNING -#undef JSON_HEDLEY_IAR_VERSION -#undef JSON_HEDLEY_IAR_VERSION_CHECK -#undef JSON_HEDLEY_IBM_VERSION -#undef JSON_HEDLEY_IBM_VERSION_CHECK -#undef JSON_HEDLEY_IMPORT -#undef JSON_HEDLEY_INLINE -#undef JSON_HEDLEY_INTEL_CL_VERSION -#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#undef JSON_HEDLEY_INTEL_VERSION -#undef JSON_HEDLEY_INTEL_VERSION_CHECK -#undef JSON_HEDLEY_IS_CONSTANT -#undef JSON_HEDLEY_IS_CONSTEXPR_ -#undef JSON_HEDLEY_LIKELY -#undef JSON_HEDLEY_MALLOC -#undef JSON_HEDLEY_MCST_LCC_VERSION -#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK -#undef JSON_HEDLEY_MESSAGE -#undef JSON_HEDLEY_MSVC_VERSION -#undef JSON_HEDLEY_MSVC_VERSION_CHECK -#undef JSON_HEDLEY_NEVER_INLINE -#undef JSON_HEDLEY_NON_NULL -#undef JSON_HEDLEY_NO_ESCAPE -#undef JSON_HEDLEY_NO_RETURN -#undef JSON_HEDLEY_NO_THROW -#undef JSON_HEDLEY_NULL -#undef JSON_HEDLEY_PELLES_VERSION -#undef JSON_HEDLEY_PELLES_VERSION_CHECK -#undef JSON_HEDLEY_PGI_VERSION -#undef JSON_HEDLEY_PGI_VERSION_CHECK -#undef JSON_HEDLEY_PREDICT -#undef JSON_HEDLEY_PRINTF_FORMAT -#undef JSON_HEDLEY_PRIVATE -#undef JSON_HEDLEY_PUBLIC -#undef JSON_HEDLEY_PURE -#undef JSON_HEDLEY_REINTERPRET_CAST -#undef JSON_HEDLEY_REQUIRE -#undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#undef JSON_HEDLEY_REQUIRE_MSG -#undef JSON_HEDLEY_RESTRICT -#undef JSON_HEDLEY_RETURNS_NON_NULL -#undef JSON_HEDLEY_SENTINEL -#undef JSON_HEDLEY_STATIC_ASSERT -#undef JSON_HEDLEY_STATIC_CAST -#undef JSON_HEDLEY_STRINGIFY -#undef JSON_HEDLEY_STRINGIFY_EX -#undef JSON_HEDLEY_SUNPRO_VERSION -#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#undef JSON_HEDLEY_TINYC_VERSION -#undef JSON_HEDLEY_TINYC_VERSION_CHECK -#undef JSON_HEDLEY_TI_ARMCL_VERSION -#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL2000_VERSION -#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL430_VERSION -#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL6X_VERSION -#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL7X_VERSION -#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#undef JSON_HEDLEY_TI_CLPRU_VERSION -#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#undef JSON_HEDLEY_TI_VERSION -#undef JSON_HEDLEY_TI_VERSION_CHECK -#undef JSON_HEDLEY_UNAVAILABLE -#undef JSON_HEDLEY_UNLIKELY -#undef JSON_HEDLEY_UNPREDICTABLE -#undef JSON_HEDLEY_UNREACHABLE -#undef JSON_HEDLEY_UNREACHABLE_RETURN -#undef JSON_HEDLEY_VERSION -#undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#undef JSON_HEDLEY_VERSION_DECODE_MINOR -#undef JSON_HEDLEY_VERSION_DECODE_REVISION -#undef JSON_HEDLEY_VERSION_ENCODE -#undef JSON_HEDLEY_WARNING -#undef JSON_HEDLEY_WARN_UNUSED_RESULT -#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#undef JSON_HEDLEY_FALL_THROUGH - - - -#endif // INCLUDE_NLOHMANN_JSON_HPP_ diff --git a/ext/opentelemetry-cpp-1.21.0/.bazelignore b/ext/opentelemetry-cpp-1.21.0/.bazelignore deleted file mode 100644 index 56306fc4b..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.bazelignore +++ /dev/null @@ -1,3 +0,0 @@ -third_party -tools -out diff --git a/ext/opentelemetry-cpp-1.21.0/.bazelrc b/ext/opentelemetry-cpp-1.21.0/.bazelrc deleted file mode 100644 index 57cd0a2fa..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.bazelrc +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -# bazel configurations for running tests under sanitizers. -# Based on https://github.com/bazelment/trunk/blob/master/tools/bazel.rc - -# Enable automatic configs based on platform -common --enable_platform_specific_config - -# Make globs that don't match anything fail -common --incompatible_disallow_empty_glob - -# Needed by gRPC to build on some platforms. -build --copt -DGRPC_BAZEL_BUILD - -# Workaround abseil libraries missing symbols -build:windows --dynamic_mode=off - -# Set minimum supported C++ version -build:macos --host_cxxopt=-std=c++14 --cxxopt=-std=c++14 -build:linux --host_cxxopt=-std=c++14 --cxxopt=-std=c++14 -build:windows --host_cxxopt=/std:c++14 --cxxopt=/std:c++14 - -# --config=asan : Address Sanitizer. -common:asan --copt -DADDRESS_SANITIZER -common:asan --copt -fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,null,return,returns-nonnull-attribute,shift-exponent,signed-integer-overflow,unreachable,vla-bound -common:asan --copt -fsanitize-address-use-after-scope -common:asan --copt -fno-sanitize-recover=all -common:asan --linkopt -fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,null,return,returns-nonnull-attribute,shift-exponent,signed-integer-overflow,unreachable,vla-bound -common:asan --linkopt -fsanitize-address-use-after-scope -common:asan --linkopt -fno-sanitize-recover=all -common:asan --cc_output_directory_tag=asan - -# --config=tsan : Thread Sanitizer. -common:tsan --copt -fsanitize=thread -common:tsan --copt -DTHREAD_SANITIZER -common:tsan --linkopt -fsanitize=thread -common:tsan --cc_output_directory_tag=tsan -# This is needed to address false positive problem with abseil.The same setting as gRPC -# https://github.com/google/sanitizers/issues/953 -common:tsan --test_env=TSAN_OPTIONS=report_atomic_races=0 diff --git a/ext/opentelemetry-cpp-1.21.0/.bazelversion b/ext/opentelemetry-cpp-1.21.0/.bazelversion deleted file mode 100644 index 21c8c7b46..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.bazelversion +++ /dev/null @@ -1 +0,0 @@ -7.1.1 diff --git a/ext/opentelemetry-cpp-1.21.0/.clang-format b/ext/opentelemetry-cpp-1.21.0/.clang-format deleted file mode 100644 index 1b5d0d488..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.clang-format +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -# See Clang docs: http://clang.llvm.org/docs/ClangFormatStyleOptions.html -BasedOnStyle: Chromium - -# Allow double brackets such as std::vector>. -Standard: Cpp11 - -# Indent 2 spaces at a time. -IndentWidth: 2 - -# Keep lines under 100 columns long. -ColumnLimit: 100 - -# Always break before braces -BreakBeforeBraces: Custom -BraceWrapping: -# TODO(lujc) wait for clang-format-9 support in Chromium tools -# AfterCaseLabel: true - AfterClass: true - AfterControlStatement: true - AfterEnum: true - AfterFunction: true - AfterNamespace: true - AfterStruct: true - AfterUnion: true - BeforeCatch: true - BeforeElse: true - IndentBraces: false - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: false - - # Keeps extern "C" blocks unindented. - AfterExternBlock: false - -# Indent case labels. -IndentCaseLabels: true - -# Right-align pointers and references -PointerAlignment: Right - -# ANGLE likes to align things as much as possible. -AlignOperands: true -AlignConsecutiveAssignments: true - -# Use 2 space negative offset for access modifiers -AccessModifierOffset: -2 - -# TODO(jmadill): Decide if we want this on. Doesn't have an "all or none" mode. -AllowShortCaseLabelsOnASingleLine: false - -# Useful for spacing out functions in classes -KeepEmptyLinesAtTheStartOfBlocks: true - -# Indent nested PP directives. -IndentPPDirectives: AfterHash - -# Include blocks style -IncludeBlocks: Preserve - -AttributeMacros: - - OPENTELEMETRY_UNLIKELY - - OPENTELEMETRY_LIKELY - - OPENTELEMETRY_MAYBE_UNUSED - - OPENTELEMETRY_DEPRECATED - - OPENTELEMETRY_API_SINGLETON - - OPENTELEMETRY_LOCAL_SYMBOL - - OPENTELEMETRY_EXPORT - - OPENTELEMETRY_SANITIZER_NO_MEMORY - - OPENTELEMETRY_SANITIZER_NO_THREAD - - OPENTELEMETRY_SANITIZER_NO_ADDRESS \ No newline at end of file diff --git a/ext/opentelemetry-cpp-1.21.0/.clang-tidy b/ext/opentelemetry-cpp-1.21.0/.clang-tidy deleted file mode 100644 index db61b810c..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.clang-tidy +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -Checks: > - -*, - performance-*, - portability-*, - abseil-*, - -abseil-string-find-str-contains, - bugprone-*, - -bugprone-easily-swappable-parameters, - -bugprone-implicit-widening-of-multiplication-result, - -bugprone-inc-dec-in-conditions, - -bugprone-narrowing-conversions, - -bugprone-unchecked-optional-access, - -bugprone-unhandled-exception-at-new, - -bugprone-unused-local-non-trivial-variable, - google-*, - -google-build-using-namespace, - -google-default-arguments, - -google-explicit-constructor, - -google-readability-avoid-underscore-in-googletest-name, - -google-readability-braces-around-statements, - -google-readability-namespace-comments, - -google-readability-todo, - -google-runtime-references, - misc-*, - -misc-const-correctness, - -misc-include-cleaner, - -misc-non-private-member-variables-in-classes, - -misc-unused-alias-decls, - -misc-use-anonymous-namespace, - cppcoreguidelines-*, - -cppcoreguidelines-owning-memory, - -cppcoreguidelines-avoid-do-while, - -cppcoreguidelines-avoid-c-arrays, - -cppcoreguidelines-avoid-magic-numbers, - -cppcoreguidelines-init-variables, - -cppcoreguidelines-macro-usage, - -cppcoreguidelines-non-private-member-variables-in-classes, - -cppcoreguidelines-avoid-non-const-global-variables, - -cppcoreguidelines-pro-* \ No newline at end of file diff --git a/ext/opentelemetry-cpp-1.21.0/.cmake-format.py b/ext/opentelemetry-cpp-1.21.0/.cmake-format.py deleted file mode 100644 index d232ac8eb..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.cmake-format.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -# If comment markup is enabled, don't reflow the first comment block in -# eachlistfile. Use this to preserve formatting of your -# copyright/licensestatements. -first_comment_is_literal = True diff --git a/ext/opentelemetry-cpp-1.21.0/.copyright-ignore b/ext/opentelemetry-cpp-1.21.0/.copyright-ignore deleted file mode 100644 index 81c51bcd5..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.copyright-ignore +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -# Ignore the following directories - -./.git/* -./.github/* -./third_party/benchmark/* -./third_party/boost/* -./third_party/googletest/* -./third_party/ms-gsl/* -./third_party/nlohmann-json/* -./third_party/opentelemetry-proto/* -./third_party/prometheus-cpp/* -./tools/vcpkg/* -./tools/ports/* - -# Third party code - -./api/include/opentelemetry/nostd/internal/absl/* -./exporters/jaeger/thrift-gen/* -./exporters/etw/include/opentelemetry/exporters/etw/TraceLoggingDynamic.h - -# Doc - -./docs/* - -## Ignore the following files patterns - -*.md -*.rst -*.png -*.log -*.patch -*.json -*.nuspec -*.pem - -# Packaging -*/CONTROL - -# LICENSE files -*/LICENSE - -# Ignore the following misc files - -./.bazelignore -./.bazelversion -./docker/.gitignore -.markdownlintignore -./ci/toc.yml -./ci/valgrind-suppressions diff --git a/ext/opentelemetry-cpp-1.21.0/.devcontainer/Dockerfile.conan b/ext/opentelemetry-cpp-1.21.0/.devcontainer/Dockerfile.conan deleted file mode 100644 index 05f6ae27f..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.devcontainer/Dockerfile.conan +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 -FROM ubuntu:24.04@sha256:1e622c5f073b4f6bfad6632f2616c7f59ef256e96fe78bf6a595d1dc4376ac02 - -RUN apt update && apt install -y \ - build-essential \ - ca-certificates \ - wget \ - cmake \ - git \ - sudo \ - nano \ - pkg-config \ - ninja-build \ - clang-format \ - clang-tidy \ - autoconf \ - automake \ - libtool \ - python3-pip - -RUN pip install "conan==2.15.1" --break-system-packages - -ARG USER_UID=1000 -ARG USER_GID=1000 -ARG USER_NAME=devuser -ENV USER_NAME=devuser -ENV USER_UID=${USER_UID} -ENV USER_GID=${USER_GID} -ENV INSTALL_PACKAGES= -ENV IS_CONTAINER_BUILD=true - -COPY ./.devcontainer/customize_container.sh /tmp/opentelemetry_cpp/devcontainer/customize_container.sh -RUN /tmp/opentelemetry_cpp/devcontainer/customize_container.sh -USER devuser - -RUN conan profile detect --force - -ARG CONAN_FILE=conanfile_stable.txt -ARG CONAN_BUILD_TYPE=Debug -ARG CXX_STANDARD=17 -WORKDIR /home/devuser/conan -COPY ./install/conan/ . - -RUN conan install ./${CONAN_FILE} --build=missing -s build_type=${CONAN_BUILD_TYPE} -ENV CMAKE_TOOLCHAIN_FILE=/home/devuser/conan/build/${CONAN_BUILD_TYPE}/generators/conan_toolchain.cmake -ENV CXX_STANDARD=${CXX_STANDARD} -ENV BUILD_TYPE=${CONAN_BUILD_TYPE} -ENV CONAN_FILE=${CONAN_FILE} - -WORKDIR /workspaces/opentelemetry-cpp - -ENTRYPOINT [] - -CMD ["/bin/bash"] diff --git a/ext/opentelemetry-cpp-1.21.0/.devcontainer/Dockerfile.dev b/ext/opentelemetry-cpp-1.21.0/.devcontainer/Dockerfile.dev deleted file mode 100644 index c0eea6d32..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.devcontainer/Dockerfile.dev +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -FROM otel/cpp_format_tools - -ARG USER_UID=1000 -ARG USER_GID=1000 -ARG INSTALL_PACKAGES= - -ARG CXX_STANDARD=17 -ARG CMAKE_VERSION=3.31.6 -ARG ABSEIL_CPP_VERSION=20230125.3 -ARG PROTOBUF_VERSION=23.3 -ARG GRPC_VERSION=v1.55.0 - -ENV CXX_STANDARD=${CXX_STANDARD} -ENV CMAKE_VERSION=${CMAKE_VERSION} -ENV ABSEIL_CPP_VERSION=${ABSEIL_CPP_VERSION} -ENV PROTOBUF_VERSION=${PROTOBUF_VERSION} -ENV GRPC_VERSION=${GRPC_VERSION} - -COPY ci /opt/ci - -RUN apt update && apt install -y wget \ - ninja-build \ - libcurl4-openssl-dev \ - clang-tidy \ - shellcheck - -RUN cd /opt/ci && bash setup_cmake.sh -RUN cd /opt/ci && bash setup_ci_environment.sh -RUN cd /opt && bash ci/setup_googletest.sh \ - && bash ci/install_abseil.sh \ - && bash ci/install_protobuf.sh \ - && bash ci/setup_grpc.sh -r $GRPC_VERSION -s $CXX_STANDARD -p protobuf -p abseil-cpp - -ADD https://github.com/bazelbuild/bazelisk/releases/download/v1.22.1/bazelisk-linux-amd64 /usr/local/bin - -RUN git config --global core.autocrlf input \ - && chmod +x /usr/local/bin/bazelisk-linux-amd64 - -ENV INSTALL_PACKAGES=${INSTALL_PACKAGES} -ENV USER_NAME=devuser -ENV USER_UID=${USER_UID} -ENV USER_GID=${USER_GID} -ENV IS_CONTAINER_BUILD=true - -COPY ./.devcontainer/customize_container.sh /tmp/opentelemetry_cpp/devcontainer/customize_container.sh -RUN /tmp/opentelemetry_cpp/devcontainer/customize_container.sh -RUN apt install -y npm && npm install -g markdownlint-cli@0.44.0 - -USER devuser - -WORKDIR /workspaces/opentelemetry-cpp - -ENTRYPOINT [] - -CMD ["/bin/bash"] \ No newline at end of file diff --git a/ext/opentelemetry-cpp-1.21.0/.devcontainer/README.md b/ext/opentelemetry-cpp-1.21.0/.devcontainer/README.md deleted file mode 100644 index bea6f8c4d..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.devcontainer/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Customizing Your Dev Container - -Customize your dev container using build arguments (for direct Docker builds) or -environment variables (for evaluation in `devcontainer.json`). - -* **CMake version:** - The version of cmake to install. (Default: 3.31.6) - * Docker ARG: - `CMAKE_VERSION` - * Host Environment Variable: - `OTEL_CPP_DEVCONTAINER_CMAKE_VERSION` - -* **CXX standard:** - This is the C++ standard to build from (eg: 17, 20, ...). (Default: 17) - * Docker ARG: - `CXX_STANDARD` - * Host Environment Variable: - `OTEL_CPP_DEVCONTAINER_CXX_STANDARD` - -* **abseil-cpp version:** - This is the version of abseil-cpp that will be used to build protobuf, gRPC, - and opentelemetry-cpp. - * Docker ARG: - `ABSEIL_CPP_VERSION` - * Host Environment Variable: - `OTEL_CPP_DEVCONTAINER_ABSEIL_CPP_VERSION` - -* **Protobuf version:** - * Docker ARG: - `PROTOBUF_VERSION` - * Host Environment Variable: - `OTEL_CPP_DEVCONTAINER_PROTOBUF_VERSION` - -* **gRPC version:** - * Docker ARG: - `GRPC_VERSION` - * Host Environment Variable: - `OTEL_CPP_DEVCONTAINER_GRPC_VERSION` - -* **User ID (UID):** - User ID (Default: `1000`) - * Docker ARG: - `USER_UID` - * Host Environment Variable: - `OTEL_CPP_DEVCONTAINER_USER_UID` - -* **Group ID (GID):** - User group ID (Default: `1000`) - * Docker ARG: - `USER_GID` - * Host Environment Variable: - `OTEL_CPP_DEVCONTAINER_USER_GID` - -* **Install Packages:** - These are the additional packages that will be installed via `apt install` in the devcontainer. This is a space separated list. - * Docker ARG: - `INSTALL_PACKAGES` (Default: ``) - * Host Environment Variable: - `OTEL_CPP_DEVCONTAINER_INSTALL_PACKAGES` (Default: ``) - -## Examples - -* `docker build --build-arg CXX_STANDARD="20" --build-arg INSTALL_PACKAGES="nano gitk"...` -* `export OTEL_CPP_DEVCONTAINER_CXX_STANDARD=20` -* `export OTEL_CPP_DEVCONTAINER_INSTALL_PACKAGES="nano gitk"` diff --git a/ext/opentelemetry-cpp-1.21.0/.devcontainer/customize_container.sh b/ext/opentelemetry-cpp-1.21.0/.devcontainer/customize_container.sh deleted file mode 100755 index ba9614e67..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.devcontainer/customize_container.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -set -eu - -if [[ $IS_CONTAINER_BUILD != "true" ]]; then - echo "This script should only run inside a Docker container." - exit 1 -fi - -if [[ -n "$INSTALL_PACKAGES" ]]; then - packages=($INSTALL_PACKAGES) - for package in "${packages[@]}"; do - apt install -y "$package" - done -fi - -if [[ $(id "$USER_NAME" 2>/dev/null) ]]; then - echo "User '$USER_NAME' already exists. Removing it." - userdel -rf "$USER_NAME" -elif [[ $(id -u "$USER_UID" 2>/dev/null) ]]; then - OTHER_USER=$(getent passwd "$USER_UID" | cut -d: -f1) - echo "User '$OTHER_USER' exists with UID $USER_UID. Removing it." - userdel -rf "$OTHER_USER" -fi - -if [[ ! $(getent group "$USER_GID" 2>/dev/null) ]]; then - echo "Group '$USER_GID' does not exist. Adding it." - groupadd -g "$USER_GID" "$USER_NAME" -fi - -useradd -m -u "$USER_UID" -g "$USER_GID" -s /bin/bash "$USER_NAME" -echo "Created user '$USER_NAME' (UID: $USER_UID, GID: $USER_GID)." - -echo "$USER_NAME ALL=(ALL) NOPASSWD:ALL" | tee /etc/sudoers.d/"$USER_NAME" - -echo "User and group setup complete." diff --git a/ext/opentelemetry-cpp-1.21.0/.devcontainer/devcontainer.json b/ext/opentelemetry-cpp-1.21.0/.devcontainer/devcontainer.json deleted file mode 100644 index 808712242..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.devcontainer/devcontainer.json +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 -// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/javascript-node -{ - "name": "opentelemetry-cpp", - "build": { - "context": "..", - "dockerfile": "Dockerfile.dev", - "args": { - "USER_UID": "${localEnv:OTEL_CPP_DEVCONTAINER_USER_UID:1000}", - "USER_GID": "${localEnv:OTEL_CPP_DEVCONTAINER_USER_GID:1000}", - "INSTALL_PACKAGES": "${localEnv:OTEL_CPP_DEVCONTAINER_INSTALL_PACKAGES:}", - "CMAKE_VERSION": "${localEnv:OTEL_CPP_DEVCONTAINER_CMAKE_VERSION:3.31.6}", - "CXX_STANDARD": "${localEnv:OTEL_CPP_DEVCONTAINER_CXX_STANDARD:17}", - "GRPC_VERSION": "${localEnv:OTEL_CPP_DEVCONTAINER_GRPC_VERSION:v1.55.0}", - "PROTOBUF_VERSION": "${localEnv:OTEL_CPP_DEVCONTAINER_PROTOBUF_VERSION:23.3}", - "ABSEIL_CPP_VERSION":"${localEnv:OTEL_CPP_DEVCONTAINER_ABSEIL_CPP_VERSION:20230125.3}" - } - }, - "customizations": { - "vscode": { - "extensions": [ - "ms-vscode.cpptools", - "ms-azuretools.vscode-docker", - "ms-vscode.cpptools-extension-pack" - ], - "settings": { - "terminal.integrated.shell.linux": "/bin/bash", - } - } - }, - - "remoteUser": "devuser" -} diff --git a/ext/opentelemetry-cpp-1.21.0/.gitattributes b/ext/opentelemetry-cpp-1.21.0/.gitattributes deleted file mode 100644 index ca2467b47..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.gitattributes +++ /dev/null @@ -1,47 +0,0 @@ -##### Source code ##### - -## C++ and C source files -*.c text eol=lf diff=cpp -*.h text eol=lf diff=cpp -*.cc text eol=lf diff=cpp -*.cpp text eol=lf diff=cpp -*.cxx text eol=lf diff=cpp -*.hpp text eol=lf diff=cpp - -## Python scripts -*.py text eol=lf diff=python - -## Perl scripts/libraries/modules -*.perl text eol=lf diff=perl -*.pl text eol=lf diff=perl -*.pm text eol=lf diff=perl - -## Shell scripts -*.sh text eol=lf -*.bash text eol=lf - -## Windows batch and PowerShell scripts -*.bat text eol=crlf -*.cmd text eol=crlf -*.ps1 text eol=crlf - -##### Other file types ##### - -## Text files and documentation -*.txt text -README* text -INSTALL* text -LICENSE* text - -## Non-text documentation -*.html text diff=html -*.pdf binary -*.rtf binary - -## git files -.gitignore text eol=lf -.gitattributes text eol=lf - -## bazel files -WORKSPACE text eol=lf -BUILD text eol=lf diff --git a/ext/opentelemetry-cpp-1.21.0/.github/.codecov.yaml b/ext/opentelemetry-cpp-1.21.0/.github/.codecov.yaml deleted file mode 100644 index 1b9921ac4..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/.codecov.yaml +++ /dev/null @@ -1,50 +0,0 @@ -codecov: - require_ci_to_pass: false - max_report_age: off - -coverage: - precision: 2 - round: up - range: "80...100" - status: - project: - default: - informational: true - target: auto - threshold: 10% - patch: false - -parsers: - gcov: - branch_detection: - conditional: yes - loop: yes - method: no - macro: no - -comment: - layout: "reach,diff,flags,tree" - behavior: default - require_changes: false - -# Relative file path fixing. -# CI file paths must match Git file paths. -# This fix removes the "/home/runner/" prefix -# to coverage report file paths. -fixes: - - "/home/runner/::" - -ignore: - - "docs/**/*" - - "docker/**/*" - - "examples/**/*" - - "bazel/**/*" - - "cmake/**/*" - - "buildscripts/**/*" - - "third_party/**/*" - - "test_common/**/*" - - "tools/**/*" - - ".vscode/**/*" - - ".github/**/*" - - "**/test/**/*" - - "**.md" \ No newline at end of file diff --git a/ext/opentelemetry-cpp-1.21.0/.github/CODEOWNERS b/ext/opentelemetry-cpp-1.21.0/.github/CODEOWNERS deleted file mode 100644 index 7a40cd0b0..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/CODEOWNERS +++ /dev/null @@ -1,8 +0,0 @@ -# Code owners file. -# This file controls who is tagged for review for any given pull request. - -# For ETW exporter -exporters/etw/* @reyang @maxgolov @lalitb @ThomsonTan @open-telemetry/cpp-approvers - -# For anything not explicitly taken by someone else: -* @open-telemetry/cpp-approvers diff --git a/ext/opentelemetry-cpp-1.21.0/.github/ISSUE_TEMPLATE/bug_report.md b/ext/opentelemetry-cpp-1.21.0/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index e0bb4cca2..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Bug Report -about: Create a report to help us improve -labels: bug ---- - -**Describe your environment** Describe any aspect of your environment relevant to the problem, including your platform, build system, version numbers of installed dependencies, etc. If you're reporting a problem with a specific version of a library in this repo, please check whether the problem has been fixed on main branch. - -**Steps to reproduce** -Describe exactly how to reproduce the error. Include a code sample if applicable. - -**What is the expected behavior?** -What did you expect to see? - -**What is the actual behavior?** -What did you see instead? - -**Additional context** -Add any other context about the problem here. diff --git a/ext/opentelemetry-cpp-1.21.0/.github/ISSUE_TEMPLATE/feature_request.md b/ext/opentelemetry-cpp-1.21.0/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 973549ab2..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Feature Request -about: Suggest an idea for this project -labels: feature-request ---- - -Before opening a feature request against this repo, consider whether the feature should/could be implemented in the [other OpenTelemetry client libraries](https://github.com/open-telemetry/). If so, please [open an issue on opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification/issues/new) first. - -**Is your feature request related to a problem?** -If so, provide a concise description of the problem. - -**Describe the solution you'd like** -What do you want to happen instead? What is the expected behavior? - -**Describe alternatives you've considered** -Which alternative solutions or features have you considered? - -**Additional context** -Add any other context about the feature request here. diff --git a/ext/opentelemetry-cpp-1.21.0/.github/dependabot.yml b/ext/opentelemetry-cpp-1.21.0/.github/dependabot.yml deleted file mode 100644 index 5cfb4cb89..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/dependabot.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" - labels: - - "GHA" - - - package-ecosystem: "devcontainers" - directory: "/" - schedule: - interval: daily diff --git a/ext/opentelemetry-cpp-1.21.0/.github/pull_request_template.md b/ext/opentelemetry-cpp-1.21.0/.github/pull_request_template.md deleted file mode 100644 index e54760323..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/pull_request_template.md +++ /dev/null @@ -1,11 +0,0 @@ -Fixes # (issue) - -## Changes - -Please provide a brief description of the changes here. - -For significant contributions please make sure you have completed the following items: - -* [ ] `CHANGELOG.md` updated for non-trivial changes -* [ ] Unit tests have been added -* [ ] Changes in public API reviewed \ No newline at end of file diff --git a/ext/opentelemetry-cpp-1.21.0/.github/repository-settings.md b/ext/opentelemetry-cpp-1.21.0/.github/repository-settings.md deleted file mode 100644 index fa86d02cf..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/repository-settings.md +++ /dev/null @@ -1,38 +0,0 @@ -# Process - -This file documents local admin changes for opentelemetry-cpp, -per the community process: https://github.com/open-telemetry/community/blob/main/docs/how-to-configure-new-repository.md - -Please note that the EasyCLA check **MUST** stay **REQUIRED**, -it should never be disabled or bypassed, at the risk of tainting the repository. - -# Guidelines - -The best is to open a PR first that describes the change, -so it can be discussed during review (maybe it is not needed, -maybe there is an alternate solution, ...). - -The PR must add a log entry in this file, detailing: - -* the date the change is implemented -* what is changed exactly (which setting) -* a short rationale - -Admin changes are then applied only when the PR is merged. - -If for some reason a change is implemented in emergency, -before a PR can be discussed and merged, -a PR should still be prepared and pushed after the fact to -describe the settings changed. - -# Log of local changes - -## 2023-11-03 - -Created log file `.github/repository-settings.md`, since admin permissions are now granted to maintainers. - -See https://github.com/open-telemetry/community/issues/1727 - -No setting changed. - - diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/benchmark.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/benchmark.yml deleted file mode 100644 index eaad6b280..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/benchmark.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: OpenTelemetry-cpp benchmarks -on: - push: - branches: - - main - -permissions: - contents: write - deployments: write - -jobs: - benchmark: - name: Run OpenTelemetry-cpp benchmarks - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_benchmark - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/install_bazelisk.sh - - name: Run benchmark - id: run_benchmarks - run: | - ./ci/do_ci.sh bazel.benchmark - mkdir -p benchmarks - mv api-benchmark_result.json benchmarks - mv sdk-benchmark_result.json benchmarks - mv exporters-benchmark_result.json benchmarks - - uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47 # main March 2025 - with: - name: benchmark_results - path: benchmarks - store_benchmark: - needs: benchmark - strategy: - matrix: - components: ["api", "sdk", "exporters"] - name: Store benchmark result - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # main March 2025 - with: - name: benchmark_results - path: benchmarks - - name: Print json files - id: print_json - run: | - cat benchmarks/* - - name: Push benchmark result - uses: benchmark-action/github-action-benchmark@d48d326b4ca9ba73ca0cd0d59f108f9e02a381c7 # v1.20.4 - with: - name: OpenTelemetry-cpp ${{ matrix.components }} Benchmark - tool: 'googlecpp' - output-file-path: benchmarks/${{ matrix.components }}-benchmark_result.json - github-token: ${{ secrets.GITHUB_TOKEN }} - auto-push: true - # Show alert with commit comment on detecting possible performance regression - alert-threshold: '200%' - comment-on-alert: true - fail-on-alert: false - gh-pages-branch: gh-pages - benchmark-data-dir-path: benchmarks diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/ci.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/ci.yml deleted file mode 100644 index bc585fc26..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/ci.yml +++ /dev/null @@ -1,1247 +0,0 @@ -name: CI - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -permissions: - contents: read - -jobs: - -# Commented 2024-11-06, lack of workers in github causes CI failures -# arm64_test: -# name: CMake test arm64 (with modern protobuf,grpc and abseil) -# runs-on: actuated-arm64-4cpu-16gb -# steps: -# - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 -# with: -# submodules: 'recursive' -# - name: setup -# env: -# PROTOBUF_VERSION: '23.3' -# ABSEIL_CPP_VERSION: '20230125.3' -# CXX_STANDARD: '14' -# CC: /usr/bin/gcc-10 -# CXX: /usr/bin/g++-10 -# run: | -# sudo -E ./ci/setup_gcc10.sh -# sudo -E ./ci/setup_ci_environment.sh -# sudo -E ./ci/setup_cmake.sh -# sudo -E ./ci/setup_googletest.sh -# sudo -E ./ci/install_abseil.sh -# sudo -E ./ci/install_protobuf.sh - - cmake_test: - name: CMake test (prometheus, elasticsearch, zipkin) - runs-on: ubuntu-22.04 - env: - CXX_STANDARD: '17' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run cmake tests - run: | - ./ci/do_ci.sh cmake.test - - cmake_fetch_content_test: - name: CMake FetchContent usage with opentelemetry-cpp - runs-on: ubuntu-24.04 - env: - CXX_STANDARD: '17' - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: Install abseil, protobuf, and grpc with apt - run: | - sudo -E apt-get update - sudo -E apt-get install -y libabsl-dev libprotobuf-dev libgrpc++-dev protobuf-compiler protobuf-compiler-grpc - - name: run fetch content cmake test - run: | - ./ci/do_ci.sh cmake.fetch_content.test - - cmake_gcc_maintainer_sync_test: - name: CMake gcc 14 (maintainer mode, sync) - runs-on: ubuntu-24.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/gcc-14 - CXX: /usr/bin/g++-14 - PROTOBUF_VERSION: 21.12 - run: | - sudo apt remove needrestart #refer: https://github.com/actions/runner-images/issues/9937 - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - sudo -E ./ci/install_protobuf.sh - - name: setup grpc - run: | - sudo ./ci/setup_grpc.sh - - name: run cmake gcc (maintainer mode, sync) - env: - CC: /usr/bin/gcc-14 - CXX: /usr/bin/g++-14 - run: | - ./ci/do_ci.sh cmake.maintainer.sync.test - - name: generate test cert - env: - CFSSL_VERSION: 1.6.3 - run: | - sudo -E ./tools/setup-cfssl.sh - (cd ./functional/cert; ./generate_cert.sh) - - name: run func test - run: | - (cd ./functional/otlp; ./run_test.sh) - - cmake_gcc_maintainer_async_test: - name: CMake gcc 14 (maintainer mode, async) - runs-on: ubuntu-24.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/gcc-14 - CXX: /usr/bin/g++-14 - PROTOBUF_VERSION: 21.12 - run: | - sudo apt remove needrestart #refer: https://github.com/actions/runner-images/issues/9937 - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - sudo -E ./ci/install_protobuf.sh - - name: setup grpc - run: | - sudo ./ci/setup_grpc.sh - - name: run cmake gcc (maintainer mode, async) - env: - CC: /usr/bin/gcc-14 - CXX: /usr/bin/g++-14 - run: | - ./ci/do_ci.sh cmake.maintainer.async.test - - name: generate test cert - env: - CFSSL_VERSION: 1.6.3 - run: | - sudo -E ./tools/setup-cfssl.sh - (cd ./functional/cert; ./generate_cert.sh) - - name: run func test - run: | - (cd ./functional/otlp; ./run_test.sh) - - cmake_clang_maintainer_sync_test: - name: CMake clang 18 (maintainer mode, sync) - runs-on: ubuntu-24.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/clang-18 - CXX: /usr/bin/clang++-18 - PROTOBUF_VERSION: 21.12 - run: | - sudo apt remove needrestart #refer: https://github.com/actions/runner-images/issues/9937 - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - sudo -E ./ci/install_protobuf.sh - - name: setup grpc - run: | - sudo ./ci/setup_grpc.sh - - name: run cmake clang (maintainer mode, sync) - env: - CC: /usr/bin/clang-18 - CXX: /usr/bin/clang++-18 - run: | - ./ci/do_ci.sh cmake.maintainer.sync.test - - name: generate test cert - env: - CFSSL_VERSION: 1.6.3 - run: | - sudo -E ./tools/setup-cfssl.sh - (cd ./functional/cert; ./generate_cert.sh) - - name: run func test - run: | - (cd ./functional/otlp; ./run_test.sh) - - cmake_clang_maintainer_async_test: - name: CMake clang 18 (maintainer mode, async) - runs-on: ubuntu-24.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/clang-18 - CXX: /usr/bin/clang++-18 - PROTOBUF_VERSION: 21.12 - run: | - sudo apt remove needrestart #refer: https://github.com/actions/runner-images/issues/9937 - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - sudo -E ./ci/install_protobuf.sh - - name: setup grpc - run: | - sudo ./ci/setup_grpc.sh - - name: run cmake clang (maintainer mode, async) - env: - CC: /usr/bin/clang-18 - CXX: /usr/bin/clang++-18 - run: | - ./ci/do_ci.sh cmake.maintainer.async.test - - name: generate test cert - env: - CFSSL_VERSION: 1.6.3 - run: | - sudo -E ./tools/setup-cfssl.sh - (cd ./functional/cert; ./generate_cert.sh) - - name: run func test - run: | - (cd ./functional/otlp; ./run_test.sh) - - cmake_clang_maintainer_abiv2_test: - name: CMake clang 18 (maintainer mode, abiv2) - runs-on: ubuntu-24.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/clang-18 - CXX: /usr/bin/clang++-18 - PROTOBUF_VERSION: 21.12 - run: | - sudo apt remove needrestart #refer: https://github.com/actions/runner-images/issues/9937 - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - sudo -E ./ci/install_protobuf.sh - - name: setup grpc - run: | - sudo ./ci/setup_grpc.sh - - name: run cmake clang (maintainer mode, abiv2) - env: - CC: /usr/bin/clang-18 - CXX: /usr/bin/clang++-18 - run: | - ./ci/do_ci.sh cmake.maintainer.abiv2.test - - name: generate test cert - env: - CFSSL_VERSION: 1.6.3 - run: | - sudo -E ./tools/setup-cfssl.sh - (cd ./functional/cert; ./generate_cert.sh) - - name: run func test - run: | - (cd ./functional/otlp; ./run_test.sh) - - cmake_msvc_maintainer_test: - name: CMake msvc (maintainer mode) - runs-on: windows-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - - name: run tests - run: ./ci/do_ci.ps1 cmake.maintainer.test - - cmake_msvc_maintainer_test_stl_cxx20: - name: CMake msvc (maintainer mode) with C++20 - runs-on: windows-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - - name: run tests - env: - CXX_STANDARD: '20' - run: ./ci/do_ci.ps1 cmake.maintainer.cxx20.stl.test - - cmake_msvc_maintainer_abiv2_test: - name: CMake msvc (maintainer mode, abiv2) - runs-on: windows-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - - name: run tests - env: - CXX_STANDARD: '20' - run: ./ci/do_ci.ps1 cmake.maintainer.abiv2.test - - cmake_with_async_export_test: - name: CMake test (without otlp-exporter and with async export) - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/gcc-12 - CXX: /usr/bin/g++-12 - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run cmake tests (without otlp-exporter) - env: - CC: /usr/bin/gcc-12 - CXX: /usr/bin/g++-12 - run: | - ./ci/do_ci.sh cmake.with_async_export.test - - cmake_opentracing_shim_test: - name: CMake test (with opentracing-shim) - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run cmake tests (enable opentracing-shim) - run: ./ci/do_ci.sh cmake.opentracing_shim.test - - cmake_test_cxx14_gcc: - name: CMake C++14 test(GCC) - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run tests (enable stl) - env: - CXX_STANDARD: '14' - run: ./ci/do_ci.sh cmake.c++14.stl.test - - cmake_test_cxx17_gcc: - name: CMake C++17 test(GCC) - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run tests (enable stl) - env: - CXX_STANDARD: '17' - run: ./ci/do_ci.sh cmake.c++17.stl.test - - cmake_test_cxx20_gcc: - name: CMake C++20 test(GCC) - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run tests - env: - CXX_STANDARD: '20' - run: ./ci/do_ci.sh cmake.c++20.test - - name: run tests (enable stl) - env: - CXX_STANDARD: '20' - run: ./ci/do_ci.sh cmake.c++20.stl.test - - cmake_test_cxx20_clang: - name: CMake C++20 test(Clang with libc++) - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/clang - CXX: /usr/bin/clang++ - CXXFLAGS: "-stdlib=libc++" - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run tests - env: - CC: /usr/bin/clang - CXX: /usr/bin/clang++ - CXXFLAGS: "-stdlib=libc++" - CXX_STANDARD: '20' - run: ./ci/do_ci.sh cmake.c++20.test - - name: run tests (enable stl) - env: - CC: /usr/bin/clang - CXX: /usr/bin/clang++ - CXXFLAGS: "-stdlib=libc++" - CXX_STANDARD: '20' - run: ./ci/do_ci.sh cmake.c++20.stl.test - - cmake_test_cxx23_gcc: - name: CMake C++23 test(GCC) - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run tests - env: - CXX_STANDARD: '23' - run: ./ci/do_ci.sh cmake.c++23.test - - name: run tests (enable stl) - env: - CXX_STANDARD: '23' - run: ./ci/do_ci.sh cmake.c++23.stl.test - - cmake_test_cxx23_clang: - name: CMake C++23 test(Clang with libc++) - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/clang - CXX: /usr/bin/clang++ - CXXFLAGS: "-stdlib=libc++" - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run tests - env: - CC: /usr/bin/clang - CXX: /usr/bin/clang++ - CXXFLAGS: "-stdlib=libc++" - CXX_STANDARD: '23' - run: ./ci/do_ci.sh cmake.c++23.test - - name: run tests (enable stl) - env: - CC: /usr/bin/clang - CXX: /usr/bin/clang++ - CXXFLAGS: "-stdlib=libc++" - CXX_STANDARD: '23' - run: ./ci/do_ci.sh cmake.c++23.stl.test - - cmake_otprotocol_test: - name: CMake test (with otlp-exporter) - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run otlp exporter tests - run: | - sudo ./ci/setup_grpc.sh - ./ci/do_ci.sh cmake.exporter.otprotocol.test - - name: generate test cert - env: - CFSSL_VERSION: 1.6.3 - run: | - sudo -E ./tools/setup-cfssl.sh - (cd ./functional/cert; ./generate_cert.sh) - - name: run func test - run: | - (cd ./functional/otlp; ./run_test.sh) - - cmake_modern_protobuf_grpc_with_abseil_test: - name: CMake test (with modern protobuf,grpc and abseil) - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - PROTOBUF_VERSION: '23.3' - ABSEIL_CPP_VERSION: '20230125.3' - CXX_STANDARD: '14' - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - sudo -E ./ci/install_abseil.sh - sudo -E ./ci/install_protobuf.sh - - name: run otlp exporter tests - env: - CXX_STANDARD: '14' - run: | - sudo -E ./ci/setup_grpc.sh -m -p protobuf -p abseil-cpp - ./ci/do_ci.sh cmake.exporter.otprotocol.test - - cmake_do_not_install_test: - name: CMake do not install test (with otlp-exporter) - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run otlp exporter tests - run: | - sudo ./ci/setup_grpc.sh - ./ci/do_ci.sh cmake.do_not_install.test - - cmake_otprotocol_shared_libs_with_static_grpc_test: - name: CMake test (build shared libraries with otlp-exporter and static gRPC) - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run otlp exporter tests - run: | - sudo ./ci/setup_grpc.sh -T - ./ci/do_ci.sh cmake.exporter.otprotocol.shared_libs.with_static_grpc.test - - plugin_test: - name: Plugin -> CMake - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/gcc-12 - CXX: /usr/bin/g++-12 - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run tests - env: - CC: /usr/bin/gcc-12 - CXX: /usr/bin/g++-12 - run: ./ci/do_ci.sh cmake.test_example_plugin - - bazel_test: - name: Bazel - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_test - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/setup_cmake.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: ./ci/do_ci.sh bazel.test - - bazel_no_bzlmod_test: - name: Bazel without bzlmod - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_test - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/setup_cmake.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: ./ci/do_ci.sh bazel.no_bzlmod.test - - bazel_test_async: - name: Bazel with async export - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_test - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/setup_cmake.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: ./ci/do_ci.sh bazel.with_async_export.test - - bazel_valgrind: - name: Bazel valgrind - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_valgrind - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/setup_cmake.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: ./ci/do_ci.sh bazel.valgrind - - bazel_noexcept: - name: Bazel noexcept - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_noexcept - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/setup_cmake.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: ./ci/do_ci.sh bazel.noexcept - - bazel_nortti: - name: Bazel nortti - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_nortti - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/setup_cmake.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: ./ci/do_ci.sh bazel.nortti - - bazel_asan: - name: Bazel asan config - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_asan - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/setup_cmake.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: ./ci/do_ci.sh bazel.asan - - bazel_tsan: - name: Bazel tsan config - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_tsan - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/setup_cmake.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: ./ci/do_ci.sh bazel.tsan - - bazel_osx: - name: Bazel on MacOS - runs-on: macos-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /Users/runner/.cache/bazel - key: bazel_osx - - name: run tests - run: ./ci/do_ci.sh bazel.macos.test - - benchmark: - name: Benchmark - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Mount Bazel Cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: bazel_cache - with: - path: /home/runner/.cache/bazel - key: bazel_benchmark - - name: setup - run: | - sudo ./ci/setup_ci_environment.sh - sudo ./ci/install_bazelisk.sh - - name: run tests - run: | - env BENCHMARK_DIR=/benchmark - ./ci/do_ci.sh benchmark - - name: Upload benchmark results - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: benchmark_reports - path: /home/runner/benchmark - - format: - name: Format - runs-on: ubuntu-24.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: setup - run: sudo apt remove needrestart && sudo ./ci/install_format_tools.sh #refer: https://github.com/actions/runner-images/issues/9937 - - name: run tests - run: ./ci/do_ci.sh format - - copyright: - name: Copyright - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: check copyright - run: ./tools/check_copyright.sh - - windows: - name: CMake -> exporter proto - runs-on: windows-2019 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - ./ci/install_windows_protobuf.ps1 - - name: run cmake test - run: ./ci/do_ci.ps1 cmake.test - - name: run otprotocol test - run: ./ci/do_ci.ps1 cmake.exporter.otprotocol.test - - windows-build-dll: - name: CMake -> exporter proto (Build as DLL) - runs-on: windows-2019 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - ./ci/install_windows_protobuf.ps1 - - name: run cmake test (DLL build) - run: ./ci/do_ci.ps1 cmake.dll.test - - name: run cmake cxx20 test (DLL build) - run: ./ci/do_ci.ps1 cmake.dll.cxx20.test - - name: run otprotocol test (DLL build) - run: ./ci/do_ci.ps1 cmake.exporter.otprotocol.dll.test - - windows_with_async_export: - name: CMake (With async export) -> exporter proto - runs-on: windows-2019 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - ./ci/install_windows_protobuf.ps1 - - name: run cmake test - run: ./ci/do_ci.ps1 cmake.with_async_export.test - - name: run otprotocol test - run: ./ci/do_ci.ps1 cmake.exporter.otprotocol.with_async_export.test - - windows_bazel: - name: Bazel Windows - runs-on: windows-2019 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - ./ci/install_windows_bazelisk.ps1 - - name: run tests - run: ./ci/do_ci.ps1 bazel.build - - windows_plugin_test: - name: Plugin -> CMake Windows - runs-on: windows-2019 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - - name: run tests - run: ./ci/do_ci.ps1 cmake.test_example_plugin - - code_coverage: - name: Code coverage - runs-on: ubuntu-22.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run tests and generate report - env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 - run: ./ci/do_ci.sh code.coverage - - name: upload report - uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3 - with: - files: /home/runner/build/coverage.info - - markdown-lint: - runs-on: ubuntu-latest - - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - name: check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: install markdownlint-cli - run: sudo npm install -g markdownlint-cli@0.44.0 - - - name: run markdownlint - run: markdownlint . - - shellcheck: - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - name: check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: install shellcheck - run: sudo apt install --assume-yes shellcheck - - name: run shellcheck - run: find . -name \*.sh | xargs shellcheck --severity=error - - misspell: - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - name: check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: install misspell - run: | - curl -L -o ./install-misspell.sh https://git.io/misspell - sh ./install-misspell.sh - - name: run misspell - run: ./bin/misspell -error . - - docfx_check: - name: DocFX check - runs-on: windows-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: install docfx - run: choco install docfx -y --version=2.58.5 - - name: run ./ci/docfx.cmd - shell: cmd - run: ./ci/docfx.cmd - - w3c_trace_context_compliance_v1: - name: W3C Distributed Tracing Validation V1 - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - name: Checkout open-telemetry/opentelemetry-cpp - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: setup - env: - CC: /usr/bin/gcc-12 - CXX: /usr/bin/g++-12 - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: run w3c trace-context test server (background) - env: - CXX_STANDARD: '14' - run: | - ./ci/do_ci.sh cmake.w3c.trace-context.build-server - cd $HOME/build/ext/test/w3c_tracecontext_http_test_server - ./w3c_tracecontext_http_test_server & - - name: Checkout w3c/trace-context repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - repository: w3c/trace-context - path: trace-context - - name: install dependencies - run: | - sudo apt update && sudo apt install python3-pip - sudo pip3 install aiohttp==3.11.18 - - name: run w3c trace-context test suite - env: - SPEC_LEVEL: 1 - run: - | - python ${GITHUB_WORKSPACE}/trace-context/test/test.py http://localhost:30000/test TraceContextTest AdvancedTest - curl http://localhost:30000/stop diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/clang-tidy.yaml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/clang-tidy.yaml deleted file mode 100644 index aec027f64..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/clang-tidy.yaml +++ /dev/null @@ -1,89 +0,0 @@ -name: clang-tidy - -on: - push: - branches: [main] - pull_request: - branches: [main] - -permissions: - contents: read - -jobs: - clang-tidy: - runs-on: ubuntu-24.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: recursive - - - name: Setup Environment - env: - PROTOBUF_VERSION: '23.3' - ABSEIL_CPP_VERSION: '20230125.3' - CXX_STANDARD: '14' - run: | - sudo apt update -y - sudo apt install -y --no-install-recommends --no-install-suggests \ - build-essential \ - iwyu \ - cmake \ - libssl-dev \ - libcurl4-openssl-dev \ - libprotobuf-dev \ - protobuf-compiler \ - libgmock-dev \ - libgtest-dev \ - libbenchmark-dev - - if ! command -v clang-tidy &> /dev/null; then - echo "clang-tidy could not be found" - exit 1 - fi - echo "Using clang-tidy version: $(clang-tidy --version)" - echo "clang-tidy installed at: $(which clang-tidy)" - - - - name: Prepare CMake - env: - CC: clang - CXX: clang++ - run: | - echo "Running cmake..." - cmake -B build \ - -DCMAKE_CXX_STANDARD=14 \ - -DWITH_STL=CXX14 \ - -DWITH_OTLP_HTTP=ON \ - -DWITH_OTLP_FILE=ON \ - -DWITH_PROMETHEUS=ON \ - -DWITH_ZIPKIN=ON \ - -DWITH_ELASTICSEARCH=ON \ - -DWITH_OTLP_HTTP_COMPRESSION=ON \ - -DWITH_EXAMPLES=ON \ - -DWITH_EXAMPLES_HTTP=ON \ - -DBUILD_W3CTRACECONTEXT_TEST=ON \ - -DWITH_METRICS_EXEMPLAR_PREVIEW=ON \ - -DWITH_ASYNC_EXPORT_PREVIEW=ON \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - - - name: Run clang-tidy - run: | - cmake --build build --target opentelemetry_proto - jq -r .[].file build/compile_commands.json | grep -vE '/(generated|third_party)/' | xargs -P $(nproc) -n 1 clang-tidy --quiet -p build 2>&1 | tee -a clang-tidy.log - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: Logs (clang-tidy) - path: ./clang-tidy.log - - - name: Count warnings - run: | - COUNT=$(grep -c "warning:" clang-tidy.log) - echo "clang-tidy reported ${COUNT} warning(s)" - -# TODO: include WITH_OTLP_GRPC flags. diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/cmake_install.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/cmake_install.yml deleted file mode 100644 index c62d7def8..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/cmake_install.yml +++ /dev/null @@ -1,372 +0,0 @@ -name: CMake Install Tests - -on: - workflow_dispatch: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -permissions: - contents: read - -jobs: - windows_2022_vcpkg_submodule: - name: Windows 2022 vcpkg submodule versions cxx17 (static libs - dll) - runs-on: windows-2022 - env: - # Set to the latest version of cmake 3.x - CMAKE_VERSION: '3.31.6' - # cxx17 is the default for windows-2022 - CXX_STANDARD: '17' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Build dependencies with vcpkg submodule - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - - name: Run Tests - run: ./ci/do_ci.ps1 cmake.install.test - - name: Run DLL Tests - run: ./ci/do_ci.ps1 cmake.dll.install.test - - windows_2019_vcpkg_submodule_min_cmake: - name: Windows 2019 vcpkg submodule versions minimum cmake cxx14 (static libs) - runs-on: windows-2019 - env: - # cmake 3.15 is the minimum for windows builds (See https://github.com/open-telemetry/opentelemetry-cpp/pull/3349#discussion_r2030319430) - CMAKE_VERSION: '3.15.0' - # cxx14 is the default for windows-2019 - CXX_STANDARD: '14' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Build dependencies with vcpkg submodule - run: | - ./ci/setup_cmake.ps1 - ./ci/setup_windows_ci_environment.ps1 - - name: Run Tests - run: ./ci/do_ci.ps1 cmake.install.test - - ubuntu_2404_system_packages: - name: Ubuntu 24.04 apt packages cxx17 (static libs - shared libs) - runs-on: ubuntu-24.04 - env: - INSTALL_TEST_DIR: '/home/runner/install_test' - # CMake 3.28 is apt package version for Ubuntu 24.04 - CMAKE_VERSION: '3.28.3' - # cxx17 is the default for Ubuntu 24.04 - CXX_STANDARD: '17' - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Install libcurl, zlib, nlohmann-json with apt - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: Install abseil, protobuf, and grpc with apt - run: | - sudo -E apt-get update - sudo -E apt-get install -y libabsl-dev libprotobuf-dev libgrpc++-dev protobuf-compiler protobuf-compiler-grpc - - name: Run Tests (static libs) - env: - BUILD_SHARED_LIBS: 'OFF' - run: ./ci/do_ci.sh cmake.install.test - - name: Run Tests (shared libs) - env: - BUILD_SHARED_LIBS: 'ON' - run: ./ci/do_ci.sh cmake.install.test - - ubuntu_2404_latest: - name: Ubuntu 24.04 latest versions cxx20 (static libs) - runs-on: ubuntu-24.04 - env: - INSTALL_TEST_DIR: '/home/runner/install_test' - # Set to the latest version of cmake 3.x - CMAKE_VERSION: '3.31.6' - # Set to the latest cxx standard supported by opentelemetry-cpp - CXX_STANDARD: '20' - # Versions below set to the latest version available - # The abseil and protobuf versions are taken from - # the grpc submodules at the GRPC_VERSION tag - GOOGLETEST_VERSION: '1.16.0' - ABSEIL_CPP_VERSION: '20240722.1' - PROTOBUF_VERSION: '29.0' - GRPC_VERSION: 'v1.71.0' - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Install gtest, libcurl, zlib, nlohmann-json with apt - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: Build abseil, protobuf, and grpc with ci scripts - run: | - sudo -E ./ci/install_abseil.sh - sudo -E ./ci/install_protobuf.sh - sudo -E ./ci/setup_grpc.sh -r $GRPC_VERSION -s $CXX_STANDARD -p protobuf -p abseil-cpp - - name: Run Tests (static libs) - env: - BUILD_SHARED_LIBS: 'OFF' - run: ./ci/do_ci.sh cmake.install.test - - ubuntu_2204_stable: - name: Ubuntu 22.04 stable versions cxx17 (static libs - shared libs) - runs-on: ubuntu-22.04 - env: - INSTALL_TEST_DIR: '/home/runner/install_test' - # CMake 3.22 is the apt package version for Ubuntu 22.04 - CMAKE_VERSION: '3.22.0' - CXX_STANDARD: '17' - # These are stable versions tested in the main ci workflow - # and defaults in the devcontainer - GOOGLETEST_VERSION: '1.14.0' - ABSEIL_CPP_VERSION: '20230125.3' - PROTOBUF_VERSION: '23.3' - GRPC_VERSION: 'v1.55.0' - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Install gtest, libcurl, zlib, nlohmann-json with apt - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: Build abseil, protobuf, and grpc with ci scripts - run: | - sudo -E ./ci/install_abseil.sh - sudo -E ./ci/install_protobuf.sh - sudo -E ./ci/setup_grpc.sh -r $GRPC_VERSION -s $CXX_STANDARD -p protobuf -p abseil-cpp - - name: Run Tests (static libs) - env: - BUILD_SHARED_LIBS: 'OFF' - run: ./ci/do_ci.sh cmake.install.test - - name: Run Tests (shared libs) - env: - BUILD_SHARED_LIBS: 'ON' - run: ./ci/do_ci.sh cmake.install.test - - ubuntu_2204_minimum: - name: Ubuntu 22.04 minimum versions cxx14 (static libs - shared libs) - runs-on: ubuntu-22.04 - env: - INSTALL_TEST_DIR: '/home/runner/install_test' - # Set to the current minimum version of cmake - CMAKE_VERSION: '3.14.0' - # cxx14 is the default for Ubuntu 22.04 - CXX_STANDARD: '14' - # This is the apt package version of googletest for Ubuntu 22.04 - GOOGLETEST_VERSION: '1.11.0' - # These are minimum versions tested in the main ci workflow - ABSEIL_CPP_VERSION: '20220623.2' - PROTOBUF_VERSION: '21.12' - GRPC_VERSION: 'v1.49.2' - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Install gtest, libcurl, zlib, nlohmann-json with apt - run: | - sudo -E ./ci/setup_ci_environment.sh - sudo -E ./ci/setup_cmake.sh - sudo -E ./ci/setup_googletest.sh - - name: Build abseil, protobuf, and grpc with ci scripts - run: | - sudo -E ./ci/install_abseil.sh - sudo -E ./ci/install_protobuf.sh - sudo -E ./ci/setup_grpc.sh -r $GRPC_VERSION -s $CXX_STANDARD -p protobuf -p abseil-cpp - - name: Run Tests (static libs) - env: - BUILD_SHARED_LIBS: 'OFF' - run: ./ci/do_ci.sh cmake.install.test - - name: Run Tests (shared libs) - env: - BUILD_SHARED_LIBS: 'ON' - run: ./ci/do_ci.sh cmake.install.test - - ubuntu_2404_conan_stable: - name: Ubuntu 24.04 conan stable versions cxx17 (static libs - shared libs - opentracing shim) - runs-on: ubuntu-24.04 - env: - INSTALL_TEST_DIR: '/home/runner/install_test' - # CMake 3.28 is apt package version for Ubuntu 24.04 - CMAKE_VERSION: '3.28.3' - CXX_STANDARD: '17' - CMAKE_TOOLCHAIN_FILE: /home/runner/conan/build/Debug/generators/conan_toolchain.cmake - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Install Conan - run: | - python3 -m pip install pip==25.0.1 - pip install "conan==2.15.1" - conan profile detect --force - - name: Install or build all dependencies with Conan - run: | - sudo -E ./ci/setup_cmake.sh - conan install install/conan/conanfile_stable.txt --build=missing -of /home/runner/conan -s build_type=${BUILD_TYPE} -s compiler.cppstd=${CXX_STANDARD} - - name: Run Tests (static libs) - env: - BUILD_SHARED_LIBS: 'OFF' - run: ./ci/do_ci.sh cmake.install.test - - name: Run Tests (shared libs) - env: - BUILD_SHARED_LIBS: 'ON' - run: ./ci/do_ci.sh cmake.install.test - - name: verify pkgconfig packages - run: | - export PKG_CONFIG_PATH=$INSTALL_TEST_DIR/lib/pkgconfig:$PKG_CONFIG_PATH - ./ci/verify_packages.sh - - name: Run OpenTracing Shim Test - run: ./ci/do_ci.sh cmake.opentracing_shim.install.test - - ubuntu_2404_conan_latest: - name: Ubuntu 24.04 conan latest versions cxx17 (static libs) - runs-on: ubuntu-24.04 - env: - INSTALL_TEST_DIR: '/home/runner/install_test' - # Set to the latest version of cmake 3.x - CMAKE_VERSION: '3.31.6' - CXX_STANDARD: '17' - CMAKE_TOOLCHAIN_FILE: /home/runner/conan/build/Debug/generators/conan_toolchain.cmake - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Install Conan - run: | - python3 -m pip install pip==25.0.1 - pip install "conan==2.15.1" - conan profile detect --force - - name: Install or build all dependencies with Conan - run: | - sudo -E ./ci/setup_cmake.sh - conan install install/conan/conanfile_latest.txt --build=missing -of /home/runner/conan -s build_type=${BUILD_TYPE} -s compiler.cppstd=${CXX_STANDARD} - - name: Run Tests (static libs) - env: - BUILD_SHARED_LIBS: 'OFF' - run: ./ci/do_ci.sh cmake.install.test - - name: verify pkgconfig packages - run: | - export PKG_CONFIG_PATH=$INSTALL_TEST_DIR/lib/pkgconfig:$PKG_CONFIG_PATH - ./ci/verify_packages.sh - - macos_14_conan_stable: - name: macOS 14 conan stable versions cxx17 (static libs) - runs-on: macos-14 - env: - INSTALL_TEST_DIR: '/Users/runner/install_test' - CMAKE_VERSION: '3.28.3' - CXX_STANDARD: '17' - CMAKE_TOOLCHAIN_FILE: '/Users/runner/conan/build/Debug/generators/conan_toolchain.cmake' - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Install Conan and tools - run: | - brew install conan autoconf automake libtool coreutils - ./ci/setup_cmake_macos.sh - conan profile detect --force - - name: Install or build all dependencies with Conan - run: conan install install/conan/conanfile_stable.txt --build=missing -of /Users/runner/conan -s build_type=${BUILD_TYPE} -s compiler.cppstd=${CXX_STANDARD} - - name: Run Tests (static libs) - env: - BUILD_SHARED_LIBS: 'OFF' - run: ./ci/do_ci.sh cmake.install.test - - macos_14_brew_packages: - name: macOS 14 brew latest versions cxx17 (static libs) - runs-on: macos-14 - env: - INSTALL_TEST_DIR: '/Users/runner/install_test' - # Set to the latest version of cmake 3.x - CMAKE_VERSION: '3.31.6' - CXX_STANDARD: '17' - BUILD_TYPE: 'Debug' - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Install Dependencies with Homebrew - run: | - ./ci/setup_cmake_macos.sh - brew install coreutils - brew install googletest - brew install google-benchmark - brew install zlib - brew install abseil - brew install protobuf - brew install grpc - brew install nlohmann-json - brew install prometheus-cpp - - name: Run Tests (static libs) - env: - BUILD_SHARED_LIBS: 'OFF' - run: ./ci/do_ci.sh cmake.install.test \ No newline at end of file diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/codeql-analysis.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 9d2fe02d7..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [main] - pull_request: - # The branches below must be a subset of the branches above - branches: [main] - -permissions: - contents: read - -jobs: - CodeQL-Build: - permissions: - actions: read # for github/codeql-action/init to get workflow details - contents: read # for actions/checkout to fetch code - security-events: write # for github/codeql-action/autobuild to send a status report - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - name: Remove Third_party Modules from Code Scan - run: | - rm -rf third_party - - name: Setup - env: - CC: /usr/bin/gcc-12 - CXX: /usr/bin/g++-12 - GOOGLETEST_VERSION: 1.12.1 - run: | - sudo -E ./ci/setup_googletest.sh - sudo -E ./ci/setup_ci_environment.sh - - name: Initialize CodeQL - uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 - with: - languages: cpp - - name: Autobuild - uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/cppcheck.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/cppcheck.yml deleted file mode 100644 index 53057354b..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/cppcheck.yml +++ /dev/null @@ -1,77 +0,0 @@ - -name: cppcheck - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -permissions: - contents: read - -jobs: - cppcheck: - runs-on: ubuntu-24.04 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - - name: Set up dependencies - run: | - sudo apt update -y - sudo apt install -y cppcheck - - - name: Run cppcheck - run: | - cppcheck --version | tee cppcheck.log - cppcheck \ - --force \ - --enable=warning,performance,portability \ - --inline-suppr \ - --suppress=unknownMacro:exporters/etw/include/opentelemetry/exporters/etw/TraceLoggingDynamic.h \ - --language=c++ \ - --std=c++14 \ - -I api/include \ - -I exporters/elasticsearch/include \ - -I exporters/etw/include \ - -I exporters/memory/include \ - -I exporters/ostream/include \ - -I exporters/otlp/include \ - -I exporters/prometheus/include \ - -I exporters/zipkin/include \ - -I ext/include \ - -I opentracing-shim/include \ - -I sdk/include \ - -i build \ - -i test \ - -i third_party \ - -j $(nproc) \ - . 2>&1 | tee --append cppcheck.log - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: success() || failure() - with: - name: Logs (cppcheck) - path: ./cppcheck.log - - - name: Count warnings - run: | - set +e - readonly WARNING_COUNT=`grep -c -E "\[.+\]" cppcheck.log` - echo "cppcheck reported ${WARNING_COUNT} warning(s)" - # Acceptable limit, to decrease over time down to 0 - readonly WARNING_LIMIT=10 - # FAIL the build if WARNING_COUNT > WARNING_LIMIT - if [ $WARNING_COUNT -gt $WARNING_LIMIT ] ; then - exit 1 - # WARN in annotations if WARNING_COUNT > 0 - elif [ $WARNING_COUNT -gt 0 ] ; then - echo "::warning::cppcheck reported ${WARNING_COUNT} warning(s)" - fi diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/dependencies_image.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/dependencies_image.yml deleted file mode 100644 index 3163dd8ca..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/dependencies_image.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: 'OpenTelemetry-cpp dependencies image' -on: - schedule: - - cron: "0 3 * * 6" - -permissions: - contents: read - -jobs: - docker_image: - name: Docker Image - runs-on: ubuntu-latest - timeout-minutes: 300 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - - name: checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Set up QEMU - uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 - - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - - - name: Build Image - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 - with: - builder: ${{ steps.buildx.outputs.name }} - context: ci/ - file: ./docker/Dockerfile - build-args: BASE_IMAGE=ubuntu:latest - platforms: linux/amd64 - # platforms: linux/amd64,linux/arm64 - push: false - tags: otel-cpp-deps - load: true - - - name: Save Image - run: | - docker images - docker save -o /opt/otel-cpp-deps-debian.tar otel-cpp-deps - - - name: Upload Image - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: otel-cpp-deps - path: /opt/otel-cpp-deps-debian.tar - retention-days: 14 diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/fossa.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/fossa.yml deleted file mode 100644 index 8b90aa167..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/fossa.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: FOSSA scanning - -on: - push: - branches: - - main - -permissions: - contents: read - -jobs: - fossa: - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0 - with: - api-key: ${{secrets.FOSSA_API_KEY}} - team: OpenTelemetry diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/iwyu.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/iwyu.yml deleted file mode 100644 index 42881ec6b..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/iwyu.yml +++ /dev/null @@ -1,92 +0,0 @@ - -name: include-what-you-use - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -permissions: - contents: read - -jobs: - iwyu: - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: 'recursive' - - - name: setup dependencies - run: | - sudo apt update -y - sudo apt install -y --no-install-recommends --no-install-suggests \ - build-essential \ - iwyu \ - ninja-build \ - libssl-dev \ - libcurl4-openssl-dev \ - libprotobuf-dev \ - protobuf-compiler \ - libgmock-dev \ - libgtest-dev \ - libbenchmark-dev - sudo ./ci/setup_cmake.sh - - - - name: setup grpc - run: | - sudo ./ci/setup_grpc.sh - - - name: Prepare CMake - run: | - TOPDIR=`pwd` - mkdir build && cd build - CC="clang" CXX="clang++" cmake \ - -DCMAKE_CXX_STANDARD=14 \ - -DWITH_STL=CXX14 \ - -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-w;-Xiwyu;--mapping_file=${TOPDIR}/.iwyu.imp;" \ - -DBUILD_TESTING=ON \ - -DBUILD_W3CTRACECONTEXT_TEST=ON \ - -DWITH_OTLP_GRPC=ON \ - -DWITH_OTLP_HTTP=ON \ - -DWITH_OTLP_FILE=ON \ - -DWITH_OPENTRACING=ON \ - -DWITH_OTLP_HTTP_COMPRESSION=ON \ - -DWITH_THREAD_INSTRUMENTATION=ON \ - -DWITH_ZIPKIN=ON \ - -DWITH_PROMETHEUS=ON \ - .. - - - name: iwyu_tool - run: | - cd build - make -k 2>&1 | tee -a iwyu.log - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: success() || failure() - with: - name: Logs (include-what-you-use) - path: ./build/*.log - - - name: count warnings - run: | - set +e - cd build - readonly WARNING_COUNT=`grep -c "include-what-you-use reported diagnostics:" iwyu.log` - echo "include-what-you-use reported ${WARNING_COUNT} warning(s)" - # Acceptable limit, to decrease over time down to 0 - readonly WARNING_LIMIT=0 - # FAIL the build if WARNING_COUNT > WARNING_LIMIT - if [ $WARNING_COUNT -gt $WARNING_LIMIT ] ; then - exit 1 - # WARN in annotations if WARNING_COUNT > 0 - elif [ $WARNING_COUNT -gt 0 ] ; then - echo "::warning::include-what-you-use reported ${WARNING_COUNT} warning(s)" - fi diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/ossf-scorecard.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/ossf-scorecard.yml deleted file mode 100644 index 4ecbe8bf8..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/ossf-scorecard.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: OSSF Scorecard - -on: - push: - branches: - - main - schedule: - - cron: "56 23 * * 6" # once a week - workflow_dispatch: - -permissions: read-all - -jobs: - analysis: - runs-on: ubuntu-latest - permissions: - # Needed for Code scanning upload - security-events: write - # Needed for GitHub OIDC token if publish_results is true - id-token: write - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 - with: - results_file: results.sarif - results_format: sarif - publish_results: true - - # Upload the results as artifacts (optional). Commenting out will disable - # uploads of run results in SARIF format to the repository Actions tab. - # https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts - - name: "Upload artifact" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: SARIF file - path: results.sarif - retention-days: 5 - - # Upload the results to GitHub's code scanning dashboard (optional). - # Commenting out will disable upload of results to your repo's Code Scanning dashboard - - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 - with: - sarif_file: results.sarif diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/project_management_comment.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/project_management_comment.yml deleted file mode 100644 index 6e64cf0aa..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/project_management_comment.yml +++ /dev/null @@ -1,28 +0,0 @@ - -name: Add comment -on: - issues: - types: - - labeled -permissions: - contents: read - -jobs: - add-comment: - if: github.event.label.name == 'help wanted' - runs-on: ubuntu-latest - permissions: - issues: write - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - name: Add comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 - with: - issue-number: ${{ github.event.issue.number }} - body: | - This issue is available for anyone to work on. **Make sure to reference this issue in your pull request.** - :sparkles: Thank you for your contribution! :sparkles: diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/project_management_issue_open.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/project_management_issue_open.yml deleted file mode 100644 index 14750d1a6..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/project_management_issue_open.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: OpenTelemetry-cpp project -on: - issues: - types: - - reopened - - opened -permissions: - contents: read - -jobs: - label_issues: - runs-on: ubuntu-latest - permissions: - issues: write - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 - with: - egress-policy: audit - - - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - script: | - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ["needs-triage"] - }) diff --git a/ext/opentelemetry-cpp-1.21.0/.github/workflows/stale.yml b/ext/opentelemetry-cpp-1.21.0/.github/workflows/stale.yml deleted file mode 100644 index 931403638..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.github/workflows/stale.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: "Mark stale issues" -on: - schedule: - - cron: "30 1 * * *" - -permissions: - contents: read - -jobs: - stale: - permissions: - issues: write # for actions/stale to close stale issues - pull-requests: write # for actions/stale to close stale PRs - runs-on: ubuntu-latest - steps: - - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 - with: - stale-issue-message: "This issue was marked as stale due to lack of activity." - days-before-issue-stale: 60 - days-before-close: -1 - exempt-issue-labels: "do-not-stale" diff --git a/ext/opentelemetry-cpp-1.21.0/.gitignore b/ext/opentelemetry-cpp-1.21.0/.gitignore deleted file mode 100644 index 580df5ac3..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.gitignore +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -# Ref. https://github.com/github/gitignore/blob/master/C%2B%2B.gitignore -# Prerequisites -*.d - -# Compiled Object files -*.slo -*.lo -*.o -*.obj - -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll -*.pdb - -# Fortran module files -*.mod -*.smod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - -# Executables -*.exe -*.out -*.app - -# Bazel files -MODULE.bazel.lock -/bazel-* - -# Mac -.DS_Store - -# Output directories -/out -/out.* -# Indicator that the tools were deployed -.buildtools - -# Temporary Bazel directories -/bazel-* -/plugin -/build - -tags -.cache/clangd/* - -# Temporary dir used when generating semconv -buildscripts/semantic-convention/tmp-semconv/ - -# Generated cert keys in functional tests -functional/cert/ca.csr -functional/cert/ca.pem -functional/cert/ca-key.pem -functional/cert/client_cert.csr -functional/cert/client_cert.pem -functional/cert/client_cert-key.pem -functional/cert/server_cert.csr -functional/cert/server_cert.pem -functional/cert/server_cert-key.pem -functional/cert/ca_b.csr -functional/cert/ca_b.pem -functional/cert/ca_b-key.pem -functional/cert/client_cert_b.csr -functional/cert/client_cert_b.pem -functional/cert/client_cert_b-key.pem -functional/cert/server_cert_b.csr -functional/cert/server_cert_b.pem -functional/cert/server_cert_b-key.pem -functional/cert/unreadable.pem - -localinstall \ No newline at end of file diff --git a/ext/opentelemetry-cpp-1.21.0/.gitmodules b/ext/opentelemetry-cpp-1.21.0/.gitmodules deleted file mode 100644 index 88a78e5f9..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.gitmodules +++ /dev/null @@ -1,39 +0,0 @@ -[submodule "third_party/prometheus-cpp"] -path = third_party/prometheus-cpp -url = https://github.com/jupp0r/prometheus-cpp -branch = master - -[submodule "tools/vcpkg"] -path = tools/vcpkg -url = https://github.com/Microsoft/vcpkg -branch = master - -[submodule "third_party/ms-gsl"] -path = third_party/ms-gsl -url = https://github.com/microsoft/GSL -branch = main - -[submodule "third_party/googletest"] -path = third_party/googletest -url = https://github.com/google/googletest -branch = main - -[submodule "third_party/benchmark"] -path = third_party/benchmark -url = https://github.com/google/benchmark -branch = main - -[submodule "third_party/opentelemetry-proto"] -path = third_party/opentelemetry-proto -url = https://github.com/open-telemetry/opentelemetry-proto -branch = main - -[submodule "third_party/nlohmann-json"] -path = third_party/nlohmann-json -url = https://github.com/nlohmann/json -branch = master - -[submodule "third_party/opentracing-cpp"] -path = third_party/opentracing-cpp -url = https://github.com/opentracing/opentracing-cpp.git -branch = master diff --git a/ext/opentelemetry-cpp-1.21.0/.iwyu.imp b/ext/opentelemetry-cpp-1.21.0/.iwyu.imp deleted file mode 100644 index 123e72f32..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.iwyu.imp +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -# include-what-you-use mapping file - -[ - # Work around for C++ STL - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - - # Local opentelemetry-cpp style - - # We prefer to include for simplicity - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - - # We prefer to include for simplicity - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - - # We prefer to include for simplicity - { "include": ["", "private", "", "public"] }, -] - diff --git a/ext/opentelemetry-cpp-1.21.0/.markdownlint.json b/ext/opentelemetry-cpp-1.21.0/.markdownlint.json deleted file mode 100644 index 48c2ae2a3..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.markdownlint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "default": true, - "MD013": - { - "code_blocks": false, - "tables": false - } -} diff --git a/ext/opentelemetry-cpp-1.21.0/.markdownlintignore b/ext/opentelemetry-cpp-1.21.0/.markdownlintignore deleted file mode 100644 index f0cec48db..000000000 --- a/ext/opentelemetry-cpp-1.21.0/.markdownlintignore +++ /dev/null @@ -1,3 +0,0 @@ -third_party/** -tools/** -examples/otlp/README.md diff --git a/ext/opentelemetry-cpp-1.21.0/CHANGELOG.md b/ext/opentelemetry-cpp-1.21.0/CHANGELOG.md deleted file mode 100644 index 30c94679e..000000000 --- a/ext/opentelemetry-cpp-1.21.0/CHANGELOG.md +++ /dev/null @@ -1,2816 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## Guideline to update the version - -Increment the: - -* MAJOR version when you make incompatible API/ABI changes, -* MINOR version when you add functionality in a backwards compatible manner, and -* PATCH version when you make backwards compatible bug fixes. - -## [Unreleased] - -## [1.21 2025-05-28] - -* [BUILD] Remove WITH_ABSEIL - [#3318](https://github.com/open-telemetry/opentelemetry-cpp/pull/3318) - -* [INSTALL] Add CMake components to the opentelemetry-cpp package - [#3320](https://github.com/open-telemetry/opentelemetry-cpp/pull/3220) - -* [CI] Harden GitHub Actions - [#3338](https://github.com/open-telemetry/opentelemetry-cpp/pull/3338) - -* [StepSecurity] Harden GibHub Actions, part 2 - [#3340](https://github.com/open-telemetry/opentelemetry-cpp/pull/3340) - -* Bump github/codeql-action from 3.28.12 to 3.28.13 - [#3341](https://github.com/open-telemetry/opentelemetry-cpp/pull/3341) - -* [DEVCONTAINER] expose cmake version setting as docker arg and environment variable - [#3347](https://github.com/open-telemetry/opentelemetry-cpp/pull/3347) - -* [CI] disable bzip2 in conan builds - [#3352](https://github.com/open-telemetry/opentelemetry-cpp/pull/3352) - -* [SEMANTIC CONVENTIONS] Upgrade semantic conventions to 1.32.0 - [#3351](https://github.com/open-telemetry/opentelemetry-cpp/pull/3351) - -* Bump github/codeql-action from 3.28.13 to 3.28.15 - [#3353](https://github.com/open-telemetry/opentelemetry-cpp/pull/3353) - -* [CMAKE] bump cmake minimum required version to 3.14 - [#3349](https://github.com/open-telemetry/opentelemetry-cpp/pull/3349) - -* Bump codecov/codecov-action from 5.4.0 to 5.4.2 - [#3362](https://github.com/open-telemetry/opentelemetry-cpp/pull/3362) - -* [DOC] Fix documentation tags in logger API - [#3371](https://github.com/open-telemetry/opentelemetry-cpp/pull/3371) - -* [CI] fix artifacts download/upload - [#3369](https://github.com/open-telemetry/opentelemetry-cpp/pull/3369) - -* [API] Add Enabled method to Tracer - [#3357](https://github.com/open-telemetry/opentelemetry-cpp/pull/3357) - -* [BUILD] Fixes warnings of ciso646 in C++17 - [#3360](https://github.com/open-telemetry/opentelemetry-cpp/pull/3360) - -* Bump github/codeql-action from 3.28.15 to 3.28.16 - [#3377](https://github.com/open-telemetry/opentelemetry-cpp/pull/3377) - -* Bump step-security/harden-runner from 2.11.1 to 2.12.0 - [#3373](https://github.com/open-telemetry/opentelemetry-cpp/pull/3373) - -* Bump docker/build-push-action from 6.15.0 to 6.16.0 - [#3382](https://github.com/open-telemetry/opentelemetry-cpp/pull/3382) - -* Bump actions/download-artifact from 4.2.1 to 4.3.0 - [#3381](https://github.com/open-telemetry/opentelemetry-cpp/pull/3381) - -* [CI] Harden Github actions - pinned-dependencies (part -1) - [#3380](https://github.com/open-telemetry/opentelemetry-cpp/pull/3380) - -* [StepSecurity] ci: Harden GitHub Actions - [#3378](https://github.com/open-telemetry/opentelemetry-cpp/pull/3378) - -* [SDK] Base2 exponential histogram aggregation - [#3346](https://github.com/open-telemetry/opentelemetry-cpp/pull/3346) - -* [StepSecurity] ci: Harden GitHub Actions - [#3379](https://github.com/open-telemetry/opentelemetry-cpp/pull/3379) - -* [BUILD] Fixes glibc++ 5 checking - [#3355](https://github.com/open-telemetry/opentelemetry-cpp/pull/3355) - -* [TEST] Add stress test for histogram metric for multiple threads validation - [#3388](https://github.com/open-telemetry/opentelemetry-cpp/pull/3388) - -* Bump github/codeql-action from 3.28.16 to 3.28.17 - [#3389](https://github.com/open-telemetry/opentelemetry-cpp/pull/3389) - -* [SDK] Optimize PeriodicExportingMetricReader Thread Usage - [#3383](https://github.com/open-telemetry/opentelemetry-cpp/pull/3383) - -* [Metrics SDK] Use nostd::function_ref in AttributesHashMap - [#3393](https://github.com/open-telemetry/opentelemetry-cpp/pull/3393) - -* [SDK] support aggregation of identical instruments - [#3358](https://github.com/open-telemetry/opentelemetry-cpp/pull/3358) - -* [BUILD] Fixes unused var - [#3397](https://github.com/open-telemetry/opentelemetry-cpp/pull/3397) - -* [INSTALL] Unify cmake install functions and dynamically set component dependencies - [#3368](https://github.com/open-telemetry/opentelemetry-cpp/pull/3368) - -* [BUILD] Upgrade nlohmann_json to 3.12.0 - [#3406](https://github.com/open-telemetry/opentelemetry-cpp/pull/3406) - -* [BUILD] Upgrade opentelemetry-proto to 1.6.0 - [#3407](https://github.com/open-telemetry/opentelemetry-cpp/pull/3407) - -* [CMAKE] add generated protobuf headers to the opentelemetry_proto target - [#3400](https://github.com/open-telemetry/opentelemetry-cpp/pull/3400) - -* [MERGE] Fix accidental rollback of nlohmann-json submodule - [#3415](https://github.com/open-telemetry/opentelemetry-cpp/pull/3415) - -* Bump fossas/fossa-action from 1.6.0 to 1.7.0 - [#3414](https://github.com/open-telemetry/opentelemetry-cpp/pull/3414) - -* Bump docker/build-push-action from 6.16.0 to 6.17.0 - [#3420](https://github.com/open-telemetry/opentelemetry-cpp/pull/3420) - -* Bump codecov/codecov-action from 5.4.2 to 5.4.3 - [#3419](https://github.com/open-telemetry/opentelemetry-cpp/pull/3419) - -* [SEMANTIC CONVENTIONS] Upgrade semantic conventions to 1.33 - [#3416](https://github.com/open-telemetry/opentelemetry-cpp/pull/3416) - -* [DOCS] update the INSTALL guide on cmake components - [#3422](https://github.com/open-telemetry/opentelemetry-cpp/pull/3422) - -* Bump github/codeql-action from 3.28.17 to 3.28.18 - [#3423](https://github.com/open-telemetry/opentelemetry-cpp/pull/3423) - -* [CMAKE] update cmake files in examples directory - [#3421](https://github.com/open-telemetry/opentelemetry-cpp/pull/3421) - -* [SDK] Fix Base2ExponentialHistogramAggregation Merge with empty buckets - [#3425](https://github.com/open-telemetry/opentelemetry-cpp/pull/3425) - -* [SDK] Fix MetricProducer interface - [#3413](https://github.com/open-telemetry/opentelemetry-cpp/pull/3413) - -* [CMAKE] remove global include_directories usage and rely on target properties - [#3426](https://github.com/open-telemetry/opentelemetry-cpp/pull/3426) - -* [BUILD] remove unused WITH_CURL build flag - [#3429](https://github.com/open-telemetry/opentelemetry-cpp/pull/3429) - -* [SEMANTIC CONVENTIONS] Upgrade to semantic conventions 1.34.0 - [#3428](https://github.com/open-telemetry/opentelemetry-cpp/pull/3428) - -* [EXPORTER] ostream log exporter, fix memory ownership issues - [#3417](https://github.com/open-telemetry/opentelemetry-cpp/pull/3417) - -* [TEST] add all components to the cmake fetch content test - [#3433](https://github.com/open-telemetry/opentelemetry-cpp/pull/3433) - -* [BUILD] Error out when building DLL without MSVC - [#3438](https://github.com/open-telemetry/opentelemetry-cpp/pull/3438) - -* [BUILD] Add missing CMake keyword for target_link_libraries - [#3442](https://github.com/open-telemetry/opentelemetry-cpp/pull/3442) - -* [CMAKE] Remove third-party version mismatch warning - [#3432](https://github.com/open-telemetry/opentelemetry-cpp/pull/3432) - -* Bump docker/build-push-action from 6.17.0 to 6.18.0 - [#3446](https://github.com/open-telemetry/opentelemetry-cpp/pull/3446) - -* [SEMANTIC CONVENTIONS] Fix comment style to preserve markup. - [#3444](https://github.com/open-telemetry/opentelemetry-cpp/pull/3444) - -* [EXPORTER] support unix sockets in grpc client - [#3410](https://github.com/open-telemetry/opentelemetry-cpp/pull/3410) - -* [BUILD] Propagate INTERFACE_COMPILE_DEFINITIONS from API through common_foo_library - [#3440](https://github.com/open-telemetry/opentelemetry-cpp/pull/3440) - -New Features: - -* [SDK] Base2 exponential histogram aggregation - [#3346](https://github.com/open-telemetry/opentelemetry-cpp/pull/3346) - - * Add base2 exponential histogram aggregation. Includes a new aggregation type, - ostream exporter, and otlp/grpc exporter. Updated histogram aggregation and - benchmark tests. - -Important changes: - -* [EXPORTER] ostream log exporter, fixed memory ownership issues - [#3417](https://github.com/open-telemetry/opentelemetry-cpp/pull/3417) - - * In the SDK, the following classes implementation has changed: - - * opentelemetry::sdk::logs::ReadableLogRecord - * opentelemetry::sdk::logs::ReadWriteLogRecord - - * An application implementing a custom log record exporter, - that reuses these classes from the opentelemetry-cpp SDK, - will need code adjustments, in particular for methods: - - * GetBody() - * GetAttributes() - - * Applications not using these SDK classes directly are not affected. - -* [BUILD] Remove WITH_ABSEIL - [#3318](https://github.com/open-telemetry/opentelemetry-cpp/pull/3318) - - * The build option `WITH_ABSEIL` is no longer used, and opentelemetry-cpp - will no longer use any release of abseil provided externally, - for its own use. - - * Instead, opentelemetry-cpp will only use an internal abseil version. - - * This change resolves long standing binary integrity issues, - that occurred in the past when mixing several versions of abseil - in the build. - -## [1.20 2025-04-01] - -* [BUILD] Update opentelemetry-proto version - [#3254](https://github.com/open-telemetry/opentelemetry-cpp/pull/3254) - -* [BUILD] Build break with CURL 7.29.0 - [#3255](https://github.com/open-telemetry/opentelemetry-cpp/pull/3255) - -* [SEMANTIC CONVENTIONS] Upgrade to semantic conventions 1.30.0 - [#3258](https://github.com/open-telemetry/opentelemetry-cpp/pull/3258) - -* [SDK] Add tracer scope configurator - [#3137](https://github.com/open-telemetry/opentelemetry-cpp/pull/3137) - -* [DOC] Add document and example for sharing gRPC Client - [#3260](https://github.com/open-telemetry/opentelemetry-cpp/pull/3260) - -* [SDK] Fix BatchLogRecordProcessor to instrument shutdown - [#3262](https://github.com/open-telemetry/opentelemetry-cpp/pull/3262) - -* [SDK] Support OTEL_SDK_DISABLED environment variable - [#3245](https://github.com/open-telemetry/opentelemetry-cpp/pull/3245) - -* [CI] OTLP in Windows builds - [#3263](https://github.com/open-telemetry/opentelemetry-cpp/pull/3263) - -* [BUILD] Fixes compatibility of type_traits - [#3274](https://github.com/open-telemetry/opentelemetry-cpp/pull/3274) - -* [BUILD] Fix compilation with Regex being disabled - [#3276](https://github.com/open-telemetry/opentelemetry-cpp/pull/3276) - -* [EXPORTER] Support exporting event_name using OTLP Exporter - [#3277](https://github.com/open-telemetry/opentelemetry-cpp/pull/3277) - -* [CI] Add FOSSA scanning workflow - [#3279](https://github.com/open-telemetry/opentelemetry-cpp/pull/3279) - -* [BUILD] Adding typecast without whom c++latest build fails - [#3281](https://github.com/open-telemetry/opentelemetry-cpp/pull/3281) - -* [ADMIN] Add FOSSA badges - [#3280](https://github.com/open-telemetry/opentelemetry-cpp/pull/3280) - -* [BUILD] Fix compiling problems with abiv2 and MSVC - [#3284](https://github.com/open-telemetry/opentelemetry-cpp/pull/3284) - -* [BUILD] Enable old behavior of CMP0092 - [#3269](https://github.com/open-telemetry/opentelemetry-cpp/pull/3269) - -* [SDK] Add meter scope configurator - [#3268](https://github.com/open-telemetry/opentelemetry-cpp/pull/3268) - -* [DEVCONTAINER] Support customization and run as non-root user - [#3270](https://github.com/open-telemetry/opentelemetry-cpp/pull/3270) - -* [ETW] Add configuration to export 64-bit integer as timestamp - [#3286](https://github.com/open-telemetry/opentelemetry-cpp/pull/3286) - -* [API] Deprecate event logger - [#3285](https://github.com/open-telemetry/opentelemetry-cpp/pull/3285) - -* [BUILD] Add link directory to support curl 8.12 - [#3272](https://github.com/open-telemetry/opentelemetry-cpp/pull/3272) - -* [API] Change the param-pack unpacking order to start from left to right - [#3296](https://github.com/open-telemetry/opentelemetry-cpp/pull/3296) - -* [SDK] Implement spec: MetricFilter - [#3235](https://github.com/open-telemetry/opentelemetry-cpp/pull/3235) - -* [SEMANTIC CONVENTIONS] Upgrade semantic conventions to 1.31.0 - [#3297](https://github.com/open-telemetry/opentelemetry-cpp/pull/3297) - -* [SDK] Add logger scope configurator - [#3282](https://github.com/open-telemetry/opentelemetry-cpp/pull/3282) - -* [EXAMPLE] fix buffer overrun in the gRPC sample project - [#3304](https://github.com/open-telemetry/opentelemetry-cpp/pull/3304) - -* [CI] Bump fossas/fossa-action from 1.5.0 to 1.6.0 - [#3305](https://github.com/open-telemetry/opentelemetry-cpp/pull/3305) - -* [TEST] fix segfault in singleton test with cmake on macos-latest - [#3316](https://github.com/open-telemetry/opentelemetry-cpp/pull/3316) - -* [TEST] fix test failure with elasticsearch exporter on cxx20 - [#3308](https://github.com/open-telemetry/opentelemetry-cpp/pull/3308) - -* [TEST] otlp grpc exporter retry test fix - [#3311](https://github.com/open-telemetry/opentelemetry-cpp/pull/3311) - -* [SDK] Use OPENTELEMETRY_EXPORT and static local variables - [#3314](https://github.com/open-telemetry/opentelemetry-cpp/pull/3314) - -* [BUILD] Fix elasticsearch exporter json compatibility - [#3313](https://github.com/open-telemetry/opentelemetry-cpp/pull/3313) - -* [BUILD] Fix missing exported definition for OTLP file exporter and forceflush - [#3319](https://github.com/open-telemetry/opentelemetry-cpp/pull/3319) - -* [BUILD] Remove gRPC header including in OtlpGrpcClientFactory - [#3321](https://github.com/open-telemetry/opentelemetry-cpp/pull/3321) - -* [ADMIN] Add Pranav Sharma in cpp-approvers - [#3323](https://github.com/open-telemetry/opentelemetry-cpp/pull/3323) - -* [DEVCONTAINER] fix grpc install - [#3325](https://github.com/open-telemetry/opentelemetry-cpp/pull/3325) - -* [ADMIN] Add dbarker to approvers - [#3331](https://github.com/open-telemetry/opentelemetry-cpp/pull/3331) - -* [CI] Upgrade CI to ubuntu 22.04 - [#3330](https://github.com/open-telemetry/opentelemetry-cpp/pull/3330) - -* [CI] Add ossf-scorecard scanning workflow - [#3332](https://github.com/open-telemetry/opentelemetry-cpp/pull/3332) - -* [CI] pin cmake in ci and devcontainer - [#3336](https://github.com/open-telemetry/opentelemetry-cpp/pull/3336) - -* [METRICS SDK] Fix hash collision in MetricAttributes - [#3322](https://github.com/open-telemetry/opentelemetry-cpp/pull/3322) - -Important changes: - -* [SDK] Support OTEL_SDK_DISABLED environment variable - [#3245](https://github.com/open-telemetry/opentelemetry-cpp/pull/3245) - - * The SDK now exposes the following new methods: - - * opentelemetry::sdk::trace::Provider::SetTracerProvider() - * opentelemetry::sdk::metrics::Provider::SetMeterProvider() - * opentelemetry::sdk::logs::Provider::SetLoggerProvider() - - * These methods do support the `OTEL_SDK_DISABLED` environment variable, - unlike the corresponding existing API Provider classes. - - * Applications are encouraged to migrate from the API to the SDK - `Provider` classes, to benefit from this feature. - - * All the example code has been updated to reflect the new usage. - -## [1.19 2025-01-22] - -* [PROMETHEUS_EXPORTER] Fix default for emitting otel_scope attributes - [#3171](https://github.com/open-telemetry/opentelemetry-cpp/pull/3171) - -* [Code health] Include what you use cleanup, part 5 - [#3140](https://github.com/open-telemetry/opentelemetry-cpp/pull/3140) - -* [BUILD] Upgrade cmake - [#3167](https://github.com/open-telemetry/opentelemetry-cpp/pull/3167) - -* [SHIM] Fix string_view mappings between OT and OTel - [#3181](https://github.com/open-telemetry/opentelemetry-cpp/pull/3181) - -* [EXPORTER] Refactor ElasticSearchRecordable - [#3164](https://github.com/open-telemetry/opentelemetry-cpp/pull/3164) - -* [SEMANTIC CONVENTIONS] Upgrade to semantic conventions 1.29.0 - [#3182](https://github.com/open-telemetry/opentelemetry-cpp/pull/3182) - -* [BUILD] Fix cross-compilation with protoc - [#3186](https://github.com/open-telemetry/opentelemetry-cpp/pull/3186) - -* [Code health] Perform cppcheck cleanup - [#3150](https://github.com/open-telemetry/opentelemetry-cpp/pull/3150) - -* [EXPORTER] add instrumentation scope attributes - to otlp proto messages for traces and metrics - [#3185](https://github.com/open-telemetry/opentelemetry-cpp/pull/3185) - -* [SDK] Tracer provider shutdown blocks in-definitively - [#3191](https://github.com/open-telemetry/opentelemetry-cpp/pull/3191) - -* [SEMANTIC CONVENTIONS] Upgrade to weaver 0.11.0 - [#3194](https://github.com/open-telemetry/opentelemetry-cpp/pull/3194) - -* [DOC] Update existing maintaining dependencies doc - [#3195](https://github.com/open-telemetry/opentelemetry-cpp/pull/3195) - -* [TEST] Change is_called_ and got_response_ to use atomic - [#3204](https://github.com/open-telemetry/opentelemetry-cpp/pull/3204) - -* [SEMANTIC CONVENTIONS] update links to openmetrics to reference the v1.0.0 release - [#3205](https://github.com/open-telemetry/opentelemetry-cpp/pull/3205) - -* [CI] Fix CI on ubuntu-latest - [#3207](https://github.com/open-telemetry/opentelemetry-cpp/pull/3207) - -* [BUILD] Build break using protoc 3.14 - [#3211](https://github.com/open-telemetry/opentelemetry-cpp/pull/3211) - -* [TEST] Build the singleton test on windows - [#3183](https://github.com/open-telemetry/opentelemetry-cpp/pull/3183) - -* [BUILD] Add cxx feature detections - [#3203](https://github.com/open-telemetry/opentelemetry-cpp/pull/3203) - -* [SDK] Do not frequently create and destroy http client threads - [#3198](https://github.com/open-telemetry/opentelemetry-cpp/pull/3198) - -* [EXPORTER] Optimize OTLP HTTP compression - [#3178](https://github.com/open-telemetry/opentelemetry-cpp/pull/3178) - -* [SDK] Fix include instrumentation scope attributes in equal method - [#3214](https://github.com/open-telemetry/opentelemetry-cpp/pull/3214) - -* Upgrade to opentelemetry-proto 1.5.0 - [#3210](https://github.com/open-telemetry/opentelemetry-cpp/pull/3210) - -* [TEST] Added support for SELINUX in functional tests - [#3212](https://github.com/open-telemetry/opentelemetry-cpp/pull/3212) - -* [EDITORIAL] fix changelog entry for PR 3185 - [#3217](https://github.com/open-telemetry/opentelemetry-cpp/pull/3217) - -* [TEST] Functional tests for OTLP/gRPC with mutual TLS - [#3227](https://github.com/open-telemetry/opentelemetry-cpp/pull/3227) - -* [SEMCONV] Metrics are incorrectly prefixed with 'metric' - [#3228](https://github.com/open-telemetry/opentelemetry-cpp/pull/3228) - -* [BUILD] Add OTLP/file exporter for dll and examples - [#3231](https://github.com/open-telemetry/opentelemetry-cpp/pull/3231) - -* [Code Health] Include what you use, part 6 - [#3216](https://github.com/open-telemetry/opentelemetry-cpp/pull/3216) - -* [CI] Spurious test failures - [#3233](https://github.com/open-telemetry/opentelemetry-cpp/pull/3233) - -* [BUILD] Fix error ‘uint8_t’ does not name a type with gcc-15 - [#3240](https://github.com/open-telemetry/opentelemetry-cpp/pull/3240) - -* [EXPORTER] fix throw in OtlpGrpcMetricExporter with shared grpc client - [#3243](https://github.com/open-telemetry/opentelemetry-cpp/pull/3243) - -* [SDK] Better control of threads executed by opentelemetry-cpp - [#3175](https://github.com/open-telemetry/opentelemetry-cpp/pull/3175) - -* [Code Health] Include what you use, part 7 - [#3238](https://github.com/open-telemetry/opentelemetry-cpp/pull/3238) - -* [SDK] Fix lifetime of GlobalLogHandler - [#3221](https://github.com/open-telemetry/opentelemetry-cpp/pull/3221) - -* [MAINTAINER] Add devcontainer - [#3123](https://github.com/open-telemetry/opentelemetry-cpp/pull/3123) - -* [SDK] enable deriving from ResourceDetector to create a Resource - [#3247](https://github.com/open-telemetry/opentelemetry-cpp/pull/3247) - -* [EXPORTER] Support handling retry-able errors for OTLP/HTTP - [#3223](https://github.com/open-telemetry/opentelemetry-cpp/pull/3223) - -* [CI] Add GRPC in maintainer CI - [#3248](https://github.com/open-telemetry/opentelemetry-cpp/pull/3248) - -* [EXPORTER] Support handling retry-able errors for OTLP/gRPC - [#3219](https://github.com/open-telemetry/opentelemetry-cpp/pull/3219) - -* [SDK] Optimize Metric Processing for Single Collector with Delta Temporality - [#3236](https://github.com/open-telemetry/opentelemetry-cpp/pull/3236) - -New features: - -* [SDK] Better control of threads executed by opentelemetry-cpp - [#3175](https://github.com/open-telemetry/opentelemetry-cpp/pull/3175) - - * This feature provides a way for applications, - when configuring the SDK and exporters, - to participate in the execution path - of internal opentelemetry-cpp threads. - - * The opentelemetry-cpp library provides the following: - - * a new ThreadInstrumentation interface, - * new runtime options structures, to optionally configure the SDK: - * BatchSpanProcessorRuntimeOptions - * PeriodicExportingMetricReaderRuntimeOptions - * BatchLogRecordProcessorRuntimeOptions - * new runtime options structures, - to optionally configure the OTLP HTTP exporters: - * OtlpHttpExporterRuntimeOptions - * OtlpHttpMetricExporterRuntimeOptions - * OtlpHttpLogRecordExporterRuntimeOptions - * new ThreadInstrumentation parameters, - to optionally configure the CURL HttpClient - * new runtime options structures, - to optionally configure the OTLP FILE exporters: - * OtlpFileExporterRuntimeOptions - * OtlpFileMetricExporterRuntimeOptions - * OtlpFileLogRecordExporterRuntimeOptions - * new runtime options structure, - to optionally configure the OTLP FILE client: - * OtlpFileClientRuntimeOptions - - * Using the optional runtime options structures, - an application can subclass the ThreadInstrumentation interface, - and be notified of specific events of interest during the execution - of an internal opentelemetry-cpp thread. - - * This allows an application to call, for example: - - * pthread_setaffinity_np(), for better performances, - * setns(), to control the network namespace used by HTTP CURL connections - * pthread_setname_np(), for better observability from the operating system - * many more specific apis, as needed - - * See the documentation for ThreadInstrumentation for details. - - * A new example program, example_otlp_instrumented_http, - shows how to use the feature, - and add application logic in the thread execution code path. - - * Note that this feature is experimental, - protected by a WITH_THREAD_INSTRUMENTATION_PREVIEW - flag in CMake. Various runtime options structures, - as well as the thread instrumentation interface, - may change without notice before this feature is declared stable. - -* [EXPORTER] Support handling retry-able errors for OTLP/HTTP - [#3223](https://github.com/open-telemetry/opentelemetry-cpp/pull/3223) - - * This feature is experimental, - protected by a WITH_OTLP_RETRY_PREVIEW - flag in CMake. - -* [EXPORTER] Support handling retry-able errors for OTLP/gRPC - [#3219](https://github.com/open-telemetry/opentelemetry-cpp/pull/3219) - - * This feature is experimental, - protected by a WITH_OTLP_RETRY_PREVIEW - flag in CMake. - -## [1.18 2024-11-25] - -* [EXPORTER] Fix crash in ElasticsearchLogRecordExporter - [#3082](https://github.com/open-telemetry/opentelemetry-cpp/pull/3082) - -* [BUILD] Avoid buggy warning with gcc <= 8 - [#3087](https://github.com/open-telemetry/opentelemetry-cpp/pull/3087) - -* [API] Jaeger Propagator should not be deprecated - [#3086](https://github.com/open-telemetry/opentelemetry-cpp/pull/3086) - -* Update bzlmod version - [#3093](https://github.com/open-telemetry/opentelemetry-cpp/pull/3093) - -* [BUILD] Remove std::make_unique - [#3098](https://github.com/open-telemetry/opentelemetry-cpp/pull/3098) - -* [BUILD] Fix compiling problems for gcc 4.8 - [#3100](https://github.com/open-telemetry/opentelemetry-cpp/pull/3100) - -* [TEST] Fix linking order and gmock linking - [#3106](https://github.com/open-telemetry/opentelemetry-cpp/pull/3106) - -* [EXPORTER] Add config options to prometheus exporter - [#3104](https://github.com/open-telemetry/opentelemetry-cpp/pull/3104) - -* [BUILD] Add a CMake option to disable shared libs - [#3095](https://github.com/open-telemetry/opentelemetry-cpp/pull/3095) - -* [EXPORTER] Remove out of date ETW exporter doc - [#3103](https://github.com/open-telemetry/opentelemetry-cpp/pull/3103) - -* [EXPORTER] Add logging for async gRPC errors - [#3108](https://github.com/open-telemetry/opentelemetry-cpp/pull/3108) - -* [BUILD] Remove aligned_storage from nostd - [#3112](https://github.com/open-telemetry/opentelemetry-cpp/pull/3112) - -* [EXPORTER] Elastic Search exporter follow ECS guidelines - [#3107](https://github.com/open-telemetry/opentelemetry-cpp/pull/3107) - -* [INSTALL] Resolve dependencies in opentelemetry-cpp-config.cmake - [#3094](https://github.com/open-telemetry/opentelemetry-cpp/pull/3094) - -* [API] Add synchronous gauge - [#3029](https://github.com/open-telemetry/opentelemetry-cpp/pull/3029) - -* [BUILD] allow building with -DWITH_OTLP_HTTP_COMPRESSION=OFF without zlib - [#3120](https://github.com/open-telemetry/opentelemetry-cpp/pull/3120) - -* [CI] Comment the arm64 CI - [#3125](https://github.com/open-telemetry/opentelemetry-cpp/pull/3125) - -* [API] Comply with W3C Trace Context - [#3115](https://github.com/open-telemetry/opentelemetry-cpp/pull/3115) - -* [EXPORTER] bump prometheus to v1.3.0 - [#3122](https://github.com/open-telemetry/opentelemetry-cpp/pull/3122) - -* [EXPORTER] Log SSL Connection Information - [#3113](https://github.com/open-telemetry/opentelemetry-cpp/pull/3113) - -* [BUILD] Improve how to handle yield() in ARM - [#3129](https://github.com/open-telemetry/opentelemetry-cpp/pull/3129) - -* [BUILD] Fix -Wmissing-template-arg-list-after-template-kw warning - [#3133](https://github.com/open-telemetry/opentelemetry-cpp/pull/3133) - -* [EXPORTER]: Elasticsearch exporter put log resource in root instead of under 'resources' - [#3131](https://github.com/open-telemetry/opentelemetry-cpp/pull/3131) - -* [TEST] Rename w3c_tracecontext_test to w3c_tracecontext_http_test_server - [#3132](https://github.com/open-telemetry/opentelemetry-cpp/pull/3132) - -* [BUILD] Patches for building on AIX - [#3127](https://github.com/open-telemetry/opentelemetry-cpp/pull/3127) - -* [SEMANTIC CONVENTIONS] Migration to weaver - [#3105](https://github.com/open-telemetry/opentelemetry-cpp/pull/3105) - -* [SEMANTIC CONVENTIONS] Upgrade to semantic conventions 1.28.0 - [#3139](https://github.com/open-telemetry/opentelemetry-cpp/pull/3139) - -* [EXPORTER] handling of invalid ports in UrlParser - [#3142](https://github.com/open-telemetry/opentelemetry-cpp/pull/3142) - -* [CI] speed up clang-tidy workflow - [#3148](https://github.com/open-telemetry/opentelemetry-cpp/pull/3148) - -* [EXPORTER] Allow to share gRPC clients between OTLP exporters - [#3041](https://github.com/open-telemetry/opentelemetry-cpp/pull/3041) - -* Bump codecov/codecov-action from 4 to 5 - [#3143](https://github.com/open-telemetry/opentelemetry-cpp/pull/3143) - -* [CI] Add cppcheck in the build - [#3151](https://github.com/open-telemetry/opentelemetry-cpp/pull/3151) - -* [BUILD] Fix error message - [#3152](https://github.com/open-telemetry/opentelemetry-cpp/pull/3152) - -* [EXPORTER] fix clang-tidy warnings in UrlParser - [#3146](https://github.com/open-telemetry/opentelemetry-cpp/pull/3146) - -* [EXPORTER] Upgrade to opentelemetry-proto 1.4.0 - [#3157](https://github.com/open-telemetry/opentelemetry-cpp/pull/3157) - -* [TEST] refactor UrlParser tests to use value-paramterized tests - [#3153](https://github.com/open-telemetry/opentelemetry-cpp/pull/3153) - -* [TEST] add a test for ElasticSearchRecordable - [#3154](https://github.com/open-telemetry/opentelemetry-cpp/pull/3154) - -* [BUILD] Fix missing dependency on protoc compiler - [#3159](https://github.com/open-telemetry/opentelemetry-cpp/pull/3159) - -* [bazel] Update prometheus-cpp in MODULE.bazel - [#3162](https://github.com/open-telemetry/opentelemetry-cpp/pull/3162) - -* [bazel] Enable --incompatible_disallow_empty_glob - [#2642](https://github.com/open-telemetry/opentelemetry-cpp/pull/2642) - -* [INSTALL] Fix cmake/opentelemetry-cpp-config.cmake.in - [#3165](https://github.com/open-telemetry/opentelemetry-cpp/pull/3165) - -* [BUILD] Do not set OTELCPP_PROTO_PATH in the CMake cache - [#3160](https://github.com/open-telemetry/opentelemetry-cpp/pull/3160) - -* [BUILD] Fix build for esp32 - [#3155](https://github.com/open-telemetry/opentelemetry-cpp/pull/3155) - -* [bazel] Update opentelemetry-proto in MODULE.bazel - [#3163](https://github.com/open-telemetry/opentelemetry-cpp/pull/3163) - -Important changes: - -* [API] Jaeger Propagator should not be deprecated - [#3086](https://github.com/open-telemetry/opentelemetry-cpp/pull/3086) - - * Deprecation of the Jaeger propagator, as announced on 2023-01-31 - in version 1.8.2, is now reverted. - * This deprecation turned out to be not justified, - as the Jaeger propagator can be used without the (now removed) - Jaeger exporter. - -* [EXPORTER] Change log resources location for ElasticsearchLogRecordExporter - [#3119](https://github.com/open-telemetry/opentelemetry-cpp/pull/3131) - - * Moved from `root/resources` to `root` - -* [SEMANTIC CONVENTIONS] Migration to weaver - [#3105](https://github.com/open-telemetry/opentelemetry-cpp/pull/3105) - - * `semantic_convention.h` header files are deprecated, - replaced by `semconv/xxx_attributes.h` header files, - for each `xxx` semantic attribute group. - * See file DEPRECATED.md for details. - -Deprecations: - -* This release contains deprecations, see file DEPRECATED.md for details. - -## [1.17 2024-10-07] - -* [CI] Add a clang-tidy build - [#3001](https://github.com/open-telemetry/opentelemetry-cpp/pull/3001) - -* [BUILD] Upgrade to opentelemetry-proto 1.3.2 - [#2991](https://github.com/open-telemetry/opentelemetry-cpp/pull/2991) - -* [REMOVAL] Remove build option `WITH_DEPRECATED_SDK_FACTORY` - [#2717](https://github.com/open-telemetry/opentelemetry-cpp/pull/2717) - -* [EXPORTER] ForceFlush before canceling the running requests on shutdown - [#2727](https://github.com/open-telemetry/opentelemetry-cpp/pull/2727) - -* [SDK] Fix crash in PeriodicExportingMetricReader - [#2983](https://github.com/open-telemetry/opentelemetry-cpp/pull/2983) - -* [SDK] Fix memory leak in TlsRandomNumberGenerator() constructor - [#2661](https://github.com/open-telemetry/opentelemetry-cpp/pull/2661) - -* [EXPORTER] Ignore exception when create thread in OTLP file exporter - [#3012](https://github.com/open-telemetry/opentelemetry-cpp/pull/3012) - -* [BUILD] Update the version in MODULE.bazel - [#3015](https://github.com/open-telemetry/opentelemetry-cpp/pull/3015) - -* [BUILD] Fix build without vcpkg on Windows when gRPC is disabled - [#3016](https://github.com/open-telemetry/opentelemetry-cpp/pull/3016) - -* [BUILD] Add abi_version_no bazel flag - [#3020](https://github.com/open-telemetry/opentelemetry-cpp/pull/3020) - -* [Code health] Expand iwyu coverage to include unit tests - [#3022](https://github.com/open-telemetry/opentelemetry-cpp/pull/3022) - -* [BUILD] Version opentelemetry_proto/proto_grpc shared libraries - [#2992](https://github.com/open-telemetry/opentelemetry-cpp/pull/2992) - -* [SEMANTIC CONVENTIONS] Upgrade semantic conventions to 1.27.0 - [#3023](https://github.com/open-telemetry/opentelemetry-cpp/pull/3023) - -* [SDK] Support empty histogram buckets - [#3027](https://github.com/open-telemetry/opentelemetry-cpp/pull/3027) - -* [TEST] Fix sync problems in OTLP File exporter tests - [#3031](https://github.com/open-telemetry/opentelemetry-cpp/pull/3031) - -* [SDK] PeriodicExportingMetricReader: future is never set, blocks until timeout - [#3030](https://github.com/open-telemetry/opentelemetry-cpp/pull/3030) - -* [Code Health] Clang Tidy cleanup, Part 2 - [#3038](https://github.com/open-telemetry/opentelemetry-cpp/pull/3038) - -* [Code Health] include-what-you-use cleanup, part 3 - [#3004](https://github.com/open-telemetry/opentelemetry-cpp/pull/3004) - -* [SDK] Fix overflow in timeout logic - [#3046](https://github.com/open-telemetry/opentelemetry-cpp/pull/3046) - -* [TEST] Add missing tests to Bazel build - [#3045](https://github.com/open-telemetry/opentelemetry-cpp/pull/3045) - -* [TEST] update collector tests with debug exporter - [#3050](https://github.com/open-telemetry/opentelemetry-cpp/pull/3050) - -* [EXAMPLE] update collector example with debug exporter - [#3049](https://github.com/open-telemetry/opentelemetry-cpp/pull/3049) - -* [TEST] update references to logging exporter - [#3053](https://github.com/open-telemetry/opentelemetry-cpp/pull/3053) - -* [EXAMPLE] Clean the tracer initialization in OStream example - [#3051](https://github.com/open-telemetry/opentelemetry-cpp/pull/3051) - -* [EXPORTER] Fix the format of SpanLink for ETW - [#3054](https://github.com/open-telemetry/opentelemetry-cpp/pull/3054) - -* [EXPORTER] Add in-memory metric exporter - [#3043](https://github.com/open-telemetry/opentelemetry-cpp/pull/3043) - -* [Code Health] include-what-you-use cleanup, part 4 - [#3040](https://github.com/open-telemetry/opentelemetry-cpp/pull/3040) - -* [BUILD] add loongarch info - [#3052](https://github.com/open-telemetry/opentelemetry-cpp/pull/3052) - -* [CI] Update otel-collector version - [#3067](https://github.com/open-telemetry/opentelemetry-cpp/pull/3067) - -* [SDK] Update MetricProducer interface to match spec - [#3044](https://github.com/open-telemetry/opentelemetry-cpp/pull/3044) - -* [EXPORTER] Fix URL in ES exporter, fix ipv6 supporting for http client - [#3081](https://github.com/open-telemetry/opentelemetry-cpp/pull/3081) - -* [EXPORTER] Add HttpHeaders in ElasticsearchLogRecordExporter - [#3083](https://github.com/open-telemetry/opentelemetry-cpp/pull/3083) - -Breaking changes: - -* [REMOVAL] Remove build option `WITH_DEPRECATED_SDK_FACTORY` - [#2717](https://github.com/open-telemetry/opentelemetry-cpp/pull/2717) - - * As announced in opentelemetry-cpp previous release 1.16.0, - CMake option `WITH_DEPRECATED_SDK_FACTORY` was temporary, - and to be removed by the next release. - * This option is now removed. - * Code configuring the SDK must be adjusted, as previously described: - - * [API/SDK] Provider cleanup - [#2664](https://github.com/open-telemetry/opentelemetry-cpp/pull/2664) - - * Before this fix: - * SDK factory methods such as: - * opentelemetry::sdk::trace::TracerProviderFactory::Create() - * opentelemetry::sdk::metrics::MeterProviderFactory::Create() - * opentelemetry::sdk::logs::LoggerProviderFactory::Create() - * opentelemetry::sdk::logs::EventLoggerProviderFactory::Create() - - returned an API object (opentelemetry::trace::TracerProvider) - to the caller. - - * After this fix, these methods return an SDK level object - (opentelemetry::sdk::trace::TracerProvider) to the caller. - * Returning an SDK object is necessary for the application to - cleanup and invoke SDK level methods, such as ForceFlush(), - on a provider. - * The application code that configures the SDK, by calling - the various provider factories, may need adjustment. - * All the examples have been updated, and in particular no - longer perform static_cast do convert an API object to an SDK object. - Please refer to examples for guidance on how to adjust. - -## [1.16.1 2024-07-17] - -* [BUILD] Add bazel missing BUILD file - [#2720](https://github.com/open-telemetry/opentelemetry-cpp/pull/2720) - -* [SDK] Added reserve for spans array in BatchSpanProcessor. - [#2724](https://github.com/open-telemetry/opentelemetry-cpp/pull/2724) - -* [DOC] Update "Using triplets" section in building-with-vcpkg documentation. - [#2726](https://github.com/open-telemetry/opentelemetry-cpp/pull/2726) - -* [DOC] Remove comment for unused LoggerProvider initialization params - [#2972](https://github.com/open-telemetry/opentelemetry-cpp/pull/2972) - -* [SECURITY] Remove OTLP HTTP support for TLS 1.0 and TLS 1.1, - require TLS 1.2 or better - [#2722](https://github.com/open-telemetry/opentelemetry-cpp/pull/2722) - -* [TEST] Fix opentelemetry-collector bind address - [#2989](https://github.com/open-telemetry/opentelemetry-cpp/pull/2989) - -* [EXPORTER] Fix references in AttributeValueVisitor - [#2985](https://github.com/open-telemetry/opentelemetry-cpp/pull/2985) - -* [Code health] include-what-you-use cleanup, part 2 - [#2704](https://github.com/open-telemetry/opentelemetry-cpp/pull/2704) - -* [Code Health] clang-tidy cleanup, part 1 - [#2990](https://github.com/open-telemetry/opentelemetry-cpp/pull/2990) - -* [CI] Build failures with ABSEIL 20240116 and CMAKE 3.30 - [#3002](https://github.com/open-telemetry/opentelemetry-cpp/pull/3002) - -* [CI] Enable bzlmod - [#2995](https://github.com/open-telemetry/opentelemetry-cpp/pull/2995) - -* [Metrics SDK] Fix hash calculation for nostd::string - [#2999](https://github.com/open-telemetry/opentelemetry-cpp/pull/2999) - -Breaking changes: - -* [SECURITY] Remove OTLP HTTP support for TLS 1.0 and TLS 1.1, - require TLS 1.2 or better - [#2722](https://github.com/open-telemetry/opentelemetry-cpp/pull/2722) - * The OTLP HTTP exporter no longer accept options like: - * min_TLS = 1.0 - * min_TLS = 1.1 - * max_TLS = 1.0 - * max_TLS = 1.1 - * When connecting to an OTLP HTTP endpoint, using `https`, - the connection will require TLS 1.2 by default, - unless min_TLS is set to 1.3 - * Plain `http` connections (insecure) are not affected. - -## [1.16.0] 2024-06-21 - -* [BUILD] Upgrade bazel abseil from 20220623.1 to 20230802.2 - [#2650](https://github.com/open-telemetry/opentelemetry-cpp/pull/2650) -* [BUILD] Use nostd::enable_if_t instead of std::enable_if_t - [#2648](https://github.com/open-telemetry/opentelemetry-cpp/pull/2648) -* [EXEMPLAR] Update ExemplarFilter and ExemplarReservoir for spec - [#2372](https://github.com/open-telemetry/opentelemetry-cpp/pull/2372) -* [BUILD] Link CoreFoundation on apple systems - [#2655](https://github.com/open-telemetry/opentelemetry-cpp/pull/2655) -* [SDK] Avoid missing conditional variable update and simplify atomic bool - [#2553](https://github.com/open-telemetry/opentelemetry-cpp/pull/2553) -* [BUILD] Build break in OLTP_FILE tests - [#2659](https://github.com/open-telemetry/opentelemetry-cpp/pull/2659) -* [EXPORTER] General cleanup for is_shutdown flags in exporters. - [#2663](https://github.com/open-telemetry/opentelemetry-cpp/pull/2663) -* [CI] Upgrade Maintainers CI to ubuntu-24.04 - [#2670](https://github.com/open-telemetry/opentelemetry-cpp/pull/2670) -* [BUILD] Upgrade to opentelemetry-proto 1.3.1 - [#2669](https://github.com/open-telemetry/opentelemetry-cpp/pull/2669) -* [API] Return NoopLogRecord from NoopLogger - [#2668](https://github.com/open-telemetry/opentelemetry-cpp/pull/2668) -* [BUILD] Remove the hard-coded separator in tracestate - [#2672](https://github.com/open-telemetry/opentelemetry-cpp/pull/2672) -* [SDK] Fix forceflush may wait for ever - [#2584](https://github.com/open-telemetry/opentelemetry-cpp/pull/2584) -* [API] DO not allow unsafe Logger::EmitLogRecord - [#2673](https://github.com/open-telemetry/opentelemetry-cpp/pull/2673) -* [BUILD] Read default proto version from third_party_release - [#2677](https://github.com/open-telemetry/opentelemetry-cpp/pull/2677) -* [CI] include-what-you-use - [#2629](https://github.com/open-telemetry/opentelemetry-cpp/pull/2629) -* [CI] Upgrade to clang-format 18 - [#2684](https://github.com/open-telemetry/opentelemetry-cpp/pull/2684) -* [CI] Fix CI failures on Ubuntu 24.04 - [#2686](https://github.com/open-telemetry/opentelemetry-cpp/pull/2686) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.26.0 - [#2687](https://github.com/open-telemetry/opentelemetry-cpp/pull/2687) -* [API/SDK] Provider cleanup - [#2664](https://github.com/open-telemetry/opentelemetry-cpp/pull/2664) -* [ETW] Add table name mapping for Logs other than the default Log table - [#2691](https://github.com/open-telemetry/opentelemetry-cpp/pull/2691) -* [CI] Remove benchmark overlay for vcpkg - [#2695](https://github.com/open-telemetry/opentelemetry-cpp/pull/2695) -* [BUILD] Remove the incorrect set of CMAKE_MSVC_RUNTIME_LIBRARY for vcpkg - [#2696](https://github.com/open-telemetry/opentelemetry-cpp/pull/2696) -* [BUILD] CMakeLists.txt: Enable CMAKE_MSVC_RUNTIME_LIBRARY support - [#2652](https://github.com/open-telemetry/opentelemetry-cpp/pull/2652) -* [EXPORTER] OTLP file: use thread-safe file/io - [#2675](https://github.com/open-telemetry/opentelemetry-cpp/pull/2675) -* [bazel] Bump version and deps - [#2679](https://github.com/open-telemetry/opentelemetry-cpp/pull/2679) -* [BUILD] Add support for bzlmod - [#2608](https://github.com/open-telemetry/opentelemetry-cpp/pull/2608) -* [BUILD] Fix Import Abseil-cpp - [#2701](https://github.com/open-telemetry/opentelemetry-cpp/pull/2701) -* [Code health] include-what-you-use cleanup - [#2692](https://github.com/open-telemetry/opentelemetry-cpp/pull/2692) -* [BUILD] Restore Bazel flag removed from public API - [#2702](https://github.com/open-telemetry/opentelemetry-cpp/pull/2702) -* [DOC] Fix typo tace_id -> trace_id in logger.h - [#2703](https://github.com/open-telemetry/opentelemetry-cpp/pull/2703) -* Bump docker/build-push-action from 5 to 6 - [#2705](https://github.com/open-telemetry/opentelemetry-cpp/pull/2705) -* [CI] Enable ARM64 build in CI - [#2699](https://github.com/open-telemetry/opentelemetry-cpp/pull/2699) -* [Code health] Remove Unicode Text from Source files - [#2707](https://github.com/open-telemetry/opentelemetry-cpp/pull/2707) -* [BUILD] Add option WITH_OTLP_GRPC_SSL_MTLS_PREVIEW - [#2714](https://github.com/open-telemetry/opentelemetry-cpp/pull/2714) -* [EXPORTER] All 2xx return codes should be considered successful. - [#2712](https://github.com/open-telemetry/opentelemetry-cpp/pull/2712) - -Important changes: - -* [API/SDK] Provider cleanup - [#2664](https://github.com/open-telemetry/opentelemetry-cpp/pull/2664) - * Before this fix: - * The API class `opentelemetry::trace::Tracer` exposed methods such - as `ForceFlush()`, `ForceFlushWithMicroseconds()`, `Close()` - and `CloseWithMicroseconds()`. - * These methods are meant to be used when configuring the SDK, - and should not be part of the API. Exposing them was an oversight. - * Two of these methods are virtual, and therefore part of the ABI. - * After this fix: - * In `OPENTELEMETRY_ABI_VERSION_NO 1`, nothing is changed, - because removing this code would break the ABI. - * In `OPENTELEMETRY_ABI_VERSION_NO 2`, these methods are moved - from the API to the SDK. This is a breaking change for ABI version 2, - which is still experimental. - * In all cases, instrumenting an application should not - invoke flush or close on a tracer, do not use these methods. - -Breaking changes: - -* [API/SDK] Provider cleanup - [#2664](https://github.com/open-telemetry/opentelemetry-cpp/pull/2664) - * Before this fix: - * SDK factory methods such as: - * opentelemetry::sdk::trace::TracerProviderFactory::Create() - * opentelemetry::sdk::metrics::MeterProviderFactory::Create() - * opentelemetry::sdk::logs::LoggerProviderFactory::Create() - * opentelemetry::sdk::logs::EventLoggerProviderFactory::Create() - returned an API object (opentelemetry::trace::TracerProvider) - to the caller. - * After this fix, these methods return an SDK level object - (opentelemetry::sdk::trace::TracerProvider) to the caller. - * Returning an SDK object is necessary for the application to - cleanup and invoke SDK level methods, such as ForceFlush(), - on a provider. - * The application code that configures the SDK, by calling - the various provider factories, may need adjustment. - * All the examples have been updated, and in particular no - longer perform static_cast do convert an API object to an SDK object. - Please refer to examples for guidance on how to adjust. - * If adjusting application code is impractical, - an alternate and temporary solution is to build with option - WITH_DEPRECATED_SDK_FACTORY=ON in CMake. - * Option WITH_DEPRECATED_SDK_FACTORY=ON will allow to build code - without application changes, posponing changes for later. - * WITH_DEPRECATED_SDK_FACTORY=ON is temporary, only to provide - an easier migration path. Expect this flag to be removed, - as early as by the next release. - -Notes on experimental features: - -* [#2372](https://github.com/open-telemetry/opentelemetry-cpp/issues/2372) - introduced `MeterProvider::SetExemplar()` which accepts en - `ExemplarFilterType` enumeration with `kAlwaysOff`, `kAlwaysOn` and - `kTraceBased`. - -## [1.15.0] 2024-04-21 - -* [EXPORTER] Change OTLP HTTP content_type default to binary - [#2564](https://github.com/open-telemetry/opentelemetry-cpp/pull/2564) -* [DOC] Fix OTLP documentation: Default endpoint is wrong for OTLP/HTTP - [#2560](https://github.com/open-telemetry/opentelemetry-cpp/pull/2560) -* [BUILD] Fix old style cast warning - [#2567](https://github.com/open-telemetry/opentelemetry-cpp/pull/2567) -* [EXPORTER] Gzip compression support for OTLP/HTTP and OTLP/gRPC exporter - [#2530](https://github.com/open-telemetry/opentelemetry-cpp/pull/2530) -* [BUILD] update vcpkg submodule to 2024.02.14 - [#2575](https://github.com/open-telemetry/opentelemetry-cpp/pull/2575) -* [SDK] Support for OTEL_SERVICE_NAME - [#2577](https://github.com/open-telemetry/opentelemetry-cpp/pull/2577) -* [EXPORTER] Support URL-encoded values for `OTEL_EXPORTER_OTLP_HEADERS` - [#2579](https://github.com/open-telemetry/opentelemetry-cpp/pull/2579) -* [BUILD] CMake cleanup for message() - [#2582](https://github.com/open-telemetry/opentelemetry-cpp/pull/2582) -* [BUILD] Bump CMake minimum required version to 3.9 - [#2581](https://github.com/open-telemetry/opentelemetry-cpp/pull/2581) -* [BUILD] Provide LIKELY / UNLIKELY macros - [#2580](https://github.com/open-telemetry/opentelemetry-cpp/pull/2580) -* [EXPORTER] OTLP: Fix missing ResourceMetrics SchemaURL - [#2587](https://github.com/open-telemetry/opentelemetry-cpp/pull/2587) -* [ETW] cleanup include path - [#2594](https://github.com/open-telemetry/opentelemetry-cpp/pull/2594) -* Upgrade to googletest 1.14.0 - [#2596](https://github.com/open-telemetry/opentelemetry-cpp/pull/2596) -* Upgrade to nlohmann_json 3.11.3 - [#2595](https://github.com/open-telemetry/opentelemetry-cpp/pull/2595) -* [BAZEL] Move -std=c++14 to .bazelrc - [#2600](https://github.com/open-telemetry/opentelemetry-cpp/pull/2600) -* [BAZEL] Fix -std=c++14 warning on Windows - [#2601](https://github.com/open-telemetry/opentelemetry-cpp/pull/2601) -* Upgrade to benchmark 1.8.3 - [#2597](https://github.com/open-telemetry/opentelemetry-cpp/pull/2597) -* Upgrade to prometheus 1.2.4 - [#2598](https://github.com/open-telemetry/opentelemetry-cpp/pull/2598) -* [DOC] Fix typo: Asynchronouse -> Asynchronous in meter.h - [#2604](https://github.com/open-telemetry/opentelemetry-cpp/pull/2604) -* [BUILD] Do not link prometheus-cpp::util when it doesn't exist - [#2606](https://github.com/open-telemetry/opentelemetry-cpp/pull/2606) -* [SDK] Remove unused variable - [#2609](https://github.com/open-telemetry/opentelemetry-cpp/pull/2609) -* [METRICS SDK] Remove extra OfferMeasurement call - in SyncMetricsStorage::OfferMeasurement - [#2610](https://github.com/open-telemetry/opentelemetry-cpp/pull/2610) -* [MISC] Use set -e on all shell scripts and pass shellcheck --severity=error - [#2616](https://github.com/open-telemetry/opentelemetry-cpp/pull/2616) -* [CI] Add shellcheck --severity=error as a CI step - [#2618](https://github.com/open-telemetry/opentelemetry-cpp/pull/2618) -* [CI] Upgrade to abseil 20240116.1 (CMake only) - [#2599](https://github.com/open-telemetry/opentelemetry-cpp/pull/2599) -* [CI] Benchmark, provide units with --benchmark_min_time - [#2621](https://github.com/open-telemetry/opentelemetry-cpp/pull/2621) -* [EXPORTER] OTLP file exporter - [#2540](https://github.com/open-telemetry/opentelemetry-cpp/pull/2540) -* [CI] Use platform CMake - [#2627](https://github.com/open-telemetry/opentelemetry-cpp/pull/2627) -* [PROTO] Upgrade to opentelemetry-proto 1.2.0 - [#2631](https://github.com/open-telemetry/opentelemetry-cpp/pull/2631) -* [SDK] DefaultLogHandler to print errors to std::cerr, add LogLevel::None - [#2622](https://github.com/open-telemetry/opentelemetry-cpp/pull/2622) -* [SEMANTIC CONVENTIONS] Upgrade to semantic convention 1.25.0 - [#2633](https://github.com/open-telemetry/opentelemetry-cpp/pull/2633) -* [DOC] Add readme and examples for OTLP FILE exporters. - [#2638](https://github.com/open-telemetry/opentelemetry-cpp/pull/2638) -* [SEMANTIC CONVENTIONS] Rework on semantic conventions 1.25.0 - [#2640](https://github.com/open-telemetry/opentelemetry-cpp/pull/2640) -* [DOC] Update INSTALL.md - [#2592](https://github.com/open-telemetry/opentelemetry-cpp/pull/2592) - -Important changes: - -* [EXPORTER] Gzip compression support for OTLP/HTTP and OTLP/gRPC exporter - [#2530](https://github.com/open-telemetry/opentelemetry-cpp/pull/2530) - * In the `OtlpHttpExporterOptions` and `OtlpGrpcExporterOptions`, a new - field called compression has been introduced. This field can be set - to "gzip” to enable gzip compression. - * The CMake option `WITH_OTLP_HTTP_COMPRESSION` is introduced to enable - gzip compression support for the OTLP HTTP Exporter and includes a - dependency on zlib. -* [SDK] Change OTLP HTTP content_type default to binary - [#2558](https://github.com/open-telemetry/opentelemetry-cpp/pull/2558) -* [CI] Use platform CMake - [#2627](https://github.com/open-telemetry/opentelemetry-cpp/pull/2627) - * The `CI` in github no longer install a different version of `cmake`. - * It now always use the `cmake` provided by the platform. - * As part of this change, the script `ci/setup_cmake.sh` was renamed - to `ci/setup_googletest.sh`, for clarity, now that this script - only installs googletest. -* [SDK] DefaultLogHandler to print to std::cerr, add LogLevel::None - [#2622](https://github.com/open-telemetry/opentelemetry-cpp/pull/2622) - * Change DefaultLogHandler output - * Before, the default internal logger, DefaultLogHandler, - used to print to std::cout. - * Now, DefaultLogHandler prints errors and warnings to std::cerr, - as expected, while printing info and debug messages to std::cout. - * Applications that expected to find the opentelemetry-cpp internal - error log in std::cout may need adjustments, either by looking - at std::cerr instead, or by using a custom log handler. - * Additional LogLevel::None - * LogLevel::None is a new supported log level, which does not print - any message. - * Custom log handlers may need to implement a new case, to avoid - compiler warnings. - * Numbering of log levels like OTEL_INTERNAL_LOG_LEVEL_ERROR - has changed, which requires to rebuild, as the SDK ABI differs. - -## [1.14.2] 2024-02-27 - -* [SDK] Fix observable attributes drop - [#2557](https://github.com/open-telemetry/opentelemetry-cpp/pull/2557) - -## [1.14.1] 2024-02-23 - -* [SDK] Restore Recordable API compatibility with versions < 1.14.0 - [#2547](https://github.com/open-telemetry/opentelemetry-cpp/pull/2547) -* [DOC] Add missing CHANGELOG. - [#2549](https://github.com/open-telemetry/opentelemetry-cpp/pull/2549) -* [EXPORTER] Error when grpc endpoint is empty - [#2507](https://github.com/open-telemetry/opentelemetry-cpp/pull/2507) -* [DOC] Fix typo in benchmarks.rst - [#2542](https://github.com/open-telemetry/opentelemetry-cpp/pull/2542) - -Important changes: - -* [SDK] Restore Recordable API compatibility with versions < 1.14.0 - [#2547](https://github.com/open-telemetry/opentelemetry-cpp/pull/2547) - * For third party _extending_ the SDK, release 1.14.0 introduced - an API breaking change compared to 1.13.0 - * This fix restores API (but not ABI) compatibility of - release 1.14.1 with release 1.13.0. - * This allows to build a third party exporter with no source code changes, - for both releases 1.14.1 and 1.13.0. - -## [1.14.0] 2024-02-16 - -* [BUILD] Add DLL build CI pipeline with CXX20 - [#2465](https://github.com/open-telemetry/opentelemetry-cpp/pull/2465) -* [EXPORTER] Set `is_monotonic` flag for Observable Counters - [#2478](https://github.com/open-telemetry/opentelemetry-cpp/pull/2478) -* [PROTO] Upgrade to opentelemetry-proto v1.1.0 - [#2488](https://github.com/open-telemetry/opentelemetry-cpp/pull/2488) -* [BUILD] Introduce CXX 20 CI pipeline for MSVC/Windows - [#2450](https://github.com/open-telemetry/opentelemetry-cpp/pull/2450) -* [API] Propagation: fix for hex conversion to binary for odd hex strings - [#2533](https://github.com/open-telemetry/opentelemetry-cpp/pull/2533) -* [DOC] Fix calendar link - [#2532](https://github.com/open-telemetry/opentelemetry-cpp/pull/2532) -* [ETW EXPORTER] Remove namespace using in ETW exporter which affects global - namespace - [#2531](https://github.com/open-telemetry/opentelemetry-cpp/pull/2531) -* [BUILD] Don't invoke vcpkg from this repo with CMAKE_TOOLCHAIN_FILE set - [#2527](https://github.com/open-telemetry/opentelemetry-cpp/pull/2527) -* [EXPORTER] Async exporting for otlp grpc - [#2407](https://github.com/open-telemetry/opentelemetry-cpp/pull/2407) -* [METRICS SDK] Fix attribute filtering for synchronous instruments. - [#2472](https://github.com/open-telemetry/opentelemetry-cpp/pull/2472) -* [BUILD] Better handling of OPENTELEMETRY_STL_VERSION under Bazel. - [#2503](https://github.com/open-telemetry/opentelemetry-cpp/pull/2503) -* [DOC] Fixes CI markdown error MD055 - Table pipe style - [#2517](https://github.com/open-telemetry/opentelemetry-cpp/pull/2517) -* [API] Propagators: do not overwrite the active span with a default invalid - span [#2511](https://github.com/open-telemetry/opentelemetry-cpp/pull/2511) -* [BUILD] Updated the recorded vcpkg submodule version - [#2513](https://github.com/open-telemetry/opentelemetry-cpp/pull/2513) -* [BUILD] Remove unnecessary usage/includes of nostd/type_traits - [#2509](https://github.com/open-telemetry/opentelemetry-cpp/pull/2509) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.24.0 - [#2461](https://github.com/open-telemetry/opentelemetry-cpp/pull/2461) -* [EXAMPLES] Improve readme of Metrics example - [#2510](https://github.com/open-telemetry/opentelemetry-cpp/pull/2510) -* [BUILD] Clang-15 warning about `__has_trivial_destructor` - [#2502](https://github.com/open-telemetry/opentelemetry-cpp/pull/2502) -* [BUILD] Fix multiple assignment operators for SpinLockMutex - [#2501](https://github.com/open-telemetry/opentelemetry-cpp/pull/2501) -* [BUILD] Alternative way of exporting symbols (generating .def file) - [#2476](https://github.com/open-telemetry/opentelemetry-cpp/pull/2476) -* [CI] Make cmake.c++20*.test actually use C++20 and add cmake.c++23*.test - [#2496](https://github.com/open-telemetry/opentelemetry-cpp/pull/2496) -* [DOCUMENTATION] Add api reference documentation for logs - [#2497](https://github.com/open-telemetry/opentelemetry-cpp/pull/2497) -* [BUILD] Fix variable shadow - [#2498](https://github.com/open-telemetry/opentelemetry-cpp/pull/2498) -* [BUILD] Fix checks on __cplusplus under MSVC, do not assume /Zc - [#2493](https://github.com/open-telemetry/opentelemetry-cpp/pull/2493) -* [EXAMPLES] Use logs API instead of logs bridge API in the example - [#2494](https://github.com/open-telemetry/opentelemetry-cpp/pull/2494) -* [EXPORTER] Fix forward protocol encoding for ETW exporter - [#2473](https://github.com/open-telemetry/opentelemetry-cpp/pull/2473) -* [BUILD] Skip patch alias target - [#2457](https://github.com/open-telemetry/opentelemetry-cpp/pull/2457) -* [EXPORTER] Rename populate_otel_scope to without_otel_scope - [#2479](https://github.com/open-telemetry/opentelemetry-cpp/pull/2479) -* [EXPORTER SDK] Additional fixes after NOMINMAX removal on Windows - [#2475](https://github.com/open-telemetry/opentelemetry-cpp/pull/2475) -* [EXPORTER] Do not use regex in `CleanUpString` because some implementations of - STL may crash. - [#2464](https://github.com/open-telemetry/opentelemetry-cpp/pull/2464) -* [EXPORTER] Fix Aggregation type detection in OTLP Exporter - [#2467](https://github.com/open-telemetry/opentelemetry-cpp/pull/2467) -* [EXPORTER] Add option to disable Prometheus otel_scope_name and - otel_scope_version attributes - [#2451](https://github.com/open-telemetry/opentelemetry-cpp/pull/2451) -* [SEMANTIC CONVENTIONS] Code generation script fails on SELINUX - [#2455](https://github.com/open-telemetry/opentelemetry-cpp/pull/2455) -* [BUILD] Fix removing of NOMINMAX on Windows - [#2449](https://github.com/open-telemetry/opentelemetry-cpp/pull/2449) -* [BUILD] Accept path list in OPENTELEMETRY_EXTERNAL_COMPONENT_PATH - [#2439](https://github.com/open-telemetry/opentelemetry-cpp/pull/2439) -* [BUILD] Remove gmock from GTEST_BOTH_LIBRARIES - [#2437](https://github.com/open-telemetry/opentelemetry-cpp/pull/2437) -* [REMOVAL] Remove option WITH_OTLP_HTTP_SSL_PREVIEW - [#2435](https://github.com/open-telemetry/opentelemetry-cpp/pull/2435) - -Important changes: - -Breaking changes: - -* [REMOVAL] Remove option WITH_OTLP_HTTP_SSL_PREVIEW - [#2435](https://github.com/open-telemetry/opentelemetry-cpp/pull/2435) - * CMake options `WITH_OTLP_HTTP_SSL_PREVIEW` and - `WITH_OTLP_HTTP_SSL_TLS_PREVIEW` are removed. Building opentelemetry-cpp - without SSL support is no longer possible. - -* [PROTO] Upgrade to opentelemetry-proto v1.1.0 - [#2488](https://github.com/open-telemetry/opentelemetry-cpp/pull/2488) - * Class `opentelemetry::sdk::trace::Recordable` has a new virtual method, - `SetTraceFlags()`. - * This is an incompatible change for the SDK Recordable API and ABI. - * Applications _configuring_ the SDK are not affected. - * Third parties providing SDK _extensions_ are affected, - and must provide a `SetTraceFlags()` implementation, - starting with opentelemetry-cpp 1.14.0. - -## [1.13.0] 2023-12-06 - -* [BUILD] Remove WITH_REMOVE_METER_PREVIEW, use WITH_ABI_VERSION_2 instead - [#2370](https://github.com/open-telemetry/opentelemetry-cpp/pull/2370) -* [SDK] Metrics ObservableRegistry Cleanup - [#2376](https://github.com/open-telemetry/opentelemetry-cpp/pull/2376) -* [BUILD] Make WITH_OTLP_HTTP_SSL_PREVIEW mainstream - [#2378](https://github.com/open-telemetry/opentelemetry-cpp/pull/2378) -* [SDK] Creating DoubleUpDownCounter with no matching view - [#2379](https://github.com/open-telemetry/opentelemetry-cpp/pull/2379) -* [API] Add InstrumentationScope attributes in TracerProvider::GetTracer() - [#2371](https://github.com/open-telemetry/opentelemetry-cpp/pull/2371) -* [BUILD] DLL export interface for Metrics - [#2344](https://github.com/open-telemetry/opentelemetry-cpp/pull/2344) -* [BUILD] enum CanonicalCode names too generic... conflict with old C defines - [#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385) -* [BUILD] Fix cpack broken package version - [#2386](https://github.com/open-telemetry/opentelemetry-cpp/pull/2386) -* [API] Add a new AddLink() operation to Span - [#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380) -* [opentracing-shim] Add check for sampled context - [#2390](https://github.com/open-telemetry/opentelemetry-cpp/pull/2390) -* [BUILD] Fix exported definitions when building DLL with STL - [#2387](https://github.com/open-telemetry/opentelemetry-cpp/pull/2387) -* [BUILD] Add missing includes to runtime_context_test - [#2395](https://github.com/open-telemetry/opentelemetry-cpp/pull/2395) -* [ADMIN] Add file .github/repository-settings.md - [#2392](https://github.com/open-telemetry/opentelemetry-cpp/pull/2392) -* [SDK] Fix GetLogger with empty library name - [#2398](https://github.com/open-telemetry/opentelemetry-cpp/pull/2398) -* [TEST] Fix compiling problem and removed -DENABLE_TEST - [#2401](https://github.com/open-telemetry/opentelemetry-cpp/pull/2401) -* [BUILD] Check windows options are not passed to non-Windows build - [#2399](https://github.com/open-telemetry/opentelemetry-cpp/pull/2399) -* [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options - [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) -* [Build] Update vcpkg to latest release - [#2412](https://github.com/open-telemetry/opentelemetry-cpp/pull/2412) -* [SDK] Cardinality limits for metrics streams - (Sync Instruments + Delta Temporality) - [#2255](https://github.com/open-telemetry/opentelemetry-cpp/pull/2255) -* [EXPORTER] Prometheus: Add unit to names, convert to word - [#2213](https://github.com/open-telemetry/opentelemetry-cpp/pull/2213) -* [Metrics] Make context optional for histogram instruments in Metrics SDK - [#2416](https://github.com/open-telemetry/opentelemetry-cpp/pull/2416) -* [BUILD] Fix references to trace namespace to be fully qualified - [#2422](https://github.com/open-telemetry/opentelemetry-cpp/pull/2422) -* [BUILD] Bump third_party/googletest to same version as bazel - [#2421](https://github.com/open-telemetry/opentelemetry-cpp/pull/2421) -* [BUILD] Remove defining NOMINMAX from api - [#2420](https://github.com/open-telemetry/opentelemetry-cpp/pull/2420) -* [BUILD] 'uint8_t' not declared in this scope with gcc 13.2.1 - [#2423](https://github.com/open-telemetry/opentelemetry-cpp/pull/2423) -* [BUILD] Improve the handling of OPENTELEMETRY_HAVE_WORKING_REGEX - [#2430](https://github.com/open-telemetry/opentelemetry-cpp/pull/2430) -* [SEMANTIC CONVENTION] Upgrade to semconv 1.23.1 - [#2428](https://github.com/open-telemetry/opentelemetry-cpp/pull/2428) -* [BUILD] Use fully qualified references to trace/common namespace - [#2424](https://github.com/open-telemetry/opentelemetry-cpp/pull/2424) -* [API] Create root span with active span - [#2427](https://github.com/open-telemetry/opentelemetry-cpp/pull/2427) -* [REMOVAL] Remove ZPAGES - [#2433](https://github.com/open-telemetry/opentelemetry-cpp/pull/2433) - -Important changes: - -* [API] Add InstrumentationScope attributes in TracerProvider::GetTracer() - [#2371](https://github.com/open-telemetry/opentelemetry-cpp/pull/2371) - * TracerProvider::GetTracer() now accepts InstrumentationScope attributes. - * Because this is an `ABI` breaking change, the fix is only available - with the `CMake` option `WITH_ABI_VERSION_2=ON`. - * When building with `CMake` option `WITH_ABI_VERSION_1=ON` (by default) - the `ABI` is unchanged, and the fix is not available. - -* [API] Add a new AddLink() operation to Span - [#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380) - * New `API` Span::AddLink() adds a single link to a span. - * New `API` Span::AddLinks() adds multiple links to a span. - * Because this is an `ABI` breaking change, the fix is only available - with the `CMake` option `WITH_ABI_VERSION_2=ON`. - * When building with `CMake` option `WITH_ABI_VERSION_1=ON` (by default) - the `ABI` is unchanged, and the fix is not available. - -* [BUILD] Make WITH_OTLP_HTTP_SSL_PREVIEW mainstream - [#2378](https://github.com/open-telemetry/opentelemetry-cpp/pull/2378) - * The experimental `CMake` option `WITH_OTLP_HTTP_SSL_PREVIEW` - is now promoted to stable. The default is changed to `ON`. - * The experimental `CMake` option `WITH_OTLP_HTTP_SSL_TLS_PREVIEW` - is now promoted to stable. The default is changed to `ON`. - * These build options are scheduled to be removed by the next release, - building without SSL/TLS will no longer be possible. - -* [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options - [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) - * `OtlpGrpcMetricExporterOptions` used to honor `_TRACES_` - environment variables, instead of `_METRICS_` environment variables. - * The implementation of `OtlpGrpcMetricExporterOptions` is now fixed. - * Please check configuration variables, - to make sure `_METRICS_` variables are set as expected. - -Breaking changes: - -* [BUILD] Remove WITH_REMOVE_METER_PREVIEW, use WITH_ABI_VERSION_2 instead - [#2370](https://github.com/open-telemetry/opentelemetry-cpp/pull/2370) - * The experimental `CMake` option `WITH_REMOVE_METER_PREVIEW` is removed, - use option `WITH_ABI_VERSION_2` instead. - -* [BUILD] enum CanonicalCode names too generic... conflict with old C defines - [#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385) - * Header file `opentelemetry/trace/canonical_code.h` is unused, - and is now removed. - * This header should not be included directly in an application. - If this is the case, please remove any remaining include directives. - -* [BUILD] Fix exported definitions when building DLL with STL - [#2387](https://github.com/open-telemetry/opentelemetry-cpp/pull/2387) - * The MeterSelector, MeterSelectorFactory, InstrumentSelector, - and InstrumentSelectorFactory APIs now use const std::string& - instead of nostd::string_view for name, version and schema to - maintain a single export definition for DLL. - -* [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options - [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) - * `OtlpGrpcLogRecordExporter` incorrectly used `OtlpGrpcExporterOptions`, - which are options for traces and not logs. - * This created a bug: the `OtlpGrpcLogRecordExporter` honors `_TRACES_` - environment variables, instead of `_LOGS_` environment variables. - * `OtlpGrpcLogRecordExporter` is changed to use - `OtlpGrpcLogRecordExporterOptions` instead, fixing the bug. - * User code that initializes the SDK with a GRPC Log exporter, - and uses exporter options, should adjust to replace - `OtlpGrpcExporterOptions` with `OtlpGrpcLogRecordExporterOptions`. - * Please check configuration variables, - to make sure `_LOGS_` variables are set as expected. - -* [REMOVAL] Remove ZPAGES - [#2433](https://github.com/open-telemetry/opentelemetry-cpp/pull/2433) - * As announced in release 1.12.0, - the deprecated ZPAGES exporter is now removed. - -## [1.12.0] 2023-10-16 - -* [BUILD] Support `pkg-config` - [#2269](https://github.com/open-telemetry/opentelemetry-cpp/pull/2269) -* [CI] Do not automatically close stale issues - [#2277](https://github.com/open-telemetry/opentelemetry-cpp/pull/2277) -* [CI] Benchmark workflow fails, C++14 required to build grpc - [#2278](https://github.com/open-telemetry/opentelemetry-cpp/pull/2278) -* [SDK] Increase metric name maximum length from 63 to 255 characters - [#2284](https://github.com/open-telemetry/opentelemetry-cpp/pull/2284) -* [SEMANTIC CONVENTION] Deprecated semconv (in the spec) - not deprecated (in C++) - [#2285](https://github.com/open-telemetry/opentelemetry-cpp/pull/2285) -* [SDK] Remove unused member variables from SyncMetricStorage - [#2294](https://github.com/open-telemetry/opentelemetry-cpp/pull/2294) -* [DEPRECATION] Deprecate ZPAGES - [#2291](https://github.com/open-telemetry/opentelemetry-cpp/pull/2291) -* [API] Deliver ABI breaking changes - [#2222](https://github.com/open-telemetry/opentelemetry-cpp/pull/2222) -* [SDK] Allow metric instrument names to contain / characters - [#2310](https://github.com/open-telemetry/opentelemetry-cpp/pull/2310) -* [SDK] Fix Observable Counters/UpDownCounters - [#2298](https://github.com/open-telemetry/opentelemetry-cpp/pull/2298) -* [SDK] Add exemplar reservoir to async metric storage - [#2319](https://github.com/open-telemetry/opentelemetry-cpp/pull/2319) -* [TEST] Fix lifetime issues in prometheus test utils - [#2322](https://github.com/open-telemetry/opentelemetry-cpp/pull/2322) -* [EXPORTER] Prometheus: Remove explicit timestamps from metric points - [#2324](https://github.com/open-telemetry/opentelemetry-cpp/pull/2324) -* [EXPORTER] Prometheus: Handle attribute key collisions from sanitation - [#2326](https://github.com/open-telemetry/opentelemetry-cpp/pull/2326) -* [EXPORTER] Prometheus cleanup, test with TranslateToPrometheus - [#2329](https://github.com/open-telemetry/opentelemetry-cpp/pull/2329) -* [SDK] Fix log message in Meter::RegisterSyncMetricStorage - [#2325](https://github.com/open-telemetry/opentelemetry-cpp/pull/2325) -* [DOC] Simplify the project status section - [#2332](https://github.com/open-telemetry/opentelemetry-cpp/pull/2332) -* [EXPORTER] Prometheus: Sanitize labels according to spec - [#2330](https://github.com/open-telemetry/opentelemetry-cpp/pull/2330) -* [SDK] Fix deadlock when shuting down http client - [#2337](https://github.com/open-telemetry/opentelemetry-cpp/pull/2337) -* [Exporter] Group spans by resource and instrumentation scope - in OTLP export requests - [#2335](https://github.com/open-telemetry/opentelemetry-cpp/pull/2335) -* [BUILD] Need fine-grained HAVE_CPP_STDLIB - [#2304](https://github.com/open-telemetry/opentelemetry-cpp/pull/2304) -* [API] Add InstrumentationScope attributes in MeterProvider::GetMeter() - [#2224](https://github.com/open-telemetry/opentelemetry-cpp/pull/2224) -* [REMOVAL] Drop C++11 support - [#2342](https://github.com/open-telemetry/opentelemetry-cpp/pull/2342) -* [EXPORTER] prometheus: add otel_scope_name and otel_scope_version labels - [#2293](https://github.com/open-telemetry/opentelemetry-cpp/pull/2293) -* [EXPORTER] Export resource for prometheus - [#2301](https://github.com/open-telemetry/opentelemetry-cpp/pull/2301) -* [BUILD] error: read-only reference ‘value’ used as ‘asm’ output - [#2354](https://github.com/open-telemetry/opentelemetry-cpp/pull/2354) -* [BUILD] Build break with external CMake nlohman_json package - [#2353](https://github.com/open-telemetry/opentelemetry-cpp/pull/2353) -* [BUILD] Upgrade libcurl to version 8.4.0 - [#2358](https://github.com/open-telemetry/opentelemetry-cpp/pull/2358) -* [BUILD] Fix opentracing-shim when added in super project - [#2356](https://github.com/open-telemetry/opentelemetry-cpp/pull/2356) -* [BUILD] Fix protoc searching with non-imported protobuf::protoc target - [#2362](https://github.com/open-telemetry/opentelemetry-cpp/pull/2362) -* [BUILD] Support to use different cmake package CONFIG of dependencies - [#2263](https://github.com/open-telemetry/opentelemetry-cpp/pull/2263) -* [SEMANTIC CONVENTION] Upgrade to semconv 1.22.0 - [#2368](https://github.com/open-telemetry/opentelemetry-cpp/pull/2368) - -Important changes: - -* [API] Add InstrumentationScope attributes in MeterProvider::GetMeter() - [#2224](https://github.com/open-telemetry/opentelemetry-cpp/pull/2224) - * MeterProvider::GetMeter() now accepts InstrumentationScope attributes. - * Because this is an `ABI` breaking change, the fix is only available - with the `CMake` option `WITH_ABI_VERSION_2=ON`. - * When building with `CMake` option `WITH_ABI_VERSION_1=ON` (by default) - the `ABI` is unchanged, and the fix is not available. - -Breaking changes: - -* [BUILD] Need fine-grained HAVE_CPP_STDLIB - [#2304](https://github.com/open-telemetry/opentelemetry-cpp/pull/2304) - * In `CMAKE`, the boolean option `WITH_STL` as changed to an option - that accepts the values `OFF`, `ON`, `CXX11`, `CXX14`, `CXX17`, - `CXX20` and `CXX23`. - * Applications makefiles that did not set WITH_STL need to use - `WITH_STL=OFF` instead (this is the default). - * Applications makefiles that did set WITH_STL need to use - `WITH_STL=ON` instead, or may choose to pick a specific value. - * In the `API` header files, the preprocessor symbol `HAVE_CPP_STDLIB` - is no longer used. - * Applications that did set `HAVE_CPP_STDLIB` before, need to set - `OPENTELEMETRY_STL_VERSION=` instead, to build with a - specific STL version (2011, 2014, 2017, 2020, 2023). - * The opentelemetry-cpp makefile no longer sets - CMAKE_CXX_STANDARD by itself. - Instead, the CMAKE_CXX_STANDARD and/or compiler options -stdc++ used - by the caller are honored. - * Applications that set neither CMAKE_CXX_STANDARD nor -stdc++ - options may need to provide a C++ standard in their makefiles. - -* [REMOVAL] Drop C++11 support - [#2342](https://github.com/open-telemetry/opentelemetry-cpp/pull/2342) - * Building with C++11 is no longer supported. - -Deprecations: - -* [DEPRECATION] Deprecate ZPAGES - [#2291](https://github.com/open-telemetry/opentelemetry-cpp/pull/2291) - -## [1.11.0] 2023-08-21 - -* [BUILD] Fix more cases for symbol name for 32-bit win32 DLL build - [#2264](https://github.com/open-telemetry/opentelemetry-cpp/pull/2264) -* [BUILD] added public link of `opentelemetry_proto_grpc` against gRPC lib (only - if gRPC library is shared) - [#2268](https://github.com/open-telemetry/opentelemetry-cpp/pull/2268) -* [CI] use ubuntu-latest for tsan CI - [#2267](https://github.com/open-telemetry/opentelemetry-cpp/pull/2267) -* [SDK] Fixing an apparent logging macro bug - [#2265](https://github.com/open-telemetry/opentelemetry-cpp/pull/2265) -* [BUILD] Support protobuf 3.22 or upper - [#2163](https://github.com/open-telemetry/opentelemetry-cpp/pull/2163) -* [BUILD] Remove extra includes - [#2252](https://github.com/open-telemetry/opentelemetry-cpp/pull/2252) -* [LOGS API SDK] Mark logs signal as stable API/SDK - [#2229](https://github.com/open-telemetry/opentelemetry-cpp/pull/2229) -* [SEMANTIC CONVENTIONS] Upgrade to 1.21.0 - [#2248](https://github.com/open-telemetry/opentelemetry-cpp/pull/2248) -* [SDK] Valgrind errors on std::atomic variables - [#2244](https://github.com/open-telemetry/opentelemetry-cpp/pull/2244) -* [BUILD] Fix compile with clang 16 and libc++ - [#2242](https://github.com/open-telemetry/opentelemetry-cpp/pull/2242) -* [Metrics SDK] Add unit to Instrument selection criteria - [#2236](https://github.com/open-telemetry/opentelemetry-cpp/pull/2236) -* [SDK] Add OStreamLogRecordExporterFactory - [#2240](https://github.com/open-telemetry/opentelemetry-cpp/pull/2240) -* [SDK] Add support for LowMemory metrics temporality - [#2234](https://github.com/open-telemetry/opentelemetry-cpp/pull/2234) -* [CI] Misc build scripts cleanup - [#2232](https://github.com/open-telemetry/opentelemetry-cpp/pull/2232) -* [CI] Upgrade GoogleTest version from 1.12.1 to 1.13.0 - [#2114](https://github.com/open-telemetry/opentelemetry-cpp/pull/2114) -* [BUILD] include cstdint - [#2230](https://github.com/open-telemetry/opentelemetry-cpp/pull/2230) -* [EXPORTER] Support protobuf 3.22 or upper - [#2163](https://github.com/open-telemetry/opentelemetry-cpp/pull/2163) -* [SDK] Mark logs signal as stable API/SDK - [#2229](https://github.com/open-telemetry/opentelemetry-cpp/pull/2229) - -Breaking changes: - -* [SDK] Add unit to Instrument selection criteria - [#2236](https://github.com/open-telemetry/opentelemetry-cpp/pull/2236) - * The `View` constructor and `ViewFactory::Create` method now takes a - `unit` criteria as optional third argument. - * Please adjust SDK configuration code accordingly. - -## [1.10.0] 2023-07-11 - -* [REMOVAL] Remove the jaeger exporter - [#2031](https://github.com/open-telemetry/opentelemetry-cpp/pull/2031) - -* [CI] Add a C++11 build - [#2152](https://github.com/open-telemetry/opentelemetry-cpp/pull/2152) - -* [CI] Add Include what you use - [#2214](https://github.com/open-telemetry/opentelemetry-cpp/pull/2214) - -* [CI] opentelemetry-cpp project CI - [#2071](https://github.com/open-telemetry/opentelemetry-cpp/pull/2071) - -* [CI] Do not tag pull_request with the "need-triage" label - [#2228](https://github.com/open-telemetry/opentelemetry-cpp/pull/2228) - -* [BUILD] Fixing CMake to build GTest on Windows - [#1887](https://github.com/open-telemetry/opentelemetry-cpp/pull/1887) - -* [BUILD] Remove option WITH_OTLP - [#2161](https://github.com/open-telemetry/opentelemetry-cpp/pull/2161) - -* [BUILD] Link to opentelemetry_logs even without OTLP - [#2177](https://github.com/open-telemetry/opentelemetry-cpp/pull/2177) - -* [BUILD] Avoid dependency on protobuf from the OTLP HTTP metrics exporter header - [#2179](https://github.com/open-telemetry/opentelemetry-cpp/pull/2179) - -* [BUILD] Add ctime header to metrics_exporter.cc - [#2187](https://github.com/open-telemetry/opentelemetry-cpp/pull/2187) - -* [BUILD] Fix the exported symbol name for 32-bit win32 DLL - [#2190](https://github.com/open-telemetry/opentelemetry-cpp/pull/2190) - -* [BUILD] Upgrade to opentelemetry-proto 0.20.0 - [#2195](https://github.com/open-telemetry/opentelemetry-cpp/pull/2195) - -* [BUILD] SDK Header files cleanup, use forward declarations - [#2182](https://github.com/open-telemetry/opentelemetry-cpp/pull/2182) - -* [BUILD] Enable building otel-cpp extensions from main repo - [#1937](https://github.com/open-telemetry/opentelemetry-cpp/pull/1937) - -* [BUILD] Fix if check on environment variable and add CMake variable - [#2207](https://github.com/open-telemetry/opentelemetry-cpp/pull/2207) - -* [BUILD] Add `OPENTELEMETRY_CPP_FOUND` into cmake CONFIG file - [#2215](https://github.com/open-telemetry/opentelemetry-cpp/pull/2215) - -* [BUILD] Upgrade opentelemetry-proto to 1.0.0 - [#2216](https://github.com/open-telemetry/opentelemetry-cpp/pull/2216) - -* [BUILD] Include nostd/string_view which is used in severity.h - [#2219](https://github.com/open-telemetry/opentelemetry-cpp/pull/2219) - -* [TEST] Expand api singleton test to cover explicit dlopen() - [#2164](https://github.com/open-telemetry/opentelemetry-cpp/pull/2164) - -* [API] Remove include_trace_context - [#2194](https://github.com/open-telemetry/opentelemetry-cpp/pull/2194) - -* [API] Remove Meters - [#2205](https://github.com/open-telemetry/opentelemetry-cpp/pull/2205) - -* [SDK] Add AdaptingCircularBufferCounter for exponential histograms - [#2158](https://github.com/open-telemetry/opentelemetry-cpp/pull/2158) - -* [SDK] Add base2 exponential histogram indexer - [#2173](https://github.com/open-telemetry/opentelemetry-cpp/pull/2173) - -* [SDK] Simplify SDK version - [#2180](https://github.com/open-telemetry/opentelemetry-cpp/pull/2180) - -* [SDK] Add benchmark for base2 exponential histogram indexer - [#2181](https://github.com/open-telemetry/opentelemetry-cpp/pull/2181) - -* [SDK] Provide builders to avoid exposing Metrics SDK internals - [#2189](https://github.com/open-telemetry/opentelemetry-cpp/pull/2189) - -* [SDK] MeterProvider should own MeterContext, not share it - [#2218](https://github.com/open-telemetry/opentelemetry-cpp/pull/2218) - -* [SDK] TracerProvider should own TracerContext, not share it - [#2221](https://github.com/open-telemetry/opentelemetry-cpp/pull/2221) - -* [EXPORTER] Change OTLP Json field name to camelCase - [#2162](https://github.com/open-telemetry/opentelemetry-cpp/pull/2162) - -* [EXPORTER] Support empty arrays in `OtlpRecordable` attributes - [#2166](https://github.com/open-telemetry/opentelemetry-cpp/pull/2166) - -* [EXPORTER] set is_monotonic only for instrument type kCounter - [#2171](https://github.com/open-telemetry/opentelemetry-cpp/pull/2171) - -* [EXPORTER] Fixed HTTP CURL for 32bits platforms - [#2178](https://github.com/open-telemetry/opentelemetry-cpp/pull/2178) - -* [EXPORTER] Fix OTLP HTTP exporting in sync mode - [#2193](https://github.com/open-telemetry/opentelemetry-cpp/pull/2193) - -* [EXPORTER] Prometheus exporter sanitizes invalid characters - [#1934](https://github.com/open-telemetry/opentelemetry-cpp/pull/1934) - -* [EXPORTER] Prometheus: Error on ingesting samples - with different value but same timestamp - [#2200](https://github.com/open-telemetry/opentelemetry-cpp/pull/2200) - -* [EXPORTER] OTLP GRPC mTLS support - [#2120](https://github.com/open-telemetry/opentelemetry-cpp/pull/2120) - -* [DOC] Small fix for Histogram documentation - [#2156](https://github.com/open-telemetry/opentelemetry-cpp/pull/2156) - -* [DOC] Move Reiley Yang to emeritus - [#2198](https://github.com/open-telemetry/opentelemetry-cpp/pull/2198) - -Important changes: - -* [API] Remove Meters - [#2205](https://github.com/open-telemetry/opentelemetry-cpp/pull/2205) - * The CMake option `WITH_REMOVE_METER_PREVIEW` was added. - * This option is experimental, and may change in the future. - * Enabling it is an ABI breaking change. - -Breaking changes: - -* [REMOVAL] Remove the jaeger exporter - [#2031](https://github.com/open-telemetry/opentelemetry-cpp/pull/2031) - * The CMake `WITH_JAEGER` option has been removed - * Please remove usage of `WITH_JAEGER` from user scripts and makefiles. - -* [SDK] MeterProvider should own MeterContext, not share it - [#2218](https://github.com/open-telemetry/opentelemetry-cpp/pull/2218) - * The `MeterProvider` constructor now takes a `unique_ptr` on - `MeterContext`, instead of a `shared_ptr`. - * Please adjust SDK configuration code accordingly. - -* [SDK] TracerProvider should own TracerContext, not share it - [#2221](https://github.com/open-telemetry/opentelemetry-cpp/pull/2221) - * The `TracerProvider` constructor now takes a `unique_ptr` on - `TracerContext`, instead of a `shared_ptr`. - * The `LoggerProvider` constructor now takes a `unique_ptr` on - `LoggerContext`, instead of a `shared_ptr`. - * Please adjust SDK configuration code accordingly. - -## [1.9.1] 2023-05-26 - -* [DEPRECATION] Drop C++11 support - [#2146](https://github.com/open-telemetry/opentelemetry-cpp/pull/2146) - -* [CI] Upgrade Bazel and Bazelisk version - [#2118](https://github.com/open-telemetry/opentelemetry-cpp/pull/2118) -* [CI] Upgrade Google Benchmark version from 1.6.0 to 1.7.1 - [#2116](https://github.com/open-telemetry/opentelemetry-cpp/pull/2116) -* [CI] Upgrade Nlohmann JSON library version from 3.10.5 to 3.11.2 - [#2115](https://github.com/open-telemetry/opentelemetry-cpp/pull/2115) - -* [BUILD] Missed include - [#2143](https://github.com/open-telemetry/opentelemetry-cpp/pull/2143) -* [BUILD] Add opentelemetry_proto_grpc and allow build shared - opentelemetry_proto and opentelemetry_proto_grpc on non-Windows platform. - [#2097](https://github.com/open-telemetry/opentelemetry-cpp/pull/2097) -* [BUILD] Warning cleanup, single character wrapped by std::string - [#2137](https://github.com/open-telemetry/opentelemetry-cpp/pull/2137) -* [BUILD] Add missing target dependencies - [#2128](https://github.com/open-telemetry/opentelemetry-cpp/pull/2128) -* [BUILD] Fix if JSON library already added another CMake target - [#2126](https://github.com/open-telemetry/opentelemetry-cpp/pull/2126) -* [BUILD] shared libraries with version suffix, along with the symbolic link - [#2109](https://github.com/open-telemetry/opentelemetry-cpp/pull/2109) -* [BUILD] Show warning message if WITH_OTLP is enabled - [#2112](https://github.com/open-telemetry/opentelemetry-cpp/pull/2112) -* [BUILD] Add missing STL header. - [#2107](https://github.com/open-telemetry/opentelemetry-cpp/pull/2107) -* [BUILD] Build break with old curl, macro CURL_VERSION_BITS unknown - [#2102](https://github.com/open-telemetry/opentelemetry-cpp/pull/2102) -* [BUILD] Transitive dependency issue with the otlp http exporter - [#2154](https://github.com/open-telemetry/opentelemetry-cpp/pull/2154) - -* [TEST] Add unit test for log body implicit conversions. - [#2136](https://github.com/open-telemetry/opentelemetry-cpp/pull/2136) -* [TEST] Add event id to logger benchmark method - [#2133](https://github.com/open-telemetry/opentelemetry-cpp/pull/2133) - -* [API] Fix inclusion header files and use forward declaration - [#2124](https://github.com/open-telemetry/opentelemetry-cpp/pull/2124) -* [API] Add user facing Logging API and Benchmarks - [#2094](https://github.com/open-telemetry/opentelemetry-cpp/pull/2094) - -* [SDK] SDK support for the new OTel log - [#2123](https://github.com/open-telemetry/opentelemetry-cpp/pull/2123) - -* [EXPORTER] Fixed HTTP session cleanup on shutdown - [#2111](https://github.com/open-telemetry/opentelemetry-cpp/pull/2111) -* [EXPORTER] Delegate all API calls of gRPC into - opentelemetry_exporter_otlp_grpc_client, - and make it contains all symbols needed. - [#2005](https://github.com/open-telemetry/opentelemetry-cpp/pull/2005) - -* [DOC] Add Marc as maintainer. - [#2027](https://github.com/open-telemetry/opentelemetry-cpp/pull/2027) - -Breaking changes: - -* Add opentelemetry_proto_grpc and move gRPC sources into it. - [#2097](https://github.com/open-telemetry/opentelemetry-cpp/pull/2097) - * There will be no breaking changes for users who only use OTLP exporters and - do not directly use opentelemetry-cpp::proto. However, it is important to - note that `opentelemetry-cpp::proto` no longer contains generated gRPC codes - , and all components that depend on these gRPC codes should also link to - `opentelemetry-cpp::proto_grpc`. - -Deprecations: - -* The Jaeger Exporter is deprecated, see [DEPRECATED](./DEPRECATED.md) for details. -* C++11 support is to end, C++14 will be supported instead, - see [DEPRECATED](./DEPRECATED.md) for details. - -## [1.9.0] 2023-04-12 - -* [CI] Make build environment parallel (Windows) - [#2080](https://github.com/open-telemetry/opentelemetry-cpp/pull/2080) -* [CI] Make build environment parallel (Linux) - [#2076](https://github.com/open-telemetry/opentelemetry-cpp/pull/2076) -* [CI] Remove separate run of metrics ostream example - [#2030](https://github.com/open-telemetry/opentelemetry-cpp/pull/2030) - -* [BUILD] Include directory path added for Zipkin exporter example - [#2069](https://github.com/open-telemetry/opentelemetry-cpp/pull/2069) -* [BUILD] Ignore more warning in generated protobuf files - [#2067](https://github.com/open-telemetry/opentelemetry-cpp/pull/2067) -* [BUILD] Clean warnings in ETW exporters - [#2063](https://github.com/open-telemetry/opentelemetry-cpp/pull/2063) -* [BUILD] Fix default value of OPENTELEMETRY_INSTALL_default - [#2062](https://github.com/open-telemetry/opentelemetry-cpp/pull/2062) - -* [SEMANTIC CONVENTIONS] Upgrade to version 1.20.0 - [#2088](https://github.com/open-telemetry/opentelemetry-cpp/pull/2088) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.19.0 - [#2017](https://github.com/open-telemetry/opentelemetry-cpp/pull/2017) - -* [API] Checking indices before dereference in string utils - [#2040](https://github.com/open-telemetry/opentelemetry-cpp/pull/2040) -* [API] Export factory class of log provider - [#2041](https://github.com/open-telemetry/opentelemetry-cpp/pull/2041) - -* [SDK] Implement Forceflush for Periodic Metric Reader - [#2064](https://github.com/open-telemetry/opentelemetry-cpp/pull/2064) -* [SDK] Add `ForceFlush` for all `LogRecordExporter` and `SpanExporter` - [#2000](https://github.com/open-telemetry/opentelemetry-cpp/pull/2000) -* [SDK] Fix schema URL precedence bug in `Resource::Merge` - [#2036](https://github.com/open-telemetry/opentelemetry-cpp/pull/2036) -* [SDK] Use sdk_start_ts for MetricData start_ts for instruments having - cumulative aggregation temporality. - [#2086](https://github.com/open-telemetry/opentelemetry-cpp/pull/2086) - -* [EXPORTER] Add OTLP HTTP SSL support - [#1793](https://github.com/open-telemetry/opentelemetry-cpp/pull/1793) -* [EXPORTER] GRPC endpoint scheme should take precedence over OTEL_EXPORTER_OTLP_TRACES_INSECURE - [#2060](https://github.com/open-telemetry/opentelemetry-cpp/pull/2060) - -* [EXAMPLES] Remove unused 'alerting' section from prometheus.yml in examples - [#2055](https://github.com/open-telemetry/opentelemetry-cpp/pull/2055) -* [EXAMPLES] Fix view names in Prometheus example - [#2034](https://github.com/open-telemetry/opentelemetry-cpp/pull/2034) - -* [DOC] Fix some docs typo - [#2057](https://github.com/open-telemetry/opentelemetry-cpp/pull/2057) -* [DOC] Update OpenTracing shim README.md - [#2028](https://github.com/open-telemetry/opentelemetry-cpp/pull/2028) -* [DOC] INSTALL doc clarifications - [#2078](https://github.com/open-telemetry/opentelemetry-cpp/pull/2078) - -Important changes: - -* [EXPORTER] GRPC endpoint scheme should take precedence over OTEL_EXPORTER_OTLP_TRACES_INSECURE - [#2060](https://github.com/open-telemetry/opentelemetry-cpp/pull/2060) - * The logic to decide whether or not an OTLP GRPC exporter uses SSL has - changed to comply with the specification: - * Before this change, the following settings were evaluated, in order: - * OTEL_EXPORTER_OTLP_TRACES_INSECURE (starting with 1.8.3) - * OTEL_EXPORTER_OTLP_INSECURE (starting with 1.8.3) - * OTEL_EXPORTER_OTLP_TRACES_SSL_ENABLE - * OTEL_EXPORTER_OTLP_SSL_ENABLE - * With this change, the following settings are evaluated, in order: - * The GRPC endpoint scheme, if provided: - * "https" imply with SSL, - * "http" imply without ssl. - * OTEL_EXPORTER_OTLP_TRACES_INSECURE - * OTEL_EXPORTER_OTLP_INSECURE - * OTEL_EXPORTER_OTLP_TRACES_SSL_ENABLE - * OTEL_EXPORTER_OTLP_SSL_ENABLE - * As a result, a behavior change for GRPC SSL is possible, - because the endpoint scheme now takes precedence. - Please verify configuration settings for the GRPC endpoint. -* [SDK] Add `ForceFlush` for all `LogRecordExporter` and `SpanExporter` - [#2000](https://github.com/open-telemetry/opentelemetry-cpp/pull/2000) - * `LogRecordExporter` and `SpanExporter` add a new virtual function - `ForceFlush`, and if users implement any customized `LogRecordExporter` and - `SpanExporter`, they should also implement this function. - There should be no impact if users only use factory to create exporters. - -Deprecations: - -* The Jaeger Exporter is deprecated, see [DEPRECATED](./DEPRECATED.md) for details. - -## [1.8.3] 2023-03-06 - -* Provide version major/minor/patch macros - [#2014](https://github.com/open-telemetry/opentelemetry-cpp/pull/2014) -* [BUILD] Add `OPENTELEMETRY_INSTALL` to allow user to skip install targets. - [#2022](https://github.com/open-telemetry/opentelemetry-cpp/pull/2022) -* [SDK] Rename the global SDK version variables to avoid naming clash - [#2011](https://github.com/open-telemetry/opentelemetry-cpp/pull/2011) -* [BUILD] Fix typo in CMakeLists.txt - [#2010](https://github.com/open-telemetry/opentelemetry-cpp/pull/2010) -* [EXPORTER] fix Prometheus test iterator iterator increment - [#2006](https://github.com/open-telemetry/opentelemetry-cpp/pull/2006) -* [SDK]Add attributes for InstrumentationScope - [#2004](https://github.com/open-telemetry/opentelemetry-cpp/pull/2004) -* [METRICS SDK] Performance improvement in measurement processing - [#1993](https://github.com/open-telemetry/opentelemetry-cpp/pull/1993) -* [EXAMPLE] Add example for logs ostream exporter - [#1992](https://github.com/open-telemetry/opentelemetry-cpp/pull/1992) -* [ETW Exporter] Support serialize span/log attributes into JSON - [#1991](https://github.com/open-telemetry/opentelemetry-cpp/pull/1991) -* [ETW Exporter]Do not overwrite ParentId when setting attribute on Span - [#1989](https://github.com/open-telemetry/opentelemetry-cpp/pull/1989) -* Upgrade prometheus-cpp to v1.1.0 - [#1954](https://github.com/open-telemetry/opentelemetry-cpp/pull/1954) -* Convert Prometheus Exporter to Pull MetricReader - [#1953](https://github.com/open-telemetry/opentelemetry-cpp/pull/1953) -* [DOCS] Add alpine packages to INSTALL.md - [#1957](https://github.com/open-telemetry/opentelemetry-cpp/pull/1957) -* [METRICS SDK] Add benchmark tests for Sum Aggregation. - [#1948](https://github.com/open-telemetry/opentelemetry-cpp/pull/1948) -* [BUILD] Build OpenTelemetry SDK and exporters into DLL - [#1932](https://github.com/open-telemetry/opentelemetry-cpp/pull/1932) -* [CI] Enforce copyright check in CI - [#1965](https://github.com/open-telemetry/opentelemetry-cpp/pull/1965) -* [BUILD] Fix typo GENENV -> GETENV - [#1972](https://github.com/open-telemetry/opentelemetry-cpp/pull/1972) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.18.0 - [#1974](https://github.com/open-telemetry/opentelemetry-cpp/pull/1974) -* [EXT] Fix thread-safety when shutdown. - [#1977](https://github.com/open-telemetry/opentelemetry-cpp/pull/1977) -* [SDK] Fix missing ObservedTimestamp. - [#1985](https://github.com/open-telemetry/opentelemetry-cpp/pull/1985) -* [METRICS SDK] fix variable names - [#1987](https://github.com/open-telemetry/opentelemetry-cpp/pull/1987) -* [EXPORTER] Fix Prometheus server crash on listening to already used port - [#1986](https://github.com/open-telemetry/opentelemetry-cpp/pull/1986) -* [EXPORTER] Boolean environment variables not parsed per the spec - [#1982](https://github.com/open-telemetry/opentelemetry-cpp/pull/1982) -* [EXPORTER] Opentracing shim - [#1909](https://github.com/open-telemetry/opentelemetry-cpp/pull/1909) - -## [1.8.2] 2023-01-31 - -* Remove redundant macro check in nostd::shared_ptr [#1939](https://github.com/open-telemetry/opentelemetry-cpp/pull/1939) -* Fix typo in packages.cmake causing incorrect nuget package versions [#1936](https://github.com/open-telemetry/opentelemetry-cpp/pull/1936) -* [METRICS] Custom Aggregation support [#1899](https://github.com/open-telemetry/opentelemetry-cpp/pull/1899) -* Small fix in INSTALL.md for enabling building package. [#1930](https://github.com/open-telemetry/opentelemetry-cpp/pull/1930) -* [METRICS] Fix warning for misconfiguration of PeriodicExportingMetricReader [#1929](https://github.com/open-telemetry/opentelemetry-cpp/pull/1929) -* Make macros.h available for all source files via version.h [#1918](https://github.com/open-telemetry/opentelemetry-cpp/pull/1918) -* [METRICS] Histogram Aggregation: Fix bucket detection logic, - performance improvements, and benchmark tests [#1869](https://github.com/open-telemetry/opentelemetry-cpp/pull/1869) -* Remove unused namespace alias for nostd [#1914](https://github.com/open-telemetry/opentelemetry-cpp/pull/1914) -* [METRICS] Update meter.h [#1907](https://github.com/open-telemetry/opentelemetry-cpp/pull/1907) -* sdk::resource::Resource::Merge should be const [#1905](https://github.com/open-telemetry/opentelemetry-cpp/pull/1905) -* [METRICS] Collect and Export metric data before - PeriodicMetricReader shutdown. [#1860](https://github.com/open-telemetry/opentelemetry-cpp/pull/1860) -* [ETW EXPORTER] Add Virtual destructor for TailSampler, Update Maintainer - mode warnings for MSVC [#1897](https://github.com/open-telemetry/opentelemetry-cpp/pull/1897) -* Fix #1867 Orderly shutdown in examples [#1868](https://github.com/open-telemetry/opentelemetry-cpp/pull/1868) -* [METRICS] minor metrics handling optimizations [#1890](https://github.com/open-telemetry/opentelemetry-cpp/pull/1890) -* fix SpinLockMutex for Intel Compiler [#1885](https://github.com/open-telemetry/opentelemetry-cpp/pull/1885) -* [LOGS] Change BatchLogRecordProcessorFactory::Create to static method [#1876](https://github.com/open-telemetry/opentelemetry-cpp/pull/1876) -* Enable generating deb, rpm, NuGet, tgz, zip package through cmake build [#1662](https://github.com/open-telemetry/opentelemetry-cpp/pull/1662) -* Updated clone command in INSTALL.md [#1818](https://github.com/open-telemetry/opentelemetry-cpp/pull/1818) -* Small cleanup to remove old metrics design docs [#1855](https://github.com/open-telemetry/opentelemetry-cpp/pull/1855) -* [BUILD] Fix build error with older version of VS2017 compiler. [1857](https://github.com/open-telemetry/opentelemetry-cpp/pull/1857) -* [EXPORTERS] Enable setting Span endtime for ETW exporter [#1846](https://github.com/open-telemetry/opentelemetry-cpp/pull/1846) -* [REMOVAL] Remove deprecated experimental semantic conventions [#1743](https://github.com/open-telemetry/opentelemetry-cpp/pull/1743) -* [EXPORTERS] Fix console debug logs for otlp exporters. [#1848](https://github.com/open-telemetry/opentelemetry-cpp/pull/1848) -* [LOGS] Add `include_trace_context` and `EventLogger` [#1884](https://github.com/open-telemetry/opentelemetry-cpp/pull/1884) -* [METRICS] Change BatchLogRecordProcessorFactory::Create to static method -* [BUILD] Fix OTELCPP_MAINTAINER_MODE [#1844](https://github.com/open-telemetry/opentelemetry-cpp/pull/1844) -* [BUILD] Fix compatibility when using clang and libc++, upgrade GTest and - cmake when using C++20 [#1852](https://github.com/open-telemetry/opentelemetry-cpp/pull/1852) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.16.0 - [#1854](https://github.com/open-telemetry/opentelemetry-cpp/pull/1854) -* [SDK] BatchSpanProcessor now logs a warning when dropping a span because the - queue is full - [1871](https://github.com/open-telemetry/opentelemetry-cpp/pull/1871) -* [BUILD] Migrate from @bazel_tools//platforms to [Bazel Platforms](https://github.com/bazelbuild/platforms) - to enable Bazel 6.0.0 compatibility [#1873](https://github.com/open-telemetry/opentelemetry-cpp/pull/1873) -* [BUILD] Cleanup CMake makefiles for nlohmann_json - [#1912](https://github.com/open-telemetry/opentelemetry-cpp/pull/1912) -* [BUILD] Cleanup CMake makefiles for CURL usage - [#1916](https://github.com/open-telemetry/opentelemetry-cpp/pull/1916) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.17.0 - [#1927](https://github.com/open-telemetry/opentelemetry-cpp/pull/1927) -* [MAINTAINER DOC] Define and document a deprecation process, - [DEPRECATION] Deprecate the Jaeger exporter, - implemented by [#1923](https://github.com/open-telemetry/opentelemetry-cpp/pull/1923) -* [BUILD] OTLP HTTP Exporter has build warnings in maintainer mode - [#1943](https://github.com/open-telemetry/opentelemetry-cpp/pull/1943) - -Deprecations: - -* [MAINTAINER DOC] Define and document a deprecation process, - [#1923](https://github.com/open-telemetry/opentelemetry-cpp/pull/1923) - * A new file, [DEPRECATED](./DEPRECATED.md) list all the code currently - deprecated. - * A new [deprecation process](./docs/deprecation-process.md) details the plan to - deprecate and later remove code. -* [DEPRECATION] Deprecate the Jaeger exporter - [#1923](https://github.com/open-telemetry/opentelemetry-cpp/pull/1923) - * The Jaeger Exporter is deprecated, see [DEPRECATED](./DEPRECATED.md) for details. - -Important changes: - -* [BUILD] Cleanup CMake makefiles for CURL usage - [#1916](https://github.com/open-telemetry/opentelemetry-cpp/pull/1916) - * CMake option `WITH_OTLP_HTTP` - * Before this change, the CMake option `WITH_OTLP_HTTP` was unpredictable, - sometime set to ON and sometime set to OFF by default, - depending on whether a CURL package was found or not. - The option `WITH_OTLP_HTTP` was sometime not displayed in the ccmake - UI, making it impossible to even discover there is an option of that name. - * With this change, CMake option `WITH_OTLP_HTTP` is always OFF by - default. WITH_OTLP_HTTP MUST be set to ON explicitly to build the - OTLP HTTP exporter. The option is always visible in the ccmake UI. - * CMake option `BUILD_W3CTRACECONTEXT_TEST` - * Before this change, the W3C trace context tests were built, or - not, in an unpredictable way, depending on the presence, or not, of a - CURL package. In particular, the build could ignore the W3C trace - context tests even when BUILD_W3CTRACECONTEXT_TEST=ON. - * With this change, option BUILD_W3CTRACECONTEXT_TEST is honored. - * HTTP client/server examples - * Before this change, the HTTP client/server examples were built, or - not, in an unpredictable way, depending on the presence, or not, of a - CURL package. - * With this change, a new option `WITH_EXAMPLES_HTTP` is used to - build the HTTP client/server examples. - -## [1.8.1] 2022-12-04 - -* [ETW Exporter] Tail based sampling support [#1780](https://github.com/open-telemetry/opentelemetry-cpp/pull/1780) -* [EXPORTERS] fix typo [affecting otlp exported histogram metrics max uint] [#1827](https://github.com/open-telemetry/opentelemetry-cpp/pull/1827) -* [EXPORTERS] fix enum-compare-switch warning [#1833](https://github.com/open-telemetry/opentelemetry-cpp/pull/1833) -* [METRICS] Change default temporality as "Cumulative" for OTLP metrics -exporters [#1828](https://github.com/open-telemetry/opentelemetry-cpp/pull/1828) -* [BUILD] Moved otlp_grpc_utils.cc to opentelemetry_exporter_otlp_grpc_client. -[#1829](https://github.com/open-telemetry/opentelemetry-cpp/pull/1829) -* Fix type mismatch when move nostd::shared_ptr [#1815](https://github.com/open-telemetry/opentelemetry-cpp/pull/1815) -* [BUILD] Fix Prometheus target name [#1820](https://github.com/open-telemetry/opentelemetry-cpp/pull/1820) -* Clean unused docker files [#1817](https://github.com/open-telemetry/opentelemetry-cpp/pull/1817) -* [BUILD] Fix default bazel build [#1816](https://github.com/open-telemetry/opentelemetry-cpp/pull/1816) -* [BUILD] move client::nosend under test_common [#1811](https://github.com/open-telemetry/opentelemetry-cpp/pull/1811) -* [BUILD] Fix opentelemetry-proto file exists check [#1824](https://github.com/open-telemetry/opentelemetry-cpp/pull/1824) - -## [1.8.0] 2022-11-27 - -* [DOC] Update Metrics status in README.md [#1722](https://github.com/open-telemetry/opentelemetry-cpp/pull/1722) -* [DOC] Remove misleading comments about ABI compatibility for nostd::span [#1731](https://github.com/open-telemetry/opentelemetry-cpp/pull/1731) -* [BUILD] Bump abseil-cpp for cmake CI [#1807](https://github.com/open-telemetry/opentelemetry-cpp/pull/1807) -* [Exporter] Add status code to OTLP grpc trace log [#1792](https://github.com/open-telemetry/opentelemetry-cpp/pull/1792) -* [Exporter] add fix for prometheus exporter build [#1795](https://github.com/open-telemetry/opentelemetry-cpp/pull/1795) -* [BUILD] Add option WITH_BENCHMARK to disable building benchmarks [#1794](https://github.com/open-telemetry/opentelemetry-cpp/pull/1794) -* [BUILD] Fix CI benchmark [#1799](https://github.com/open-telemetry/opentelemetry-cpp/pull/1799) -* [BUILD] bump to gRPC v1.48.1 for bazel CIs [#1786](https://github.com/open-telemetry/opentelemetry-cpp/pull/1786) -* [BUILD] Fix CI build [#1798](https://github.com/open-telemetry/opentelemetry-cpp/pull/1798) -* [BUILD] Fix clang-format in CI [#1796](https://github.com/open-telemetry/opentelemetry-cpp/pull/1796) -* Fix session lock of OtlpHttpClient [#1760](https://github.com/open-telemetry/opentelemetry-cpp/pull/1760) -* [Metrics SDK] Add MeterContext::ForEachMeter() method to process callbacks on - Meter in thread-safe manner [#1783](https://github.com/open-telemetry/opentelemetry-cpp/pull/1783) -* [DOC] Document that clang-format version 10.0 is used. [#1782](https://github.com/open-telemetry/opentelemetry-cpp/pull/1782) -* [BUILD] Upgrade bazel build to use abseil-cpp-20220623.1 [#1779](https://github.com/open-telemetry/opentelemetry-cpp/pull/1779) -* Fix GlobalLogHandler singleton creation order [#1767](https://github.com/open-telemetry/opentelemetry-cpp/pull/1767) -* [Metrics SDK] Change Prometheus CMake target name [#1765](https://github.com/open-telemetry/opentelemetry-cpp/pull/1765) -* [DOC] Cleanup INSTALL.md [#1757](https://github.com/open-telemetry/opentelemetry-cpp/pull/1757) -* [DOC] Format config options in OTLP exporter readme [#1748](https://github.com/open-telemetry/opentelemetry-cpp/pull/1748) -* [DOC] Cleanup ENABLE_METRICS_PREVIEW [#1745](https://github.com/open-telemetry/opentelemetry-cpp/pull/1745) -* [Build] Multiple CURL packages leads to invalid build (#1738) [#1739](https://github.com/open-telemetry/opentelemetry-cpp/pull/1739) -* [Metrics SDK] Cleanup ENABLE_METRICS_PREVIEW [#1735](https://github.com/open-telemetry/opentelemetry-cpp/pull/1735) -* [Logs SDK] LogProcessor, LogExporter class name [#1736](https://github.com/open-telemetry/opentelemetry-cpp/pull/1736) -* [Metrics SDK] Cleanup of old _metric api/sdk [#1734](https://github.com/open-telemetry/opentelemetry-cpp/pull/1734) -* [ETW Exporter] Fix span timestamp(s) precision to nanoseconds [#1726](https://github.com/open-telemetry/opentelemetry-cpp/pull/1726) -* [LOGS SDK] Rename LogProcessor and LogExporter to LogRecordProcessor and LogRecordExporter - [#1727](https://github.com/open-telemetry/opentelemetry-cpp/pull/1727) -* [METRICS SDK] - Remove old metrics from Github CI - [#1733](https://github.com/open-telemetry/opentelemetry-cpp/pull/1733) -* [BUILD] Add CMake OTELCPP_PROTO_PATH [#1730](https://github.com/open-telemetry/opentelemetry-cpp/pull/1730) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.15.0 - [#1761](https://github.com/open-telemetry/opentelemetry-cpp/pull/1761) -* [LOGS SDK] New LogRecord and logs::Recordable implementations. - [#1766](https://github.com/open-telemetry/opentelemetry-cpp/pull/1766) - -Deprecation notes: - -* [Deprecation] Deprecate experimental semantic conventions - [#1744](https://github.com/open-telemetry/opentelemetry-cpp/pull/1744) - * The file - `api/include/opentelemetry/trace/experimental_semantic_conventions.h` - is deprecated, and will be removed in a future release. - Use file - `api/include/opentelemetry/trace/semantic_conventions.h` - instead. - - * The file - `sdk/include/opentelemetry/sdk/resource/experimental_semantic_conventions.h` - is deprecated, and will be removed in a future release. - Use file - `sdk/include/opentelemetry/sdk/resource/semantic_conventions.h` - instead. - - * The function, declared in the global namespace - `uint32_t hashCode(const char *str, uint32_t h = 0)` - is deprecated, and will be removed in a future release. - No replacement will be provided. - Note that function `opentelemetry::utils::hashCode`, - declared in the ETW exporter, is not affected by this deprecation. - -Breaking changes: - -* [SEMANTIC CONVENTIONS] Upgrade to version 1.15.0 - [#1761](https://github.com/open-telemetry/opentelemetry-cpp/pull/1761) - * Naming of semantic conventions has changed from uppercase constants, - like `SemanticConventions::SERVICE_NAME`, - to camel case, like `SemanticConventions::kServiceName`. - This is necessary to avoid collisions with macros in general, - which breaks the build on some platforms. - * Semantic conventions are flagged as experimental, - which is why this change is done in this release. - -## [1.7.0] 2022-10-28 - -* [METRICS SDK] Validate Instrument meta data (name, unit, description) [#1713](https://github.com/open-telemetry/opentelemetry-cpp/pull/1713) -* [DOCS] Document libthrift 0.12.0 doesn't work with Jaeger exporter [#1714](https://github.com/open-telemetry/opentelemetry-cpp/pull/1714) -* [Metrics SDK] Add Monotonic Property to Sum Aggregation, and -unit tests for Up Down Counter [#1675](https://github.com/open-telemetry/opentelemetry-cpp/pull/1675) -* [Metrics SDK] Move Metrics Exemplar processing behind feature flag [#1710](https://github.com/open-telemetry/opentelemetry-cpp/pull/1710) -* [Metrics API/SDK] Change Meter API/SDK to return nostd::unique_ptr - for Sync Instruments [#1707](https://github.com/open-telemetry/opentelemetry-cpp/pull/1707) -which includes breaking change in the Metrics api and sdk. -* [BUILD] Add e2e test to asan & tsan CI [#1670](https://github.com/open-telemetry/opentelemetry-cpp/pull/1670) -* [BUILD] Add otlp-grpc example bazel [#1708](https://github.com/open-telemetry/opentelemetry-cpp/pull/1708) -* [TRACE SDK] Fix debug log of OTLP HTTP exporter and ES log exporter [#1703](https://github.com/open-telemetry/opentelemetry-cpp/pull/1703) -* [METRICS SDK] Fix a potential precision loss on integer in -ReservoirCellIndexFor [#1696](https://github.com/open-telemetry/opentelemetry-cpp/pull/1696) -* [METRICS SDK] Fix Histogram crash [#1685](https://github.com/open-telemetry/opentelemetry-cpp/pull/1685) -* [METRICS SDK] Fix:1676 Segfault when short export period is used for metrics [#1682](https://github.com/open-telemetry/opentelemetry-cpp/pull/1682) -* [METRICS SDK] Add timeout support to MeterContext::ForceFlush [#1673](https://github.com/open-telemetry/opentelemetry-cpp/pull/1673) -* [DOCS] - Minor updates to OStream Metrics exporter documentation [#1679](https://github.com/open-telemetry/opentelemetry-cpp/pull/1679) -* [DOCS] Fix:#1575 API Documentation for Metrics SDK and API [#1678](https://github.com/open-telemetry/opentelemetry-cpp/pull/1678) -* [BUILD] Fixed compiler warnings [#1677](https://github.com/open-telemetry/opentelemetry-cpp/pull/1677) -* [METRICS SDK] Fix threading issue between Meter::RegisterSyncMetricStorage - and Meter::Collect [#1666](https://github.com/open-telemetry/opentelemetry-cpp/pull/1666) -* [METRICS SDK] Fix data race on MeterContext::meters_ [#1668](https://github.com/open-telemetry/opentelemetry-cpp/pull/1668) -* [METRICS SDK] Fix observable Gauge metrics generation [#1651](https://github.com/open-telemetry/opentelemetry-cpp/pull/1651) -* [BUILD] Detect ARCH=sparc in CMake [#1660](https://github.com/open-telemetry/opentelemetry-cpp/pull/1660) -* [SDK] Add user agent for OTLP http/grpc client [#1657](https://github.com/open-telemetry/opentelemetry-cpp/pull/1657) -* [BUILD] Fix clang and gcc warnings [#1658](https://github.com/open-telemetry/opentelemetry-cpp/pull/1658) -* [Metrics SDK] Add Metrics ExemplarFilter and ExemplarReservoir [#1584](https://github.com/open-telemetry/opentelemetry-cpp/pull/1584) -* [LOGS SDK] Rename OnReceive to OnEmit [#1652](https://github.com/open-telemetry/opentelemetry-cpp/pull/1652) -* [METRICS SDK] Fix Observable Gauge does not reflect updated values, -and send the old value always [#1641](https://github.com/open-telemetry/opentelemetry-cpp/pull/1641) -* [Metrics SDK] Change boundary type to double for Explicit Bucket Histogram Aggregation, -and change default bucket range [#1626](https://github.com/open-telemetry/opentelemetry-cpp/pull/1626) -* [METRICS SDK] Fix occasional Segfault with LongCounter instrument [#1638](https://github.com/open-telemetry/opentelemetry-cpp/pull/1638) -* [BUILD] Bump vcpk to 2022.08.15 [#1633](https://github.com/open-telemetry/opentelemetry-cpp/pull/1633) -* [BUILD] Bump gRPC to v1.48.1 for CMake Linux CI [#1608](https://github.com/open-telemetry/opentelemetry-cpp/pull/1608) -* [Metrics] Switch to explicit 64 bit integers [#1686](https://github.com/open-telemetry/opentelemetry-cpp/pull/1686) - which includes breaking change in the Metrics api and sdk. -* [Metrics SDK] Add support for Pull Metric Exporter [#1701](https://github.com/open-telemetry/opentelemetry-cpp/pull/1701) - which includes breaking change in the Metrics api. -* [BUILD] Add CMake OTELCPP_MAINTAINER_MODE [#1650](https://github.com/open-telemetry/opentelemetry-cpp/pull/1650) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.14.0 [#1697](https://github.com/open-telemetry/opentelemetry-cpp/pull/1697) - -Notes: - -Metrics API/SDK GA release includes PRs [#1686](https://github.com/open-telemetry/opentelemetry-cpp/pull/1686), -[#1701](https://github.com/open-telemetry/opentelemetry-cpp/pull/1701), and -[#1707](https://github.com/open-telemetry/opentelemetry-cpp/pull/1707) -with breaking changes in the Metrics API and SDK. - -## [1.6.1] 2022-09-22 - -* [BUILD] Upgrade opentelemetry-proto to v0.19.0 [#1579](https://github.com/open-telemetry/opentelemetry-cpp/pull/1579) -* [METRICS EXPORTER] Add `OtlpGrpcMetricExporterFactory` and `OtlpHttpMetricExporterFactory`. - [#1606](https://github.com/open-telemetry/opentelemetry-cpp/pull/1606) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.13.0 [#1624](https://github.com/open-telemetry/opentelemetry-cpp/pull/1624) -* [BUILD] Fixes span creation benchmark issue. [#1622](https://github.com/open-telemetry/opentelemetry-cpp/pull/1622) -* [BUILD] Fix more build warnings (#1616) [#1620](https://github.com/open-telemetry/opentelemetry-cpp/pull/1620) -* [SDK gRPC]: Fix out-of-bounds access of string_view in GrpcClientCarrier in - the example - [#1619](https://github.com/open-telemetry/opentelemetry-cpp/pull/1619) -* [EXPORTER ETW] Add Trace flags in SpanContext [#1618](https://github.com/open-telemetry/opentelemetry-cpp/pull/1618) -* [SDK] resource sdk: Update Resource::Merge function docs [#1615](https://github.com/open-telemetry/opentelemetry-cpp/pull/1615) -* [BUILD] Fix build warnings [#1613](https://github.com/open-telemetry/opentelemetry-cpp/pull/1613) -* [API BUILD] Fix header only api singletons (#1520) [#1604](https://github.com/open-telemetry/opentelemetry-cpp/pull/1604) -* [METRICS SDK] Fix default value of - `OtlpHttpMetricExporterOptions::aggregation_temporality`. - [#1601](https://github.com/open-telemetry/opentelemetry-cpp/pull/1601) -* [METRICS EXAMPLE] Example for OTLP gRPC exporter for Metrics. [#1598](https://github.com/open-telemetry/opentelemetry-cpp/pull/1598) -* [SDK] Fix `LoggerContext::Shutdown` and tsan of `OtlpHttpClient` [#1592](https://github.com/open-telemetry/opentelemetry-cpp/pull/1592) -* [METRICS SDK] Fix 1585 - Multiple cumulative metric collections without - measurement recording. - [#1586](https://github.com/open-telemetry/opentelemetry-cpp/pull/1586) -* [BUILD] metrics warnings [#1583](https://github.com/open-telemetry/opentelemetry-cpp/pull/1583) -* [METRICS SDK] Fix ObservableInstrument::RemoveCallback [#1582](https://github.com/open-telemetry/opentelemetry-cpp/pull/1582) -* [SDK] Add error log when getting a http error code [#1581](https://github.com/open-telemetry/opentelemetry-cpp/pull/1581) -* [EXPORTER] ETW Exporter - Add support for Sampler and ID Generator [#1547](https://github.com/open-telemetry/opentelemetry-cpp/pull/1547) - -Notes: - -While [OpenTelemetry semantic -convention](https://github.com/open-telemetry/opentelemetry-specification/tree/main/semantic_conventions) -is still in experimental state, PR -[#1624](https://github.com/open-telemetry/opentelemetry-cpp/pull/1624) upgraded -it from 1.12.0 to 1.13.0 which **MAY** break the instrumentation library. Please -update the semantic convention in instrumentation library is needed. - -## [1.6.0] 2022-08-15 - -* [METRICS SDK] Calling Observable Instruments callback during metrics - collection - [#1554](https://github.com/open-telemetry/opentelemetry-cpp/pull/1554) -* [METRICS CI] Add CI jobs for new and deprecated metrics [#1531](https://github.com/open-telemetry/opentelemetry-cpp/pull/1531) -* [METRICS BUILD] Fix metrics asan and tsan CI [#1562](https://github.com/open-telemetry/opentelemetry-cpp/pull/1562) -* [METRICS SDK] remove throw check from metrics with noexcept [#1560](https://github.com/open-telemetry/opentelemetry-cpp/pull/1560) -* [METRICS SDK] fix metrics race condition [#1552](https://github.com/open-telemetry/opentelemetry-cpp/pull/1552) -* [METRICS SDK] Fix metrics context circular reference [#1535](https://github.com/open-telemetry/opentelemetry-cpp/pull/1535) -* [METRICS EXPORTER] Improve scope/instrument names in metrics ostream exporter [#1544](https://github.com/open-telemetry/opentelemetry-cpp/pull/1544) -* [METRICS BUILD] fix IWYU error in instruments.h [#1555](https://github.com/open-telemetry/opentelemetry-cpp/pull/1555) -* [EXPORTER] Prometheus exporter support Gauge Type [#1553](https://github.com/open-telemetry/opentelemetry-cpp/pull/1553) -* [METRICS SDK] Fix default Metric view name [#1515](https://github.com/open-telemetry/opentelemetry-cpp/pull/1515) -* [SDK] Fix infinitely waiting when shutdown with more than one running http - sessions. - [#1549](https://github.com/open-telemetry/opentelemetry-cpp/pull/1549) -* [METRICS SDK] Fix OTLP gRPC Metrics env variables [#1543](https://github.com/open-telemetry/opentelemetry-cpp/pull/1543) -* [METRICS SDK] Metric aggregation temporality controls [#1541](https://github.com/open-telemetry/opentelemetry-cpp/pull/1541) -* [METRICS SDK] Histogram min/max support [#1540](https://github.com/open-telemetry/opentelemetry-cpp/pull/1540) -* [METRICS EXPORTER] ostream exporter should print out resource attributes [#1523](https://github.com/open-telemetry/opentelemetry-cpp/pull/1523) -* [METRICS SDK] Support multiple async callbacks [#1495](https://github.com/open-telemetry/opentelemetry-cpp/pull/1495) -* [BUILD] Fix code scanning alert [#1530](https://github.com/open-telemetry/opentelemetry-cpp/pull/1530) -* [BUILD] Fix several compiling/linking errors [#1539](https://github.com/open-telemetry/opentelemetry-cpp/pull/1539) -* [TRACE SDK] Add SpanData getter for Span Recordable [#1508](https://github.com/open-telemetry/opentelemetry-cpp/pull/1508) -* [LOG SDK] Fix log sdk builder (#1486) [#1524](https://github.com/open-telemetry/opentelemetry-cpp/pull/1524) -* [METRICS SDK] Add configuration options for Aggregation creation [#1513](https://github.com/open-telemetry/opentelemetry-cpp/pull/1513) -* [METRICS TEST] Fix metrics unit test memory leack [#1533](https://github.com/open-telemetry/opentelemetry-cpp/pull/1533) -* [LOG SDK] Add log sdk builders (#1486) [#1524](https://github.com/open-telemetry/opentelemetry-cpp/pull/1524) - -## [1.5.0] 2022-07-29 - -* [EXPORTER BUILD] Add resources to dep list of prometheus exporter test [#1527](https://github.com/open-telemetry/opentelemetry-cpp/pull/1527) -* [BUILD] Don't require applications using jaeger exporter to know about libcurl - [#1518](https://github.com/open-telemetry/opentelemetry-cpp/pull/1518) -* [EXPORTER] Inline print_value() in ostream exporter [#1512](https://github.com/open-telemetry/opentelemetry-cpp/pull/1512) -* [SDK] fix: urlPaser will incorrect parsing url like `http://abc.com/xxx@xxx/a/b` - [#1511](https://github.com/open-telemetry/opentelemetry-cpp/pull/1511) -* [SDK] Rename `InstrumentationLibrary` to `InstrumentationScope` [#1507](https://github.com/open-telemetry/opentelemetry-cpp/pull/1507) -* [BUILD] Try to build nlohmann-json only it's depended. [#1505](https://github.com/open-telemetry/opentelemetry-cpp/pull/1505) -* [EXPORTER BUILD] Link opentelemetry_api to ETW exporter test [#1503](https://github.com/open-telemetry/opentelemetry-cpp/pull/1503) -* [SDK] Add automatically semantic conventions from the spec (#873) [#1497](https://github.com/open-telemetry/opentelemetry-cpp/pull/1497) -* [SDK] Use template class for in-memory data. [#1496](https://github.com/open-telemetry/opentelemetry-cpp/pull/1496) -* [SDK] fix compiler warnings [#1499](https://github.com/open-telemetry/opentelemetry-cpp/pull/1499) -* [TRACE SDK] Add trace sdk builders (#1393) [#1471](https://github.com/open-telemetry/opentelemetry-cpp/pull/1471) -* [METRICS BUILD] Enable bazel build for metrics proto files [#1489](https://github.com/open-telemetry/opentelemetry-cpp/pull/1489) -* [METRICS EXPORTER] Add metrics OTLP/HTTP exporter [#1487](https://github.com/open-telemetry/opentelemetry-cpp/pull/1487) -* [EXPORTER] fix otlp grpc exporter naming [#1488](https://github.com/open-telemetry/opentelemetry-cpp/pull/1488) -* [BUILD] Remove `--config Debug` when installing. [#1480](https://github.com/open-telemetry/opentelemetry-cpp/pull/1480) -* [EXPORTER] Fix endpoint in otlp grpc exporter [#1474](https://github.com/open-telemetry/opentelemetry-cpp/pull/1474) -* [EXAMPLE] Fix memory ownership of InMemorySpanExporter (#1473) [#1471](https://github.com/open-telemetry/opentelemetry-cpp/pull/1471) -* [EXPORTER TESTS] Prometheus unit test [#1461](https://github.com/open-telemetry/opentelemetry-cpp/pull/1461) -* [DOCS] Update docs to use relative code links. [#1447](https://github.com/open-telemetry/opentelemetry-cpp/pull/1447) -* [SDK] Remove reference to deprecated InstrumentationLibrary in OTLP [#1469](https://github.com/open-telemetry/opentelemetry-cpp/pull/1469) -* [SDK] Fix trace kIsSampled flag set incorrectly [#1465](https://github.com/open-telemetry/opentelemetry-cpp/pull/1465) -* [METRICS EXPORTER] OTLP gRPC Metrics Exporter [#1454](https://github.com/open-telemetry/opentelemetry-cpp/pull/1454) -* [EXPORTER] fix prometheus exporter failure type [#1460](https://github.com/open-telemetry/opentelemetry-cpp/pull/1460) -* [SDK] Fix build warnings about missing aggregates. [#1368](https://github.com/open-telemetry/opentelemetry-cpp/pull/1368) -* [EXT] `curl::HttpClient` use `curl_multi_handle` instead of creating a thread - for every request and it's able to reuse connections now. ([#1317](https://github.com/open-telemetry/opentelemetry-cpp/pull/1317)) -* [SEMANTIC CONVENTIONS] Upgrade to version 1.12.0 [#873](https://github.com/open-telemetry/opentelemetry-cpp/pull/873) - -## [1.4.1] 2022-06-19 - -* [METRICS SDK] Fix variables inizialization [#1430](https://github.com/open-telemetry/opentelemetry-cpp/pull/1430) -* [DOCS] Fixed broken link to OpenTelemetry.io (#1445) [#1446](https://github.com/open-telemetry/opentelemetry-cpp/pull/1446) -* [BUILD] Upgrade nlohmann_json to 3.10.5 (#1438) [#1441](https://github.com/open-telemetry/opentelemetry-cpp/pull/1441) -* [METRICS SDK] fix histogram [#1440](https://github.com/open-telemetry/opentelemetry-cpp/pull/1440) -* [DOCS] Fix GettingStarted documentation for Jaeger HTTP exporter (#1347) [#1439](https://github.com/open-telemetry/opentelemetry-cpp/pull/1439) -* [BUILD] install sdk-config.h [#1419](https://github.com/open-telemetry/opentelemetry-cpp/pull/1419) -* [EXAMPLE] Log current timestamp instead of epoch time [#1434](https://github.com/open-telemetry/opentelemetry-cpp/pull/1434) -* [METRICS SDK] Add attributes/dimensions to metrics ostream exporter [#1400](https://github.com/open-telemetry/opentelemetry-cpp/pull/1400) -* [SDK] Fix global log handle symbols when using dlopen [#1420](https://github.com/open-telemetry/opentelemetry-cpp/pull/1420) -* [METRICS] Only record non-negative / finite / Non-NAN histogram values([#1427](https://github.com/open-telemetry/opentelemetry-cpp/pull/1427)) -* [ETW EXPORTER] Fix ETW log exporter header inclusion [#1426](https://github.com/open-telemetry/opentelemetry-cpp/pull/1426) -* [ETW EXPORTER] Copy string_view passed to ETW exporter in PropertyVariant [#1425](https://github.com/open-telemetry/opentelemetry-cpp/pull/1425) -* [METRICS API/SDK] Pass state to async callback function. [#1408](https://github.com/open-telemetry/opentelemetry-cpp/pull/1408) -* [BUILD] fix nlohmann_json's (third party) include dir [#1415](https://github.com/open-telemetry/opentelemetry-cpp/pull/1415) -* [SDK] fix: WaitOnSocket select error when sockfd above FD_SETSIZE [#1410](https://github.com/open-telemetry/opentelemetry-cpp/pull/1410) -* [SDK] fix OTEL_INTERNAL_LOG_INFO [#1407](https://github.com/open-telemetry/opentelemetry-cpp/pull/1407) -* [DOCS] Document Getting Started with Prometheus and Grafana [#1396](https://github.com/open-telemetry/opentelemetry-cpp/pull/1396) - -## [1.4.0] 2022-05-17 - -* [API SDK] Upgrade proto to v0.17.0, update log data model ([#1383](https://github.com/open-telemetry/opentelemetry-cpp/pull/1383)) -* [BUILD] Alpine image ([#1382](https://github.com/open-telemetry/opentelemetry-cpp/pull/1382)) -* [LOGS SDK] Get span_id from context when Logger::Log received invalid span_id - ([#1398](https://github.com/open-telemetry/opentelemetry-cpp/pull/1398)) -* [METRICS SDK] Connect async storage with async instruments ([#1388](https://github.com/open-telemetry/opentelemetry-cpp/pull/1388)) -* [DOCS] Getting started document using ostream exporter ([#1394](https://github.com/open-telemetry/opentelemetry-cpp/pull/1394)) -* [BUILD] Fix missing link to nlohmann_json ([#1390](https://github.com/open-telemetry/opentelemetry-cpp/pull/1390)) -* [SDK] Fix sharing resource in batched exported spans ([#1386](https://github.com/open-telemetry/opentelemetry-cpp/pull/1386)) -* [PROTOCOL \& LOGS] Upgrade proto to v0.17.0, update log data model ([#1383](https://github.com/open-telemetry/opentelemetry-cpp/pull/1383)) -* [METRICS SDK] Remove un-necessary files. ([#1379](https://github.com/open-telemetry/opentelemetry-cpp/pull/1379)) -* [EXPORTER] Prometheus exporter meters and instrument name ([#1378](https://github.com/open-telemetry/opentelemetry-cpp/pull/1378)) -* [API] Add noexcept/const qualifier at missing places for Trace API. ([#1374](https://github.com/open-telemetry/opentelemetry-cpp/pull/1374)) -* [SDK] Fix empty tracestate header propagation ([#1373](https://github.com/open-telemetry/opentelemetry-cpp/pull/1373)) -* [METRICS SDK] Reuse temporal metric storage for sync storage ([#1369](https://github.com/open-telemetry/opentelemetry-cpp/pull/1369)) -* [SDK] Fix baggage propagation for empty/invalid baggage context ([#1367](https://github.com/open-telemetry/opentelemetry-cpp/pull/1367)) -* [BUILD] Export opentelemetry_otlp_recordable ([#1365](https://github.com/open-telemetry/opentelemetry-cpp/pull/1365)) -* [TESTS] Disable test on prometheus-cpp which not need ([#1363](https://github.com/open-telemetry/opentelemetry-cpp/pull/1363)) -* [METRICS] Fix class member initialization order ([#1360](https://github.com/open-telemetry/opentelemetry-cpp/pull/1360)) -* [METRICS SDK] Simplify SDK Configuration: Use View with default aggregation if - no matching View is configured - ([#1358](https://github.com/open-telemetry/opentelemetry-cpp/pull/1358)) -* [BUILD] Add missing include guard ([#1357](https://github.com/open-telemetry/opentelemetry-cpp/pull/1357)) -* [ETW EXPORTER] Fix scalar delete against array ([#1356](https://github.com/open-telemetry/opentelemetry-cpp/pull/1356)) -* [ETW EXPORTER] Conditional include for codecvt header ([#1355](https://github.com/open-telemetry/opentelemetry-cpp/pull/1355)) -* [BUILD] Use latest TraceLoggingDynamic.h ([#1354](https://github.com/open-telemetry/opentelemetry-cpp/pull/1354)) -* [SDK] Add explicit type cast in baggage UrlDecode ([#1353](https://github.com/open-telemetry/opentelemetry-cpp/pull/1353)) -* [METRICS SDK] Remove exporter registration to meter provider ([#1350](https://github.com/open-telemetry/opentelemetry-cpp/pull/1350)) -* [METRICS SDK] Fix output time in metrics OStream exporter ([#1346](https://github.com/open-telemetry/opentelemetry-cpp/pull/1346)) -* [BUILD] ostream metrics cmake ([#1344](https://github.com/open-telemetry/opentelemetry-cpp/pull/1344)) -* [BUILD] Link `opentelemetry_ext` with `opentelemetry_api` ([#1336](https://github.com/open-telemetry/opentelemetry-cpp/pull/1336)) -* [METRICS SDK] Enable metric collection for Async Instruments - Delta and - Cumulative - ([#1334](https://github.com/open-telemetry/opentelemetry-cpp/pull/1334)) -* [BUILD] Dependencies image as artifact ([#1333](https://github.com/open-telemetry/opentelemetry-cpp/pull/1333)) -* [EXAMPLE] Prometheus example ([#1332](https://github.com/open-telemetry/opentelemetry-cpp/pull/1332)) -* [METRICS EXPORTER] Prometheus exporter ([#1331](https://github.com/open-telemetry/opentelemetry-cpp/pull/1331)) -* [METRICS] Metrics histogram example ([#1330](https://github.com/open-telemetry/opentelemetry-cpp/pull/1330)) -* [TESTS] Replace deprecated googletest API ([#1327](https://github.com/open-telemetry/opentelemetry-cpp/pull/1327)) -* [BUILD] Fix Ninja path ([#1326](https://github.com/open-telemetry/opentelemetry-cpp/pull/1326)) -* [API] Update yield logic for ARM processor ([#1325](https://github.com/open-telemetry/opentelemetry-cpp/pull/1325)) -* [BUILD] Fix metrics compiler warnings ([#1328](https://github.com/open-telemetry/opentelemetry-cpp/pull/1328)) -* [METRICS SDK] Implement Merge and Diff operation for Histogram Aggregation ([#1303](https://github.com/open-telemetry/opentelemetry-cpp/pull/1303)) - -Notes: - -While opentelemetry-cpp Logs are still in experimental stage, -[#1383](https://github.com/open-telemetry/opentelemetry-cpp/pull/1383) updated -opentelemetry-proto to 0.17.0, which includes some breaking change in the -protocol, like -[this](https://github.com/open-telemetry/opentelemetry-proto/pull/373). This -makes `name` parameter for our log API unnecessary. However, this parameter is -marked deprecated instead of being removed in this release, and it will be -removed in future release. - -## [1.3.0] 2022-04-11 - -* [ETW EXPORTER] ETW provider handle cleanup ([#1322](https://github.com/open-telemetry/opentelemetry-cpp/pull/1322)) -* [BUILD] Move public definitions into `opentelemetry_api`. ([#1314](https://github.com/open-telemetry/opentelemetry-cpp/pull/1314)) -* [METRICS] OStream example ([#1312](https://github.com/open-telemetry/opentelemetry-cpp/pull/1312)) -* [BUILD] Rename `http_client_curl` to `opentelemetry_http_client_curl` ([#1301](https://github.com/open-telemetry/opentelemetry-cpp/pull/1301)) -* [METRICS SDK] Add InstrumentationInfo and Resource to the metrics data to be - exported. - ([#1299](https://github.com/open-telemetry/opentelemetry-cpp/pull/1299)) -* [TESTS] Add building test without RTTI ([#1294](https://github.com/open-telemetry/opentelemetry-cpp/pull/1294)) -* [METRICS SDK] Implement periodic exporting metric reader ([#1286](https://github.com/open-telemetry/opentelemetry-cpp/pull/1286)) -* [SDK] Bugfix: span SetAttribute crash ([#1283](https://github.com/open-telemetry/opentelemetry-cpp/pull/1283)) -* [BUG] Remove implicitly deleted default constructor ([#1267](https://github.com/open-telemetry/opentelemetry-cpp/pull/1267)) -* [METRICS SDK] Synchronous Metric collection (Delta , Cumulative) ([#1265](https://github.com/open-telemetry/opentelemetry-cpp/pull/1265)) -* [METRICS SDK] Metrics exemplar round 1 ([#1264](https://github.com/open-telemetry/opentelemetry-cpp/pull/1264)) -* [EXPORTER] Fix: use CURLOPT_TIMEOUT_MS to config OtlpHttpExporter's timeout - instead of CURLOPT_TIMEOUT - ([#1261](https://github.com/open-telemetry/opentelemetry-cpp/pull/1261)) -* [EXPORTER] Jaeger Exporter - Populate Span Links ([#1251](https://github.com/open-telemetry/opentelemetry-cpp/pull/1251)) -* [SDK] Reorder the destructor of members in LoggerProvider and TracerProvider ([#1245](https://github.com/open-telemetry/opentelemetry-cpp/pull/1245)) -* [METRICS SDK] Enable metric collection from MetricReader ([#1241](https://github.com/open-telemetry/opentelemetry-cpp/pull/1241)) -* [METRICS SDK] Asynchronous Aggregation storage ([#1232](https://github.com/open-telemetry/opentelemetry-cpp/pull/1232)) -* [METRICS SDK] Synchronous Instruments - Aggregation Storage(s) creation for - configured views - ([#1219](https://github.com/open-telemetry/opentelemetry-cpp/pull/1219)) -* [BUILD] Added s390x arch into CMake build. ([#1216](https://github.com/open-telemetry/opentelemetry-cpp/pull/1216)) -* [API] Allow extension of the lifetime of ContextStorage. ([#1214](https://github.com/open-telemetry/opentelemetry-cpp/pull/1214)) -* [METRICS SDK] Add Aggregation storage ([#1213](https://github.com/open-telemetry/opentelemetry-cpp/pull/1213)) -* [TESTS] Fix ostream_log_test Mac ([#1208](https://github.com/open-telemetry/opentelemetry-cpp/pull/1208)) -* [BUILD] Update grpc to v1.43.2 to support VS2022/MSVC 19.30 and bazel 5.0 ([#1207](https://github.com/open-telemetry/opentelemetry-cpp/pull/1207)) -* [DOCS] Benchmark documentation ([#1205](https://github.com/open-telemetry/opentelemetry-cpp/pull/1205)) -* [DOCS] Fix errors in SDK documentation ([#1201](https://github.com/open-telemetry/opentelemetry-cpp/pull/1201)) -* [METRICS EXPORTER] Ostream metric exporter ([#1196](https://github.com/open-telemetry/opentelemetry-cpp/pull/1196)) -* [Metrics SDK] Filtering metrics attributes ([#1191](https://github.com/open-telemetry/opentelemetry-cpp/pull/1191)) -* [Metrics SDK] Sync and Async Instruments SDK ([#1184](https://github.com/open-telemetry/opentelemetry-cpp/pull/1184)) -* [Metrics SDK] Add Aggregation as part of metrics SDK. ([#1178](https://github.com/open-telemetry/opentelemetry-cpp/pull/1178)) -* [BUILD] Cmake: thrift requires boost headers, include them as - Boost_INCLUDE_DIRS - ([#1100](https://github.com/open-telemetry/opentelemetry-cpp/pull/1100)) - -Notes: - -[#1301](https://github.com/open-telemetry/opentelemetry-cpp/pull/1301) added -`opentelemetry_` as prefix to http_client_curl library for resolving potential -naming conflict, this could break existing cmake build if http_client_curl is -listed as explicit dependency in user's cmake file. - -## [1.2.0] 2022-01-31 - -* [CI] Continuous benchmark tests as part of the CI ([#1174](https://github.com/open-telemetry/opentelemetry-cpp/pull/1174)) -* [API] Allow to use external abseil for bazel targets ([#1172](https://github.com/open-telemetry/opentelemetry-cpp/pull/1172)) -* [EXPORTER] Importing gsl::span if std::span is not available ([#1167](https://github.com/open-telemetry/opentelemetry-cpp/pull/1167)) -* [EXPORTER] Synchronized calls to Exporter::Export & Shutdown ([#1164](https://github.com/open-telemetry/opentelemetry-cpp/pull/1164)) -* [EXPORTER] OTLP http exporter block thread ([#1163](https://github.com/open-telemetry/opentelemetry-cpp/pull/1163)) -* [TESTS] Jaeger: ThriftSender unit test ([#1162](https://github.com/open-telemetry/opentelemetry-cpp/pull/1162)) -* [EXPORTER] InMemorySpanExporter shutdown fix ([#1161](https://github.com/open-telemetry/opentelemetry-cpp/pull/1161)) -* [EXPORTER] Fix leak in Jaeger exporter ([#1160](https://github.com/open-telemetry/opentelemetry-cpp/pull/1160)) -* [TESTS] ZipkinExporter unit-tests ([#1155](https://github.com/open-telemetry/opentelemetry-cpp/pull/1155)) -* [SDK] Logger: propagating resources through LoggerProvider ([#1154](https://github.com/open-telemetry/opentelemetry-cpp/pull/1154)) -* [SDK] Logger: support for instrumentation library ([#1149](https://github.com/open-telemetry/opentelemetry-cpp/pull/1149)) -* [SDK] Add log level for internal log of sdk ([#1147](https://github.com/open-telemetry/opentelemetry-cpp/pull/1147)) -* [METRICS] Metrics SDK: View API ([#1110](https://github.com/open-telemetry/opentelemetry-cpp/pull/1110)) - -Notes on experimental features: - -[#1149](https://github.com/open-telemetry/opentelemetry-cpp/pull/1149) and -[#1154](https://github.com/open-telemetry/opentelemetry-cpp/pull/1154) from -above CHANGELOG introduced API changes which are not backward compatible with -previous logs, please update API package to this release if -`ENABLE_LOGS_PREVIEW` is turned on (it is turned off by default). - -## [1.1.1] 2021-12-20 - -* [SDK] Rename OTEL_CPP_GET_ATTR macro, and define it using fully qualified attr - function - ([#1140](https://github.com/open-telemetry/opentelemetry-cpp/pull/1140)) -* [SDK] Default resource attributes and attributes in OTEL_RESOURCE_ATTRIBUTES - are missing when using Otlp*LogExporter - ([#1082](https://github.com/open-telemetry/opentelemetry-cpp/pull/1082)) -* [METRICS] Add Meter and MeterProvider in the SDK - ([#1078](https://github.com/open-telemetry/opentelemetry-cpp/pull/1078)) -* [EXPORTER] ZipkinExporter shutdown - ([#1153](https://github.com/open-telemetry/opentelemetry-cpp/pull/1153)) -* [EXPORTER] Jaeger exporter shutdown - ([#1150](https://github.com/open-telemetry/opentelemetry-cpp/pull/1150)) -* [EXPORTER] Bugfix: `jaeger::TUDPTransport::write` crash when `getaddrinfo` - returns error - ([#1116](https://github.com/open-telemetry/opentelemetry-cpp/pull/1116)) -* [EXPORTER] Bugfix: Jaeger exporter: extend supported attributes types - ([#1106](https://github.com/open-telemetry/opentelemetry-cpp/pull/1106)) -* [EXPORTER] Fix otlp generates null span ids - ([#1113](https://github.com/open-telemetry/opentelemetry-cpp/pull/1113)) -* [EXPORTER] Jaeger bazel (Linux only) - ([#1077](https://github.com/open-telemetry/opentelemetry-cpp/pull/1077)) -* [DOCS] Add note on DLL support - ([#1137](https://github.com/open-telemetry/opentelemetry-cpp/pull/1137)) -* [DOCS] Improve the instructions for Bazel build - ([#1136](https://github.com/open-telemetry/opentelemetry-cpp/pull/1136)) -* [DOCS] Document dependencies - ([#1119](https://github.com/open-telemetry/opentelemetry-cpp/pull/1119)) -* [DOCS] Dockerfile for quick demo/troubleshooting purpose - ([#905](https://github.com/open-telemetry/opentelemetry-cpp/pull/905)) -* [TESTS] Fix data race in BM_ThreadYieldSpinLockThrashing - ([#1099](https://github.com/open-telemetry/opentelemetry-cpp/pull/1099)) -* [EXAMPLE] Otlp gRPC log example - ([#1083](https://github.com/open-telemetry/opentelemetry-cpp/pull/1083)) -* [BUILD] C++20 not Building with VS2019 - ([#1144](https://github.com/open-telemetry/opentelemetry-cpp/pull/1144)) -* [BUILD] Mark tags to bazel - targets([#1075](https://github.com/open-telemetry/opentelemetry-cpp/pull/1075)) - -## [1.1.0] 2021-11-19 - -* [BUILD] build release tarball when nlohmann-json not installed - ([#1074](https://github.com/open-telemetry/opentelemetry-cpp/pull/1074)) -* [SDK] Bugfix: regex is neither working on GCC 4.9.x - ([#1069](https://github.com/open-telemetry/opentelemetry-cpp/pull/1069)) -* [SDK] Improvement: span_id should not break strict aliasing. - ([#1068](https://github.com/open-telemetry/opentelemetry-cpp/pull/1068)) -* [EXAMPLE] OTLP HTTP log example - ([#1062](https://github.com/open-telemetry/opentelemetry-cpp/pull/1062)) -* [SDK] OTLP gRPC log export should fail after shutdown - ([#1064](https://github.com/open-telemetry/opentelemetry-cpp/pull/1064)) -* [BUILD] Building otlp exporter from the release tarball - ([#1056](https://github.com/open-telemetry/opentelemetry-cpp/pull/1056)) -* [METRICS] Move old metrics implementation to different directory, and rename - targets to \_deprecated - ([#1053](https://github.com/open-telemetry/opentelemetry-cpp/pull/1053)) -* [EXPORTER] Add OTLP/gRPC Log Exporter - ([#1048](https://github.com/open-telemetry/opentelemetry-cpp/pull/1048)) -* [EXPORTER] Prometheus Exporter - ([#1031](https://github.com/open-telemetry/opentelemetry-cpp/pull/1031)) -* [EXPORTER] Add OTLP/HTTP Log Exporter - ([#1030](https://github.com/open-telemetry/opentelemetry-cpp/pull/1030)) -* [SDK] fix: issue 368- consistent namespace scope resolution - ([#1008](https://github.com/open-telemetry/opentelemetry-cpp/pull/1008)) - -## [1.0.1] 2021-10-21 - -* [EXPORTER] Exports span attributes to ETW - ([#1021](https://github.com/open-telemetry/opentelemetry-cpp/pull/1021)) -* [BUILD] cmake: add FindThrift.cmake find module method for thrift - ([#1020](https://github.com/open-telemetry/opentelemetry-cpp/pull/1020)) -* [BUILD] Fix nlohmann_json package dependency - ([#1017](https://github.com/open-telemetry/opentelemetry-cpp/pull/1017)) -* [EXPORTER] Change OTLP/HTTP default port from 4317 to 4318 - ([#1018](https://github.com/open-telemetry/opentelemetry-cpp/pull/1018)) -* [EXPORTER] ETW Log Exporter - ([#1006](https://github.com/open-telemetry/opentelemetry-cpp/pull/1006)) -* [API] Adding new Logger:log() method - ([#1005](https://github.com/open-telemetry/opentelemetry-cpp/pull/1005)) -* [EXPORTER] Remove scheme from OTLP endpoint before passing to gRPC - ([#988](https://github.com/open-telemetry/opentelemetry-cpp/pull/988)) -* [BUILD] Update opentelemetry-proto for bazel build to 0.9.0 - ([#984](https://github.com/open-telemetry/opentelemetry-cpp/pull/984)) -* [BUILD] Cross compling grpc_cpp_plugin not found bug - ([#982](https://github.com/open-telemetry/opentelemetry-cpp/pull/982)) -* [EXPORTER] Support environment variables for both `OtlpGrpcExporter` and - `OtlpHttpExporter` - ([#983](https://github.com/open-telemetry/opentelemetry-cpp/pull/983)) -* [API/SDK] Add schema_url support to both Resource and InstrumentationLibrary - ([#979](https://github.com/open-telemetry/opentelemetry-cpp/pull/979)) -* [BUILD] Fix build issue where _memcpy_ was not declared in scope - ([#985](https://github.com/open-telemetry/opentelemetry-cpp/issues/985)) - -## [1.0.0] 2021-09-16 - -### API - -* Document DefaultSpan, remove DefaultTracer - ([#959](https://github.com/open-telemetry/opentelemetry-cpp/pull/959)) -* Separate baggage<->Context api from Baggage Propagator - ([#963](https://github.com/open-telemetry/opentelemetry-cpp/pull/963)) -* Remove unused public API to_span_ptr - ([#964](https://github.com/open-telemetry/opentelemetry-cpp/pull/964)) -* :collision: Make span context management public - ([#967](https://github.com/open-telemetry/opentelemetry-cpp/pull/967)) -* Support determining parent span from Context while creating new Span - ([#969](https://github.com/open-telemetry/opentelemetry-cpp/pull/969)) -* :collision: Traces: Add note on experimental semantic convention - implementation, prefix semantics headers with experimental tag - ([#970](https://github.com/open-telemetry/opentelemetry-cpp/pull/970)) -* Increment OPENTELEMETRY_ABI_VERSION_NO to 1 - ([#980](https://github.com/open-telemetry/opentelemetry-cpp/pull/980)) - -### SDK - -* Clean up `GetEnvironmentVariable` and remove unused variable under `NO_GETENV` - ([#976](https://github.com/open-telemetry/opentelemetry-cpp/pull/976)) -* :collision: Resources: Add note on experimental semantic convention - implementation, prefix semantics headers with experimental tag - ([#970](https://github.com/open-telemetry/opentelemetry-cpp/pull/970)) - -### OTLP Exporter - -* :bug: Ignore status description if status code is not Error - ([#962](https://github.com/open-telemetry/opentelemetry-cpp/pull/962)) -* :collision: Make Otlp exporter configuration environment variables - specs-compliant - ([#974](https://github.com/open-telemetry/opentelemetry-cpp/pull/974)) - -### Zipkin Exporter - -* :bug: Don't set parentId in case parentId is empty - ([#943](https://github.com/open-telemetry/opentelemetry-cpp/pull/943)) -* :rocket: Extend zipkin exporter with ability to provide headers - ([#951](https://github.com/open-telemetry/opentelemetry-cpp/pull/951)) - -### DOCS - -* :book: Add getting-started documentation for SDK: - ([#942](https://github.com/open-telemetry/opentelemetry-cpp/pull/942)) -* :book: Remove unnecessary spaces and spelling of gRPC in README - ([#965](https://github.com/open-telemetry/opentelemetry-cpp/pull/965)) - -### BUILD - -* Disable bazel build for gcc 4.8, upgrade versions for grpc(v1.39.1) and - bazel(4.2.0), document bazel support - ([#953](https://github.com/open-telemetry/opentelemetry-cpp/pull/953)) -* Move CMake config template to cmake folder - ([#958](https://github.com/open-telemetry/opentelemetry-cpp/pull/958)) -* Enable CMake to search the new package variable `_ROOT` - ([#975](https://github.com/open-telemetry/opentelemetry-cpp/pull/975)) -* :bug: Do not override CMAKE_CXX_STANDARD - ([#977](https://github.com/open-telemetry/opentelemetry-cpp/pull/977)) - -### :construction: Experiemental Features (Will change in future) - -* Semantic Conventions for traces - As the specs is still experimental, the - implementation will change in future. -* Semantic Convention for resource - As the specs is still experimental, the - implementation will change in future. -* Logs and Metrics API & SDK - These are not compliant, and are behind feature - flag. Not recommended to use for now. - -## [1.0.0-rc4] 2021-08-04 - -* [EXPORTER] `BREAKING CHANGE` Fix default HTTP port for OTLP HTTP Exporter - ([#939](https://github.com/open-telemetry/opentelemetry-cpp/pull/939)) -* [API] Fix timeout calculation for Tracer::Flush() and Tracer::Close() - ([#937](https://github.com/open-telemetry/opentelemetry-cpp/pull/937)) -* [API] Fix for Stack::Resize that new_capacity is not assigned to capacity_ - ([#934](https://github.com/open-telemetry/opentelemetry-cpp/pull/934)) -* [SDK] Fix race condition in circular buffer simulation test - ([#931](https://github.com/open-telemetry/opentelemetry-cpp/pull/931)) -* [EXPORTER] Fix error logging in Jaeger Exporter - ([#930](https://github.com/open-telemetry/opentelemetry-cpp/pull/930)) -* [BUILD] Use latest grpc version (v1.39.0) for cmake build of otlp exporter - ([#927](https://github.com/open-telemetry/opentelemetry-cpp/pull/927)) -* [EXPORTER] Add Jaeger Thrift HTTP exporter - ([#926](https://github.com/open-telemetry/opentelemetry-cpp/pull/926)) -* [SDK] Move env-var read logic to common dir, and optional reading of env-var - ([#924](https://github.com/open-telemetry/opentelemetry-cpp/pull/924)) -* [EXPORTER] Remove recordable header from CMake install rules for exporters - ([#923](https://github.com/open-telemetry/opentelemetry-cpp/pull/923)) -* [EXPORTER] `BREAKING CHANGE` Rename Recordable to JaegerRecordable in Jaeger - exporter - ([#919](https://github.com/open-telemetry/opentelemetry-cpp/pull/919)) -* [EXPORTER] `BREAKING CHANGE` Rename Jaeger exporter target - ([#918](https://github.com/open-telemetry/opentelemetry-cpp/pull/918)) -* [EXPORTER] Add Zipkin exporter example - ([#917](https://github.com/open-telemetry/opentelemetry-cpp/pull/917)) -* [EXPORTER] Bazel build for Zipkin exorter - ([#916](https://github.com/open-telemetry/opentelemetry-cpp/pull/916)) -* [BUILD] Allow to use local GSL - ([#915](https://github.com/open-telemetry/opentelemetry-cpp/pull/915)) -* [DOCS] Document vcpkg toolchain configuration - ([#913](https://github.com/open-telemetry/opentelemetry-cpp/pull/913)) -* [SDK] Fix for resource deletion after tracer provider shutdown - ([#911](https://github.com/open-telemetry/opentelemetry-cpp/pull/911)) -* [BUILD] Add bazel build for grpc example - ([#910](https://github.com/open-telemetry/opentelemetry-cpp/pull/910)) -* [EXPORTER] Add resource and instrumentation library support for - OStreamSpanExporter - ([#906](https://github.com/open-telemetry/opentelemetry-cpp/pull/906)) -* [API] Adding semantic-convention attributes for trace - ([#868](https://github.com/open-telemetry/opentelemetry-cpp/pull/868)) - -## [1.0.0-rc3] 2021-07-12 - -* [DOCS] Add doxygen reference docs for SDK - ([#902](https://github.com/open-telemetry/opentelemetry-cpp/pull/902)) -* [EXPORTER] Jaeger Exporter - Populate resource attributes into process tags in - Jaeger ([#897](https://github.com/open-telemetry/opentelemetry-cpp/pull/897)) -* [EXPORTER] Zipkin Exporter - Report Event timestamp into microseconds - ([#896](https://github.com/open-telemetry/opentelemetry-cpp/pull/896)) -* [EXPORTER] Jaeger Exporter - Handle span events - ([#895](https://github.com/open-telemetry/opentelemetry-cpp/pull/895)) -* [DOCS] Fix API docs for Scope object - ([#894](https://github.com/open-telemetry/opentelemetry-cpp/pull/894)) -* [BUILD] Fix Linking error for libcurl on some macOS environments - ([#893](https://github.com/open-telemetry/opentelemetry-cpp/pull/893)) -* [API] Context cleanup from Runtime Storage - ([#885](https://github.com/open-telemetry/opentelemetry-cpp/pull/885)) -* [DOCS] Document strategy to avoid conflict between two different versions of - Abseil ([#883](https://github.com/open-telemetry/opentelemetry-cpp/pull/883/)) -* [EXPORTER] ETW Exporter - Document example for ETW Exporter - ([#882](https://github.com/open-telemetry/opentelemetry-cpp/pull/882)) -* [SDK] Create Span with Valid spanId and traceId irrespective of Sampling - decision - ([#879](https://github.com/open-telemetry/opentelemetry-cpp/pull/879)) -* [EXPORTER] Jaeger Exporter - Rename bswap macros to avoid clash on some - systems ([#876](https://github.com/open-telemetry/opentelemetry-cpp/pull/876)) -* [API] Add Semantics Conventions attributes for Resources - ([#872](https://github.com/open-telemetry/opentelemetry-cpp/pull/872)) -* [BUILD] Use nlohmann-json from submodules if not already installed - ([#870](https://github.com/open-telemetry/opentelemetry-cpp/pull/870)) - -## [1.0.0-rc2] 2021-06-18 - -* [EXPORTER] Jaeger Exporter - Support for Instrumentation Library - ([#864](https://github.com/open-telemetry/opentelemetry-cpp/pull/864)) -* [TESTS] Adding benchmark tests for baggage api - ([#861](https://github.com/open-telemetry/opentelemetry-cpp/pull/861)) -* [BUILD] Fix for GCC9/C++20 Support for using STL for modern C++ features - ([#860](https://github.com/open-telemetry/opentelemetry-cpp/pull/860)) -* [TESTS] Adding benchmark tests for span create api - ([#856](https://github.com/open-telemetry/opentelemetry-cpp/pull/856)) -* [BUILD] Fix for using Abseil library for modern C++ features - ([#850](https://github.com/open-telemetry/opentelemetry-cpp/pull/850)) -* [BUILD] Fix issues with win32/x86 compilation - ([#847](https://github.com/open-telemetry/opentelemetry-cpp/pull/847)) -* [DOCS] Document OSS dependencies and their licenses - ([#844](https://github.com/open-telemetry/opentelemetry-cpp/pull/844)) -* [BUILD] Various fixes to build with Visual Studio 2015 - ([#840](https://github.com/open-telemetry/opentelemetry-cpp/pull/840)) -* [INSTRUMENTATION] HTTPClient: Change support for full URL argument - ([#833](https://github.com/open-telemetry/opentelemetry-cpp/pull/833)) -* [EXPORTER] Jaeger Exporter - fix endianness of Jaeger IDs for transmission - ([#832](https://github.com/open-telemetry/opentelemetry-cpp/pull/832)) -* [INSTRUMENTATION] fix protobuf compilation warning in gRPC example - ([#830](https://github.com/open-telemetry/opentelemetry-cpp/pull/830)) -* [EXPORTER] `BREAKING CHANGE` - Add OTLP/HTTP+JSON Protocol exporter; Rename - `OtlpExporter` to `OtlpGrpcExporter` - ([#810](https://github.com/open-telemetry/opentelemetry-cpp/pull/810)) - -## [1.0.0-rc1] 2021-06-04 - -* [BUILD] Enable Jaeger exporter build in Windows - ([#815](https://github.com/open-telemetry/opentelemetry-cpp/pull/815)) -* [DOCS] Versioning doc update to clarify release and versioning policy - ([#811](https://github.com/open-telemetry/opentelemetry-cpp/pull/811)) -* [LOGS] Move Logging implementation under feature-flag - ([#807](https://github.com/open-telemetry/opentelemetry-cpp/pull/807)) -* [BUILD] Filter metric headers files from `opentelemetry-api` and - `opentelemetry-sdk` targets if metrics feature-flag is disabled - ([#806](https://github.com/open-telemetry/opentelemetry-cpp/pull/806)) -* [BUILD] Fix install rule for ostream exporter, Jaeger, ETW, ElasticSearch - ([#805](Fix install rule for header files of ostream exporter)) -* [API/SDK] Switch from mpark::variant to absl::variant as default - ([#771](https://github.com/open-telemetry/opentelemetry-cpp/pull/771)) -* [API/SDK] Support `const char *` as acceptable data type for attributes and - resources - ([#771](https://github.com/open-telemetry/opentelemetry-cpp/pull/771)) -* [EXAMPLE] gRPC instrumentation example with context propagation - ([#729](https://github.com/open-telemetry/opentelemetry-cpp/pull/729)) - -## [0.7.0] 2021-05-26 - -* [METRICS] Move metrics api/sdk under preview feature flag - ([#745](https://github.com/open-telemetry/opentelemetry-cpp/pull/745)) -* [DOCS] Add instructions to build using Bazel - ([#747](https://github.com/open-telemetry/opentelemetry-cpp/pull/747)) -* [DOCS] Update copyright headers - ([#754](https://github.com/open-telemetry/opentelemetry-cpp/pull/754)) -* [EXPORTER] Populate resource to OTLP proto data - ([#758](https://github.com/open-telemetry/opentelemetry-cpp/pull/758)) -* [CI] Add CodeQL security scan CI workflow - ([#770](https://github.com/open-telemetry/opentelemetry-cpp/pull/770)) -* [BUILD] Enable building API only CMake Project - ([#778](https://github.com/open-telemetry/opentelemetry-cpp/pull/778)) -* [SDK] Fix for sampling of root span - ([#784](https://github.com/open-telemetry/opentelemetry-cpp/pull/784)) -* [CI] Add Jaeger exporter to CMake CI build - ([#786](https://github.com/open-telemetry/opentelemetry-cpp/pull/786)) -* [API] `BREAKING CHANGE` - Tracer::WithActiveSpan() to return Scope object - intead of unique_ptr - ([#788](https://github.com/open-telemetry/opentelemetry-cpp/pull/788)) -* [DOCS] Add docs for nested spans and context propagation in readthedocs - ([#792](https://github.com/open-telemetry/opentelemetry-cpp/pull/792)) -* [CI] Output verbose error for failed unit-test in CI - ([#796](https://github.com/open-telemetry/opentelemetry-cpp/pull/796)) - -## [0.6.0] 2021-05-11 - -* [EXPORTER] Add Jaeger exporter - ([#534](https://github.com/open-telemetry/opentelemetry-cpp/pull/534)) -* [SDK] Support multiple processors - ([#692](https://github.com/open-telemetry/opentelemetry-cpp/pull/692)) -* [SDK] Add instrumentation library and multiple tracer support - ([#693](https://github.com/open-telemetry/opentelemetry-cpp/pull/693)) -* [SDK] Resource integration with Exporters - ([#706](https://github.com/open-telemetry/opentelemetry-cpp/pull/706)) -* [EXAMPLE] Enhance existing http example with propagation - ([#727](https://github.com/open-telemetry/opentelemetry-cpp/pull/727)) - -## [0.5.0] 2021-04-26 - -* [SDK] Support custom span-id and trace-id generator - ([#681](https://github.com/open-telemetry/opentelemetry-cpp/pull/681)) -* [SDK] Add SpanContext (and TraceState) to Recordable - ([#667](https://github.com/open-telemetry/opentelemetry-cpp/pull/667)) -* [SDK] Global Propagator - ([#668](https://github.com/open-telemetry/opentelemetry-cpp/pull/668)) -* [SDK] Create SharedContext for updating span pipeline - ([#650](https://github.com/open-telemetry/opentelemetry-cpp/pull/650)) -* [API] Baggage implementation - ([#676](https://github.com/open-telemetry/opentelemetry-cpp/pull/676)) -* [API] Move class from opentelemetry::core namespace to opentelemetry::common - namespace - ([#686](https://github.com/open-telemetry/opentelemetry-cpp/pull/686)) - -## [0.4.0] 2021-04-12 - -* [EXPORTER] ETW Exporter enhancements - ([#519](https://github.com/open-telemetry/opentelemetry-cpp/pull/519)) -* [EXPORTER] Read Zipkin endpoint from environment variable. - ([#624](https://github.com/open-telemetry/opentelemetry-cpp/pull/624)) -* [EXPORTER] Split Zpages webserver hosting from Exporter - ([#626](https://github.com/open-telemetry/opentelemetry-cpp/pull/626)) -* [EXPORTER] ETW Exporter Usage Instructions - ([#628](https://github.com/open-telemetry/opentelemetry-cpp/pull/628)) -* [INSTRUMENTATION] HTTP Client/Server Instrumentation example - ([#632](https://github.com/open-telemetry/opentelemetry-cpp/pull/632)) -* [EXPORTER] Enable tls authentication for otlp grpc exporter ([#635](Enable tls - authentication for otlp grpc exporter)) -* [API] Refactoring trace_state to reuse common functionality in baggage - ([#638](https://github.com/open-telemetry/opentelemetry-cpp/pull/638/files)) - -## [0.3.0] 2021-03-19 - -* [EXPORTER] Added Zipkin Exporter. - ([#471](https://github.com/open-telemetry/opentelemetry-cpp/pull/471)) -* [API] Added Jaeger propagator. - ([#599](https://github.com/open-telemetry/opentelemetry-cpp/pull/599)) -* [PROPAGATOR] Added Composite Propagator - ([#597](https://github.com/open-telemetry/opentelemetry-cpp/pull/597)) -* [API] Propagate traceflag from parent - ([#603](https://github.com/open-telemetry/opentelemetry-cpp/pull/603)) -* [DOCS] Add sphinx support for api doc generation - ([595](https://github.com/open-telemetry/opentelemetry-cpp/pull/595)) -* [SDK] Add service.name if missing in Resource - ([#616](https://github.com/open-telemetry/opentelemetry-cpp/pull/616)) - -## [0.2.0] 2021-03-02 - -* [SDK] Added `ForceFlush` to `TracerProvider`. - ([#588](https://github.com/open-telemetry/opentelemetry-cpp/pull/588)). -* [SDK] Added Resource API. - ([#502](https://github.com/open-telemetry/opentelemetry-cpp/pull/502)) -* [API] Modified TraceState support for w3c trace context as per specs. -* [SDK] TraceState implementation as per spec - ([#551](https://github.com/open-telemetry/opentelemetry-cpp/pull/551)) -* [API] Added B3 Propagator. - ([#523](https://github.com/open-telemetry/opentelemetry-cpp/pull/523)) -* [Exporter] Added ETW Exporter. - ([#376](https://github.com/open-telemetry/opentelemetry-cpp/pull/376)) -* [CI] Enable cache for Bazel for faster builds. - ([#505](https://github.com/open-telemetry/opentelemetry-cpp/pull/505)) - -## [0.0.1] 2020-12-16 - -### Added - -* Trace API and SDK experimental -* OTLP Exporter - -### Changed - -### Removed diff --git a/ext/opentelemetry-cpp-1.21.0/CMakeLists.txt b/ext/opentelemetry-cpp-1.21.0/CMakeLists.txt deleted file mode 100644 index 4e65f0493..000000000 --- a/ext/opentelemetry-cpp-1.21.0/CMakeLists.txt +++ /dev/null @@ -1,927 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.14) - -# See https://cmake.org/cmake/help/latest/policy/CMP0074.html required by -# certain version of zlib which CURL depends on. -if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12") - cmake_policy(SET CMP0074 NEW) -endif() - -# Allow to use normal variable for option() -if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13") - cmake_policy(SET CMP0077 NEW) -endif() - -# Prefer CMAKE_MSVC_RUNTIME_LIBRARY if possible -if(POLICY CMP0091) - cmake_policy(SET CMP0091 NEW) -endif() - -if(POLICY CMP0092) - # https://cmake.org/cmake/help/latest/policy/CMP0092.html#policy:CMP0092 Make - # sure the /W3 is not removed from CMAKE_CXX_FLAGS since CMake 3.15 - cmake_policy(SET CMP0092 OLD) -endif() - -# MSVC RTTI flag /GR should not be not added to CMAKE_CXX_FLAGS by default. @see -# https://cmake.org/cmake/help/latest/policy/CMP0117.html -if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.20.0") - cmake_policy(SET CMP0117 NEW) -endif() - -project(opentelemetry-cpp) - -# Mark variables as used so cmake doesn't complain about them -mark_as_advanced(CMAKE_TOOLCHAIN_FILE) - -# Note: CMAKE_FIND_PACKAGE_PREFER_CONFIG requires cmake 3.15. Prefer cmake -# CONFIG search mode to find dependencies. This is important to properly find -# protobuf versions 3.22.0 and above due to the abseil-cpp dependency. -set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) - -# Don't use customized cmake modules if vcpkg is used to resolve dependence. -if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) - list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") -endif() - -if(EXISTS "${CMAKE_SOURCE_DIR}/third_party_release") - file(STRINGS "${CMAKE_SOURCE_DIR}/third_party_release" third_party_tags) - foreach(third_party ${third_party_tags}) - string(REGEX REPLACE "^[ ]+" "" third_party ${third_party}) - string(REGEX MATCH "^[^=]+" third_party_name ${third_party}) - string(REPLACE "${third_party_name}=" "" third_party_tag ${third_party}) - set(${third_party_name} "${third_party_tag}") - endforeach() -endif() - -if(DEFINED ENV{ARCH}) - # Architecture may be specified via ARCH environment variable - set(ARCH $ENV{ARCH}) -else() - # Autodetection logic that populates ARCH variable - if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*") - # Windows may report AMD64 even if target is 32-bit - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH x64) - elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(ARCH x86) - endif() - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*") - # Windows may report x86 even if target is 64-bit - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH x64) - elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(ARCH x86) - endif() - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "powerpc") - # AIX will report the processor as 'powerpc' even if building in 64-bit mode - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH ppc64) - else() - set(ARCH ppc32) - endif() - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES - "^(aarch64.*|AARCH64.*|arm64.*|ARM64.*)") - set(ARCH arm64) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)") - set(ARCH arm) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le") - set(ARCH ppc64le) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64") - set(ARCH ppc64) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(mips.*|MIPS.*)") - set(ARCH mips) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv.*|RISCV.*)") - set(ARCH riscv) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x.*|S390X.*)") - set(ARCH s390x) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(sparc.*|SPARC.*)") - set(ARCH sparc) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(loongarch.*|LOONGARCH.*)") - set(ARCH loongarch) - else() - message( - FATAL_ERROR - "opentelemetry-cpp: unrecognized target processor ${CMAKE_SYSTEM_PROCESSOR} configuration!" - ) - endif() -endif() -message(STATUS "Building for architecture ARCH=${ARCH}") - -# Autodetect vcpkg toolchain -if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) - set(CMAKE_TOOLCHAIN_FILE - "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - CACHE STRING "") -endif() - -if(VCPKG_CHAINLOAD_TOOLCHAIN_FILE) - include("${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}") -endif() - -option(WITH_ABI_VERSION_1 "ABI version 1" ON) -option(WITH_ABI_VERSION_2 "EXPERIMENTAL: ABI version 2 preview" OFF) - -file(READ "${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h" - OPENTELEMETRY_CPP_HEADER_VERSION_H) - -# -# We do not want to have WITH_ABI_VERSION = "1" or "2", and instead prefer two -# distinct flags, WITH_ABI_VERSION_1 and WITH_ABI_VERSION_2. -# -# This allows: -# -# * to have a specific option description for each ABI -# * to mark experimental/stable/deprecated on flags, for clarity -# * to search for exact abi usage move easily, discouraging: -# -# * cmake -DWITH_ABI_VERSION=${ARG} -# -# While not supported, having distinct WITH_ABI_VERSION_1 and WITH_ABI_VERSION_2 -# flags also opens the possibility to support multiple ABI concurrently, should -# that become necessary. -# -if(WITH_ABI_VERSION_1 AND WITH_ABI_VERSION_2) - # - # Only one ABI is supported in a build. - # - message( - FATAL_ERROR "Set either WITH_ABI_VERSION_1 or WITH_ABI_VERSION_2, not both") -endif() - -if(WITH_ABI_VERSION_2) - set(OPENTELEMETRY_ABI_VERSION_NO "2") -elseif(WITH_ABI_VERSION_1) - set(OPENTELEMETRY_ABI_VERSION_NO "1") -else() - if(OPENTELEMETRY_CPP_HEADER_VERSION_H MATCHES - "OPENTELEMETRY_ABI_VERSION_NO[ \t\r\n]+\"?([0-9]+)\"?") - math(EXPR OPENTELEMETRY_ABI_VERSION_NO ${CMAKE_MATCH_1}) - else() - message( - FATAL_ERROR - "OPENTELEMETRY_ABI_VERSION_NO not found on ${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h" - ) - endif() -endif() - -message(STATUS "OPENTELEMETRY_ABI_VERSION_NO=${OPENTELEMETRY_ABI_VERSION_NO}") - -if(OPENTELEMETRY_CPP_HEADER_VERSION_H MATCHES - "OPENTELEMETRY_VERSION[ \t\r\n]+\"?([^\"]+)\"?") - set(OPENTELEMETRY_VERSION ${CMAKE_MATCH_1}) -else() - message( - FATAL_ERROR - "OPENTELEMETRY_VERSION not found on ${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h" - ) -endif() - -message(STATUS "OPENTELEMETRY_VERSION=${OPENTELEMETRY_VERSION}") - -option(WITH_NO_DEPRECATED_CODE "Do not include deprecated code" OFF) - -set(WITH_STL - "OFF" - CACHE STRING "Which version of the Standard Library for C++ to use") - -option(WITH_GSL - "Whether to use Guidelines Support Library for C++ latest features" OFF) - -set(OPENTELEMETRY_INSTALL_default ON) -if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) - set(OPENTELEMETRY_INSTALL_default OFF) -endif() -option(OPENTELEMETRY_INSTALL "Whether to install opentelemetry targets" - ${OPENTELEMETRY_INSTALL_default}) - -include("${PROJECT_SOURCE_DIR}/cmake/tools.cmake") - -if(NOT WITH_STL STREQUAL "OFF") - # These definitions are needed for test projects that do not link against - # opentelemetry-api library directly. We ensure that variant implementation - # (absl::variant or std::variant) in variant unit test code is consistent with - # the global project build definitions. Optimize for speed to reduce the hops - if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - if(CMAKE_BUILD_TYPE MATCHES Debug) - # Turn off optimizations for DEBUG - set(MSVC_CXX_OPT_FLAG "/Od") - else() - string(REGEX MATCH "\/O" result ${CMAKE_CXX_FLAGS}) - if(NOT ${result} MATCHES "\/O") - set(MSVC_CXX_OPT_FLAG "/O2") - endif() - endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MSVC_CXX_OPT_FLAG}") - endif() -endif() - -option(WITH_OTLP_RETRY_PREVIEW - "Whether to enable experimental retry functionality" OFF) - -option(WITH_OTLP_GRPC_SSL_MTLS_PREVIEW - "Whether to enable mTLS support fro gRPC" OFF) - -option(WITH_OTLP_GRPC "Whether to include the OTLP gRPC exporter in the SDK" - OFF) - -option(WITH_OTLP_HTTP "Whether to include the OTLP http exporter in the SDK" - OFF) - -option(WITH_OTLP_FILE "Whether to include the OTLP file exporter in the SDK" - OFF) - -option( - WITH_OTLP_HTTP_COMPRESSION - "Whether to include gzip compression for the OTLP http exporter in the SDK" - OFF) - -option(WITH_CURL_LOGGING "Whether to enable select CURL verbosity in OTel logs" - OFF) - -option(WITH_ZIPKIN "Whether to include the Zipkin exporter in the SDK" OFF) - -option(WITH_PROMETHEUS "Whether to include the Prometheus Client in the SDK" - OFF) - -option(WITH_ELASTICSEARCH - "Whether to include the Elasticsearch Client in the SDK" OFF) - -option(WITH_NO_GETENV "Whether the platform supports environment variables" OFF) - -option(BUILD_TESTING "Whether to enable tests" ON) - -option(WITH_BENCHMARK "Whether to build benchmark program" ON) - -option(BUILD_W3CTRACECONTEXT_TEST "Whether to build w3c trace context" OFF) - -option(OTELCPP_MAINTAINER_MODE "Build in maintainer mode (-Wall -Werror)" OFF) - -option(WITH_OPENTRACING "Whether to include the Opentracing shim" OFF) - -option(OTELCPP_VERSIONED_LIBS "Whether to generate the versioned shared libs" - OFF) - -# -# This option is experimental, subject to change in the spec: -# -# * https://github.com/open-telemetry/opentelemetry-specification/issues/2232 -# -option(WITH_REMOVE_METER_PREVIEW - "EXPERIMENTAL, ABI BREAKING: Allow to remove a meter" OFF) - -if(OTELCPP_VERSIONED_LIBS AND NOT BUILD_SHARED_LIBS) - message(FATAL_ERROR "OTELCPP_VERSIONED_LIBS=ON requires BUILD_SHARED_LIBS=ON") -endif() - -if(WIN32) - option(WITH_ETW "Whether to include the ETW Exporter in the SDK" ON) -else() - if(DEFINED (WITH_ETW)) - message(FATAL_ERROR "WITH_ETW is only supported on Windows") - endif() -endif(WIN32) - -# Do not convert deprecated message to error -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") - add_compile_options(-Wno-error=deprecated-declarations) -endif() - -option( - WITH_API_ONLY - "Only build the API (use as a header-only library). Overrides WITH_EXAMPLES and all options to enable exporters" - OFF) -option(WITH_EXAMPLES "Whether to build examples" ON) - -# This requires CURL, OFF by default. -option( - WITH_EXAMPLES_HTTP - "Whether to build http client/server examples. Requires WITH_EXAMPLES and CURL" - OFF) - -option(WITH_FUNC_TESTS "Whether to build functional tests" ON) - -option(WITH_ASYNC_EXPORT_PREVIEW "Whether to enable async export" OFF) - -# Exemplar specs status is experimental, so behind feature flag by default -option(WITH_METRICS_EXEMPLAR_PREVIEW - "Whether to enable exemplar within metrics" OFF) - -# Experimental, so behind feature flag by default -option(WITH_THREAD_INSTRUMENTATION_PREVIEW - "Whether to enable thread instrumentation" OFF) - -option(OPENTELEMETRY_SKIP_DYNAMIC_LOADING_TESTS - "Whether to build test libraries that are always linked as shared libs" - OFF) - -# -# Verify options dependencies -# - -if(WITH_EXAMPLES_HTTP AND NOT WITH_EXAMPLES) - message(FATAL_ERROR "WITH_EXAMPLES_HTTP=ON requires WITH_EXAMPLES=ON") -endif() - -find_package(Threads) - -function(install_windows_deps) - # Bootstrap vcpkg from CMake and auto-install deps in case if we are missing - # deps on Windows. Respect the target architecture variable. - set(VCPKG_TARGET_ARCHITECTURE - ${ARCH} - PARENT_SCOPE) - message(STATUS "Installing build tools and dependencies...") - set(ENV{ARCH} ${ARCH}) - execute_process( - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/setup-buildtools.cmd) - set(CMAKE_TOOLCHAIN_FILE - ${CMAKE_CURRENT_SOURCE_DIR}/tools/vcpkg/scripts/buildsystems/vcpkg.cmake - CACHE FILEPATH "") - message( - STATUS - "Make sure that vcpkg.cmake is set as the CMAKE_TOOLCHAIN_FILE at the START of the cmake build process! - Can be command-line arg (cmake -DCMAKE_TOOLCHAIN_FILE=...) or set in your editor of choice." - ) - -endfunction() - -function(set_target_version target_name) - if(OTELCPP_VERSIONED_LIBS) - set_target_properties( - ${target_name} PROPERTIES VERSION ${OPENTELEMETRY_VERSION} - SOVERSION ${OPENTELEMETRY_ABI_VERSION_NO}) - endif() -endfunction() - -if(MSVC) - # Options for Visual C++ compiler: /Zc:__cplusplus - report an updated value - # for recent C++ language standards. Without this option MSVC returns the - # value of __cplusplus="199711L" - if(MSVC_VERSION GREATER 1900) - # __cplusplus flag is not supported by Visual Studio 2015 - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus") - endif() -endif() - -# include GNUInstallDirs before include cmake/opentelemetry-proto.cmake because -# opentelemetry-proto installs targets to the location variables defined in -# GNUInstallDirs. -include(GNUInstallDirs) - -if(WITH_PROMETHEUS) - find_package(prometheus-cpp CONFIG QUIET) - if(NOT prometheus-cpp_FOUND) - message(STATUS "Trying to use local prometheus-cpp from submodule") - if(EXISTS ${PROJECT_SOURCE_DIR}/third_party/prometheus-cpp/.git) - set(SAVED_ENABLE_TESTING ${ENABLE_TESTING}) - set(SAVED_CMAKE_CXX_CLANG_TIDY ${CMAKE_CXX_CLANG_TIDY}) - set(SAVED_CMAKE_CXX_INCLUDE_WHAT_YOU_USE - ${CMAKE_CXX_INCLUDE_WHAT_YOU_USE}) - set(ENABLE_TESTING OFF) - set(CMAKE_CXX_CLANG_TIDY "") - set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "") - add_subdirectory(third_party/prometheus-cpp) - set(ENABLE_TESTING ${SAVED_ENABLE_TESTING}) - set(CMAKE_CXX_CLANG_TIDY ${SAVED_CMAKE_CXX_CLANG_TIDY}) - set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE - ${SAVED_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}) - - # Get the version of the prometheus-cpp submodule - find_package(Git QUIET) - if(Git_FOUND) - execute_process( - COMMAND ${GIT_EXECUTABLE} describe --tags --always - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/third_party/prometheus-cpp - OUTPUT_VARIABLE prometheus-cpp_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REGEX REPLACE "^v" "" prometheus-cpp_VERSION - "${prometheus-cpp_VERSION}") - endif() - - message( - STATUS - "Using local prometheus-cpp from submodule. Version = ${prometheus-cpp_VERSION}" - ) - else() - message( - FATAL_ERROR - "\nprometheus-cpp package was not found. Please either provide it manually or clone with submodules. " - "To initialize, fetch and checkout any nested submodules, you can use the following command:\n" - "git submodule update --init --recursive") - endif() - else() - message(STATUS "Using external prometheus-cpp") - endif() -endif() - -if(WITH_OTLP_GRPC - OR WITH_OTLP_HTTP - OR WITH_OTLP_FILE) - - # Including the CMakeFindDependencyMacro resolves an error from - # gRPCConfig.cmake on some grpc versions. See - # https://github.com/grpc/grpc/pull/33361 for more details. - include(CMakeFindDependencyMacro) - - # Protobuf 3.22+ depends on abseil-cpp and must be found using the cmake - # find_package CONFIG search mode. The following attempts to find Protobuf - # using the CONFIG mode first, and if not found, falls back to the MODULE - # mode. See https://gitlab.kitware.com/cmake/cmake/-/issues/24321 for more - # details. - find_package(Protobuf CONFIG) - if(NOT Protobuf_FOUND) - find_package(Protobuf MODULE) - if(Protobuf_FOUND AND Protobuf_VERSION VERSION_GREATER_EQUAL "3.22.0") - message( - WARNING - "Found Protobuf version ${Protobuf_VERSION} using MODULE mode. " - "Linking errors may occur. Protobuf 3.22+ depends on abseil-cpp " - "and should be found using the CONFIG mode.") - endif() - endif() - - if(WITH_OTLP_GRPC) - find_package(gRPC CONFIG) - endif() - if((NOT Protobuf_FOUND) OR (WITH_OTLP_GRPC AND NOT gRPC_FOUND)) - if(WIN32 AND (NOT DEFINED CMAKE_TOOLCHAIN_FILE)) - install_windows_deps() - endif() - - if(WIN32 AND (NOT DEFINED CMAKE_TOOLCHAIN_FILE)) - message(FATAL_ERROR "Windows dependency installation failed!") - endif() - if(WIN32) - include(${CMAKE_TOOLCHAIN_FILE}) - endif() - - if(NOT Protobuf_FOUND) - find_package(Protobuf CONFIG REQUIRED) - endif() - if(NOT gRPC_FOUND AND WITH_OTLP_GRPC) - find_package(gRPC CONFIG) - endif() - if(WIN32) - # Always use x64 protoc.exe - if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}") - set(Protobuf_PROTOC_EXECUTABLE - ${CMAKE_CURRENT_SOURCE_DIR}/tools/vcpkg/packages/protobuf_x64-windows/tools/protobuf/protoc.exe - ) - endif() - endif() - endif() - # Latest Protobuf imported targets and without legacy module support - if(TARGET protobuf::protoc) - if(CMAKE_CROSSCOMPILING AND Protobuf_PROTOC_EXECUTABLE) - set(PROTOBUF_PROTOC_EXECUTABLE ${Protobuf_PROTOC_EXECUTABLE}) - else() - project_build_tools_get_imported_location(PROTOBUF_PROTOC_EXECUTABLE - protobuf::protoc) - # If protobuf::protoc is not a imported target, then we use the target - # directly for fallback - if(NOT PROTOBUF_PROTOC_EXECUTABLE) - set(PROTOBUF_PROTOC_EXECUTABLE protobuf::protoc) - endif() - endif() - elseif(Protobuf_PROTOC_EXECUTABLE) - # Some versions of FindProtobuf.cmake uses mixed case instead of uppercase - set(PROTOBUF_PROTOC_EXECUTABLE ${Protobuf_PROTOC_EXECUTABLE}) - endif() - include(CMakeDependentOption) - - message(STATUS "PROTOBUF_PROTOC_EXECUTABLE=${PROTOBUF_PROTOC_EXECUTABLE}") - set(SAVED_CMAKE_CXX_CLANG_TIDY ${CMAKE_CXX_CLANG_TIDY}) - set(CMAKE_CXX_CLANG_TIDY "") - include(cmake/opentelemetry-proto.cmake) - set(CMAKE_CXX_CLANG_TIDY ${SAVED_CMAKE_CXX_CLANG_TIDY}) -endif() - -# -# Do we need HTTP CLIENT CURL ? -# - -if(WITH_OTLP_HTTP - OR WITH_ELASTICSEARCH - OR WITH_ZIPKIN - OR BUILD_W3CTRACECONTEXT_TEST - OR WITH_EXAMPLES_HTTP) - set(WITH_HTTP_CLIENT_CURL ON) -else() - set(WITH_HTTP_CLIENT_CURL OFF) -endif() - -# -# Do we need CURL ? -# - -if((NOT WITH_API_ONLY) AND WITH_HTTP_CLIENT_CURL) - # No specific version required. - find_package(CURL REQUIRED) - # Set the CURL_VERSION from the legacy CURL_VERSION_STRING Required for CMake - # versions below 4.0 - if(NOT DEFINED CURL_VERSION AND DEFINED CURL_VERSION_STRING) - set(CURL_VERSION ${CURL_VERSION_STRING}) - endif() -endif() - -# -# Do we need ZLIB ? -# - -if((NOT WITH_API_ONLY) - AND WITH_HTTP_CLIENT_CURL - AND WITH_OTLP_HTTP_COMPRESSION) - # No specific version required. - find_package(ZLIB REQUIRED) - # Set the ZLIB_VERSION from the legacy ZLIB_VERSION_STRING Required for CMake - # versions below 3.26 - if(NOT DEFINED ZLIB_VERSION AND DEFINED ZLIB_VERSION_STRING) - set(ZLIB_VERSION ${ZLIB_VERSION_STRING}) - endif() -endif() - -# -# Do we need NLOHMANN_JSON ? -# - -if(WITH_ELASTICSEARCH - OR WITH_ZIPKIN - OR WITH_OTLP_HTTP - OR WITH_OTLP_FILE - OR BUILD_W3CTRACECONTEXT_TEST - OR WITH_ETW) - set(USE_NLOHMANN_JSON ON) -else() - set(USE_NLOHMANN_JSON OFF) -endif() - -if((NOT WITH_API_ONLY) AND USE_NLOHMANN_JSON) - include(cmake/nlohmann-json.cmake) -endif() - -if(OTELCPP_MAINTAINER_MODE) - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - message(STATUS "Building with gcc in maintainer mode.") - - add_compile_options(-Wall) - add_compile_options(-Werror) - add_compile_options(-Wextra) - - # Tested with GCC 9.4 on github. - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 9.4) - message(STATUS "Building with additional warnings for gcc.") - - # Relaxed warnings - - # Enforced warnings - - # C++ options only - add_compile_options($<$,CXX>:-Wextra-semi>) - add_compile_options( - $<$,CXX>:-Woverloaded-virtual>) - add_compile_options( - $<$,CXX>:-Wsuggest-override>) - add_compile_options( - $<$,CXX>:-Wold-style-cast>) - - # C and C++ - add_compile_options(-Wcast-qual) - add_compile_options(-Wformat-security) - add_compile_options(-Wlogical-op) - add_compile_options(-Wmissing-include-dirs) - add_compile_options(-Wstringop-truncation) - add_compile_options(-Wundef) - add_compile_options(-Wvla) - endif() - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - message(STATUS "Building with clang in maintainer mode.") - - add_compile_options(-Wall) - add_compile_options(-Werror) - add_compile_options(-Wextra) - - # Tested with Clang 11.0 on github. - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) - message(STATUS "Building with additional warnings for clang.") - - # Relaxed warnings - add_compile_options(-Wno-error=unused-private-field) - - # Enforced warnings - add_compile_options(-Wcast-qual) - add_compile_options(-Wconditional-uninitialized) - add_compile_options(-Wextra-semi) - add_compile_options(-Wformat-security) - add_compile_options(-Wheader-hygiene) - add_compile_options(-Winconsistent-missing-destructor-override) - add_compile_options(-Winconsistent-missing-override) - add_compile_options(-Wnewline-eof) - add_compile_options(-Wnon-virtual-dtor) - add_compile_options(-Woverloaded-virtual) - add_compile_options(-Wrange-loop-analysis) - add_compile_options(-Wundef) - add_compile_options(-Wundefined-reinterpret-cast) - add_compile_options(-Wvla) - add_compile_options(-Wold-style-cast) - endif() - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - message(STATUS "Building with msvc in maintainer mode.") - - add_compile_options(/WX) - add_compile_options(/W4) - - # Relaxed warnings - add_compile_options(/wd4100) - add_compile_options(/wd4125) - add_compile_options(/wd4566) - add_compile_options(/wd4127) - add_compile_options(/wd4512) - add_compile_options(/wd4267) - add_compile_options(/wd4996) - - # Enforced warnings - add_compile_options(/we4265) # 'class': class has virtual functions, but - # destructor is not virtual - add_compile_options(/we5204) # A class with virtual functions has - # non-virtual trivial destructor. - - elseif() - message(FATAL_ERROR "Building with unknown compiler in maintainer mode.") - endif() -endif(OTELCPP_MAINTAINER_MODE) - -list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}") - -include(CTest) -if(BUILD_TESTING) - if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a) - # Prefer GTest from build tree. GTest is not always working with - # CMAKE_PREFIX_PATH - set(GTEST_INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googletest/include - ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googlemock/include) - if(TARGET gtest) - set(GTEST_BOTH_LIBRARIES gtest gtest_main) - else() - set(GTEST_BOTH_LIBRARIES ${CMAKE_BINARY_DIR}/lib/libgtest.a - ${CMAKE_BINARY_DIR}/lib/libgtest_main.a) - endif() - elseif(WIN32) - # Make sure we are always bootsrapped with vcpkg on Windows - find_package(GTest) - if(NOT (GTEST_FOUND OR GTest_FOUND)) - if(DEFINED CMAKE_TOOLCHAIN_FILE) - message( - FATAL_ERROR - "Pleaes install GTest with the CMAKE_TOOLCHAIN_FILE at ${CMAKE_TOOLCHAIN_FILE}" - ) - else() - install_windows_deps() - include(${CMAKE_TOOLCHAIN_FILE}) - find_package(GTest REQUIRED) - endif() - endif() - else() - # Prefer GTest installed by OS distro, brew or vcpkg package manager - find_package(GTest REQUIRED) - endif() - if(NOT GTEST_BOTH_LIBRARIES) - # New GTest package names - if(TARGET GTest::gtest) - set(GTEST_BOTH_LIBRARIES GTest::gtest GTest::gtest_main) - elseif(TARGET GTest::GTest) - set(GTEST_BOTH_LIBRARIES GTest::GTest GTest::Main) - endif() - endif() - if(GTEST_INCLUDE_DIRS) - include_directories(SYSTEM ${GTEST_INCLUDE_DIRS}) - endif() - message(STATUS "GTEST_INCLUDE_DIRS = ${GTEST_INCLUDE_DIRS}") - message(STATUS "GTEST_BOTH_LIBRARIES = ${GTEST_BOTH_LIBRARIES}") - - # Try to find gmock - if(NOT GMOCK_LIB AND TARGET GTest::gmock) - set(GMOCK_LIB GTest::gmock) - elseif(MSVC) - # Explicitly specify that we consume GTest from shared library. The rest of - # code logic below determines whether we link Release or Debug flavor of the - # library. These flavors have different prefix on Windows, gmock and gmockd - # respectively. - add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) - if(GMOCK_LIB) - # unset GMOCK_LIB to force find_library to redo the lookup, as the cached - # entry could cause linking to incorrect flavor of gmock and leading to - # runtime error. - unset(GMOCK_LIB CACHE) - endif() - endif() - if(NOT GMOCK_LIB) - if(MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") - find_library(GMOCK_LIB gmockd PATH_SUFFIXES lib) - else() - find_library(GMOCK_LIB gmock PATH_SUFFIXES lib) - endif() - # Reset GMOCK_LIB if it was not found, or some target may link - # GMOCK_LIB-NOTFOUND - if(NOT GMOCK_LIB) - unset(GMOCK_LIB) - unset(GMOCK_LIB CACHE) - endif() - endif() - - enable_testing() - if(WITH_BENCHMARK) - # Benchmark respects the CMAKE_PREFIX_PATH - find_package(benchmark CONFIG REQUIRED) - endif() -endif() - -# Record build config and versions -message(STATUS "---------------------------------------------") -message(STATUS "build settings") -message(STATUS "---------------------------------------------") -message(STATUS "OpenTelemetry: ${OPENTELEMETRY_VERSION}") -message(STATUS "OpenTelemetry ABI: ${OPENTELEMETRY_ABI_VERSION_NO}") -message(STATUS "ARCH: ${ARCH}") -message(STATUS "CXX: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") -message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") -message(STATUS "CXXFLAGS: ${CMAKE_CXX_FLAGS}") -message(STATUS "CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}") -message(STATUS "CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}") -message(STATUS "BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") - -message(STATUS "---------------------------------------------") -message(STATUS "opentelemetry-cpp build options") -message(STATUS "---------------------------------------------") -message(STATUS "WITH_API_ONLY: ${WITH_API_ONLY}") -message(STATUS "WITH_NO_DEPRECATED_CODE: ${WITH_NO_DEPRECATED_CODE}") -message(STATUS "WITH_ABI_VERSION_1: ${WITH_ABI_VERSION_1}") -message(STATUS "WITH_ABI_VERSION_2: ${WITH_ABI_VERSION_2}") -message(STATUS "OTELCPP_VERSIONED_LIBS: ${OTELCPP_VERSIONED_LIBS}") -message(STATUS "OTELCPP_MAINTAINER_MODE: ${OTELCPP_MAINTAINER_MODE}") -message(STATUS "WITH_STL: ${WITH_STL}") -message(STATUS "WITH_GSL: ${WITH_GSL}") -message(STATUS "WITH_NO_GETENV: ${WITH_NO_GETENV}") - -message(STATUS "---------------------------------------------") -message(STATUS "opentelemetry-cpp cmake component options") -message(STATUS "---------------------------------------------") -message(STATUS "WITH_OTLP_GRPC: ${WITH_OTLP_GRPC}") -message(STATUS "WITH_OTLP_HTTP: ${WITH_OTLP_HTTP}") -message(STATUS "WITH_OTLP_FILE: ${WITH_OTLP_FILE}") -message(STATUS "WITH_HTTP_CLIENT_CURL: ${WITH_HTTP_CLIENT_CURL}") -message(STATUS "WITH_ZIPKIN: ${WITH_ZIPKIN}") -message(STATUS "WITH_PROMETHEUS: ${WITH_PROMETHEUS}") -message(STATUS "WITH_ELASTICSEARCH: ${WITH_ELASTICSEARCH}") -message(STATUS "WITH_OPENTRACING: ${WITH_OPENTRACING}") -message(STATUS "WITH_ETW: ${WITH_ETW}") -message(STATUS "OPENTELEMETRY_BUILD_DLL: ${OPENTELEMETRY_BUILD_DLL}") - -message(STATUS "---------------------------------------------") -message(STATUS "feature preview options") -message(STATUS "---------------------------------------------") -message(STATUS "WITH_ASYNC_EXPORT_PREVIEW: ${WITH_ASYNC_EXPORT_PREVIEW}") -message( - STATUS - "WITH_THREAD_INSTRUMENTATION_PREVIEW: ${WITH_THREAD_INSTRUMENTATION_PREVIEW}" -) -message( - STATUS "WITH_METRICS_EXEMPLAR_PREVIEW: ${WITH_METRICS_EXEMPLAR_PREVIEW}") -message(STATUS "WITH_REMOVE_METER_PREVIEW: ${WITH_REMOVE_METER_PREVIEW}") -message( - STATUS "WITH_OTLP_GRPC_SSL_MTLS_PREVIEW: ${WITH_OTLP_GRPC_SSL_MTLS_PREVIEW}") -message(STATUS "WITH_OTLP_RETRY_PREVIEW: ${WITH_OTLP_RETRY_PREVIEW}") -message(STATUS "---------------------------------------------") -message(STATUS "third-party options") -message(STATUS "---------------------------------------------") -message(STATUS "WITH_NLOHMANN_JSON: ${USE_NLOHMANN_JSON}") -message(STATUS "WITH_CURL_LOGGING: ${WITH_CURL_LOGGING}") -message(STATUS "WITH_OTLP_HTTP_COMPRESSION: ${WITH_OTLP_HTTP_COMPRESSION}") -message(STATUS "---------------------------------------------") -message(STATUS "examples and test options") -message(STATUS "---------------------------------------------") -message(STATUS "WITH_BENCHMARK: ${WITH_BENCHMARK}") -message(STATUS "WITH_EXAMPLES: ${WITH_EXAMPLES}") -message(STATUS "WITH_EXAMPLES_HTTP: ${WITH_EXAMPLES_HTTP}") -message(STATUS "WITH_FUNC_TESTS: ${WITH_FUNC_TESTS}") -message(STATUS "BUILD_W3CTRACECONTEXT_TEST: ${BUILD_W3CTRACECONTEXT_TEST}") -message(STATUS "BUILD_TESTING: ${BUILD_TESTING}") -message(STATUS "---------------------------------------------") -message(STATUS "versions") -message(STATUS "---------------------------------------------") -message(STATUS "CMake: ${CMAKE_VERSION}") -message(STATUS "GTest: ${GTest_VERSION}") -message(STATUS "benchmark: ${benchmark_VERSION}") -if(WITH_GSL) - message(STATUS "GSL: ${GSL_VERSION}") -endif() -if(absl_FOUND) - message(STATUS "Abseil: ${absl_VERSION}") -endif() -if(Protobuf_FOUND) - message(STATUS "Protobuf: ${Protobuf_VERSION}") -endif() -if(gRPC_FOUND) - message(STATUS "gRPC: ${gRPC_VERSION}") -endif() -if(CURL_FOUND) - message(STATUS "CURL: ${CURL_VERSION}") -endif() -if(ZLIB_FOUND) - message(STATUS "ZLIB: ${ZLIB_VERSION}") -endif() -if(USE_NLOHMANN_JSON) - message(STATUS "nlohmann-json: ${nlohmann_json_VERSION}") -endif() -if(prometheus-cpp_FOUND) - message(STATUS "prometheus-cpp: ${prometheus-cpp_VERSION}") -endif() -message(STATUS "---------------------------------------------") - -include("${PROJECT_SOURCE_DIR}/cmake/otel-install-functions.cmake") - -include(CMakePackageConfigHelpers) - -if(DEFINED OPENTELEMETRY_BUILD_DLL) - if(NOT WIN32) - message(FATAL_ERROR "Build DLL is only supported on Windows!") - endif() - if(NOT MSVC) - message(WARNING "Build DLL is supposed to work with MSVC!") - endif() - if(WITH_STL) - message( - WARNING "Build DLL with C++ STL could cause binary incompatibility!") - endif() - add_definitions(-DOPENTELEMETRY_BUILD_EXPORT_DLL) -endif() - -add_subdirectory(api) - -if(WITH_OPENTRACING) - find_package(OpenTracing CONFIG QUIET) - if(NOT OpenTracing_FOUND) - set(OPENTRACING_DIR "third_party/opentracing-cpp") - message(STATUS "Trying to use local ${OPENTRACING_DIR} from submodule") - if(EXISTS "${PROJECT_SOURCE_DIR}/${OPENTRACING_DIR}/.git") - set(SAVED_BUILD_TESTING ${BUILD_TESTING}) - set(BUILD_TESTING OFF) - set(SAVED_CMAKE_CXX_INCLUDE_WHAT_YOU_USE - ${CMAKE_CXX_INCLUDE_WHAT_YOU_USE}) - set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "") - add_subdirectory(${OPENTRACING_DIR}) - set(BUILD_TESTING ${SAVED_BUILD_TESTING}) - set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE - ${SAVED_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}) - else() - message( - FATAL_ERROR - "\nopentracing-cpp package was not found. Please either provide it manually or clone with submodules. " - "To initialize, fetch and checkout any nested submodules, you can use the following command:\n" - "git submodule update --init --recursive") - endif() - else() - message(STATUS "Using external opentracing-cpp") - endif() - add_subdirectory(opentracing-shim) -endif() - -if(NOT WITH_API_ONLY) - set(BUILD_TESTING ${BUILD_TESTING}) - - add_subdirectory(sdk) - add_subdirectory(ext) - add_subdirectory(exporters) - - if(BUILD_TESTING) - add_subdirectory(test_common) - endif() - if(WITH_EXAMPLES) - add_subdirectory(examples) - endif() - if(WITH_FUNC_TESTS) - add_subdirectory(functional) - endif() -endif() - -include(cmake/opentelemetry-build-external-component.cmake) -include(cmake/patch-imported-config.cmake) - -if(OPENTELEMETRY_INSTALL) - # Install the cmake config and version files - otel_install_cmake_config() - - # Install the components and associated files - otel_install_components() - - # Install the thirdparty dependency definition file - otel_install_thirdparty_definitions() - - if(BUILD_PACKAGE) - include(cmake/package.cmake) - include(CPack) - endif() -endif() diff --git a/ext/opentelemetry-cpp-1.21.0/CMakeSettings.json b/ext/opentelemetry-cpp-1.21.0/CMakeSettings.json deleted file mode 100644 index 02d068a3a..000000000 --- a/ext/opentelemetry-cpp-1.21.0/CMakeSettings.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "configurations": [ - { - "name": "nostd-x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ - "msvc_x64_x64" - ], - "buildRoot": "${projectDir}\\out\\vs2019\\${name}", - "installRoot": "${projectDir}\\out\\vs2019\\${name}\\install", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "variables": [ - { - "name": "WITH_OTLP_GRPC", - "value": "True", - "type": "BOOL" - }, - { - "name": "WITH_EXAMPLES", - "value": "true", - "type": "BOOL" - } - ] - }, - { - "name": "nostd-x64-Release", - "generator": "Ninja", - "configurationType": "Release", - "inheritEnvironments": [ - "msvc_x64_x64" - ], - "buildRoot": "${projectDir}\\out\\vs2019\\${name}", - "installRoot": "${projectDir}\\out\\vs2019\\${name}\\install", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "cmakeToolchain": "", - "variables": [ - { - "name": "WITH_OTLP_GRPC", - "value": "True", - "type": "BOOL" - }, - { - "name": "WITH_EXAMPLES", - "value": "true", - "type": "BOOL" - } - ] - }, - { - "name": "stdlib-x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ - "msvc_x64_x64" - ], - "buildRoot": "${projectDir}\\out\\vs2019\\${name}", - "installRoot": "${projectDir}\\out\\vs2019\\${name}\\install", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "variables": [ - { - "name": "WITH_STL", - "value": "True", - "type": "BOOL" - }, - { - "name": "WITH_OTLP_GRPC", - "value": "True", - "type": "BOOL" - }, - { - "name": "WITH_EXAMPLES", - "value": "true", - "type": "BOOL" - }, - { - "name": "WITH_PROMETHEUS", - "value": "True", - "type": "BOOL" - } - ] - }, - { - "name": "stdlib-x64-Release", - "generator": "Ninja", - "configurationType": "Release", - "inheritEnvironments": [ - "msvc_x64_x64" - ], - "buildRoot": "${projectDir}\\out\\vs2019\\${name}", - "installRoot": "${projectDir}\\out\\vs2019\\${name}\\install", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "cmakeToolchain": "", - "variables": [ - { - "name": "WITH_STL", - "value": "True", - "type": "BOOL" - }, - { - "name": "WITH_OTLP_GRPC", - "value": "True", - "type": "BOOL" - }, - { - "name": "WITH_EXAMPLES", - "value": "true", - "type": "BOOL" - }, - { - "name": "WITH_PROMETHEUS", - "value": "True", - "type": "BOOL" - } - ] - } - ] -} diff --git a/ext/opentelemetry-cpp-1.21.0/CODE_OF_CONDUCT.md b/ext/opentelemetry-cpp-1.21.0/CODE_OF_CONDUCT.md deleted file mode 100644 index fee94ae58..000000000 --- a/ext/opentelemetry-cpp-1.21.0/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,3 +0,0 @@ -# OpenTelemetry Community Code of Conduct - -OpenTelemetry follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). diff --git a/ext/opentelemetry-cpp-1.21.0/CONTRIBUTING.md b/ext/opentelemetry-cpp-1.21.0/CONTRIBUTING.md deleted file mode 100644 index fda99e097..000000000 --- a/ext/opentelemetry-cpp-1.21.0/CONTRIBUTING.md +++ /dev/null @@ -1,322 +0,0 @@ -# Contributing to opentelemetry-cpp - -The OpenTelemetry C/C++ special interest group (SIG) meets regularly. See the -OpenTelemetry [community](https://github.com/open-telemetry/community#cc-sdk) -repo for information on this and other language SIGs. - -See the [public meeting -notes](https://docs.google.com/document/d/1i1E4-_y4uJ083lCutKGDhkpi3n4_e774SBLi9hPLocw/edit) -for a summary description of past meetings. To request edit access, join the -meeting or get in touch on -[Slack](https://cloud-native.slack.com/archives/C01N3AT62SJ). - -See the [community membership -document](https://github.com/open-telemetry/community/blob/main/community-membership.md) -on how to become a -[**Member**](https://github.com/open-telemetry/community/blob/main/community-membership.md#member), -[**Approver**](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver) -and -[**Maintainer**](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer). - -## Development - -OpenTelemetry C++ uses the [Google naming -convention](https://google.github.io/styleguide/cppguide.html#Naming). - -Code is formatted automatically and enforced by CI. - -### Build and Run Code Examples - -Note: these instructions apply to examples configured with Bazel, see -example-specific documentation for other build automation tools. - -Install the latest bazel version by following the steps listed -[here](https://docs.bazel.build/versions/master/install.html). - -Select an example of interest from the [examples -folder](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/examples). -Inside each example directory is a `BUILD` file containing instructions for -Bazel. Find the binary name of your example by inspecting the contents of this -`BUILD` file. - -Build the example from the root of the opentelemetry-cpp directory using Bazel. -Replace `` with the identifier found in the previous step: - -```sh -bazel build //examples/: -``` - -Run the resulting executable to see telemetry from the application as it calls -the instrumented library: - -```sh -bazel-bin/examples// -``` - -For instance, building and running the `simple` example can be done as follows: - -```sh -bazel build //examples/simple:example_simple -bazel-bin/examples/simple/example_simple -``` - -### DevContainer Setup for Project - -This guide provides instructions on how to set up and use the development -container (`devcontainer`) environment to streamline testing and development -for this project. With the DevContainer, you can work in a consistent environment -configured with all the necessary dependencies and tools. - -#### Prerequisites - -Before getting started, ensure you have the following installed: - -* **Docker**: DevContainers require Docker for containerization. -* **Visual Studio Code (VSCode)** with the **Remote - Containers** extension. - -#### Getting Started - -* **Open the Project in DevContainer**: - - Open the project in VSCode. When prompted to "Reopen in Container," select - this option. If you’re not prompted, you can manually open the container by - selecting **Remote-Containers: Reopen in Container** from the command palette - (`F1` or `Ctrl+Shift+P`). - -* **Container Setup**: - - The DevContainer environment will automatically build based on the configuration - files provided (e.g., `.devcontainer/devcontainer.json`). This setup will install - required dependencies, tools, and environment variables needed for the project. - -* **Container Customization**: - See `.devcontainer/README.md` for devcontainer configuration options. - -#### Available Commands - -Once inside the DevContainer, you can use the following commands to run tests -and CI workflows. - -##### 1. Run Tests with Bazelisk - -To run tests with Bazelisk using specific compilation options, use: - -```bash -bazelisk-linux-amd64 test --copt=-DENABLE_LOGS_PREVIEW ---test_output=errors --cache_test_results=no --copt=-DENABLE_TEST //exporters/otlp/... -``` - -###### Command Breakdown - -* `--copt=-DENABLE_LOGS_PREVIEW`: Enables preview logs. -* `--test_output=errors`: Shows only the errors in the test output. -* `--cache_test_results=no`: Forces Bazel to re-run tests without caching. -* `--copt=-DENABLE_TEST`: Enables testing capabilities for the target code. -* `//exporters/otlp/...`: Specifies the test target path. - -##### 2. Run CI Script - -You can also run the CI script provided to perform testing with the -following command as an -example: - -```bash -bash ci/do_ci.sh cmake.exporter.otprotocol.test -``` - -This command initiates the CI pipeline, executing tests specifically for the -**cmake.exporter.otprotocol** module. - -#### Troubleshooting - -If you encounter issues: - -* **Rebuild the DevContainer**: From the command palette, run - **Remote-Containers: Rebuild Container** to reinitialize the environment. -* **Check Bazelisk and CI Script Logs**: Inspect logs for any configuration or - dependency issues. - -#### Additional Notes - -* You can adjust compiler options (`--copt`) as needed to test additional flags - or enable/disable specific features. -* The test results will be displayed in the terminal within the DevContainer for - easy debugging. - -#### Resources - -* **Bazelisk Documentation**: [https://github.com/bazelbuild/bazelisk](https://github.com/bazelbuild/bazelisk) -* **VSCode DevContainer Documentation**: [https://code.visualstudio.com/docs/remote/containers](https://code.visualstudio.com/docs/remote/containers) - -### Docker Development Image - -The `.devcontainer/Dockerfile.dev` -dockerfile can be built directly with the following command. - -```sh - docker build -t opentelemetry-cpp-dev -f ./.devcontainer/Dockerfile.dev . -``` - -You can customize the image using build arguments - to match permissions with the host user. - -```sh - docker build -t opentelemetry-cpp-dev \ - --build-arg USER_UID="$(id -u)" \ - --build-arg USER_GID="$(id -g)" \ - -f ./.devcontainer/Dockerfile.dev . - -``` - -Run an interactive bash session binding your host - opentelemetry-cpp directory to the container's workspace: - -```sh -docker run -it -v "$PWD:/workspaces/opentelemetry-cpp" opentelemetry-cpp-dev bash -``` - -## Pull Requests - -### How to Send Pull Requests - -Everyone is welcome to contribute code to `opentelemetry-cpp` via GitHub pull -requests (PRs). - -To create a new PR, fork the project in GitHub and clone the upstream repo: - -```sh -git clone --recursive https://github.com/open-telemetry/opentelemetry-cpp.git -``` - -Add your fork as a remote: - -```sh -git remote add fork https://github.com/YOUR_GITHUB_USERNAME/opentelemetry-cpp.git -``` - -If you haven't, make sure you are loading the submodules required to build -OpenTelemetry - -```sh -git submodule init -git submodule update -``` - -The source code is automatically formatted using clang-format. - -The output can vary between versions, so make sure to install `clang-format` -version `10.0`, and have `clang-format-10` in your execution path, -so that the helper script `tools/format.sh` can find it. - -Check out a new branch, make modifications and push the branch to your fork: - -```sh -git checkout -b feature -# edit files -tools/format.sh -git commit -git push fork feature -``` - -If you made changes to the Markdown documents (`*.md` files), install the latest -[`markdownlint-cli`](https://github.com/igorshubovych/markdownlint-cli) and run: - -```sh -markdownlint . -``` - -If you modified shell scripts (`*.sh` files), install `shellcheck` and run: - -```sh -shellcheck --severity=error .sh -``` - -Open a pull request against the main `opentelemetry-cpp` repo. - -To run tests locally, please read the [CI instructions](ci/README.md). - -### How to Receive Comments - -* If the PR is not ready for review, please put `[WIP]` in the title, tag it as - `work-in-progress`, or mark it as - [`draft`](https://github.blog/2019-02-14-introducing-draft-pull-requests/). -* Make sure [CLA](https://identity.linuxfoundation.org/projects/cncf) is signed - and CI is clear. -* For non-trivial changes, please update the [CHANGELOG](./CHANGELOG.md). - -### How to Get PRs Merged - -A PR is considered to be **ready to merge** when: - -* It has received two approvals with at least one approval from - [Approver](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver) - / - [Maintainer](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer) - (at different company). -* A pull request opened by an Approver / Maintainer can be merged with only one - approval from Approver / Maintainer (at different company). -* Major feedback items/points are resolved. -* It has been open for review for at least one working day. This gives people - reasonable time to review. -* Trivial changes (typo, cosmetic, doc, etc.) don't have to wait for one day. -* Urgent fixes can take exceptions as long as it has been actively communicated. - -Any Maintainer can merge the PR once it is **ready to merge**. Maintainer can -make conscious judgement to merge pull requests which have not strictly met -above mentioned requirements. - -If a PR has been stuck (e.g. there are lots of debates and people couldn't agree -on each other), the owner should try to get people aligned by: - -* Consolidating the perspectives and putting a summary in the PR. It is - recommended to add a link into the PR description, which points to a comment - with a summary in the PR conversation -* Stepping back to see if it makes sense to narrow down the scope of the PR or - split it up. - -If none of the above worked and the PR has been stuck for more than 2 weeks, the -owner should bring it to the OpenTelemetry C++ SIG meeting. See -[README.md](README.md#contributing) for the meeting link. - -## Design Choices - -As with other OpenTelemetry clients, opentelemetry-cpp follows the -[opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification). - -It's especially valuable to read through the [library -guidelines](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/library-guidelines.md). - -## Useful Resources - -Hi! If you’re looking at this document, these resources will provide you the -knowledge to get started as a newcomer to the OpenTelemetry project. They will -help you understand the OpenTelemetry Project, its components, and specifically -the C++ repository. - -### Reading Resources - -* Medium - [article](https://medium.com/opentelemetry/how-to-start-contributing-to-opentelemetry-b23991ad91f4) - (October 2019) on how to start contributing to the OpenTelemetry project. -* Medium - [article](https://medium.com/opentelemetry/opentelemetry-beyond-getting-started-5ac43cd0fe26) - (January 2020) describing the overarching goals and use cases for - OpenTelemetry. - -### Relevant Documentation - -* [OpenTelemetry - Specification](https://github.com/open-telemetry/opentelemetry-specification) -* The OpenTelemetry Specification describes the requirements and expectations - of for all OpenTelemetry implementations. - -* Read through the OpenTelemetry C++ documentation -* The - [API](https://opentelemetry-cpp.readthedocs.io/en/latest/api/api.html) - and - [SDK](https://opentelemetry-cpp.readthedocs.io/en/latest/sdk/sdk.html) - documentation provides a lot of information on what the classes and their - functions are used for. - -Please contribute! You’re welcome to add more information if you come across any -helpful resources. diff --git a/ext/opentelemetry-cpp-1.21.0/DEPRECATED.md b/ext/opentelemetry-cpp-1.21.0/DEPRECATED.md deleted file mode 100644 index ec97f420f..000000000 --- a/ext/opentelemetry-cpp-1.21.0/DEPRECATED.md +++ /dev/null @@ -1,139 +0,0 @@ -# Deprecated - -This document lists all the items currently deprecated in opentelemetry-cpp. - -Deprecated items will be removed in the future. - -## Guidelines - -### Maintainer guidelines - -See the [deprecation-process](./docs/deprecation-process.md) - -## [TEMPLATE] - -### New Deprecation Title (Template) - -#### Announcement (Template) - -#### Motivation (Template) - -#### Scope (Template) - -#### Mitigation (Template) - -#### Planned removal (Template) - -## [Platforms] - -N/A - -## [Compilers] - -N/A - -## [Third party dependencies] - -N/A - -## [Build tools] - -N/A - -## [Build scripts] - -N/A - -## [opentelemetry-cpp API] - -N/A - -## [opentelemetry-cpp SDK] - -N/A - -## [opentelemetry-cpp Exporter] - -N/A - -## [Documentation] - -N/A - -## Semantic conventions - -### Header files "semantic_conventions.h" - -#### Announcement (semantic_conventions.h) - -Deprecation is announced as part of the migration to weaver: - -* `Version:` release following opentelemetry-cpp 1.17.0 -* `Date:` Nov 9, 2024 -* `PR:` [PR 3105](https://github.com/open-telemetry/opentelemetry-cpp/pull/3105) - -#### Motivation (semantic_conventions.h) - -The header files for semantic conventions are generated automatically. -The tooling to generate these files is changing: - -* before, the build-tool repository was used -* now, the weaver repository is used - -Changes in tooling allows to generate code that is better organized, -with dedicated header files per group of semantic conventions, -instead of a single header file for everything. - -#### Scope (semantic_conventions.h) - -The following files: - -* `api/include/opentelemetry/trace/semantic_conventions.h` -* `sdk/include/opentelemetry/sdk/resource/semantic_conventions.h` - -are now deprecated. - -They correspond to semantic conventions v1.27.0, -and will no longer be maintained up to date. - -These files will be removed in the future. - -#### Mitigation (semantic_conventions.h) - -Two things have changed: - -* the header file to use -* the symbol name to use. - -Before, the semantic convention for `url.full` was: - -* declared in file `semantic_conventions.h` -* declared as symbol `SemanticConventions::kUrlFull` - -Now, the `url.full` convention, which is part or the `url` group, is: - -* declared in file `semconv/url_attributes.h` -* declared as symbol `semconv::url::kUrlFull` - -Application code that uses semantic conventions must be adjusted -accordingly. - -In addition, semantic conventions that are not marked as stable -are generated in a different header file, placed under directory -`incubating`, to better separate stable and non stable code. - -For example, file `semconv/incubating/url_attributes.h` -defines `semconv::url::kUrlDomain`, -which is not marked as stable in semconv v1.27.0 - -#### Planned removal (semantic_conventions.h) - -The following files: - -* `api/include/opentelemetry/trace/semantic_conventions.h` -* `sdk/include/opentelemetry/sdk/resource/semantic_conventions.h` - -will be removed. - -The removal date is planned for July 1, 2025. -This allows more than six months for applications to adjust. diff --git a/ext/opentelemetry-cpp-1.21.0/INSTALL.md b/ext/opentelemetry-cpp-1.21.0/INSTALL.md deleted file mode 100644 index 296a61c44..000000000 --- a/ext/opentelemetry-cpp-1.21.0/INSTALL.md +++ /dev/null @@ -1,452 +0,0 @@ -# Building opentelemetry-cpp - -[CMake](https://cmake.org/) and [Bazel](https://bazel.build) are the official -build systems for opentelemetry-cpp. - -## Dependencies - -You can link OpenTelemetry C++ SDK with libraries provided in -[dependencies.md](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/docs/dependencies.md) -(complete list of libraries with versions used in our CI can be found -[here](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/third_party_release)). - -## Build instructions using CMake - -### Prerequisites for CMake build - -- A supported platform (e.g. Windows, macOS or Linux). Refer to [Platforms - Supported](./README.md#supported-development-platforms) for more information. -- A compatible C++ compiler supporting at least C++14. Major compilers are - supported. Refer to [Supported Compilers](./README.md#supported-c-versions) - for more information. -- [Git](https://git-scm.com/) for fetching opentelemetry-cpp source code from - repository. To install Git, consult the [Set up - Git](https://help.github.com/articles/set-up-git/) guide on GitHub. -- [CMake](https://cmake.org/) for building opentelemetry-cpp API, SDK with their - unittests. The minimum CMake version is 3.14. - CMake 3.15+ is recommended on Windows due to known CI test failures with 3.14. - To install CMake, - consult the [Installing CMake](https://cmake.org/install/) guide. -- [GoogleTest](https://github.com/google/googletest) framework to build and run - the unittests. Refer to - [third_party_release](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/third_party_release#L5) - for version of GoogleTest used in CI. To install GoogleTest, consult the - [GoogleTest Build - Instructions](https://github.com/google/googletest/blob/master/googletest/README.md#generic-build-instructions). -- [Google Benchmark](https://github.com/google/benchmark) framework to build and - run benchmark tests. Refer to - [third_party_release](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/third_party_release#L4) - for version of Benchmark used in CI. To install Benchmark, consult the - [GoogleBenchmark Build - Instructions](https://github.com/google/benchmark#installation). -- Apart from above core requirements, the Exporters and Propagators have their - build dependencies. - -### Building dependencies for the OTLP exporters - -The opentelemetry-cpp OTLP exporters depend on Protobuf and gRPC - (in the case of the otlp grpc exporters). -Protobuf (since version 3.22.0) and gRPC depend on Abseil. -For cmake builds, it is best practice to build and install Abseil -, Protobuf, and gPRC as independent packages - -configuring cmake for Protobuf and gRPC to build against - the installed packages instead of using their submodule option. - -If building and installing Protobuf and gRPC manually with cmake the - recommended approach is: - -1. Choose the desired tag version of grpc. Find the compatible versions of abseil - and protobuf by inspecting the submodules of grpc at that tag. -2. Build and install the required version of abseil -3. Build and install the required version of protobuf - - Set the cmake option of Protobuf to build against the installed - package of Abseil (`protobuf_ABSL_PROVIDER=package`) -4. Build and install the required version of grpc - - Set the cmake option of grpc to build against the installed packages - of Abseil and Protobuf (cmake options - `gRPC_ABSL_PROVIDER=package` and `gRPC_PROTOBUF_PROVIDER=package`) - -### Building as standalone CMake Project - -1. Getting the opentelemetry-cpp source with its submodules: - - ```console - # Change to the directory where you want to create the code repository - $ cd ~ - $ mkdir source && cd source && git clone --recurse-submodules https://github.com/open-telemetry/opentelemetry-cpp - Cloning into 'opentelemetry-cpp'... - ... - Resolving deltas: 100% (3225/3225), done. - $ - ``` - -2. Navigate to the repository cloned above, and create the `CMake` build - configuration. - - ```console - $ cd opentelemetry-cpp - $ mkdir build && cd build && cmake .. - -- The C compiler identification is GNU 9.3.0 - -- The CXX compiler identification is GNU 9.3.0 - ... - -- Configuring done - -- Generating done - -- Build files have been written to: /home//source/opentelemetry-cpp/build - $ - ``` - - Some of the available cmake build variables we can use during cmake - configuration: - - - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON` : Please note that with default - configuration, the code is compiled without `-fpic` option, so it is not - suitable for inclusion in shared libraries. To enable the code for - inclusion in shared libraries, this variable is used. - - `-DBUILD_SHARED_LIBS=ON` : To build shared libraries for the targets. - Please refer to note [below](#building-shared-libs-for-windows) for - Windows DLL support. - - `-DWITH_OTLP_GRPC=ON` : To enable building OTLP GRPC exporter. - - `-DWITH_OTLP_HTTP=ON` : To enable building OTLP HTTP exporter. - - `-DWITH_PROMETHEUS=ON` : To enable building prometheus exporter. - - `-DOPENTELEMETRY_INSTALL=ON`: To install `otel-cpp` library needed - for external code linking. - -3. Once the build configuration is created, build the CMake targets - this - includes building SDKs and unittests for API and SDK. Note that since API is - header only library, no separate build is triggered for it. - - ```console - $ cmake --build . --target all - Scanning dependencies of target timestamp_test - [ 0%] Building CXX object api/test/core/CMakeFiles/timestamp_test.dir/timestamp_test.cc.o - [ 1%] Linking CXX executable timestamp_test - ... - Scanning dependencies of target w3c_tracecontext_test - [ 99%] Building CXX object ext/test/w3c_tracecontext_test/CMakeFiles/w3c_tracecontext_test.dir/main.cc.o - [100%] Linking CXX executable w3c_tracecontext_test - [100%] Built target w3c_tracecontext_test - $ - ``` - -4. Once CMake tests are built, run them with `ctest` command - - ```console - $ ctest - Test project /tmp/opentelemetry-cpp/build - Start 1: trace.SystemTimestampTest.Construction - ... - Start 380: ext.http.urlparser.UrlParserTests.BasicTests - ... - 100% tests passed, 0 tests failed out of 380 - $ - ``` - -5. Optionally install the header files for API, and generated targets and header - files for SDK at custom/default install location. - - ```console - $ cmake --install . --prefix // - -- Installing: //lib/cmake/opentelemetry-cpp/opentelemetry-cpp-config.cmake - -- Installing: //lib/cmake/opentelemetry-cpp/opentelemetry-cpp-config-version.cmake - ... - $ - ``` - -### Incorporating into an external CMake Project - -There are two approaches to incoporate `opentelemetry-cpp` into - an external CMake project: - -1. Build and install `opentelemetry-cpp` then use `find_package` - to import its targets - - ```cmake - # Find all installed components and link all imported targets - find_package(opentelemetry-cpp CONFIG REQUIRED) - ... - target_include_directories(foo PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) - target_link_libraries(foo PRIVATE ${OPENTELEMETRY_CPP_LIBRARIES}) - ``` - - ```cmake - # Find a specific component and link its imported target(s) - find_package(opentelemetry-cpp CONFIG REQUIRED COMPONENTS api) - ... - target_link_libraries(foo PRIVATE opentelemetry-cpp::api) - ``` - -2. Use CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) - module to fetch and build `opentelemetry-cpp` then make its targets available - - ```cmake - # Fetch from an existing clone and build - include(FetchContent) - FetchContent_Declare(opentelemetry-cpp SOURCE_DIR "") - FetchContent_MakeAvailable(opentelemetry-cpp) - ... - target_link_libraries(foo PRIVATE opentelemetry-cpp::api) - ``` - - ```cmake - # Clone and build opentelemetry-cpp from a git tag - include(FetchContent) - FetchContent_Declare( - opentelemetry-cpp - GIT_REPOSITORY https://github.com/open-telemetry/opentelemetry-cpp.git - GIT_TAG v1.20.0) - FetchContent_MakeAvailable(opentelemetry-cpp) - ... - target_link_libraries(foo PRIVATE opentelemetry-cpp::api) - ``` - -In both cases the project's built or imported CMake targets will be - available in the `opentelemetry-cpp` namespace (ie: `opentelemetry-cpp::api`) - -#### Using opentelemetry-cpp package components - -> **Note:** `opentelemetry-cpp` CMake package components were introduced in `v1.21.0` - -The `opentelemetry-cpp` package supports using the `COMPONENTS` argument to -`find_package`. The following example illustrates using this feature to include -and link the `api` header only target to an instrumented `foo_lib` while only including -and linking the `sdk` and `otlp_grpc_exporter` targets to the `foo_app`. - -```cmake -# foo_lib/CMakeLists.txt -find_package(opentelemetry-cpp CONFIG REQUIRED COMPONENTS api) -add_library(foo_lib foo.cpp) -target_link_libraries(foo_lib PRIVATE opentelemetry-cpp::api) -``` - -```cmake -# foo_app/CMakeLists.txt -find_package(opentelemetry-cpp CONFIG REQUIRED COMPONENTS api sdk exporters_otlp_grpc) -add_executable(foo_app main.cpp) -target_link_libraries(foo_app PRIVATE foo_lib opentelemetry-cpp::api opentelemetry-cpp::trace opentelemetry-cpp::otlp_grpc_exporter ) -``` - -The following table provides the mapping between components and targets. Components -and targets available in the installation depends on the opentelemetry-cpp package -build configuration. - -> **Note:** components `exporters_elasticsearch` and `exporters_etw` - may be moved out of the core package and to `opentelemetry-cpp-contrib` - in a future release - -| Component | Targets | -|----------------------------|--------------------------------------------------------------------------------------------------| -| **api** | opentelemetry-cpp::api | -| **sdk** | opentelemetry-cpp::sdk | -| | opentelemetry-cpp::version | -| | opentelemetry-cpp::common | -| | opentelemetry-cpp::resources | -| | opentelemetry-cpp::trace | -| | opentelemetry-cpp::metrics | -| | opentelemetry-cpp::logs | -| **ext_common** | opentelemetry-cpp::ext | -| **ext_http_curl** | opentelemetry-cpp::http_client_curl | -| **ext_dll** | opentelemetry-cpp::opentelemetry_cpp | -| **exporters_in_memory** | opentelemetry-cpp::in_memory_span_exporter | -| | opentelemetry-cpp::in_memory_metric_exporter | -| **exporters_ostream** | opentelemetry-cpp::ostream_log_record_exporter | -| | opentelemetry-cpp::ostream_metrics_exporter | -| | opentelemetry-cpp::ostream_span_exporter | -| **exporters_otlp_common** | opentelemetry-cpp::proto | -| | opentelemetry-cpp::otlp_recordable | -| **exporters_otlp_file** | opentelemetry-cpp::otlp_file_client | -| | opentelemetry-cpp::otlp_file_exporter | -| | opentelemetry-cpp::otlp_file_log_record_exporter | -| | opentelemetry-cpp::otlp_file_metric_exporter | -| **exporters_otlp_grpc** | opentelemetry-cpp::proto_grpc | -| | opentelemetry-cpp::otlp_grpc_client | -| | opentelemetry-cpp::otlp_grpc_exporter | -| | opentelemetry-cpp::otlp_grpc_log_record_exporter | -| | opentelemetry-cpp::otlp_grpc_metrics_exporter | -| **exporters_otlp_http** | opentelemetry-cpp::otlp_http_client | -| | opentelemetry-cpp::otlp_http_exporter | -| | opentelemetry-cpp::otlp_http_log_record_exporter | -| | opentelemetry-cpp::otlp_http_metric_exporter | -| **exporters_prometheus** | opentelemetry-cpp::prometheus_exporter | -| **exporters_elasticsearch**| opentelemetry-cpp::elasticsearch_log_record_exporter | -| **exporters_etw** | opentelemetry-cpp::etw_exporter | -| **exporters_zipkin** | opentelemetry-cpp::zipkin_trace_exporter | -| **shims_opentracing** | opentelemetry-cpp::opentracing_shim | - -## Build instructions using Bazel - -NOTE: Experimental, and not supported for all the components. Make sure the -[GoogleTest](https://github.com/google/googletest) installation may fail if -there is a different version of googletest already installed in system-defined -path. - -### Prerequisites for Bazel build - -- A supported platform (e.g. Windows, macOS or Linux). Refer to [Platforms -Supported](./README.md#supported-development-platforms) for more information. -- A compatible C++ compiler supporting at least C++14. Major compilers are -supported. Refer to [Supported Compilers](./README.md#supported-c-versions) for -more information. -- [Git](https://git-scm.com/) for fetching opentelemetry-cpp source code from -repository. To install Git, consult the [Set up -Git](https://help.github.com/articles/set-up-git/) guide on GitHub. -- [Bazel](https://www.bazel.build/) for building opentelemetry-cpp API, SDK with -their unittests. We use 3.7.2 in our build system. - -To install Bazel, consult the [Installing -Bazel](https://docs.bazel.build/versions/3.7.0/install.html) guide. - -### Building as standalone Bazel Project - -1. Getting the opentelemetry-cpp source: - - ```console - # Change to the directory where you want to create the code repository - $ cd ~ - $ mkdir source && cd source - $ git clone https://github.com/open-telemetry/opentelemetry-cpp - Cloning into 'opentelemetry-cpp'... - ... - Resolving deltas: 100% (3225/3225), done. - $ - ``` - -2. Navigate to the repository cloned above, download the dependencies and build - the source code: - - ```console - $ cd opentelemetry-cpp - $ bazel build //... - bazel build -- //... -//exporters/otlp/... -//exporters/prometheus/... - Extracting Bazel installation... - Starting local Bazel server and connecting to it... - INFO: Analyzed 121 targets (98 packages loaded, 3815 targets configured). - INFO: Found 121 targets... - INFO: From Compiling sdk/src/trace/tracer_context.cc: - ... - - ``` - -3. Once Bazel tests are built, run them with `bazel test //...` command - - ```console - $ bazel test //... - .. - $ - ``` - -4. The build artifacts will be located under `bazel-bin` - -### Incorporating into an existing Bazel Project - -- WORKSPACE file: - -```console -http_archive( - name = "io_opentelemetry_cpp", - sha256 = "", - strip_prefix = "opentelemetry-cpp-1.0.1", - urls = [ - "https://github.com/open-telemetry/opentelemetry-cpp/archive/refs/tags/v1.0.1.tar.gz" - ], -) - -# Load OpenTelemetry dependencies after load. -load("@io_opentelemetry_cpp//bazel:repository.bzl", "opentelemetry_cpp_deps") - -opentelemetry_cpp_deps() - -# (required after v1.8.0) Load extra dependencies required for OpenTelemetry -load("@io_opentelemetry_cpp//bazel:extra_deps.bzl", "opentelemetry_extra_deps") - -opentelemetry_extra_deps() - -# Load gRPC dependencies after load. -load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") - -grpc_deps() - -# Load extra gRPC dependencies due to https://github.com/grpc/grpc/issues/20511 -load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") - -grpc_extra_deps() - -``` - -- Component level BUILD file: - -```console -cc_library( - name = "" - ... - deps = [ - "@io_opentelemetry_cpp//api", - "@io_opentelemetry_cpp//exporters/otlp:otlp_exporter", - "@io_opentelemetry_cpp//sdk/src/trace", - ... - ], - ... -) -``` - -## Building shared libs for Windows - -Windows DLL build is supported under **preview**. Please check the -[doc](./docs/build-as-dll.md) for more details. - -## Generating binary packages - -OpenTelemetry C++ supports generating platform specific binary packages from CMake -configuration. The packages generated through this mayn't be production ready, -and user may have to customize it further before using it as distribution. - -- Linux : deb, rpm, tgz -- MacOS : tgz -- Windows : NuGet, zip - -This requires platform specific package generators already installed. The package -generation can subsequently be enabled by using BUILD_PACKAGE option during cmake -configuration - - ```console - $ cd opentelemetry-cpp - $ mkdir build && cd build && cmake -DBUILD_PACKAGE=ON .. - - -- Package name: opentelemetry-cpp-1.8.1-ubuntu-20.04-x86_64.deb - -- Configuring done - -- Generating done - ... - $ - ``` - -Once build is complete as specified in [standalone build section](#building-as-standalone-cmake-project), -the package can be generated as below. - - ```console - $ cpack -C debug - CPack: Create package using DEB - ... - CPack: - package: /home//opentelemetry-cpp/build/opentelemetry-cpp-1.8.1-ubuntu-20.04-x86_64.deb generated. - $ - ``` - -## Using Package Managers - -If you are using [Conan](https://www.conan.io/) to manage your dependencies, add -[`opentelemetry-cpp/x.y.z`](https://conan.io/center/opentelemetry-cpp) to your -`conanfile`'s requires, where `x.y.z` is the release version you want to use. -Please file issues [here](https://github.com/conan-io/conan-center-index/issues) -if you experience problems with the packages. - -If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project -for external dependencies, then you can install the [opentelemetry-cpp -package](https://github.com/microsoft/vcpkg/tree/master/ports/opentelemetry-cpp) -with `vcpkg install opentelemetry-cpp` and follow the then displayed -descriptions. Please see the vcpkg project for any issues regarding the -packaging. - -If you are using [alpine linux](https://www.alpinelinux.org/) you can install -the [opentelemetry-cpp packages](https://pkgs.alpinelinux.org/packages?name=opentelemetry-cpp-*) -with `apk add -X http://dl-cdn.alpinelinux.org/alpine/edge/testing opentelemetry-cpp-dev`. - -Please note, these packages are not officially provided and maintained by -OpenTelemetry C++ project, and are just listed here to consolidate all such -efforts for ease of developers. diff --git a/ext/opentelemetry-cpp-1.21.0/LICENSE b/ext/opentelemetry-cpp-1.21.0/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/ext/opentelemetry-cpp-1.21.0/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/ext/opentelemetry-cpp-1.21.0/MODULE.bazel b/ext/opentelemetry-cpp-1.21.0/MODULE.bazel deleted file mode 100644 index 59d844090..000000000 --- a/ext/opentelemetry-cpp-1.21.0/MODULE.bazel +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -module( - name = "opentelemetry-cpp", - version = "1.21.0", - compatibility_level = 0, - repo_name = "io_opentelemetry_cpp", -) - -bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "com_google_absl") -bazel_dep(name = "bazel_skylib", version = "1.5.0") -bazel_dep(name = "curl", version = "8.8.0") -bazel_dep(name = "grpc", version = "1.63.1.bcr.1", repo_name = "com_github_grpc_grpc") -bazel_dep(name = "nlohmann_json", version = "3.12.0", repo_name = "github_nlohmann_json") -bazel_dep(name = "opentelemetry-proto", version = "1.6.0", repo_name = "com_github_opentelemetry_proto") -bazel_dep(name = "opentracing-cpp", version = "1.6.0", repo_name = "com_github_opentracing") -bazel_dep(name = "platforms", version = "0.0.8") -bazel_dep(name = "prometheus-cpp", version = "1.3.0", repo_name = "com_github_jupp0r_prometheus_cpp") -bazel_dep(name = "protobuf", version = "26.0", repo_name = "com_google_protobuf") -bazel_dep(name = "rules_proto", version = "5.3.0-21.7") -bazel_dep(name = "zlib", version = "1.3.1.bcr.1") - -bazel_dep(name = "google_benchmark", version = "1.8.3", dev_dependency = True, repo_name = "com_github_google_benchmark") -bazel_dep(name = "googletest", version = "1.14.0.bcr.1", dev_dependency = True, repo_name = "com_google_googletest") diff --git a/ext/opentelemetry-cpp-1.21.0/README.md b/ext/opentelemetry-cpp-1.21.0/README.md deleted file mode 100644 index 01645aa8c..000000000 --- a/ext/opentelemetry-cpp-1.21.0/README.md +++ /dev/null @@ -1,127 +0,0 @@ -# OpenTelemetry C++ - -[![Slack](https://img.shields.io/badge/slack-@cncf/otel/cpp-brightgreen.svg?logo=slack)](https://cloud-native.slack.com/archives/C01N3AT62SJ) -[![codecov.io](https://codecov.io/gh/open-telemetry/opentelemetry-cpp/branch/main/graphs/badge.svg?)](https://codecov.io/gh/open-telemetry/opentelemetry-cpp/) -[![Build -Status](https://github.com/open-telemetry/opentelemetry-cpp/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/open-telemetry/opentelemetry-cpp/actions) -[![Release](https://img.shields.io/github/v/release/open-telemetry/opentelemetry-cpp?include_prereleases&style=)](https://github.com/open-telemetry/opentelemetry-cpp/releases/) -[![FOSSA License Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-cpp.svg?type=shield&issueType=license)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-cpp?ref=badge_shield&issueType=license) -[![FOSSA Security Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-cpp.svg?type=shield&issueType=security)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-cpp?ref=badge_shield&issueType=security) - -The C++ [OpenTelemetry](https://opentelemetry.io/) client. - -## Project Status - -**Stable** across all 3 signals i.e. `Logs`, `Metrics`, and `Traces`. - -See [Spec Compliance -Matrix](https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md) -to understand which portions of the specification has been implemented in this -repo. - -## Supported C++ Versions - -Code shipped from this repository generally supports the following versions of -C++ standards: - -* ISO/IEC 14882:2014 (C++14) -* ISO/IEC 14882:2017 (C++17) -* ISO/IEC 14882:2020 (C++20) - -Any exceptions to this are noted in the individual `README.md` files. - -Please note that supporting the [C Programming -Language](https://en.wikipedia.org/wiki/C_(programming_language)) is not a goal -of the current project. - -## Supported Development Platforms - - Our CI pipeline builds and tests on following `x86-64` platforms: - -| Platform | Build type | -|---------------------------------------------------------------------|---------------| -| ubuntu-22.04 (GCC 10, GCC 12, Clang 14) | CMake, Bazel | -| ubuntu-20.04 (GCC 9.4.0 - default compiler) | CMake, Bazel | -| ubuntu-20.04 (GCC 9.4.0 with -std=c++14/17/20 flags) | CMake, Bazel | -| macOS 12.7 (Xcode 14.2) | Bazel | -| Windows Server 2019 (Visual Studio Enterprise 2019) | CMake, Bazel | -| Windows Server 2022 (Visual Studio Enterprise 2022) | CMake | - -In general, the code shipped from this repository should build on all platforms -having C++ compiler with [supported C++ standards](#supported-c-versions). - -## Dependencies - -Please refer to [Dependencies.md](docs/dependencies.md) for OSS Dependencies and -license requirements. - -## Installation - -Please refer to [INSTALL.md](./INSTALL.md). - -## Getting Started - -As an application owner or the library author, you can find the getting started -guide and reference documentation on -[opentelemetry-cpp.readthedocs.io](https://opentelemetry-cpp.readthedocs.io/en/latest/) - -The `examples/simple` directory contains a minimal program demonstrating how to -instrument a small library using a simple `processor` and console `exporter`, -along with build files for CMake and Bazel. - -## Contributing - -See [CONTRIBUTING.md](CONTRIBUTING.md) - -We meet weekly, and the time of the meeting alternates between Monday at 13:00 -PT and Wednesday at 9:00 PT. The meeting is subject to change depending on -contributors' availability. Check the [OpenTelemetry community -calendar](https://github.com/open-telemetry/community#calendar) -for specific dates and Zoom meeting links. - -Meeting notes are available as a public [Google -doc](https://docs.google.com/document/d/1i1E4-_y4uJ083lCutKGDhkpi3n4_e774SBLi9hPLocw/edit?usp=sharing). -For edit access, get in touch on -[Slack](https://cloud-native.slack.com/archives/C01N3AT62SJ). - -[Maintainers](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer) -([@open-telemetry/cpp-maintainers](https://github.com/orgs/open-telemetry/teams/cpp-maintainers)): - -* [Ehsan Saei](https://github.com/esigo) -* [Lalit Kumar Bhasin](https://github.com/lalitb), Microsoft -* [Marc Alff](https://github.com/marcalff), Oracle -* [Tom Tan](https://github.com/ThomsonTan), Microsoft - -[Approvers](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver) -([@open-telemetry/cpp-approvers](https://github.com/orgs/open-telemetry/teams/cpp-approvers)): - -* [Doug Barker](https://github.com/dbarker) -* [Josh Suereth](https://github.com/jsuereth), Google -* [Pranav Sharma](https://github.com/psx95), Google -* [WenTao Ou](https://github.com/owent), Tencent - -[Emeritus -Maintainer/Approver/Triager](https://github.com/open-telemetry/community/blob/main/community-membership.md#emeritus-maintainerapprovertriager): - -* [Alolita Sharma](https://github.com/alolita) -* [Emil Mikulic](https://github.com/g-easy) -* [Jodee Varney](https://github.com/jodeev) -* [Johannes Tax](https://github.com/pyohannes) -* [Max Golovanov](https://github.com/maxgolov) -* [Reiley Yang](https://github.com/reyang) -* [Ryan Burn](https://github.com/rnburn) - -### Thanks to all the people who have contributed - -[![contributors](https://contributors-img.web.app/image?repo=open-telemetry/opentelemetry-cpp)](https://github.com/open-telemetry/opentelemetry-cpp/graphs/contributors) - -## Release Schedule - -See the [release -notes](https://github.com/open-telemetry/opentelemetry-cpp/releases) for -existing releases. - -See the [project -milestones](https://github.com/open-telemetry/opentelemetry-cpp/milestones) for -details on upcoming releases. The dates and features described in issues and -milestones are estimates, and subject to change. diff --git a/ext/opentelemetry-cpp-1.21.0/RELEASING.md b/ext/opentelemetry-cpp-1.21.0/RELEASING.md deleted file mode 100644 index 852332e82..000000000 --- a/ext/opentelemetry-cpp-1.21.0/RELEASING.md +++ /dev/null @@ -1,96 +0,0 @@ -# Release Process - -## Pre Release - -1: Upgrade to latest [dependencies](docs/maintaining-dependencies.md) -if required. - -2: Make sure all relevant changes for this release are included under -`Unreleased` section in `CHANGELOG.md` and are in language that non-contributors -to the project can understand. - -3: Run the pre-release script. It creates a branch `pre_release_` and -updates `CHANGELOG.md` with the ``: - -```sh -./buildscripts/pre_release.sh -t -``` - -4: Verify that CHANGELOG.md is updated properly: - -```sh -git diff main -``` - -5: Push the changes to upstream and create a Pull Request on GitHub. Be sure to -include the curated changes from the [Changelog](./CHANGELOG.md) in the -description. - -## Tag - -Once the above Pull Request has been approved and merged it is time to tag the -merged commit. - -***IMPORTANT***: It is critical you use the same tag that you used in the -Pre-Release step! Failure to do so will leave things in a broken state. - -1: Note down the commit hash of the master branch after above PR request is -merged: `` - -```sh -git show -s --format=%H -``` - -2: Create a github tag on this commit hash: - -```sh -git tag -a "" -s -m "Version " "" -``` - -3: Push tag to upstream remote - -```sh -git push upstream -``` - -## Versioning - -Once tag is created, it's time to use that tag for Runtime Versioning - -1: Create a new brach for updating version information in -`./sdk/src/version.cc`. - -```sh -git checkout -b update_version_${tag} master -``` - -2: Run the pre-commit script to update the version: - -```sh -./buildscripts/pre-commit -``` - -3: Check if any changes made since last release broke ABI compatibility. If yes, -update `OPENTELEMETRY_ABI_VERSION_NO` in -[version.h](api/include/opentelemetry/version.h). - -4: Push the changes to upstream and create a Pull Request on GitHub. - -5: Once changes are merged, move the tag created earlier to the new commit hash -from step 4. - -```sh -git tag -f -git push --tags --force -``` - -## Release - -Finally create a Release for the new `` on GitHub. The release body -should include all the release notes from the Changelog for this release. - -## Post Release - -Update the OpenTelemetry.io document -[here](https://github.com/open-telemetry/opentelemetry.io/tree/main/content/en/docs/instrumentation/cpp) -by sending a Pull Request. diff --git a/ext/opentelemetry-cpp-1.21.0/Versioning.md b/ext/opentelemetry-cpp-1.21.0/Versioning.md deleted file mode 100644 index b6cbe490e..000000000 --- a/ext/opentelemetry-cpp-1.21.0/Versioning.md +++ /dev/null @@ -1,107 +0,0 @@ -# Versioning - -This document describes the versioning policy for this repository. - -## Goals - -### API and SDK Compatibility - -Once the API for a given signal (spans, logs, metrics, baggage) has been -officially released, that API module will function with any SDK that has the -same MAJOR version and equal or greater MINOR or PATCH version. For example, -application compiled with API v1.1 is compatible with SDK v1.1.2, v1.2.0, etc. - -For example, libraries that are instrumented with `opentelemetry 1.0.1` will -function in applications using `opentelemetry 1.11.33` or `opentelemetry 1.3.4`, -buy may not work in applications using `opentelemetry 2.0.0`. - -### ABI Stability - -Refer to the [ABI Policy](./docs/abi-policy.md) for more details. To summarise: - -* The API is header only, and uses ABI compliant interfaces. However, ABI - stability is not guaranteed for SDK. -* In case of ABI breaking changes, a new `inline namespace` version will be - introduced, and the existing linked applications can continue using the older - version unless they relink with newer version. - -## Release Policy - -* Release versions will follow [SemVer 2.0](https://semver.org/). -* Only a single source package containing the API, SDK, and exporters which are - required by the specification would be released. All these components are - always versioned and released together. For example, any changes in one of the - exporter would result in version update of the entire source package even - though there is no changes in API, SDK and other exporters. -* Experimental releases: New (unstable) telemetry signals and features will be - introduced behind feature flag protected by a preprocessor macro. - - ```cpp - #ifdef FEATURE_FLAG - - #endif - ``` - - As we deliver the package in source form, and the user is responsible to build - it for their platform, the user must be aware of these feature flags - (documented in the [CHANGELOG.md](CHANGELOG.md) file). The user must enable - them explicitly through their build system (CMake, Bazel or others) to use any - preview features. - - The guidelines in creating feature flag would be: - - * Naming: - * `ENABLE__PREVIEW` : For experimental release of signal api/sdks - eg, `METRICS_PREVIEW`, `LOGS_PREVIEW`, - * `ENABLE___PREVIEW` : For experimental release for - any feature within stable signal. For example, `TRACING_JAEGER_PREVIEW` to - release the experimental Jaeger exporter for tracing. - * Cleanup: It is good practice to keep feature-flags as shortlived as - possible. And, also important to keep the number of them low. They should be - used such that it is easy to remove/cleanup them once the experimental - feature is stable. - -* New signals will be stabilized via a **minor version bump**, and are not - allowed to break existing stable interfaces. Feature flags will be removed - once we have a stable implementation for the signal. - -* As an exception, small experimental features in otherwise stable - signals/components mayn't necessarily be released under feature flag. These - would be flagged as experimental by adding a `NOTE` in it's header file - - either at the beginning of file, or as the comment for the experimental API - methods. Also, if the complete header is experimental, it would be prefixed as - `experimental_`. As an example, the semantic conventions for trace signal is - experimental at the time of the writing and is within - `experimental_semantic_conventions.h` - -* Code under the "*::detail" namespace implements internal details, and is NOT - part of public interface. Also, any API not documented in the [public - documentation](https://opentelemetry-cpp.readthedocs.io/en/latest/) is NOT - part of the public interface. - -* GitHub releases will be made for all released versions. - -## Example Versioning Lifecycle - -Purely for illustration purposes, not intended to represent actual releases: - -* v0.0.1 release: - * Contains experimental API and SDK of trace (without feature flag) - * No API and SDK of logging and metrics available -* v1.0.0-rc1 release: - * Pre-release, no API/ABI guarantees, but more stable than alpha/beta. - * Contains pre-release API and SDK of trace, baggage and resource - * experimental metrics and logging API/SDK behind feature flag -* v1.0.0: ( with traces ) - * Contains stable API and SDK of trace, baggage and resource - * experimental metrics and logging API/SDK behind feature flag -* v1.5.0 release (with metrics) - * Contains stable API and SDK of metrics, trace, baggage, resource. - * experimental logging API/SDK behind feature flag -* v1.10.0 release (with logging) - * Contains stable API and SDK of logging, metrics, trace, baggage, resource. - -### Before moving to version 1.0.0 - -* Major version zero (0.y.z) is for initial development. Anything MAY change at - any time. The public API SHOULD NOT be considered stable. diff --git a/ext/opentelemetry-cpp-1.21.0/WORKSPACE b/ext/opentelemetry-cpp-1.21.0/WORKSPACE deleted file mode 100644 index a52788ece..000000000 --- a/ext/opentelemetry-cpp-1.21.0/WORKSPACE +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -workspace(name = "io_opentelemetry_cpp") - -# Load our direct dependencies. -load("//bazel:repository.bzl", "opentelemetry_cpp_deps") - -opentelemetry_cpp_deps() - -load("//bazel:extra_deps.bzl", "opentelemetry_extra_deps") - -opentelemetry_extra_deps() - -# Load gRPC dependencies after load. -load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") - -grpc_deps() - -# Load extra gRPC dependencies due to https://github.com/grpc/grpc/issues/20511 -load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") - -grpc_extra_deps() diff --git a/ext/opentelemetry-cpp-1.21.0/WORKSPACE.bzlmod b/ext/opentelemetry-cpp-1.21.0/WORKSPACE.bzlmod deleted file mode 100644 index 0db1b0462..000000000 --- a/ext/opentelemetry-cpp-1.21.0/WORKSPACE.bzlmod +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -# Disables the default WORKSPACE when using bzlmod diff --git a/ext/opentelemetry-cpp-1.21.0/api/BUILD b/ext/opentelemetry-cpp-1.21.0/api/BUILD deleted file mode 100644 index fb3139356..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/BUILD +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "int_flag", "string_flag") - -package(default_visibility = ["//visibility:public"]) - -CPP_STDLIBS = [ - "none", - "best", - "2014", - "2017", - "2020", - "2023", -] - -string_flag( - name = "with_cxx_stdlib", - build_setting_default = "best", - values = CPP_STDLIBS, -) - -cc_library( - name = "api", - hdrs = glob(["include/**/*.h"]), - defines = select({ - ":set_cxx_stdlib_none": [], - ### automatic selection - ":set_cxx_stdlib_best": ["OPENTELEMETRY_STL_VERSION=(__cplusplus/100)"], - # See https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus - ":set_cxx_stdlib_best_and_msvc": ["OPENTELEMETRY_STL_VERSION=(_MSVC_LANG/100)"], - ### manual selection - ":set_cxx_stdlib_2014": ["OPENTELEMETRY_STL_VERSION=2014"], - ":set_cxx_stdlib_2017": ["OPENTELEMETRY_STL_VERSION=2017"], - ":set_cxx_stdlib_2020": ["OPENTELEMETRY_STL_VERSION=2020"], - ":set_cxx_stdlib_2023": ["OPENTELEMETRY_STL_VERSION=2023"], - "//conditions:default": [], - }) + select({ - ":abi_version_no_1": ["OPENTELEMETRY_ABI_VERSION_NO=1"], - ":abi_version_no_2": ["OPENTELEMETRY_ABI_VERSION_NO=2"], - }), - strip_include_prefix = "include", - tags = ["api"], - deps = [ - "@com_google_absl//absl/base", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/types:variant", - ], -) - -[config_setting( - name = "set_cxx_stdlib_%s" % v, - flag_values = {":with_cxx_stdlib": v}, -) for v in CPP_STDLIBS] - -config_setting( - name = "set_cxx_stdlib_best_and_msvc", - constraint_values = ["@bazel_tools//tools/cpp:msvc"], - flag_values = {":with_cxx_stdlib": "best"}, -) - -bool_flag( - name = "with_abseil", - build_setting_default = False, - deprecation = "The value of this flag is ignored. Bazel builds always depend on Abseil for its pre-adopted `std::` types. You should remove this flag from your build command.", -) - -int_flag( - name = "abi_version_no", - build_setting_default = 1, -) - -config_setting( - name = "abi_version_no_1", - flag_values = {":abi_version_no": "1"}, -) - -config_setting( - name = "abi_version_no_2", - flag_values = {":abi_version_no": "2"}, -) diff --git a/ext/opentelemetry-cpp-1.21.0/api/CMakeLists.txt b/ext/opentelemetry-cpp-1.21.0/api/CMakeLists.txt deleted file mode 100644 index 0707464b3..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/CMakeLists.txt +++ /dev/null @@ -1,140 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -add_library(opentelemetry_api INTERFACE) -target_include_directories( - opentelemetry_api - INTERFACE "$" - "$") - -set_target_properties(opentelemetry_api PROPERTIES EXPORT_NAME api) - -otel_add_component( - COMPONENT - api - TARGETS - opentelemetry_api - FILES_DIRECTORY - "include/opentelemetry" - FILES_DESTINATION - "include" - FILES_MATCHING - PATTERN - "*.h") - -if(OPENTELEMETRY_INSTALL) - unset(TARGET_DEPS) -endif() - -if(BUILD_TESTING) - add_subdirectory(test) -endif() - -if(WITH_NO_DEPRECATED_CODE) - target_compile_definitions(opentelemetry_api - INTERFACE OPENTELEMETRY_NO_DEPRECATED_CODE) -endif() - -if(WITH_STL STREQUAL "OFF") - message(STATUS "Building WITH_STL=OFF") -elseif(WITH_STL STREQUAL "CXX11") - message(STATUS "Building WITH_STL=CXX11") - target_compile_definitions(opentelemetry_api - INTERFACE OPENTELEMETRY_STL_VERSION=2011) -elseif(WITH_STL STREQUAL "CXX14") - message(STATUS "Building WITH_STL=CXX14") - target_compile_definitions(opentelemetry_api - INTERFACE OPENTELEMETRY_STL_VERSION=2014) -elseif(WITH_STL STREQUAL "CXX17") - message(STATUS "Building WITH_STL=CXX17") - target_compile_definitions(opentelemetry_api - INTERFACE OPENTELEMETRY_STL_VERSION=2017) -elseif(WITH_STL STREQUAL "CXX20") - message(STATUS "Building WITH_STL=CXX20") - target_compile_definitions(opentelemetry_api - INTERFACE OPENTELEMETRY_STL_VERSION=2020) -elseif(WITH_STL STREQUAL "CXX23") - message(STATUS "Building WITH_STL=CXX23") - target_compile_definitions(opentelemetry_api - INTERFACE OPENTELEMETRY_STL_VERSION=2023) -elseif(WITH_STL STREQUAL "ON") - message(STATUS "Building WITH_STL=ON") - # "ON" corresponds to "CXX23" at this time. - target_compile_definitions(opentelemetry_api - INTERFACE OPENTELEMETRY_STL_VERSION=2023) -else() - message( - FATAL_ERROR "WITH_STL must be ON, OFF, CXX11, CXX14, CXX17, CXX20 or CXX23") -endif() - -if(WITH_GSL) - target_compile_definitions(opentelemetry_api INTERFACE HAVE_GSL) - - # Guidelines Support Library path. Used if we are not on not get C++20. - # - find_package(Microsoft.GSL QUIET) - if(TARGET Microsoft.GSL::GSL) - target_link_libraries(opentelemetry_api INTERFACE Microsoft.GSL::GSL) - list(APPEND TARGET_DEPS "gsl") - else() - set(GSL_DIR third_party/ms-gsl) - target_include_directories( - opentelemetry_api INTERFACE "$") - endif() -endif() - -if(WITH_NO_GETENV) - target_compile_definitions(opentelemetry_api INTERFACE NO_GETENV) -endif() - -if(WIN32) - if(WITH_ETW) - target_compile_definitions(opentelemetry_api INTERFACE HAVE_MSGPACK) - endif() -endif() - -if(WITH_ASYNC_EXPORT_PREVIEW) - target_compile_definitions(opentelemetry_api INTERFACE ENABLE_ASYNC_EXPORT) -endif() - -target_compile_definitions( - opentelemetry_api - INTERFACE OPENTELEMETRY_ABI_VERSION_NO=${OPENTELEMETRY_ABI_VERSION_NO}) - -if(WITH_OTLP_RETRY_PREVIEW) - target_compile_definitions(opentelemetry_api - INTERFACE ENABLE_OTLP_RETRY_PREVIEW) -endif() - -if(WITH_OTLP_GRPC_SSL_MTLS_PREVIEW) - target_compile_definitions(opentelemetry_api - INTERFACE ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW) -endif() - -if(WITH_METRICS_EXEMPLAR_PREVIEW) - target_compile_definitions(opentelemetry_api - INTERFACE ENABLE_METRICS_EXEMPLAR_PREVIEW) -endif() - -if(WITH_THREAD_INSTRUMENTATION_PREVIEW) - target_compile_definitions(opentelemetry_api - INTERFACE ENABLE_THREAD_INSTRUMENTATION_PREVIEW) -endif() - -if(WITH_OTLP_HTTP_COMPRESSION) - target_compile_definitions(opentelemetry_api - INTERFACE ENABLE_OTLP_COMPRESSION_PREVIEW) -endif() - -if(APPLE) - target_link_libraries(opentelemetry_api INTERFACE "-framework CoreFoundation") -endif() - -include(${PROJECT_SOURCE_DIR}/cmake/pkgconfig.cmake) - -if(OPENTELEMETRY_INSTALL) - opentelemetry_add_pkgconfig( - api "OpenTelemetry API" - "A header-only library to support instrumentation with OpenTelemetry." - "${TARGET_DEPS}") -endif() diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/baggage.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/baggage.h deleted file mode 100644 index 6c799cda2..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/baggage.h +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/common/kv_properties.h" -#include "opentelemetry/common/macros.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE - -namespace baggage -{ - -class OPENTELEMETRY_EXPORT Baggage -{ -public: - static constexpr size_t kMaxKeyValuePairs = 180; - static constexpr size_t kMaxKeyValueSize = 4096; - static constexpr size_t kMaxSize = 8192; - static constexpr char kKeyValueSeparator = '='; - static constexpr char kMembersSeparator = ','; - static constexpr char kMetadataSeparator = ';'; - - Baggage() noexcept : kv_properties_(new common::KeyValueProperties()) {} - Baggage(size_t size) noexcept : kv_properties_(new common::KeyValueProperties(size)) {} - - template - Baggage(const T &keys_and_values) noexcept - : kv_properties_(new common::KeyValueProperties(keys_and_values)) - {} - - OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr GetDefault() - { - static nostd::shared_ptr baggage{new Baggage()}; - return baggage; - } - - /* Get value for key in the baggage - @returns true if key is found, false otherwise - */ - bool GetValue(nostd::string_view key, std::string &value) const noexcept - { - return kv_properties_->GetValue(key, value); - } - - /* Returns shared_ptr of new baggage object which contains new key-value pair. If key or value is - invalid, copy of current baggage is returned - */ - nostd::shared_ptr Set(const nostd::string_view &key, - const nostd::string_view &value) noexcept - { - - nostd::shared_ptr baggage(new Baggage(kv_properties_->Size() + 1)); - const bool valid_kv = IsValidKey(key) && IsValidValue(value); - - if (valid_kv) - { - baggage->kv_properties_->AddEntry(key, value); - } - - // add rest of the fields. - kv_properties_->GetAllEntries( - [&baggage, &key, &valid_kv](nostd::string_view e_key, nostd::string_view e_value) { - // if key or value was not valid, add all the entries. Add only remaining entries - // otherwise. - if (!valid_kv || key != e_key) - { - baggage->kv_properties_->AddEntry(e_key, e_value); - } - - return true; - }); - - return baggage; - } - - // @return all key-values entries by repeatedly invoking the function reference passed as argument - // for each entry - bool GetAllEntries( - nostd::function_ref callback) const noexcept - { - return kv_properties_->GetAllEntries(callback); - } - - // delete key from the baggage if it exists. Returns shared_ptr of new baggage object. - // if key does not exist, copy of current baggage is returned. - // Validity of key is not checked as invalid keys should never be populated in baggage in the - // first place. - nostd::shared_ptr Delete(nostd::string_view key) noexcept - { - // keeping size of baggage same as key might not be found in it - nostd::shared_ptr baggage(new Baggage(kv_properties_->Size())); - kv_properties_->GetAllEntries( - [&baggage, &key](nostd::string_view e_key, nostd::string_view e_value) { - if (key != e_key) - baggage->kv_properties_->AddEntry(e_key, e_value); - return true; - }); - return baggage; - } - - // Returns shared_ptr of baggage after extracting key-value pairs from header - static nostd::shared_ptr FromHeader(nostd::string_view header) noexcept - { - if (header.size() > kMaxSize) - { - // header size exceeds maximum threshold, return empty baggage - return GetDefault(); - } - - common::KeyValueStringTokenizer kv_str_tokenizer(header); - size_t cnt = kv_str_tokenizer.NumTokens(); // upper bound on number of kv pairs - if (cnt > kMaxKeyValuePairs) - { - cnt = kMaxKeyValuePairs; - } - - nostd::shared_ptr baggage(new Baggage(cnt)); - bool kv_valid; - nostd::string_view key, value; - - while (kv_str_tokenizer.next(kv_valid, key, value) && baggage->kv_properties_->Size() < cnt) - { - if (!kv_valid || (key.size() + value.size() > kMaxKeyValueSize)) - { - // if kv pair is not valid, skip it - continue; - } - - // NOTE : metadata is kept as part of value only as it does not have any semantic meaning. - // but, we need to extract it (else Decode on value will return error) - nostd::string_view metadata; - auto metadata_separator = value.find(kMetadataSeparator); - if (metadata_separator != std::string::npos) - { - metadata = value.substr(metadata_separator); - value = value.substr(0, metadata_separator); - } - - bool err = 0; - auto key_str = UrlDecode(common::StringUtil::Trim(key), err); - auto value_str = UrlDecode(common::StringUtil::Trim(value), err); - - if (err == false && IsValidKey(key_str) && IsValidValue(value_str)) - { - if (!metadata.empty()) - { - value_str.append(metadata.data(), metadata.size()); - } - baggage->kv_properties_->AddEntry(key_str, value_str); - } - } - - return baggage; - } - - // Creates string from baggage object. - std::string ToHeader() const noexcept - { - std::string header_s; - bool first = true; - kv_properties_->GetAllEntries([&](nostd::string_view key, nostd::string_view value) { - if (!first) - { - header_s.push_back(kMembersSeparator); - } - else - { - first = false; - } - header_s.append(UrlEncode(key)); - header_s.push_back(kKeyValueSeparator); - - // extracting metadata from value. We do not encode metadata - auto metadata_separator = value.find(kMetadataSeparator); - if (metadata_separator != std::string::npos) - { - header_s.append(UrlEncode(value.substr(0, metadata_separator))); - auto metadata = value.substr(metadata_separator); - header_s.append(std::string(metadata.data(), metadata.size())); - } - else - { - header_s.append(UrlEncode(value)); - } - return true; - }); - return header_s; - } - -private: - static bool IsPrintableString(nostd::string_view str) - { - for (const auto ch : str) - { - if (ch < ' ' || ch > '~') - { - return false; - } - } - - return true; - } - - static bool IsValidKey(nostd::string_view key) { return key.size() && IsPrintableString(key); } - - static bool IsValidValue(nostd::string_view value) { return IsPrintableString(value); } - - // Uri encode key value pairs before injecting into header - // Implementation inspired from : https://golang.org/src/net/url/url.go?s=7851:7884#L264 - static std::string UrlEncode(nostd::string_view str) - { - auto to_hex = [](char c) -> char { - static const char *hex = "0123456789ABCDEF"; - return hex[c & 15]; - }; - - std::string ret; - - for (auto c : str) - { - if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') - { - ret.push_back(c); - } - else if (c == ' ') - { - ret.push_back('+'); - } - else - { - ret.push_back('%'); - ret.push_back(to_hex(c >> 4)); - ret.push_back(to_hex(c & 15)); - } - } - - return ret; - } - - // Uri decode key value pairs after extracting from header - static std::string UrlDecode(nostd::string_view str, bool &err) - { - auto IsHex = [](char c) { - return std::isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); - }; - - auto from_hex = [](char c) -> char { - // c - '0' produces integer type which could trigger error/warning when casting to char, - // but the cast is safe here. - return static_cast(std::isdigit(c) ? c - '0' : std::toupper(c) - 'A' + 10); - }; - - std::string ret; - - for (size_t i = 0; i < str.size(); i++) - { - if (str[i] == '%') - { - if (i + 2 >= str.size() || !IsHex(str[i + 1]) || !IsHex(str[i + 2])) - { - err = 1; - return ""; - } - ret.push_back(from_hex(str[i + 1]) << 4 | from_hex(str[i + 2])); - i += 2; - } - else if (str[i] == '+') - { - ret.push_back(' '); - } - else if (std::isalnum(str[i]) || str[i] == '-' || str[i] == '_' || str[i] == '.' || - str[i] == '~') - { - ret.push_back(str[i]); - } - else - { - err = 1; - return ""; - } - } - - return ret; - } - -private: - // Store entries in a C-style array to avoid using std::array or std::vector. - nostd::unique_ptr kv_properties_; -}; - -} // namespace baggage - -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/baggage_context.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/baggage_context.h deleted file mode 100644 index a0016353b..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/baggage_context.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/baggage/baggage.h" -#include "opentelemetry/context/context.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE - -namespace baggage -{ - -static const std::string kBaggageHeader = "baggage"; - -inline nostd::shared_ptr GetBaggage(const context::Context &context) noexcept -{ - context::ContextValue context_value = context.GetValue(kBaggageHeader); - if (nostd::holds_alternative>(context_value)) - { - return nostd::get>(context_value); - } - static nostd::shared_ptr empty_baggage{new Baggage()}; - return empty_baggage; -} - -inline context::Context SetBaggage(context::Context &context, - const nostd::shared_ptr &baggage) noexcept -{ - return context.SetValue(kBaggageHeader, baggage); -} - -} // namespace baggage -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/propagation/baggage_propagator.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/propagation/baggage_propagator.h deleted file mode 100644 index d75409ed6..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/baggage/propagation/baggage_propagator.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/baggage/baggage.h" -#include "opentelemetry/baggage/baggage_context.h" -#include "opentelemetry/context/context.h" -#include "opentelemetry/context/propagation/text_map_propagator.h" -#include "opentelemetry/nostd/function_ref.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace baggage -{ -namespace propagation -{ - -class BaggagePropagator : public context::propagation::TextMapPropagator -{ -public: - void Inject(context::propagation::TextMapCarrier &carrier, - const context::Context &context) noexcept override - { - auto baggage = baggage::GetBaggage(context); - auto header = baggage->ToHeader(); - if (header.size()) - { - carrier.Set(kBaggageHeader, header); - } - } - - context::Context Extract(const context::propagation::TextMapCarrier &carrier, - context::Context &context) noexcept override - { - nostd::string_view baggage_str = carrier.Get(baggage::kBaggageHeader); - auto baggage = baggage::Baggage::FromHeader(baggage_str); - - if (baggage->ToHeader().size()) - { - return baggage::SetBaggage(context, baggage); - } - else - { - return context; - } - } - - bool Fields(nostd::function_ref callback) const noexcept override - { - return callback(kBaggageHeader); - } -}; -} // namespace propagation -} // namespace baggage -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/attribute_value.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/attribute_value.h deleted file mode 100644 index af4cc83d4..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/attribute_value.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/nostd/span.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/variant.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ -/// OpenTelemetry signals can be enriched by adding attributes. The -/// \c AttributeValue type is defined as a variant of all attribute value -/// types the OpenTelemetry C++ API supports. -/// -/// The following attribute value types are supported by the OpenTelemetry -/// specification: -/// - Primitive types: string, boolean, double precision floating point -/// (IEEE 754-1985) or signed 64 bit integer. -/// - Homogenous arrays of primitive type values. -/// -/// \warning -/// \parblock The OpenTelemetry C++ API currently supports several attribute -/// value types that are not covered by the OpenTelemetry specification: -/// - \c uint64_t -/// - \c nostd::span -/// - \c nostd::span -/// -/// Those types are reserved for future use and currently should not be -/// used. There are no guarantees around how those values are handled by -/// exporters. -/// \endparblock -using AttributeValue = - nostd::variant, - nostd::span, - nostd::span, - nostd::span, - nostd::span, - nostd::span, - // Not currently supported by the specification, but reserved for future use. - // Added to provide support for all primitive C++ types. - uint64_t, - // Not currently supported by the specification, but reserved for future use. - // Added to provide support for all primitive C++ types. - nostd::span, - // Not currently supported by the specification, but reserved for future use. - // See https://github.com/open-telemetry/opentelemetry-specification/issues/780 - nostd::span>; - -enum AttributeType -{ - kTypeBool, - kTypeInt, - kTypeInt64, - kTypeUInt, - kTypeDouble, - kTypeCString, - kTypeString, - kTypeSpanBool, - kTypeSpanInt, - kTypeSpanInt64, - kTypeSpanUInt, - kTypeSpanDouble, - kTypeSpanString, - kTypeUInt64, - kTypeSpanUInt64, - kTypeSpanByte -}; - -} // namespace common -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/key_value_iterable.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/key_value_iterable.h deleted file mode 100644 index 9d43e1571..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/key_value_iterable.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/common/attribute_value.h" -#include "opentelemetry/nostd/function_ref.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ -/** - * Supports internal iteration over a collection of key-value pairs. - */ -class KeyValueIterable -{ -public: - virtual ~KeyValueIterable() = default; - - /** - * Iterate over key-value pairs - * @param callback a callback to invoke for each key-value. If the callback returns false, - * the iteration is aborted. - * @return true if every key-value pair was iterated over - */ - virtual bool ForEachKeyValue(nostd::function_ref - callback) const noexcept = 0; - - /** - * @return the number of key-value pairs - */ - virtual size_t size() const noexcept = 0; -}; - -/** - * Supports internal iteration over a collection of key-value pairs. - */ -class NoopKeyValueIterable : public KeyValueIterable -{ -public: - ~NoopKeyValueIterable() override = default; - - /** - * Iterate over key-value pairs - * @param callback a callback to invoke for each key-value. If the callback returns false, - * the iteration is aborted. - * @return true if every key-value pair was iterated over - */ - bool ForEachKeyValue( - nostd::function_ref) const noexcept override - { - return true; - } - - /** - * @return the number of key-value pairs - */ - size_t size() const noexcept override { return 0; } -}; - -} // namespace common -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/key_value_iterable_view.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/key_value_iterable_view.h deleted file mode 100644 index e22fb6f06..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/key_value_iterable_view.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "opentelemetry/common/attribute_value.h" -#include "opentelemetry/common/key_value_iterable.h" -#include "opentelemetry/nostd/function_ref.h" -#include "opentelemetry/nostd/span.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/type_traits.h" -#include "opentelemetry/nostd/utility.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ -// NOTE - code within `detail` namespace implements internal details, and not part -// of the public interface. -namespace detail -{ -inline void take_key_value(nostd::string_view, common::AttributeValue) {} - -template -auto is_key_value_iterable_impl(T iterable) - -> decltype(take_key_value(std::begin(iterable)->first, std::begin(iterable)->second), - nostd::size(iterable), - std::true_type{}); - -std::false_type is_key_value_iterable_impl(...); - -template -struct is_key_value_iterable -{ - static const bool value = decltype(detail::is_key_value_iterable_impl(std::declval()))::value; -}; -} // namespace detail - -/** - * @brief Container for key-value pairs that can transform every value in it to one of types - * listed in common::AttributeValue. It may contain value types that are not directly map'able - * to primitive value types. In that case the `ForEachKeyValue` method acts as a transform to - * convert the value type to one listed under AtributeValue (bool, int32_t, int64_t, uint32_t, - * uint64_t, double, nostd::string_view, or arrays of primite types). For example, if UUID, - * GUID, or UTF-16 string type is passed as one of values stored inside this container, the - * container itself may provide a custom implementation of `ForEachKeyValue` to transform the - * 'non-standard' type to one of the standard types. - */ -template -class KeyValueIterableView final : public KeyValueIterable -{ - -public: - explicit KeyValueIterableView(const T &container) noexcept : container_{&container} {} - - // KeyValueIterable - bool ForEachKeyValue(nostd::function_ref - callback) const noexcept override - { - auto iter = std::begin(*container_); - auto last = std::end(*container_); - for (; iter != last; ++iter) - { - if (!callback(iter->first, iter->second)) - { - return false; - } - } - return true; - } - - size_t size() const noexcept override { return nostd::size(*container_); } - -private: - const T *container_; -}; - -template ::value> * = nullptr> -KeyValueIterableView MakeKeyValueIterableView(const T &container) noexcept -{ - return KeyValueIterableView(container); -} - -/** - * Utility function to help to make a attribute view from initializer_list - * - * @param attributes - * @return nostd::span> - */ -inline static nostd::span> -MakeAttributes(std::initializer_list> - attributes) noexcept -{ - return nostd::span>{ - attributes.begin(), attributes.end()}; -} - -/** - * Utility function to help to make a attribute view from a span - * - * @param attributes - * @return nostd::span> - */ -inline static nostd::span> -MakeAttributes( - nostd::span> attributes) noexcept -{ - return attributes; -} - -/** - * Utility function to help to make a attribute view from a KeyValueIterable - * - * @param attributes - * @return common::KeyValueIterable - */ -inline static const common::KeyValueIterable &MakeAttributes( - const common::KeyValueIterable &attributes) noexcept -{ - return attributes; -} - -/** - * Utility function to help to make a attribute view from a key-value iterable object - * - * @param attributes - * @return nostd::span> - */ -template < - class ArgumentType, - nostd::enable_if_t::value> * = nullptr> -inline static common::KeyValueIterableView MakeAttributes( - const ArgumentType &arg) noexcept -{ - return common::KeyValueIterableView(arg); -} - -} // namespace common -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/kv_properties.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/kv_properties.h deleted file mode 100644 index b5accab40..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/kv_properties.h +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/common/key_value_iterable_view.h" -#include "opentelemetry/common/string_util.h" -#include "opentelemetry/nostd/function_ref.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/unique_ptr.h" -#include "opentelemetry/version.h" - -#include -#include -#include - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ - -// Constructor parameter for KeyValueStringTokenizer -struct KeyValueStringTokenizerOptions -{ - char member_separator = ','; - char key_value_separator = '='; - bool ignore_empty_members = true; -}; - -// Tokenizer for key-value headers -class KeyValueStringTokenizer -{ -public: - KeyValueStringTokenizer( - nostd::string_view str, - const KeyValueStringTokenizerOptions &opts = KeyValueStringTokenizerOptions()) noexcept - : str_(str), opts_(opts), index_(0) - {} - - static nostd::string_view GetDefaultKeyOrValue() - { - static std::string default_str = ""; - return default_str; - } - - // Returns next key value in the string header - // @param valid_kv : if the found kv pair is valid or not - // @param key : key in kv pair - // @param key : value in kv pair - // @returns true if next kv pair was found, false otherwise. - bool next(bool &valid_kv, nostd::string_view &key, nostd::string_view &value) noexcept - { - valid_kv = true; - while (index_ < str_.size()) - { - bool is_empty_pair = false; - size_t end = str_.find(opts_.member_separator, index_); - if (end == std::string::npos) - { - end = str_.size() - 1; - } - else if (end == index_) // empty pair. do not update end - { - is_empty_pair = true; - } - else - { - end--; - } - - auto list_member = StringUtil::Trim(str_, index_, end); - if (list_member.size() == 0 || is_empty_pair) - { - // empty list member - index_ = end + 2 - is_empty_pair; - if (opts_.ignore_empty_members) - { - continue; - } - - valid_kv = true; - key = GetDefaultKeyOrValue(); - value = GetDefaultKeyOrValue(); - return true; - } - - auto key_end_pos = list_member.find(opts_.key_value_separator); - if (key_end_pos == std::string::npos) - { - // invalid member - valid_kv = false; - } - else - { - key = list_member.substr(0, key_end_pos); - value = list_member.substr(key_end_pos + 1); - } - - index_ = end + 2; - - return true; - } - - // no more entries remaining - return false; - } - - // Returns total number of tokens in header string - size_t NumTokens() const noexcept - { - size_t cnt = 0, begin = 0; - while (begin < str_.size()) - { - ++cnt; - size_t end = str_.find(opts_.member_separator, begin); - if (end == std::string::npos) - { - break; - } - - begin = end + 1; - } - - return cnt; - } - - // Resets the iterator - void reset() noexcept { index_ = 0; } - -private: - nostd::string_view str_; - KeyValueStringTokenizerOptions opts_; - size_t index_; -}; - -// Class to store fixed size array of key-value pairs of string type -class KeyValueProperties -{ - // Class to store key-value pairs of string types -public: - class Entry - { - public: - Entry() : key_(nullptr), value_(nullptr) {} - - // Copy constructor - Entry(const Entry ©) - { - key_ = CopyStringToPointer(copy.key_.get()); - value_ = CopyStringToPointer(copy.value_.get()); - } - - // Copy assignment operator - Entry &operator=(Entry &other) - { - key_ = CopyStringToPointer(other.key_.get()); - value_ = CopyStringToPointer(other.value_.get()); - return *this; - } - - // Move contructor and assignment operator - Entry(Entry &&other) = default; - Entry &operator=(Entry &&other) = default; - - // Creates an Entry for a given key-value pair. - Entry(nostd::string_view key, nostd::string_view value) - { - key_ = CopyStringToPointer(key); - value_ = CopyStringToPointer(value); - } - - // Gets the key associated with this entry. - nostd::string_view GetKey() const noexcept { return key_.get(); } - - // Gets the value associated with this entry. - nostd::string_view GetValue() const noexcept { return value_.get(); } - - // Sets the value for this entry. This overrides the previous value. - void SetValue(nostd::string_view value) noexcept { value_ = CopyStringToPointer(value); } - - private: - // Store key and value as raw char pointers to avoid using std::string. - nostd::unique_ptr key_; - nostd::unique_ptr value_; - - // Copies string into a buffer and returns a unique_ptr to the buffer. - // This is a workaround for the fact that memcpy doesn't accept a const destination. - nostd::unique_ptr CopyStringToPointer(nostd::string_view str) - { - char *temp = new char[str.size() + 1]; - memcpy(temp, str.data(), str.size()); - temp[str.size()] = '\0'; - return nostd::unique_ptr(temp); - } - }; - - // Maintain the number of entries in entries_. - size_t num_entries_; - - // Max size of allocated array - size_t max_num_entries_; - - // Store entries in a C-style array to avoid using std::array or std::vector. - nostd::unique_ptr entries_; - -public: - // Create Key-value list of given size - // @param size : Size of list. - KeyValueProperties(size_t size) noexcept - : num_entries_(0), max_num_entries_(size), entries_(new Entry[size]) - {} - - // Create Empty Key-Value list - KeyValueProperties() noexcept : num_entries_(0), max_num_entries_(0), entries_(nullptr) {} - - template ::value>::type> - KeyValueProperties(const T &keys_and_values) noexcept - : num_entries_(0), - max_num_entries_(keys_and_values.size()), - entries_(new Entry[max_num_entries_]) - { - for (auto &e : keys_and_values) - { - Entry entry(e.first, e.second); - (entries_.get())[num_entries_++] = std::move(entry); - } - } - - // Adds new kv pair into kv properties - void AddEntry(nostd::string_view key, nostd::string_view value) noexcept - { - if (num_entries_ < max_num_entries_) - { - Entry entry(key, value); - (entries_.get())[num_entries_++] = std::move(entry); - } - } - - // Returns all kv pair entries - bool GetAllEntries( - nostd::function_ref callback) const noexcept - { - for (size_t i = 0; i < num_entries_; i++) - { - auto &entry = (entries_.get())[i]; - if (!callback(entry.GetKey(), entry.GetValue())) - { - return false; - } - } - return true; - } - - // Return value for key if exists, return false otherwise - bool GetValue(nostd::string_view key, std::string &value) const noexcept - { - for (size_t i = 0; i < num_entries_; i++) - { - auto &entry = (entries_.get())[i]; - if (entry.GetKey() == key) - { - const auto &entry_value = entry.GetValue(); - value = std::string(entry_value.data(), entry_value.size()); - return true; - } - } - return false; - } - - size_t Size() const noexcept { return num_entries_; } -}; -} // namespace common -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/macros.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/macros.h deleted file mode 100644 index 71d12a57b..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/macros.h +++ /dev/null @@ -1,523 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -/* - OPENTELEMETRY_HAVE_BUILTIN&OPENTELEMETRY_HAVE_FEATURE - - Checks whether the compiler supports a Clang Feature Checking Macro, and if - so, checks whether it supports the provided builtin function "x" where x - is one of the functions noted in - https://clang.llvm.org/docs/LanguageExtensions.html - - Note: Use this macro to avoid an extra level of #ifdef __has_builtin check. - http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html -*/ -#if !defined(OPENTELEMETRY_HAVE_BUILTIN) -# ifdef __has_builtin -# define OPENTELEMETRY_HAVE_BUILTIN(x) __has_builtin(x) -# else -# define OPENTELEMETRY_HAVE_BUILTIN(x) 0 -# endif -#endif - -#if !defined(OPENTELEMETRY_HAVE_FEATURE) -# ifdef __has_feature -# define OPENTELEMETRY_HAVE_FEATURE(f) __has_feature(f) -# else -# define OPENTELEMETRY_HAVE_FEATURE(f) 0 -# endif -#endif - -/* - has feature - - OPENTELEMETRY_HAVE_ATTRIBUTE - - A function-like feature checking macro that is a wrapper around - `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a - nonzero constant integer if the attribute is supported or 0 if not. - - It evaluates to zero if `__has_attribute` is not defined by the compiler. - - GCC: https://gcc.gnu.org/gcc-5/changes.html - Clang: https://clang.llvm.org/docs/LanguageExtensions.html -*/ -#if !defined(OPENTELEMETRY_HAVE_ATTRIBUTE) -# ifdef __has_attribute -# define OPENTELEMETRY_HAVE_ATTRIBUTE(x) __has_attribute(x) -# else -# define OPENTELEMETRY_HAVE_ATTRIBUTE(x) 0 -# endif -#endif - -/* - OPENTELEMETRY_HAVE_CPP_ATTRIBUTE - - A function-like feature checking macro that accepts C++11 style attributes. - It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 - (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't - find `__has_cpp_attribute`, will evaluate to 0. -*/ -#if !defined(OPENTELEMETRY_HAVE_CPP_ATTRIBUTE) -# if defined(__cplusplus) && defined(__has_cpp_attribute) -// NOTE: requiring __cplusplus above should not be necessary, but -// works around https://bugs.llvm.org/show_bug.cgi?id=23435. -# define OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) -# else -# define OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(x) 0 -# endif -#endif - -/* - Expected usage pattern: - - if OPENTELEMETRY_LIKELY_CONDITION (ptr != nullptr) - { - do_something_likely(); - } else { - do_something_unlikely(); - } - - This pattern works with gcc/clang and __builtin_expect(), - as well as with C++20. - It is unclear if __builtin_expect() will be deprecated - in favor of C++20 [[likely]] or not. - - OPENTELEMETRY_LIKELY_CONDITION is preferred over OPENTELEMETRY_LIKELY, - to be revisited when C++20 is required. -*/ - -#if !defined(OPENTELEMETRY_LIKELY_CONDITION) && defined(__cplusplus) -// Only use likely with C++20 -# if __cplusplus >= 202002L -// GCC 9 has likely attribute but do not support declare it at the beginning of statement -# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) -# if __has_cpp_attribute(likely) -# define OPENTELEMETRY_LIKELY_CONDITION(C) (C) [[likely]] -# endif -# endif -# endif -#endif -#if !defined(OPENTELEMETRY_LIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__)) -// Only use if supported by the compiler -# define OPENTELEMETRY_LIKELY_CONDITION(C) (__builtin_expect(!!(C), true)) -#endif -#ifndef OPENTELEMETRY_LIKELY_CONDITION -// Do not use likely annotations -# define OPENTELEMETRY_LIKELY_CONDITION(C) (C) -#endif - -#if !defined(OPENTELEMETRY_UNLIKELY_CONDITION) && defined(__cplusplus) -// Only use unlikely with C++20 -# if __cplusplus >= 202002L -// GCC 9 has unlikely attribute but do not support declare it at the beginning of statement -# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) -# if __has_cpp_attribute(unlikely) -# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (C) [[unlikely]] -# endif -# endif -# endif -#endif -#if !defined(OPENTELEMETRY_UNLIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__)) -// Only use if supported by the compiler -# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (__builtin_expect(!!(C), false)) -#endif -#ifndef OPENTELEMETRY_UNLIKELY_CONDITION -// Do not use unlikely annotations -# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (C) -#endif - -/* - Expected usage pattern: - - if (ptr != nullptr) - OPENTELEMETRY_LIKELY - { - do_something_likely(); - } else { - do_something_unlikely(); - } - - This pattern works starting with C++20. - See https://en.cppreference.com/w/cpp/language/attributes/likely - - Please use OPENTELEMETRY_LIKELY_CONDITION instead for now. -*/ - -#if !defined(OPENTELEMETRY_LIKELY) && defined(__cplusplus) -// Only use likely with C++20 -# if __cplusplus >= 202002L -// GCC 9 has likely attribute but do not support declare it at the beginning of statement -# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) -# if __has_cpp_attribute(likely) -# define OPENTELEMETRY_LIKELY [[likely]] -# endif -# endif -# endif -#endif - -#ifndef OPENTELEMETRY_LIKELY -# define OPENTELEMETRY_LIKELY -#endif - -#if !defined(OPENTELEMETRY_UNLIKELY) && defined(__cplusplus) -// Only use unlikely with C++20 -# if __cplusplus >= 202002L -// GCC 9 has unlikely attribute but do not support declare it at the beginning of statement -# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) -# if __has_cpp_attribute(unlikely) -# define OPENTELEMETRY_UNLIKELY [[unlikely]] -# endif -# endif -# endif -#endif - -#ifndef OPENTELEMETRY_UNLIKELY -# define OPENTELEMETRY_UNLIKELY -#endif - -/// \brief Declare variable as maybe unused -/// usage: -/// OPENTELEMETRY_MAYBE_UNUSED int a; -/// class OPENTELEMETRY_MAYBE_UNUSED a; -/// OPENTELEMETRY_MAYBE_UNUSED int a(); -/// -#if defined(__cplusplus) && __cplusplus >= 201703L -# define OPENTELEMETRY_MAYBE_UNUSED [[maybe_unused]] -#elif defined(__clang__) -# define OPENTELEMETRY_MAYBE_UNUSED __attribute__((unused)) -#elif defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) -# define OPENTELEMETRY_MAYBE_UNUSED __attribute__((unused)) -#elif (defined(_MSC_VER) && _MSC_VER >= 1910) && (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -# define OPENTELEMETRY_MAYBE_UNUSED [[maybe_unused]] -#else -# define OPENTELEMETRY_MAYBE_UNUSED -#endif - -#ifndef OPENTELEMETRY_RTTI_ENABLED -# if defined(__clang__) -# if __has_feature(cxx_rtti) -# define OPENTELEMETRY_RTTI_ENABLED -# endif -# elif defined(__GNUG__) -# if defined(__GXX_RTTI) -# define OPENTELEMETRY_RTTI_ENABLED -# endif -# elif defined(_MSC_VER) -# if defined(_CPPRTTI) -# define OPENTELEMETRY_RTTI_ENABLED -# endif -# endif -#endif - -#if defined(__cplusplus) && __cplusplus >= 201402L -# define OPENTELEMETRY_DEPRECATED [[deprecated]] -#elif defined(__clang__) -# define OPENTELEMETRY_DEPRECATED __attribute__((deprecated)) -#elif defined(__GNUC__) -# define OPENTELEMETRY_DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) -# if _MSC_VER >= 1910 && defined(_MSVC_LANG) && _MSVC_LANG >= 201703L -# define OPENTELEMETRY_DEPRECATED [[deprecated]] -# else -# define OPENTELEMETRY_DEPRECATED __declspec(deprecated) -# endif -#else -# define OPENTELEMETRY_DEPRECATED -#endif - -#if defined(__cplusplus) && __cplusplus >= 201402L -# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) [[deprecated(msg)]] -#elif defined(__clang__) -# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __attribute__((deprecated(msg))) -#elif defined(__GNUC__) -# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __attribute__((deprecated(msg))) -#elif defined(_MSC_VER) -# if _MSC_VER >= 1910 && defined(_MSVC_LANG) && _MSVC_LANG >= 201703L -# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) [[deprecated(msg)]] -# else -# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __declspec(deprecated(msg)) -# endif -#else -# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) -#endif - -// Regex support -#if (__GNUC__ == 4 && (__GNUC_MINOR__ == 8 || __GNUC_MINOR__ == 9)) -# define OPENTELEMETRY_HAVE_WORKING_REGEX 0 -#else -# define OPENTELEMETRY_HAVE_WORKING_REGEX 1 -#endif - -/* clang-format off */ - -/** - @page HEADER_ONLY_SINGLETON Header only singleton. - - @section ELF_SINGLETON - - For clang and gcc, the desired coding pattern is as follows. - - @verbatim - class Foo - { - // (a) - __attribute__((visibility("default"))) - // (b) - T& get_singleton() - { - // (c) - static T singleton; - return singleton; - } - }; - @endverbatim - - (a) is needed when the code is build with - @code -fvisibility="hidden" @endcode - to ensure that all instances of (b) are visible to the linker. - - What is duplicated in the binary is @em code, in (b). - - The linker will make sure only one instance - of all the (b) methods is used. - - (c) is a singleton implemented inside a method. - - This is very desirable, because: - - - the C++ compiler guarantees that construction - of the variable (c) is thread safe. - - - constructors for (c) singletons are executed in code path order, - or not at all if the singleton is never used. - - @section OTHER_SINGLETON - - For other platforms, header only singletons are not supported at this -point. - - @section CODING_PATTERN - - The coding pattern to use in the source code is as follows - - @verbatim - class Foo - { - OPENTELEMETRY_API_SINGLETON - T& get_singleton() - { - static T singleton; - return singleton; - } - }; - @endverbatim -*/ - -/* clang-format on */ - -#if defined(__clang__) - -# define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) -# define OPENTELEMETRY_LOCAL_SYMBOL __attribute__((visibility("hidden"))) - -#elif defined(__GNUC__) - -# define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) -# define OPENTELEMETRY_LOCAL_SYMBOL __attribute__((visibility("hidden"))) - -#else - -/* Add support for other compilers here. */ - -# define OPENTELEMETRY_API_SINGLETON -# define OPENTELEMETRY_LOCAL_SYMBOL - -#endif - -// -// Atomic wrappers based on compiler intrinsics for memory read/write. -// The tailing number is read/write length in bits. -// -// N.B. Compiler intrinsic is used because the usage of C++ standard library is restricted in the -// OpenTelemetry C++ API. -// -#if defined(__GNUC__) - -# define OPENTELEMETRY_ATOMIC_READ_8(ptr) __atomic_load_n(ptr, __ATOMIC_SEQ_CST) -# define OPENTELEMETRY_ATOMIC_WRITE_8(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST) - -#elif defined(_MSC_VER) - -# include - -# define OPENTELEMETRY_ATOMIC_READ_8(ptr) \ - static_cast(_InterlockedCompareExchange8(reinterpret_cast(ptr), 0, 0)) -# define OPENTELEMETRY_ATOMIC_WRITE_8(ptr, value) \ - _InterlockedExchange8(reinterpret_cast(ptr), static_cast(value)) - -#else -# error port atomics read/write for the current platform -#endif - -/* clang-format on */ -// -// The if/elif order matters here. If both OPENTELEMETRY_BUILD_IMPORT_DLL and -// OPENTELEMETRY_BUILD_EXPORT_DLL are defined, the former takes precedence. -// -// TODO: consider define OPENTELEMETRY_EXPORT for cygwin/gcc, see below link. -// https://gcc.gnu.org/wiki/Visibility#How_to_use_the_new_C.2B-.2B-_visibility_support -// -#if defined(_MSC_VER) && defined(OPENTELEMETRY_BUILD_IMPORT_DLL) - -# define OPENTELEMETRY_EXPORT __declspec(dllimport) - -#elif defined(_MSC_VER) && defined(OPENTELEMETRY_BUILD_EXPORT_DLL) - -# define OPENTELEMETRY_EXPORT __declspec(dllexport) - -#else - -// -// build OpenTelemetry as static library or not on Windows. -// -# define OPENTELEMETRY_EXPORT - -#endif - -// OPENTELEMETRY_HAVE_EXCEPTIONS -// -// Checks whether the compiler both supports and enables exceptions. Many -// compilers support a "no exceptions" mode that disables exceptions. -// -// Generally, when OPENTELEMETRY_HAVE_EXCEPTIONS is not defined: -// -// * Code using `throw` and `try` may not compile. -// * The `noexcept` specifier will still compile and behave as normal. -// * The `noexcept` operator may still return `false`. -// -// For further details, consult the compiler's documentation. -#ifndef OPENTELEMETRY_HAVE_EXCEPTIONS -# if defined(__clang__) && ((__clang_major__ * 100) + __clang_minor__) < 306 -// Clang < 3.6 -// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro -# if defined(__EXCEPTIONS) && OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions) -# define OPENTELEMETRY_HAVE_EXCEPTIONS 1 -# endif // defined(__EXCEPTIONS) && OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions) -# elif OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions) -# define OPENTELEMETRY_HAVE_EXCEPTIONS 1 -// Handle remaining special cases and default to exceptions being supported. -# elif !(defined(__GNUC__) && !defined(__EXCEPTIONS) && !defined(__cpp_exceptions)) && \ - !(defined(_MSC_VER) && !defined(_CPPUNWIND)) -# define OPENTELEMETRY_HAVE_EXCEPTIONS 1 -# endif -#endif -#ifndef OPENTELEMETRY_HAVE_EXCEPTIONS -# define OPENTELEMETRY_HAVE_EXCEPTIONS 0 -#endif - -/* - OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function - parameter or implicit object parameter is retained by the return value of the - annotated function (or, for a parameter of a constructor, in the value of the - constructed object). This attribute causes warnings to be produced if a - temporary object does not live long enough. - - When applied to a reference parameter, the referenced object is assumed to be - retained by the return value of the function. When applied to a non-reference - parameter (for example, a pointer or a class type), all temporaries - referenced by the parameter are assumed to be retained by the return value of - the function. - - See also the upstream documentation: - https://clang.llvm.org/docs/AttributeReference.html#lifetimebound -*/ -#ifndef OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND -# if OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) -# define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] -# elif OPENTELEMETRY_HAVE_ATTRIBUTE(lifetimebound) -# define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) -# else -# define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND -# endif -#endif - -// OPENTELEMETRY_HAVE_MEMORY_SANITIZER -// -// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of -// a compiler instrumentation module and a run-time library. -#ifndef OPENTELEMETRY_HAVE_MEMORY_SANITIZER -# if !defined(__native_client__) && OPENTELEMETRY_HAVE_FEATURE(memory_sanitizer) -# define OPENTELEMETRY_HAVE_MEMORY_SANITIZER 1 -# else -# define OPENTELEMETRY_HAVE_MEMORY_SANITIZER 0 -# endif -#endif - -#if OPENTELEMETRY_HAVE_MEMORY_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_memory) -# define OPENTELEMETRY_SANITIZER_NO_MEMORY \ - __attribute__((no_sanitize_memory)) // __attribute__((no_sanitize("memory"))) -#else -# define OPENTELEMETRY_SANITIZER_NO_MEMORY -#endif - -// OPENTELEMETRY_HAVE_THREAD_SANITIZER -// -// ThreadSanitizer (TSan) is a fast data race detector. -#ifndef OPENTELEMETRY_HAVE_THREAD_SANITIZER -# if defined(__SANITIZE_THREAD__) -# define OPENTELEMETRY_HAVE_THREAD_SANITIZER 1 -# elif OPENTELEMETRY_HAVE_FEATURE(thread_sanitizer) -# define OPENTELEMETRY_HAVE_THREAD_SANITIZER 1 -# else -# define OPENTELEMETRY_HAVE_THREAD_SANITIZER 0 -# endif -#endif - -#if OPENTELEMETRY_HAVE_THREAD_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_thread) -# define OPENTELEMETRY_SANITIZER_NO_THREAD \ - __attribute__((no_sanitize_thread)) // __attribute__((no_sanitize("thread"))) -#else -# define OPENTELEMETRY_SANITIZER_NO_THREAD -#endif - -// OPENTELEMETRY_HAVE_ADDRESS_SANITIZER -// -// AddressSanitizer (ASan) is a fast memory error detector. -#ifndef OPENTELEMETRY_HAVE_ADDRESS_SANITIZER -# if defined(__SANITIZE_ADDRESS__) -# define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 1 -# elif OPENTELEMETRY_HAVE_FEATURE(address_sanitizer) -# define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 1 -# else -# define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 0 -# endif -#endif - -// OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER -// -// Hardware-Assisted AddressSanitizer (or HWASAN) is even faster than asan -// memory error detector which can use CPU features like ARM TBI, Intel LAM or -// AMD UAI. -#ifndef OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER -# if defined(__SANITIZE_HWADDRESS__) -# define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 1 -# elif OPENTELEMETRY_HAVE_FEATURE(hwaddress_sanitizer) -# define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 1 -# else -# define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 0 -# endif -#endif - -#if OPENTELEMETRY_HAVE_ADDRESS_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_address) -# define OPENTELEMETRY_SANITIZER_NO_ADDRESS \ - __attribute__((no_sanitize_address)) // __attribute__((no_sanitize("address"))) -#elif OPENTELEMETRY_HAVE_ADDRESS_SANITIZER && defined(_MSC_VER) && _MSC_VER >= 1928 -# define OPENTELEMETRY_SANITIZER_NO_ADDRESS __declspec(no_sanitize_address) -#elif OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize) -# define OPENTELEMETRY_SANITIZER_NO_ADDRESS __attribute__((no_sanitize("hwaddress"))) -#else -# define OPENTELEMETRY_SANITIZER_NO_ADDRESS -#endif diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/spin_lock_mutex.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/spin_lock_mutex.h deleted file mode 100644 index 7031fa4d2..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/spin_lock_mutex.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include - -#include "opentelemetry/version.h" - -#if defined(_MSC_VER) -# define _WINSOCKAPI_ // stops including winsock.h -# include -#elif defined(__i386__) || defined(__x86_64__) -# if defined(__clang__) -# include -# elif defined(__INTEL_COMPILER) -# include -# endif -#endif - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ - -constexpr int SPINLOCK_FAST_ITERATIONS = 100; -constexpr int SPINLOCK_SLEEP_MS = 1; - -/** - * A Mutex which uses atomic flags and spin-locks instead of halting threads. - * - * This mutex uses an incremental back-off strategy with the following phases: - * 1. A tight spin-lock loop (pending: using hardware PAUSE/YIELD instructions) - * 2. A loop where the current thread yields control after checking the lock. - * 3. Issuing a thread-sleep call before starting back in phase 1. - * - * This is meant to give a good balance of perofrmance and CPU consumption in - * practice. - * - * This mutex uses an incremental back-off strategy with the following phases: - * 1. A tight spin-lock loop (pending: using hardware PAUSE/YIELD instructions) - * 2. A loop where the current thread yields control after checking the lock. - * 3. Issuing a thread-sleep call before starting back in phase 1. - * - * This is meant to give a good balance of perofrmance and CPU consumption in - * practice. - * - * This class implements the `BasicLockable` specification: - * https://en.cppreference.com/w/cpp/named_req/BasicLockable - */ -class SpinLockMutex -{ -public: - SpinLockMutex() noexcept {} - ~SpinLockMutex() noexcept = default; - SpinLockMutex(const SpinLockMutex &) = delete; - SpinLockMutex &operator=(const SpinLockMutex &) = delete; - - static inline void fast_yield() noexcept - { -// Issue a Pause/Yield instruction while spinning. -#if defined(_MSC_VER) - YieldProcessor(); -#elif defined(__i386__) || defined(__x86_64__) -# if defined(__clang__) || defined(__INTEL_COMPILER) - _mm_pause(); -# else - __builtin_ia32_pause(); -# endif -#elif defined(__armel__) || defined(__ARMEL__) - asm volatile("nop" ::: "memory"); -#elif defined(__arm__) || defined(__aarch64__) // arm big endian / arm64 - __asm__ __volatile__("yield" ::: "memory"); -#else - // TODO: Issue PAGE/YIELD on other architectures. -#endif - } - - /** - * Attempts to lock the mutex. Return immediately with `true` (success) or `false` (failure). - */ - bool try_lock() noexcept - { - return !flag_.load(std::memory_order_relaxed) && - !flag_.exchange(true, std::memory_order_acquire); - } - - /** - * Blocks until a lock can be obtained for the current thread. - * - * This mutex will spin the current CPU waiting for the lock to be available. This can have - * decent performance in scenarios where there is low lock contention and lock-holders achieve - * their work quickly. It degrades in scenarios where locked tasks take a long time. - */ - void lock() noexcept - { - for (;;) - { - // Try once - if (!flag_.exchange(true, std::memory_order_acquire)) - { - return; - } - // Spin-Fast (goal ~10ns) - for (std::size_t i = 0; i < SPINLOCK_FAST_ITERATIONS; ++i) - { - if (try_lock()) - { - return; - } - fast_yield(); - } - // Yield then try again (goal ~100ns) - std::this_thread::yield(); - if (try_lock()) - { - return; - } - // Sleep and then start the whole process again. (goal ~1000ns) - std::this_thread::sleep_for(std::chrono::milliseconds(SPINLOCK_SLEEP_MS)); - } - return; - } - /** Releases the lock held by the execution agent. Throws no exceptions. */ - void unlock() noexcept { flag_.store(false, std::memory_order_release); } - -private: - std::atomic flag_{false}; -}; - -} // namespace common -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/string_util.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/string_util.h deleted file mode 100644 index 273a65272..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/string_util.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ - -class StringUtil -{ -public: - static nostd::string_view Trim(nostd::string_view str, size_t left, size_t right) noexcept - { - while (left <= right && isspace(str[left])) - { - left++; - } - while (left <= right && isspace(str[right])) - { - right--; - } - return str.substr(left, 1 + right - left); - } - - static nostd::string_view Trim(nostd::string_view str) noexcept - { - if (str.empty()) - { - return str; - } - - return Trim(str, 0, str.size() - 1); - } -}; - -} // namespace common - -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/timestamp.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/timestamp.h deleted file mode 100644 index f7c79b8b5..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/common/timestamp.h +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ -/** - * @brief A timepoint relative to the system clock epoch. - * - * This is used for marking the beginning and end of an operation. - */ -class SystemTimestamp -{ -public: - /** - * @brief Initializes a system timestamp pointing to the start of the epoch. - */ - SystemTimestamp() noexcept : nanos_since_epoch_{0} {} - - /** - * @brief Initializes a system timestamp from a duration. - * - * @param time_since_epoch Time elapsed since the beginning of the epoch. - */ - template - explicit SystemTimestamp(const std::chrono::duration &time_since_epoch) noexcept - : nanos_since_epoch_{static_cast( - std::chrono::duration_cast(time_since_epoch).count())} - {} - - /** - * @brief Initializes a system timestamp based on a point in time. - * - * @param time_point A point in time. - */ - /*implicit*/ SystemTimestamp(const std::chrono::system_clock::time_point &time_point) noexcept - : SystemTimestamp{time_point.time_since_epoch()} - {} - - /** - * @brief Returns a time point for the time stamp. - * - * @return A time point corresponding to the time stamp. - */ - operator std::chrono::system_clock::time_point() const noexcept - { - return std::chrono::system_clock::time_point{ - std::chrono::duration_cast( - std::chrono::nanoseconds{nanos_since_epoch_})}; - } - - /** - * @brief Returns the nanoseconds since the beginning of the epoch. - * - * @return Elapsed nanoseconds since the beginning of the epoch for this timestamp. - */ - std::chrono::nanoseconds time_since_epoch() const noexcept - { - return std::chrono::nanoseconds{nanos_since_epoch_}; - } - - /** - * @brief Compare two steady time stamps. - * - * @return true if the two time stamps are equal. - */ - bool operator==(const SystemTimestamp &other) const noexcept - { - return nanos_since_epoch_ == other.nanos_since_epoch_; - } - - /** - * @brief Compare two steady time stamps for inequality. - * - * @return true if the two time stamps are not equal. - */ - bool operator!=(const SystemTimestamp &other) const noexcept - { - return nanos_since_epoch_ != other.nanos_since_epoch_; - } - -private: - int64_t nanos_since_epoch_; -}; - -/** - * @brief A timepoint relative to the monotonic clock epoch - * - * This is used for calculating the duration of an operation. - */ -class SteadyTimestamp -{ -public: - /** - * @brief Initializes a monotonic timestamp pointing to the start of the epoch. - */ - SteadyTimestamp() noexcept : nanos_since_epoch_{0} {} - - /** - * @brief Initializes a monotonic timestamp from a duration. - * - * @param time_since_epoch Time elapsed since the beginning of the epoch. - */ - template - explicit SteadyTimestamp(const std::chrono::duration &time_since_epoch) noexcept - : nanos_since_epoch_{static_cast( - std::chrono::duration_cast(time_since_epoch).count())} - {} - - /** - * @brief Initializes a monotonic timestamp based on a point in time. - * - * @param time_point A point in time. - */ - /*implicit*/ SteadyTimestamp(const std::chrono::steady_clock::time_point &time_point) noexcept - : SteadyTimestamp{time_point.time_since_epoch()} - {} - - /** - * @brief Returns a time point for the time stamp. - * - * @return A time point corresponding to the time stamp. - */ - operator std::chrono::steady_clock::time_point() const noexcept - { - return std::chrono::steady_clock::time_point{ - std::chrono::duration_cast( - std::chrono::nanoseconds{nanos_since_epoch_})}; - } - - /** - * @brief Returns the nanoseconds since the beginning of the epoch. - * - * @return Elapsed nanoseconds since the beginning of the epoch for this timestamp. - */ - std::chrono::nanoseconds time_since_epoch() const noexcept - { - return std::chrono::nanoseconds{nanos_since_epoch_}; - } - - /** - * @brief Compare two steady time stamps. - * - * @return true if the two time stamps are equal. - */ - bool operator==(const SteadyTimestamp &other) const noexcept - { - return nanos_since_epoch_ == other.nanos_since_epoch_; - } - - /** - * @brief Compare two steady time stamps for inequality. - * - * @return true if the two time stamps are not equal. - */ - bool operator!=(const SteadyTimestamp &other) const noexcept - { - return nanos_since_epoch_ != other.nanos_since_epoch_; - } - -private: - int64_t nanos_since_epoch_; -}; - -class DurationUtil -{ -public: - template - static std::chrono::duration AdjustWaitForTimeout( - std::chrono::duration timeout, - std::chrono::duration indefinite_value) noexcept - { - // Do not call now() when this duration is max value, now() may have a expensive cost. - if (timeout == (std::chrono::duration::max)()) - { - return indefinite_value; - } - - // std::future::wait_for, std::this_thread::sleep_for, and std::condition_variable::wait_for - // may use steady_clock or system_clock.We need make sure now() + timeout do not overflow. - auto max_timeout = std::chrono::duration_cast>( - (std::chrono::steady_clock::time_point::max)() - std::chrono::steady_clock::now()); - if (timeout >= max_timeout) - { - return indefinite_value; - } - max_timeout = std::chrono::duration_cast>( - (std::chrono::system_clock::time_point::max)() - std::chrono::system_clock::now()); - if (timeout >= max_timeout) - { - return indefinite_value; - } - - return timeout; - } -}; - -} // namespace common -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/config.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/config.h deleted file mode 100644 index cb52f3b5d..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/config.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include // IWYU pragma: keep - -#if defined(OPENTELEMETRY_ABI_VERSION_NO) && OPENTELEMETRY_ABI_VERSION_NO >= 2 -# error \ - "opentelemetry/config.h is removed in ABI version 2 and later. Please use opentelemetry/version.h instead." -#else -# if defined(__clang__) || defined(__GNUC__) -# pragma GCC warning \ - "opentelemetry/config.h is deprecated. Please use opentelemetry/version.h instead." -# elif defined(_MSC_VER) -# pragma message( \ - "[WARNING]: opentelemetry/config.h is deprecated. Please use opentelemetry/version.h instead.") -# endif -#endif diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/context.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/context.h deleted file mode 100644 index 924036efa..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/context.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/context/context_value.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/variant.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace context -{ - -// The context class provides a context identifier. Is built as a linked list -// of DataList nodes and each context holds a shared_ptr to a place within -// the list that determines which keys and values it has access to. All that -// come before and none that come after. -class Context -{ - -public: - Context() = default; - // Creates a context object from a map of keys and identifiers, this will - // hold a shared_ptr to the head of the DataList linked list - template - Context(const T &keys_and_values) noexcept - : head_{nostd::shared_ptr{new DataList(keys_and_values)}} - {} - - // Creates a context object from a key and value, this will - // hold a shared_ptr to the head of the DataList linked list - Context(nostd::string_view key, ContextValue value) noexcept - : head_{nostd::shared_ptr{new DataList(key, value)}} - {} - - // Accepts a new iterable and then returns a new context that - // contains the new key and value data. It attaches the - // exisiting list to the end of the new list. - template - Context SetValues(T &values) noexcept - { - Context context = Context(values); - nostd::shared_ptr last = context.head_; - while (last->next_ != nullptr) - { - last = last->next_; - } - last->next_ = head_; - return context; - } - - // Accepts a new iterable and then returns a new context that - // contains the new key and value data. It attaches the - // exisiting list to the end of the new list. - Context SetValue(nostd::string_view key, ContextValue value) noexcept - { - Context context = Context(key, value); - context.head_->next_ = head_; - return context; - } - - // Returns the value associated with the passed in key. - context::ContextValue GetValue(const nostd::string_view key) const noexcept - { - for (DataList *data = head_.get(); data != nullptr; data = data->next_.get()) - { - if (key.size() == data->key_length_) - { - if (std::memcmp(key.data(), data->key_, data->key_length_) == 0) - { - return data->value_; - } - } - } - return ContextValue{}; - } - - // Checks for key and returns true if found - bool HasKey(const nostd::string_view key) const noexcept - { - return !nostd::holds_alternative(GetValue(key)); - } - - bool operator==(const Context &other) const noexcept { return (head_ == other.head_); } - -private: - // A linked list to contain the keys and values of this context node - struct DataList - { - char *key_ = nullptr; - - nostd::shared_ptr next_{nullptr}; - - size_t key_length_ = 0UL; - - ContextValue value_; - - DataList() = default; - - // Builds a data list off of a key and value iterable and returns the head - template - DataList(const T &keys_and_vals) - { - bool first = true; - auto *node = this; - for (auto &iter : keys_and_vals) - { - if (first) - { - *node = DataList(iter.first, iter.second); - first = false; - } - else - { - node->next_ = nostd::shared_ptr(new DataList(iter.first, iter.second)); - node = node->next_.get(); - } - } - } - - // Builds a data list with just a key and value, so it will just be the head - // and returns that head. - DataList(nostd::string_view key, const ContextValue &value) - { - key_ = new char[key.size()]; - key_length_ = key.size(); - std::memcpy(key_, key.data(), key.size() * sizeof(char)); - next_ = nostd::shared_ptr{nullptr}; - value_ = value; - } - - DataList(const DataList &other) - : key_(new char[other.key_length_]), - next_(other.next_), - key_length_(other.key_length_), - value_(other.value_) - { - std::memcpy(key_, other.key_, other.key_length_ * sizeof(char)); - } - - DataList &operator=(DataList &&other) noexcept - { - key_length_ = other.key_length_; - value_ = std::move(other.value_); - next_ = std::move(other.next_); - - key_ = other.key_; - other.key_ = nullptr; - - return *this; - } - - ~DataList() - { - if (key_ != nullptr) - { - delete[] key_; - } - } - }; - - // Head of the list which holds the keys and values of this context - nostd::shared_ptr head_; -}; -} // namespace context -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/context_value.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/context_value.h deleted file mode 100644 index 27bd40fb0..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/context_value.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/variant.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace baggage -{ -class Baggage; -} // namespace baggage - -namespace trace -{ -class Span; -class SpanContext; -} // namespace trace - -namespace context -{ -using ContextValue = nostd::variant, - nostd::shared_ptr, - nostd::shared_ptr>; -} // namespace context -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/composite_propagator.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/composite_propagator.h deleted file mode 100644 index f7afe23bf..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/composite_propagator.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/context/propagation/text_map_propagator.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace context -{ -namespace propagation -{ - -class CompositePropagator : public TextMapPropagator -{ -public: - CompositePropagator(std::vector> propagators) - : propagators_(std::move(propagators)) - {} - - /** - * Run each of the configured propagators with the given context and carrier. - * Propagators are run in the order they are configured, so if multiple - * propagators write the same carrier key, the propagator later in the list - * will "win". - * - * @param carrier Carrier into which context will be injected - * @param context Context to inject - * - */ - - void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept override - { - for (auto &p : propagators_) - { - p->Inject(carrier, context); - } - } - - /** - * Run each of the configured propagators with the given context and carrier. - * Propagators are run in the order they are configured, so if multiple - * propagators write the same context key, the propagator later in the list - * will "win". - * - * @param carrier Carrier from which to extract context - * @param context Context to add values to - */ - context::Context Extract(const TextMapCarrier &carrier, - context::Context &context) noexcept override - { - auto first = true; - context::Context tmp_context; - for (auto &p : propagators_) - { - if (first) - { - tmp_context = p->Extract(carrier, context); - first = false; - } - else - { - tmp_context = p->Extract(carrier, tmp_context); - } - } - return propagators_.size() ? tmp_context : context; - } - - /** - * Invoke callback with fields set to carrier by `inject` method for all the - * configured propagators - * Returns true if all invocation return true - */ - bool Fields(nostd::function_ref callback) const noexcept override - { - bool status = true; - for (auto &p : propagators_) - { - status = status && p->Fields(callback); - } - return status; - } - -private: - std::vector> propagators_; -}; -} // namespace propagation -} // namespace context -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/global_propagator.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/global_propagator.h deleted file mode 100644 index 85293202f..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/global_propagator.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/context/propagation/noop_propagator.h" - -#include "opentelemetry/common/macros.h" -#include "opentelemetry/common/spin_lock_mutex.h" -#include "opentelemetry/nostd/shared_ptr.h" - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace context -{ -namespace propagation -{ - -class TextMapPropagator; - -/* Stores the singleton TextMapPropagator */ - -class OPENTELEMETRY_EXPORT GlobalTextMapPropagator -{ -public: - static nostd::shared_ptr GetGlobalPropagator() noexcept - { - std::lock_guard guard(GetLock()); - return nostd::shared_ptr(GetPropagator()); - } - - static void SetGlobalPropagator(const nostd::shared_ptr &prop) noexcept - { - std::lock_guard guard(GetLock()); - GetPropagator() = prop; - } - -private: - OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetPropagator() noexcept - { - static nostd::shared_ptr propagator(new NoOpPropagator()); - return propagator; - } - - OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept - { - static common::SpinLockMutex lock; - return lock; - } -}; - -} // namespace propagation -} // namespace context -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/noop_propagator.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/noop_propagator.h deleted file mode 100644 index 4e1b30c17..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/noop_propagator.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/context/propagation/text_map_propagator.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace context -{ -namespace propagation -{ - -/** - * No-op implementation TextMapPropagator - */ -class NoOpPropagator : public TextMapPropagator -{ -public: - /** Noop extract function does nothing and returns the input context */ - context::Context Extract(const TextMapCarrier & /*carrier*/, - context::Context &context) noexcept override - { - return context; - } - - /** Noop inject function does nothing */ - void Inject(TextMapCarrier & /*carrier*/, - const context::Context & /* context */) noexcept override - {} - - bool Fields(nostd::function_ref /* callback */) const noexcept override - { - return true; - } -}; -} // namespace propagation -} // namespace context -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/text_map_propagator.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/text_map_propagator.h deleted file mode 100644 index 21bc29361..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/propagation/text_map_propagator.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/context/context.h" -#include "opentelemetry/nostd/function_ref.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace context -{ -namespace propagation -{ - -// TextMapCarrier is the storage medium used by TextMapPropagator. -class TextMapCarrier -{ -public: - // returns the value associated with the passed key. - virtual nostd::string_view Get(nostd::string_view key) const noexcept = 0; - - // stores the key-value pair. - virtual void Set(nostd::string_view key, nostd::string_view value) noexcept = 0; - - /* list of all the keys in the carrier. - By default, it returns true without invoking callback */ - virtual bool Keys(nostd::function_ref /* callback */) const noexcept - { - return true; - } - virtual ~TextMapCarrier() = default; -}; - -// The TextMapPropagator class provides an interface that enables extracting and injecting -// context into carriers that travel in-band across process boundaries. HTTP frameworks and clients -// can integrate with TextMapPropagator by providing the object containing the -// headers, and a getter and setter function for the extraction and -// injection of values, respectively. - -class TextMapPropagator -{ -public: - // Returns the context that is stored in the carrier with the TextMapCarrier as extractor. - virtual context::Context Extract(const TextMapCarrier &carrier, - context::Context &context) noexcept = 0; - - // Sets the context for carrier with self defined rules. - virtual void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept = 0; - - // Gets the fields set in the carrier by the `inject` method - virtual bool Fields(nostd::function_ref callback) const noexcept = 0; - - virtual ~TextMapPropagator() = default; -}; -} // namespace propagation -} // namespace context -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/runtime_context.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/runtime_context.h deleted file mode 100644 index e3f88254c..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/context/runtime_context.h +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/common/macros.h" -#include "opentelemetry/context/context.h" -#include "opentelemetry/context/context_value.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/unique_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace context -{ -// The Token object provides is returned when attaching objects to the -// RuntimeContext object and is associated with a context object, and -// can be provided to the RuntimeContext Detach method to remove the -// associated context from the RuntimeContext. -class Token -{ -public: - bool operator==(const Context &other) const noexcept { return context_ == other; } - - ~Token() noexcept; - -private: - friend class RuntimeContextStorage; - - // A constructor that sets the token's Context object to the - // one that was passed in. - Token(const Context &context) : context_(context) {} - - const Context context_; -}; - -/** - * RuntimeContextStorage is used by RuntimeContext to store Context frames. - * - * Custom context management strategies can be implemented by deriving from - * this class and passing an initialized RuntimeContextStorage object to - * RuntimeContext::SetRuntimeContextStorage. - */ -class OPENTELEMETRY_EXPORT RuntimeContextStorage -{ -public: - /** - * Return the current context. - * @return the current context - */ - virtual Context GetCurrent() noexcept = 0; - - /** - * Set the current context. - * @param the new current context - * @return a token for the new current context. This never returns a nullptr. - */ - virtual nostd::unique_ptr Attach(const Context &context) noexcept = 0; - - /** - * Detach the context related to the given token. - * @param token a token related to a context - * @return true if the context could be detached - */ - virtual bool Detach(Token &token) noexcept = 0; - - virtual ~RuntimeContextStorage() {} - -protected: - nostd::unique_ptr CreateToken(const Context &context) noexcept - { - return nostd::unique_ptr(new Token(context)); - } -}; - -/** - * Construct and return the default RuntimeContextStorage - * @return a ThreadLocalContextStorage - */ -static RuntimeContextStorage *GetDefaultStorage() noexcept; - -// Provides a wrapper for propagating the context object globally. -// -// By default, a thread-local runtime context storage is used. -class OPENTELEMETRY_EXPORT RuntimeContext -{ -public: - // Return the current context. - static Context GetCurrent() noexcept { return GetRuntimeContextStorage()->GetCurrent(); } - - // Sets the current 'Context' object. Returns a token - // that can be used to reset to the previous Context. - static nostd::unique_ptr Attach(const Context &context) noexcept - { - return GetRuntimeContextStorage()->Attach(context); - } - - // Resets the context to a previous value stored in the - // passed in token. Returns true if successful, false otherwise - static bool Detach(Token &token) noexcept { return GetRuntimeContextStorage()->Detach(token); } - - // Sets the Key and Value into the passed in context or if a context is not - // passed in, the RuntimeContext. - // Should be used to SetValues to the current RuntimeContext, is essentially - // equivalent to RuntimeContext::GetCurrent().SetValue(key,value). Keep in - // mind that the current RuntimeContext will not be changed, and the new - // context will be returned. - static Context SetValue(nostd::string_view key, - const ContextValue &value, - Context *context = nullptr) noexcept - { - Context temp_context; - if (context == nullptr) - { - temp_context = GetCurrent(); - } - else - { - temp_context = *context; - } - return temp_context.SetValue(key, value); - } - - // Returns the value associated with the passed in key and either the - // passed in context* or the runtime context if a context is not passed in. - // Should be used to get values from the current RuntimeContext, is - // essentially equivalent to RuntimeContext::GetCurrent().GetValue(key). - static ContextValue GetValue(nostd::string_view key, Context *context = nullptr) noexcept - { - Context temp_context; - if (context == nullptr) - { - temp_context = GetCurrent(); - } - else - { - temp_context = *context; - } - return temp_context.GetValue(key); - } - - /** - * Provide a custom runtime context storage. - * - * This provides a possibility to override the default thread-local runtime - * context storage. This has to be set before any spans are created by the - * application, otherwise the behavior is undefined. - * - * @param storage a custom runtime context storage - */ - static void SetRuntimeContextStorage( - const nostd::shared_ptr &storage) noexcept - { - GetStorage() = storage; - } - - /** - * Provide a pointer to const runtime context storage. - * - * The returned pointer can only be used for extending the lifetime of the runtime context - * storage. - * - */ - static nostd::shared_ptr GetConstRuntimeContextStorage() noexcept - { - return GetRuntimeContextStorage(); - } - -private: - static nostd::shared_ptr GetRuntimeContextStorage() noexcept - { - return GetStorage(); - } - - OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetStorage() noexcept - { - static nostd::shared_ptr context(GetDefaultStorage()); - return context; - } -}; - -inline Token::~Token() noexcept -{ - context::RuntimeContext::Detach(*this); -} - -// The ThreadLocalContextStorage class is a derived class from -// RuntimeContextStorage and provides a wrapper for propagating context through -// cpp thread locally. This file must be included to use the RuntimeContext -// class if another implementation has not been registered. -class ThreadLocalContextStorage : public RuntimeContextStorage -{ -public: - ThreadLocalContextStorage() noexcept = default; - - // Return the current context. - Context GetCurrent() noexcept override { return GetStack().Top(); } - - // Resets the context to the value previous to the passed in token. This will - // also detach all child contexts of the passed in token. - // Returns true if successful, false otherwise. - bool Detach(Token &token) noexcept override - { - // In most cases, the context to be detached is on the top of the stack. - if (token == GetStack().Top()) - { - GetStack().Pop(); - return true; - } - - if (!GetStack().Contains(token)) - { - return false; - } - - while (!(token == GetStack().Top())) - { - GetStack().Pop(); - } - - GetStack().Pop(); - - return true; - } - - // Sets the current 'Context' object. Returns a token - // that can be used to reset to the previous Context. - nostd::unique_ptr Attach(const Context &context) noexcept override - { - GetStack().Push(context); - return CreateToken(context); - } - -private: - // A nested class to store the attached contexts in a stack. - class Stack - { - friend class ThreadLocalContextStorage; - - Stack() noexcept : size_(0), capacity_(0), base_(nullptr) {} - - // Pops the top Context off the stack. - void Pop() noexcept - { - if (size_ == 0) - { - return; - } - // Store empty Context before decrementing `size`, to ensure - // the shared_ptr object (if stored in prev context object ) are released. - // The stack is not resized, and the unused memory would be reutilised - // for subsequent context storage. - base_[size_ - 1] = Context(); - size_ -= 1; - } - - bool Contains(const Token &token) const noexcept - { - for (size_t pos = size_; pos > 0; --pos) - { - if (token == base_[pos - 1]) - { - return true; - } - } - - return false; - } - - // Returns the Context at the top of the stack. - Context Top() const noexcept - { - if (size_ == 0) - { - return Context(); - } - return base_[size_ - 1]; - } - - // Pushes the passed in context pointer to the top of the stack - // and resizes if necessary. - void Push(const Context &context) noexcept - { - size_++; - if (size_ > capacity_) - { - Resize(size_ * 2); - } - base_[size_ - 1] = context; - } - - // Reallocates the storage array to the pass in new capacity size. - void Resize(size_t new_capacity) noexcept - { - size_t old_size = size_ - 1; - if (new_capacity == 0) - { - new_capacity = 2; - } - Context *temp = new Context[new_capacity]; - if (base_ != nullptr) - { - // vs2015 does not like this construct considering it unsafe: - // - std::copy(base_, base_ + old_size, temp); - // Ref. - // https://stackoverflow.com/questions/12270224/xutility2227-warning-c4996-std-copy-impl - for (size_t i = 0; i < (std::min)(old_size, new_capacity); i++) - { - temp[i] = base_[i]; - } - delete[] base_; - } - base_ = temp; - capacity_ = new_capacity; - } - - ~Stack() noexcept { delete[] base_; } - - size_t size_; - size_t capacity_; - Context *base_; - }; - - OPENTELEMETRY_API_SINGLETON Stack &GetStack() - { - static thread_local Stack stack_ = Stack(); - return stack_; - } -}; - -static RuntimeContextStorage *GetDefaultStorage() noexcept -{ - return new ThreadLocalContextStorage(); -} -} // namespace context -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/detail/preprocessor.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/detail/preprocessor.h deleted file mode 100644 index acdf02eb0..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/detail/preprocessor.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// NOTE - code within detail namespace implements internal details, and not part -// of the public interface. - -#pragma once - -#define OPENTELEMETRY_STRINGIFY(S) OPENTELEMETRY_STRINGIFY_(S) -#define OPENTELEMETRY_STRINGIFY_(S) #S - -#define OPENTELEMETRY_CONCAT(A, B) OPENTELEMETRY_CONCAT_(A, B) -#define OPENTELEMETRY_CONCAT_(A, B) A##B - -// Import the C++20 feature-test macros -#ifdef __has_include -# if __has_include() -# include -# endif -#elif defined(_MSC_VER) && ((defined(__cplusplus) && __cplusplus >= 202002L) || \ - (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) -# if _MSC_VER >= 1922 -# include -# endif -#endif diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_id.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_id.h deleted file mode 100644 index 65306ef79..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_id.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/unique_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace logs -{ - -/** - * EventId class which acts the Id of the event with an optional name. - */ -class EventId -{ -public: - EventId(int64_t id, nostd::string_view name) noexcept - : id_{id}, name_{nostd::unique_ptr{new char[name.length() + 1]}} - { - std::copy(name.begin(), name.end(), name_.get()); - name_.get()[name.length()] = 0; - } - - EventId(int64_t id) noexcept : id_{id}, name_{nullptr} {} - -public: - int64_t id_; - nostd::unique_ptr name_; -}; - -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_logger.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_logger.h deleted file mode 100644 index bcc103562..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_logger.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/logs/log_record.h" -#include "opentelemetry/logs/logger.h" -#include "opentelemetry/logs/logger_type_traits.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/unique_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace logs -{ -#if OPENTELEMETRY_ABI_VERSION_NO < 2 -/** - * Handles event log record creation. - **/ -class OPENTELEMETRY_DEPRECATED EventLogger -{ -public: - virtual ~EventLogger() = default; - - /* Returns the name of the logger */ - virtual const nostd::string_view GetName() noexcept = 0; - - /* Returns the delegate logger of this event logger */ - virtual nostd::shared_ptr GetDelegateLogger() noexcept = 0; - - /** - * Emit a event Log Record object - * - * @param event_name Event name - * @param log_record Log record - */ - virtual void EmitEvent(nostd::string_view event_name, - nostd::unique_ptr &&log_record) noexcept = 0; - - /** - * Emit a event Log Record object with arguments - * - * @param event_name Event name - * @tparam args Arguments which can be used to set data of log record by type. - * Severity -> severity, severity_text - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,tace_id and trace_flags - * SpanId -> span_id - * TraceId -> tace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void EmitEvent(nostd::string_view event_name, ArgumentType &&...args) - { - nostd::shared_ptr delegate_logger = GetDelegateLogger(); - if (!delegate_logger) - { - return; - } - nostd::unique_ptr log_record = delegate_logger->CreateLogRecord(); - - IgnoreTraitResult(detail::LogRecordSetterTrait::type>::Set( - log_record.get(), std::forward(args))...); - - EmitEvent(event_name, std::move(log_record)); - } - -private: - template - void IgnoreTraitResult(ValueType &&...) - {} -}; -#endif -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_logger_provider.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_logger_provider.h deleted file mode 100644 index 9eea0ca23..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/event_logger_provider.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace logs -{ - -class EventLogger; -class Logger; - -#if OPENTELEMETRY_ABI_VERSION_NO < 2 -/** - * Creates new EventLogger instances. - */ -class OPENTELEMETRY_DEPRECATED EventLoggerProvider -{ -public: - virtual ~EventLoggerProvider() = default; - - /** - * Creates a named EventLogger instance. - * - */ - - virtual nostd::shared_ptr CreateEventLogger( - nostd::shared_ptr delegate_logger, - nostd::string_view event_domain) noexcept = 0; -}; -#endif -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/log_record.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/log_record.h deleted file mode 100644 index 81dec568e..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/log_record.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/common/attribute_value.h" -#include "opentelemetry/common/timestamp.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace trace -{ -class SpanId; -class TraceId; -class TraceFlags; -} // namespace trace - -namespace logs -{ - -enum class Severity : uint8_t; - -/** - * Maintains a representation of a log in a format that can be processed by a recorder. - * - * This class is thread-compatible. - */ -class LogRecord -{ -public: - virtual ~LogRecord() = default; - - /** - * Set the timestamp for this log. - * @param timestamp the timestamp to set - */ - virtual void SetTimestamp(common::SystemTimestamp timestamp) noexcept = 0; - - /** - * Set the observed timestamp for this log. - * @param timestamp the timestamp to set - */ - virtual void SetObservedTimestamp(common::SystemTimestamp timestamp) noexcept = 0; - - /** - * Set the severity for this log. - * @param severity the severity of the event - */ - virtual void SetSeverity(logs::Severity severity) noexcept = 0; - - /** - * Set body field for this log. - * @param message the body to set - */ - virtual void SetBody(const common::AttributeValue &message) noexcept = 0; - - /** - * Set an attribute of a log. - * @param key the name of the attribute - * @param value the attribute value - */ - virtual void SetAttribute(nostd::string_view key, - const common::AttributeValue &value) noexcept = 0; - - /** - * Set the Event Id. - * @param id The event id to set - * @param name Optional event name to set - */ - // TODO: mark this as pure virtual once all exporters have been updated - virtual void SetEventId(int64_t id, nostd::string_view name = {}) noexcept = 0; - - /** - * Set the trace id for this log. - * @param trace_id the trace id to set - */ - virtual void SetTraceId(const trace::TraceId &trace_id) noexcept = 0; - - /** - * Set the span id for this log. - * @param span_id the span id to set - */ - virtual void SetSpanId(const trace::SpanId &span_id) noexcept = 0; - - /** - * Inject trace_flags for this log. - * @param trace_flags the trace flags to set - */ - virtual void SetTraceFlags(const trace::TraceFlags &trace_flags) noexcept = 0; -}; -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger.h deleted file mode 100644 index 52f403b0a..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger.h +++ /dev/null @@ -1,492 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/logs/logger_type_traits.h" -#include "opentelemetry/logs/severity.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/unique_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ -class KeyValueIterable; -} // namespace common - -namespace logs -{ - -class EventId; -class LogRecord; - -/** - * Handles log record creation. - **/ -class Logger -{ -public: - virtual ~Logger() = default; - - /* Returns the name of the logger */ - virtual const nostd::string_view GetName() noexcept = 0; - - /** - * Create a Log Record object - * - * @return nostd::unique_ptr - */ - virtual nostd::unique_ptr CreateLogRecord() noexcept = 0; - - /** - * Emit a Log Record object - * - * @param log_record Log record - */ - virtual void EmitLogRecord(nostd::unique_ptr &&log_record) noexcept = 0; - - /** - * Emit a Log Record object with arguments - * - * @param log_record Log record - * @param args Arguments which can be used to set data of log record by type. - * Severity -> severity, severity_text - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,trace_id and trace_flags - * SpanId -> span_id - * TraceId -> trace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void EmitLogRecord(nostd::unique_ptr &&log_record, ArgumentType &&...args) - { - if (!log_record) - { - return; - } - - // - // Keep the parameter pack unpacking order from left to right because left - // ones are usually more important like severity and event_id than the - // attributes. The left to right unpack order could pass the more important - // data to processors to avoid caching and memory allocating. - // -#if __cplusplus <= 201402L - // C++14 does not support fold expressions for parameter pack expansion. - int dummy[] = {(detail::LogRecordSetterTrait::type>::Set( - log_record.get(), std::forward(args)), - 0)...}; - IgnoreTraitResult(dummy); -#else - IgnoreTraitResult((detail::LogRecordSetterTrait::type>::Set( - log_record.get(), std::forward(args)), - ...)); -#endif - - EmitLogRecord(std::move(log_record)); - } - - /** - * Emit a Log Record object with arguments - * - * @param args Arguments which can be used to set data of log record by type. - * Severity -> severity, severity_text - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,trace_id and trace_flags - * SpanId -> span_id - * TraceId -> trace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void EmitLogRecord(ArgumentType &&...args) - { - nostd::unique_ptr log_record = CreateLogRecord(); - - EmitLogRecord(std::move(log_record), std::forward(args)...); - } - - /** - * Writes a log with a severity of trace. - * @param args Arguments which can be used to set data of log record by type. - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,trace_id and trace_flags - * SpanId -> span_id - * TraceId -> trace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void Trace(ArgumentType &&...args) noexcept - { - static_assert( - !detail::LogRecordHasType::type...>::value, - "Severity is already set."); - this->EmitLogRecord(Severity::kTrace, std::forward(args)...); - } - - /** - * Writes a log with a severity of debug. - * @param args Arguments which can be used to set data of log record by type. - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,trace_id and trace_flags - * SpanId -> span_id - * TraceId -> trace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void Debug(ArgumentType &&...args) noexcept - { - static_assert( - !detail::LogRecordHasType::type...>::value, - "Severity is already set."); - this->EmitLogRecord(Severity::kDebug, std::forward(args)...); - } - - /** - * Writes a log with a severity of info. - * @param args Arguments which can be used to set data of log record by type. - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,trace_id and trace_flags - * SpanId -> span_id - * TraceId -> trace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void Info(ArgumentType &&...args) noexcept - { - static_assert( - !detail::LogRecordHasType::type...>::value, - "Severity is already set."); - this->EmitLogRecord(Severity::kInfo, std::forward(args)...); - } - - /** - * Writes a log with a severity of warn. - * @param args Arguments which can be used to set data of log record by type. - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,trace_id and trace_flags - * SpanId -> span_id - * TraceId -> trace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void Warn(ArgumentType &&...args) noexcept - { - static_assert( - !detail::LogRecordHasType::type...>::value, - "Severity is already set."); - this->EmitLogRecord(Severity::kWarn, std::forward(args)...); - } - - /** - * Writes a log with a severity of error. - * @param args Arguments which can be used to set data of log record by type. - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,trace_id and trace_flags - * SpanId -> span_id - * TraceId -> trace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void Error(ArgumentType &&...args) noexcept - { - static_assert( - !detail::LogRecordHasType::type...>::value, - "Severity is already set."); - this->EmitLogRecord(Severity::kError, std::forward(args)...); - } - - /** - * Writes a log with a severity of fatal. - * @param args Arguments which can be used to set data of log record by type. - * string_view -> body - * AttributeValue -> body - * SpanContext -> span_id,trace_id and trace_flags - * SpanId -> span_id - * TraceId -> trace_id - * TraceFlags -> trace_flags - * SystemTimestamp -> timestamp - * system_clock::time_point -> timestamp - * KeyValueIterable -> attributes - * Key value iterable container -> attributes - * span> -> attributes(return type of MakeAttributes) - */ - template - void Fatal(ArgumentType &&...args) noexcept - { - static_assert( - !detail::LogRecordHasType::type...>::value, - "Severity is already set."); - this->EmitLogRecord(Severity::kFatal, std::forward(args)...); - } - - // - // OpenTelemetry C++ user-facing Logs API - // - - inline bool Enabled(Severity severity, const EventId &event_id) const noexcept - { - if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity)) - { - return false; - } - return EnabledImplementation(severity, event_id); - } - - inline bool Enabled(Severity severity, int64_t event_id) const noexcept - { - if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity)) - { - return false; - } - return EnabledImplementation(severity, event_id); - } - - inline bool Enabled(Severity severity) const noexcept - { - return static_cast(severity) >= OPENTELEMETRY_ATOMIC_READ_8(&minimum_severity_); - } - - /** - * Log an event - * - * @severity severity of the log - * @event_id event identifier of the log - * @format an utf-8 string following https://messagetemplates.org/ - * @attributes key value pairs of the log - */ - virtual void Log(Severity severity, - const EventId &event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->EmitLogRecord(severity, event_id, format, attributes); - } - - virtual void Log(Severity severity, - int64_t event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->EmitLogRecord(severity, EventId{event_id}, format, attributes); - } - - virtual void Log(Severity severity, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->EmitLogRecord(severity, format, attributes); - } - - virtual void Log(Severity severity, nostd::string_view message) noexcept - { - this->EmitLogRecord(severity, message); - } - - // Convenient wrappers based on virtual methods Log(). - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber - - inline void Trace(const EventId &event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kTrace, event_id, format, attributes); - } - - inline void Trace(int64_t event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kTrace, EventId{event_id}, format, attributes); - } - - inline void Trace(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kTrace, format, attributes); - } - - inline void Trace(nostd::string_view message) noexcept { this->Log(Severity::kTrace, message); } - - inline void Debug(const EventId &event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kDebug, event_id, format, attributes); - } - - inline void Debug(int64_t event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kDebug, EventId{event_id}, format, attributes); - } - - inline void Debug(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kDebug, format, attributes); - } - - inline void Debug(nostd::string_view message) noexcept { this->Log(Severity::kDebug, message); } - - inline void Info(const EventId &event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kInfo, event_id, format, attributes); - } - - inline void Info(int64_t event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kInfo, EventId{event_id}, format, attributes); - } - - inline void Info(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kInfo, format, attributes); - } - - inline void Info(nostd::string_view message) noexcept { this->Log(Severity::kInfo, message); } - - inline void Warn(const EventId &event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kWarn, event_id, format, attributes); - } - - inline void Warn(int64_t event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kWarn, EventId{event_id}, format, attributes); - } - - inline void Warn(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kWarn, format, attributes); - } - - inline void Warn(nostd::string_view message) noexcept { this->Log(Severity::kWarn, message); } - - inline void Error(const EventId &event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kError, event_id, format, attributes); - } - - inline void Error(int64_t event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kError, EventId{event_id}, format, attributes); - } - - inline void Error(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kError, format, attributes); - } - - inline void Error(nostd::string_view message) noexcept { this->Log(Severity::kError, message); } - - inline void Fatal(const EventId &event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kFatal, event_id, format, attributes); - } - - inline void Fatal(int64_t event_id, - nostd::string_view format, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kFatal, EventId{event_id}, format, attributes); - } - - inline void Fatal(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept - { - this->Log(Severity::kFatal, format, attributes); - } - - inline void Fatal(nostd::string_view message) noexcept { this->Log(Severity::kFatal, message); } - - // - // End of OpenTelemetry C++ user-facing Log API. - // - -protected: - // TODO: discuss with community about naming for internal methods. - virtual bool EnabledImplementation(Severity /*severity*/, - const EventId & /*event_id*/) const noexcept - { - return false; - } - - virtual bool EnabledImplementation(Severity /*severity*/, int64_t /*event_id*/) const noexcept - { - return false; - } - - void SetMinimumSeverity(uint8_t severity_or_max) noexcept - { - OPENTELEMETRY_ATOMIC_WRITE_8(&minimum_severity_, severity_or_max); - } - -private: - template - void IgnoreTraitResult(ValueType &&...) - {} - - // - // minimum_severity_ can be updated concurrently by multiple threads/cores, so race condition on - // read/write should be handled. And std::atomic can not be used here because it is not ABI - // compatible for OpenTelemetry C++ API. - // - mutable uint8_t minimum_severity_{kMaxSeverity}; -}; -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger_provider.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger_provider.h deleted file mode 100644 index ab1493c5c..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger_provider.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/common/key_value_iterable.h" -#include "opentelemetry/common/key_value_iterable_view.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/span.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/type_traits.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace logs -{ - -class Logger; - -/** - * Creates new Logger instances. - */ -class OPENTELEMETRY_EXPORT LoggerProvider -{ -public: - virtual ~LoggerProvider() = default; - - /** - * Gets or creates a named Logger instance. - * - * Optionally a version can be passed to create a named and versioned Logger - * instance. - * - * Optionally a configuration file name can be passed to create a configuration for - * the Logger instance. - * - */ - - virtual nostd::shared_ptr GetLogger( - nostd::string_view logger_name, - nostd::string_view library_name = "", - nostd::string_view library_version = "", - nostd::string_view schema_url = "", - const common::KeyValueIterable &attributes = common::NoopKeyValueIterable()) = 0; - - nostd::shared_ptr GetLogger( - nostd::string_view logger_name, - nostd::string_view library_name, - nostd::string_view library_version, - nostd::string_view schema_url, - std::initializer_list> attributes) - { - return GetLogger(logger_name, library_name, library_version, schema_url, - nostd::span>{ - attributes.begin(), attributes.end()}); - } - - template ::value> * = nullptr> - nostd::shared_ptr GetLogger(nostd::string_view logger_name, - nostd::string_view library_name, - nostd::string_view library_version, - nostd::string_view schema_url, - const T &attributes) - { - return GetLogger(logger_name, library_name, library_version, schema_url, - common::KeyValueIterableView(attributes)); - } -}; -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger_type_traits.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger_type_traits.h deleted file mode 100644 index d88a6ffbd..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/logger_type_traits.h +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include - -#include "opentelemetry/common/attribute_value.h" -#include "opentelemetry/common/key_value_iterable.h" -#include "opentelemetry/common/timestamp.h" -#include "opentelemetry/logs/event_id.h" -#include "opentelemetry/logs/log_record.h" -#include "opentelemetry/logs/severity.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/type_traits.h" -#include "opentelemetry/trace/span_context.h" -#include "opentelemetry/trace/span_id.h" -#include "opentelemetry/trace/trace_flags.h" -#include "opentelemetry/trace/trace_id.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace logs -{ -namespace detail -{ -template -struct LogRecordSetterTrait; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetSeverity(std::forward(arg)); - - return log_record; - } -}; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetEventId(arg.id_, nostd::string_view{arg.name_.get()}); - - return log_record; - } -}; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetSpanId(arg.span_id()); - log_record->SetTraceId(arg.trace_id()); - log_record->SetTraceFlags(arg.trace_flags()); - - return log_record; - } -}; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetSpanId(std::forward(arg)); - - return log_record; - } -}; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetTraceId(std::forward(arg)); - - return log_record; - } -}; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetTraceFlags(std::forward(arg)); - - return log_record; - } -}; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetTimestamp(std::forward(arg)); - - return log_record; - } -}; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetTimestamp(common::SystemTimestamp(std::forward(arg))); - - return log_record; - } -}; - -template <> -struct LogRecordSetterTrait -{ - template - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - arg.ForEachKeyValue( - [&log_record](nostd::string_view key, common::AttributeValue value) noexcept { - log_record->SetAttribute(key, value); - return true; - }); - - return log_record; - } -}; - -template -struct LogRecordSetterTrait -{ - static_assert(!std::is_same, ValueType>::value && - !std::is_same, ValueType>::value, - "unique_ptr is not allowed, please use std::move()"); - - template ::value || - std::is_convertible::value, - void> * = nullptr> - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - log_record->SetBody(std::forward(arg)); - - return log_record; - } - - template ::value, bool> - * = nullptr> - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - return LogRecordSetterTrait::Set(log_record, - std::forward(arg)); - } - - template ::value, int> * = - nullptr> - inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept - { - for (auto &argv : arg) - { - log_record->SetAttribute(argv.first, argv.second); - } - - return log_record; - } -}; - -template -struct LogRecordHasType; - -template -struct LogRecordHasType : public std::false_type -{}; - -template -struct LogRecordHasType - : public std::conditional::value, - std::true_type, - LogRecordHasType>::type -{}; - -} // namespace detail - -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/noop.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/noop.h deleted file mode 100644 index 24312f061..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/noop.h +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -// Please refer to provider.h for documentation on how to obtain a Logger object. -// -// This file is part of the internal implementation of OpenTelemetry. Nothing in this file should be -// used directly. Please refer to logger.h for documentation on these interfaces. - -#include "opentelemetry/logs/event_logger.h" -#include "opentelemetry/logs/event_logger_provider.h" -#include "opentelemetry/logs/logger.h" -#include "opentelemetry/logs/logger_provider.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/unique_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace common -{ -class KeyValueIterable; -} // namespace common - -namespace logs -{ -/** - * No-op implementation of Logger. This class should not be used directly. It should only be - * instantiated using a LoggerProvider's GetLogger() call. - */ -class NoopLogger final : public Logger -{ -public: - const nostd::string_view GetName() noexcept override { return "noop logger"; } - - nostd::unique_ptr CreateLogRecord() noexcept override - { - /* - * Do not return memory shared between threads, - * a `new` + `delete` for each noop record can not be avoided, - * due to the semantic of unique_ptr. - */ - return nostd::unique_ptr(new NoopLogRecord()); - } - - using Logger::EmitLogRecord; - - void EmitLogRecord(nostd::unique_ptr &&) noexcept override {} - -private: - class NoopLogRecord : public LogRecord - { - public: - NoopLogRecord() = default; - ~NoopLogRecord() override = default; - - void SetTimestamp(common::SystemTimestamp /* timestamp */) noexcept override {} - void SetObservedTimestamp(common::SystemTimestamp /* timestamp */) noexcept override {} - void SetSeverity(logs::Severity /* severity */) noexcept override {} - void SetBody(const common::AttributeValue & /* message */) noexcept override {} - void SetAttribute(nostd::string_view /* key */, - const common::AttributeValue & /* value */) noexcept override - {} - void SetEventId(int64_t /* id */, nostd::string_view /* name */) noexcept override {} - void SetTraceId(const trace::TraceId & /* trace_id */) noexcept override {} - void SetSpanId(const trace::SpanId & /* span_id */) noexcept override {} - void SetTraceFlags(const trace::TraceFlags & /* trace_flags */) noexcept override {} - }; -}; - -/** - * No-op implementation of a LoggerProvider. - */ -class NoopLoggerProvider final : public LoggerProvider -{ -public: - NoopLoggerProvider() : logger_{nostd::shared_ptr(new NoopLogger())} {} - - nostd::shared_ptr GetLogger(nostd::string_view /* logger_name */, - nostd::string_view /* library_name */, - nostd::string_view /* library_version */, - nostd::string_view /* schema_url */, - const common::KeyValueIterable & /* attributes */) override - { - return logger_; - } - -private: - nostd::shared_ptr logger_; -}; - -#if OPENTELEMETRY_ABI_VERSION_NO < 2 -class NoopEventLogger final : public EventLogger -{ -public: - NoopEventLogger() : logger_{nostd::shared_ptr(new NoopLogger())} {} - - const nostd::string_view GetName() noexcept override { return "noop event logger"; } - - nostd::shared_ptr GetDelegateLogger() noexcept override { return logger_; } - - void EmitEvent(nostd::string_view, nostd::unique_ptr &&) noexcept override {} - -private: - nostd::shared_ptr logger_; -}; - -/** - * No-op implementation of a EventLoggerProvider. - */ -class NoopEventLoggerProvider final : public EventLoggerProvider -{ -public: - NoopEventLoggerProvider() : event_logger_{nostd::shared_ptr(new NoopEventLogger())} - {} - - nostd::shared_ptr CreateEventLogger( - nostd::shared_ptr /*delegate_logger*/, - nostd::string_view /*event_domain*/) noexcept override - { - return event_logger_; - } - -private: - nostd::shared_ptr event_logger_; -}; -#endif - -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/provider.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/provider.h deleted file mode 100644 index 0c1b4deea..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/provider.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/common/macros.h" -#include "opentelemetry/common/spin_lock_mutex.h" -#include "opentelemetry/logs/noop.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace logs -{ - -#if OPENTELEMETRY_ABI_VERSION_NO < 2 -class EventLoggerProvider; -#endif -class LoggerProvider; - -/** - * Stores the singleton global LoggerProvider. - */ -class OPENTELEMETRY_EXPORT Provider -{ -public: - /** - * Returns the singleton LoggerProvider. - * - * By default, a no-op LoggerProvider is returned. This will never return a - * nullptr LoggerProvider. - */ - static nostd::shared_ptr GetLoggerProvider() noexcept - { - std::lock_guard guard(GetLock()); - return nostd::shared_ptr(GetProvider()); - } - - /** - * Changes the singleton LoggerProvider. - */ - static void SetLoggerProvider(const nostd::shared_ptr &tp) noexcept - { - std::lock_guard guard(GetLock()); - GetProvider() = tp; - } - -#if OPENTELEMETRY_ABI_VERSION_NO < 2 - /** - * Returns the singleton EventLoggerProvider. - * - * By default, a no-op EventLoggerProvider is returned. This will never return a - * nullptr EventLoggerProvider. - */ - OPENTELEMETRY_DEPRECATED static nostd::shared_ptr - GetEventLoggerProvider() noexcept - { - std::lock_guard guard(GetLock()); - return nostd::shared_ptr(GetEventProvider()); - } - - /** - * Changes the singleton EventLoggerProvider. - */ - OPENTELEMETRY_DEPRECATED static void SetEventLoggerProvider( - const nostd::shared_ptr &tp) noexcept - { - std::lock_guard guard(GetLock()); - GetEventProvider() = tp; - } -#endif - -private: - OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept - { - static nostd::shared_ptr provider(new NoopLoggerProvider); - return provider; - } - -#if OPENTELEMETRY_ABI_VERSION_NO < 2 - OPENTELEMETRY_DEPRECATED - OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr & - GetEventProvider() noexcept - { - static nostd::shared_ptr provider(new NoopEventLoggerProvider); - return provider; - } -#endif - - OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept - { - static common::SpinLockMutex lock; - return lock; - } -}; - -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/severity.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/severity.h deleted file mode 100644 index f4d961615..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/logs/severity.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace logs -{ - -/** - * Severity Levels assigned to log events, based on Log Data Model, - * with the addition of kInvalid (mapped to a severity number of 0). - * - * See - * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber - */ -enum class Severity : uint8_t -{ - kInvalid = 0, - kTrace = 1, - kTrace2 = 2, - kTrace3 = 3, - kTrace4 = 4, - kDebug = 5, - kDebug2 = 6, - kDebug3 = 7, - kDebug4 = 8, - kInfo = 9, - kInfo2 = 10, - kInfo3 = 11, - kInfo4 = 12, - kWarn = 13, - kWarn2 = 14, - kWarn3 = 15, - kWarn4 = 16, - kError = 17, - kError2 = 18, - kError3 = 19, - kError4 = 20, - kFatal = 21, - kFatal2 = 22, - kFatal3 = 23, - kFatal4 = 24 -}; - -const uint8_t kMaxSeverity = 255; - -/** - * Mapping of the severity enum above, to a severity text string (in all caps). - * This severity text can be printed out by exporters. Capital letters follow the - * spec naming convention. - * - * Included to follow the specification's recommendation to print both - * severity number and text in each log record. - */ -const nostd::string_view SeverityNumToText[25] = { - "INVALID", "TRACE", "TRACE2", "TRACE3", "TRACE4", "DEBUG", "DEBUG2", "DEBUG3", "DEBUG4", - "INFO", "INFO2", "INFO3", "INFO4", "WARN", "WARN2", "WARN3", "WARN4", "ERROR", - "ERROR2", "ERROR3", "ERROR4", "FATAL", "FATAL2", "FATAL3", "FATAL4"}; - -} // namespace logs -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/async_instruments.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/async_instruments.h deleted file mode 100644 index f73eb2f51..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/async_instruments.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/metrics/observer_result.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace metrics -{ - -using ObservableCallbackPtr = void (*)(ObserverResult, void *); - -class ObservableInstrument -{ -public: - ObservableInstrument() = default; - virtual ~ObservableInstrument() = default; - - /** - * Sets up a function that will be called whenever a metric collection is initiated. - */ - virtual void AddCallback(ObservableCallbackPtr, void *state) noexcept = 0; - - /** - * Remove a function that was configured to be called whenever a metric collection is initiated. - */ - virtual void RemoveCallback(ObservableCallbackPtr, void *state) noexcept = 0; -}; - -} // namespace metrics -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/meter.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/meter.h deleted file mode 100644 index 59cfb8782..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/meter.h +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/unique_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace metrics -{ - -template -class Counter; - -template -class Histogram; - -template -class UpDownCounter; - -template -class Gauge; - -class ObservableInstrument; - -/** - * Handles instrument creation and provides a facility for batch recording. - * - * This class provides methods to create new metric instruments, record a - * batch of values to a specified set of instruments, and collect - * measurements from all instruments. - * - */ -class Meter -{ -public: - virtual ~Meter() = default; - - /** - * Creates a Counter with the passed characteristics and returns a unique_ptr to that Counter. - * - * @param name the name of the new Counter. - * @param description a brief description of what the Counter is used for. - * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. - * @return a shared pointer to the created Counter. - */ - - virtual nostd::unique_ptr> CreateUInt64Counter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - virtual nostd::unique_ptr> CreateDoubleCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - /** - * Creates a Asynchronous (Observable) counter with the passed characteristics and returns a - * shared_ptr to that Observable Counter - * - * @param name the name of the new Observable Counter. - * @param description a brief description of what the Observable Counter is used for. - * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. - */ - virtual nostd::shared_ptr CreateInt64ObservableCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - virtual nostd::shared_ptr CreateDoubleObservableCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - /** - * Creates a Histogram with the passed characteristics and returns a unique_ptr to that Histogram. - * - * @param name the name of the new Histogram. - * @param description a brief description of what the Histogram is used for. - * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. - * @return a shared pointer to the created Histogram. - */ - virtual nostd::unique_ptr> CreateUInt64Histogram( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - virtual nostd::unique_ptr> CreateDoubleHistogram( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 - /** - * Creates a Gauge with the passed characteristics and returns a unique_ptr to that Gauge. - * - * @param name the name of the new Gauge. - * @param description a brief description of what the Gauge is used for. - * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. - * @return a unique pointer to the created Gauge. - */ - - virtual nostd::unique_ptr> CreateInt64Gauge( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - virtual nostd::unique_ptr> CreateDoubleGauge( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; -#endif - - /** - * Creates a Asynchronous (Observable) Gauge with the passed characteristics and returns a - * shared_ptr to that Observable Gauge - * - * @param name the name of the new Observable Gauge. - * @param description a brief description of what the Observable Gauge is used for. - * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. - */ - virtual nostd::shared_ptr CreateInt64ObservableGauge( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - virtual nostd::shared_ptr CreateDoubleObservableGauge( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - /** - * Creates an UpDownCounter with the passed characteristics and returns a unique_ptr to that - * UpDownCounter. - * - * @param name the name of the new UpDownCounter. - * @param description a brief description of what the UpDownCounter is used for. - * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. - * @return a shared pointer to the created UpDownCounter. - */ - virtual nostd::unique_ptr> CreateInt64UpDownCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - virtual nostd::unique_ptr> CreateDoubleUpDownCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - /** - * Creates a Asynchronous (Observable) UpDownCounter with the passed characteristics and returns - * a shared_ptr to that Observable UpDownCounter - * - * @param name the name of the new Observable UpDownCounter. - * @param description a brief description of what the Observable UpDownCounter is used for. - * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. - */ - virtual nostd::shared_ptr CreateInt64ObservableUpDownCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; - - virtual nostd::shared_ptr CreateDoubleObservableUpDownCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept = 0; -}; -} // namespace metrics -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/meter_provider.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/meter_provider.h deleted file mode 100644 index fca960bb8..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/meter_provider.h +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/common/key_value_iterable.h" -#include "opentelemetry/common/key_value_iterable_view.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/type_traits.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace metrics -{ - -class Meter; - -/** - * Creates new Meter instances. - */ -class MeterProvider -{ -public: - virtual ~MeterProvider() = default; - -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 - - /** - * Gets or creates a named Meter instance (ABI). - * - * @since ABI_VERSION 2 - * - * @param[in] name Meter instrumentation scope - * @param[in] version Instrumentation scope version - * @param[in] schema_url Instrumentation scope schema URL - * @param[in] attributes Instrumentation scope attributes (optional, may be nullptr) - */ - virtual nostd::shared_ptr GetMeter( - nostd::string_view name, - nostd::string_view version, - nostd::string_view schema_url, - const common::KeyValueIterable *attributes) noexcept = 0; - - /** - * Gets or creates a named Meter instance (API helper). - * - * @since ABI_VERSION 2 - * - * @param[in] name Meter instrumentation scope - * @param[in] version Instrumentation scope version, optional - * @param[in] schema_url Instrumentation scope schema URL, optional - */ - nostd::shared_ptr GetMeter(nostd::string_view name, - nostd::string_view version = "", - nostd::string_view schema_url = "") - { - return GetMeter(name, version, schema_url, nullptr); - } - - /** - * Gets or creates a named Meter instance (API helper). - * - * @since ABI_VERSION 2 - * - * @param[in] name Meter instrumentation scope - * @param[in] version Instrumentation scope version - * @param[in] schema_url Instrumentation scope schema URL - * @param[in] attributes Instrumentation scope attributes - */ - nostd::shared_ptr GetMeter( - nostd::string_view name, - nostd::string_view version, - nostd::string_view schema_url, - std::initializer_list> attributes) - { - /* Build a container from std::initializer_list. */ - nostd::span> attributes_span{ - attributes.begin(), attributes.end()}; - - /* Build a view on the container. */ - common::KeyValueIterableView< - nostd::span>> - iterable_attributes{attributes_span}; - - /* Add attributes using the view. */ - return GetMeter(name, version, schema_url, &iterable_attributes); - } - - /** - * Gets or creates a named Meter instance (API helper). - * - * @since ABI_VERSION 2 - * - * @param[in] name Meter instrumentation scope - * @param[in] version Instrumentation scope version - * @param[in] schema_url Instrumentation scope schema URL - * @param[in] attributes Instrumentation scope attributes container - */ - template ::value> * = nullptr> - nostd::shared_ptr GetMeter(nostd::string_view name, - nostd::string_view version, - nostd::string_view schema_url, - const T &attributes) - { - /* Build a view on the container. */ - common::KeyValueIterableView iterable_attributes(attributes); - - /* Add attributes using the view. */ - return GetMeter(name, version, schema_url, &iterable_attributes); - } - -#else - /** - * Gets or creates a named Meter instance (ABI) - * - * @since ABI_VERSION 1 - * - * @param[in] name Meter instrumentation scope - * @param[in] version Instrumentation scope version, optional - * @param[in] schema_url Instrumentation scope schema URL, optional - */ - virtual nostd::shared_ptr GetMeter(nostd::string_view name, - nostd::string_view version = "", - nostd::string_view schema_url = "") noexcept = 0; -#endif - -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 - /** - * Remove a named Meter instance (ABI). - * - * This API is experimental, see - * https://github.com/open-telemetry/opentelemetry-specification/issues/2232 - * - * @since ABI_VERSION 2 - * - * @param[in] name Meter instrumentation scope - * @param[in] version Instrumentation scope version, optional - * @param[in] schema_url Instrumentation scope schema URL, optional - */ - virtual void RemoveMeter(nostd::string_view name, - nostd::string_view version = "", - nostd::string_view schema_url = "") noexcept = 0; -#endif -}; -} // namespace metrics -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/noop.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/noop.h deleted file mode 100644 index 1d508b938..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/noop.h +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/metrics/async_instruments.h" -#include "opentelemetry/metrics/meter.h" -#include "opentelemetry/metrics/meter_provider.h" -#include "opentelemetry/metrics/observer_result.h" -#include "opentelemetry/metrics/sync_instruments.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace metrics -{ - -template -class NoopCounter : public Counter -{ -public: - NoopCounter(nostd::string_view /* name */, - nostd::string_view /* description */, - nostd::string_view /* unit */) noexcept - {} - void Add(T /* value */) noexcept override {} - void Add(T /* value */, const context::Context & /* context */) noexcept override {} - void Add(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {} - void Add(T /* value */, - const common::KeyValueIterable & /* attributes */, - const context::Context & /* context */) noexcept override - {} -}; - -template -class NoopHistogram : public Histogram -{ -public: - NoopHistogram(nostd::string_view /* name */, - nostd::string_view /* description */, - nostd::string_view /* unit */) noexcept - {} - void Record(T /* value */, const context::Context & /* context */) noexcept override {} - void Record(T /* value */, - const common::KeyValueIterable & /* attributes */, - const context::Context & /* context */) noexcept override - {} -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 - void Record(T /*value*/, - const opentelemetry::common::KeyValueIterable & /*attributes*/) noexcept override - {} - - void Record(T /*value*/) noexcept override {} -#endif -}; - -template -class NoopUpDownCounter : public UpDownCounter -{ -public: - NoopUpDownCounter(nostd::string_view /* name */, - nostd::string_view /* description */, - nostd::string_view /* unit */) noexcept - {} - ~NoopUpDownCounter() override = default; - void Add(T /* value */) noexcept override {} - void Add(T /* value */, const context::Context & /* context */) noexcept override {} - void Add(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {} - void Add(T /* value */, - const common::KeyValueIterable & /* attributes */, - const context::Context & /* context */) noexcept override - {} -}; - -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 -template -class NoopGauge : public Gauge -{ -public: - NoopGauge(nostd::string_view /* name */, - nostd::string_view /* description */, - nostd::string_view /* unit */) noexcept - {} - ~NoopGauge() override = default; - void Record(T /* value */) noexcept override {} - void Record(T /* value */, const context::Context & /* context */) noexcept override {} - void Record(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {} - void Record(T /* value */, - const common::KeyValueIterable & /* attributes */, - const context::Context & /* context */) noexcept override - {} -}; -#endif - -class NoopObservableInstrument : public ObservableInstrument -{ -public: - NoopObservableInstrument(nostd::string_view /* name */, - nostd::string_view /* description */, - nostd::string_view /* unit */) noexcept - {} - - void AddCallback(ObservableCallbackPtr, void * /* state */) noexcept override {} - void RemoveCallback(ObservableCallbackPtr, void * /* state */) noexcept override {} -}; - -/** - * No-op implementation of Meter. - */ -class NoopMeter final : public Meter -{ -public: - nostd::unique_ptr> CreateUInt64Counter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::unique_ptr>{new NoopCounter(name, description, unit)}; - } - - nostd::unique_ptr> CreateDoubleCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::unique_ptr>{new NoopCounter(name, description, unit)}; - } - - nostd::shared_ptr CreateInt64ObservableCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::shared_ptr( - new NoopObservableInstrument(name, description, unit)); - } - - nostd::shared_ptr CreateDoubleObservableCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::shared_ptr( - new NoopObservableInstrument(name, description, unit)); - } - - nostd::unique_ptr> CreateUInt64Histogram( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::unique_ptr>{ - new NoopHistogram(name, description, unit)}; - } - - nostd::unique_ptr> CreateDoubleHistogram( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::unique_ptr>{new NoopHistogram(name, description, unit)}; - } - -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 - nostd::unique_ptr> CreateInt64Gauge(nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::unique_ptr>{new NoopGauge(name, description, unit)}; - } - - nostd::unique_ptr> CreateDoubleGauge(nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::unique_ptr>{new NoopGauge(name, description, unit)}; - } -#endif - - nostd::shared_ptr CreateInt64ObservableGauge( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::shared_ptr( - new NoopObservableInstrument(name, description, unit)); - } - - nostd::shared_ptr CreateDoubleObservableGauge( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::shared_ptr( - new NoopObservableInstrument(name, description, unit)); - } - - nostd::unique_ptr> CreateInt64UpDownCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::unique_ptr>{ - new NoopUpDownCounter(name, description, unit)}; - } - - nostd::unique_ptr> CreateDoubleUpDownCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::unique_ptr>{ - new NoopUpDownCounter(name, description, unit)}; - } - - nostd::shared_ptr CreateInt64ObservableUpDownCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::shared_ptr( - new NoopObservableInstrument(name, description, unit)); - } - - nostd::shared_ptr CreateDoubleObservableUpDownCounter( - nostd::string_view name, - nostd::string_view description = "", - nostd::string_view unit = "") noexcept override - { - return nostd::shared_ptr( - new NoopObservableInstrument(name, description, unit)); - } -}; - -/** - * No-op implementation of a MeterProvider. - */ -class NoopMeterProvider final : public MeterProvider -{ -public: - NoopMeterProvider() : meter_{nostd::shared_ptr(new NoopMeter)} {} - -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 - nostd::shared_ptr GetMeter( - nostd::string_view /* name */, - nostd::string_view /* version */, - nostd::string_view /* schema_url */, - const common::KeyValueIterable * /* attributes */) noexcept override - { - return meter_; - } -#else - nostd::shared_ptr GetMeter(nostd::string_view /* name */, - nostd::string_view /* version */, - nostd::string_view /* schema_url */) noexcept override - { - return meter_; - } -#endif - -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 - void RemoveMeter(nostd::string_view /* name */, - nostd::string_view /* version */, - nostd::string_view /* schema_url */) noexcept override - {} -#endif - -private: - nostd::shared_ptr meter_; -}; -} // namespace metrics -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/observer_result.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/observer_result.h deleted file mode 100644 index 56c42bc20..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/observer_result.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/common/attribute_value.h" -#include "opentelemetry/common/key_value_iterable_view.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/nostd/span.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/type_traits.h" -#include "opentelemetry/nostd/variant.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace metrics -{ - -/** - * ObserverResultT class is necessary for the callback recording asynchronous - * instrument use. - */ -template -class ObserverResultT -{ - -public: - virtual ~ObserverResultT() = default; - - virtual void Observe(T value) noexcept = 0; - - virtual void Observe(T value, const common::KeyValueIterable &attributes) noexcept = 0; - - template ::value> * = nullptr> - void Observe(T value, const U &attributes) noexcept - { - this->Observe(value, common::KeyValueIterableView{attributes}); - } - - void Observe(T value, - std::initializer_list> - attributes) noexcept - { - this->Observe(value, nostd::span>{ - attributes.begin(), attributes.end()}); - } -}; - -using ObserverResult = nostd::variant>, - nostd::shared_ptr>>; - -} // namespace metrics -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/provider.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/provider.h deleted file mode 100644 index 20a606a77..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/provider.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/common/spin_lock_mutex.h" -#include "opentelemetry/metrics/meter_provider.h" -#include "opentelemetry/metrics/noop.h" -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace metrics -{ - -/** - * Stores the singleton global MeterProvider. - */ -class Provider -{ -public: - /** - * Returns the singleton MeterProvider. - * - * By default, a no-op MeterProvider is returned. This will never return a - * nullptr MeterProvider. - */ - static nostd::shared_ptr GetMeterProvider() noexcept - { - std::lock_guard guard(GetLock()); - return nostd::shared_ptr(GetProvider()); - } - - /** - * Changes the singleton MeterProvider. - */ - static void SetMeterProvider(const nostd::shared_ptr &tp) noexcept - { - std::lock_guard guard(GetLock()); - GetProvider() = tp; - } - -private: - OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept - { - static nostd::shared_ptr provider(new NoopMeterProvider); - return provider; - } - - OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept - { - static common::SpinLockMutex lock; - return lock; - } -}; - -} // namespace metrics -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/sync_instruments.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/sync_instruments.h deleted file mode 100644 index 9eaec3352..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/metrics/sync_instruments.h +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/common/attribute_value.h" -#include "opentelemetry/common/key_value_iterable_view.h" -#include "opentelemetry/context/context.h" -#include "opentelemetry/nostd/span.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/nostd/type_traits.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace metrics -{ - -class SynchronousInstrument -{ -public: - SynchronousInstrument() = default; - virtual ~SynchronousInstrument() = default; -}; - -/* A Counter instrument that adds values. */ -template -class Counter : public SynchronousInstrument -{ - -public: - /** - * Record a value - * - * @param value The increment amount. MUST be non-negative. - */ - virtual void Add(T value) noexcept = 0; - - /** - * Record a value - * - * @param value The increment amount. MUST be non-negative. - * @param context The explicit context to associate with this measurement. - */ - virtual void Add(T value, const context::Context &context) noexcept = 0; - - /** - * Record a value with a set of attributes. - * - * @param value The increment amount. MUST be non-negative. - * @param attributes A set of attributes to associate with the value. - */ - - virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0; - - /** - * Record a value with a set of attributes. - * - * @param value The increment amount. MUST be non-negative. - * @param attributes A set of attributes to associate with the value. - * @param context The explicit context to associate with this measurement. - */ - virtual void Add(T value, - const common::KeyValueIterable &attributes, - const context::Context &context) noexcept = 0; - - template ::value> * = nullptr> - void Add(T value, const U &attributes) noexcept - { - this->Add(value, common::KeyValueIterableView{attributes}); - } - - template ::value> * = nullptr> - void Add(T value, const U &attributes, const context::Context &context) noexcept - { - this->Add(value, common::KeyValueIterableView{attributes}, context); - } - - void Add(T value, - std::initializer_list> - attributes) noexcept - { - this->Add(value, nostd::span>{ - attributes.begin(), attributes.end()}); - } - - void Add(T value, - std::initializer_list> attributes, - const context::Context &context) noexcept - { - this->Add(value, - nostd::span>{ - attributes.begin(), attributes.end()}, - context); - } -}; - -/** A histogram instrument that records values. */ - -template -class Histogram : public SynchronousInstrument -{ -public: -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 - /** - * @since ABI_VERSION 2 - * Records a value. - * - * @param value The measurement value. MUST be non-negative. - */ - virtual void Record(T value) noexcept = 0; - - /** - * @since ABI_VERSION 2 - * Records a value with a set of attributes. - * - * @param value The measurement value. MUST be non-negative. - * @param attribute A set of attributes to associate with the value. - */ - virtual void Record(T value, const common::KeyValueIterable &attribute) noexcept = 0; - - template ::value> * = nullptr> - void Record(T value, const U &attributes) noexcept - { - this->Record(value, common::KeyValueIterableView{attributes}); - } - - void Record(T value, - std::initializer_list> - attributes) noexcept - { - this->Record(value, nostd::span>{ - attributes.begin(), attributes.end()}); - } -#endif - - /** - * Records a value. - * - * @param value The measurement value. MUST be non-negative. - * @param context The explicit context to associate with this measurement. - */ - virtual void Record(T value, const context::Context &context) noexcept = 0; - - /** - * Records a value with a set of attributes. - * - * @param value The measurement value. MUST be non-negative. - * @param attributes A set of attributes to associate with the value.. - * @param context The explicit context to associate with this measurement. - */ - virtual void Record(T value, - const common::KeyValueIterable &attributes, - const context::Context &context) noexcept = 0; - - template ::value> * = nullptr> - void Record(T value, const U &attributes, const context::Context &context) noexcept - { - this->Record(value, common::KeyValueIterableView{attributes}, context); - } - - void Record( - T value, - std::initializer_list> attributes, - const context::Context &context) noexcept - { - this->Record(value, - nostd::span>{ - attributes.begin(), attributes.end()}, - context); - } -}; - -/** An up-down-counter instrument that adds or reduce values. */ - -template -class UpDownCounter : public SynchronousInstrument -{ -public: - /** - * Record a value. - * - * @param value The increment amount. May be positive, negative or zero. - */ - virtual void Add(T value) noexcept = 0; - - /** - * Record a value. - * - * @param value The increment amount. May be positive, negative or zero. - * @param context The explicit context to associate with this measurement. - */ - virtual void Add(T value, const context::Context &context) noexcept = 0; - - /** - * Record a value with a set of attributes. - * - * @param value The increment amount. May be positive, negative or zero. - * @param attributes A set of attributes to associate with the count. - */ - virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0; - - /** - * Record a value with a set of attributes. - * - * @param value The increment amount. May be positive, negative or zero. - * @param attributes A set of attributes to associate with the count. - * @param context The explicit context to associate with this measurement. - */ - virtual void Add(T value, - const common::KeyValueIterable &attributes, - const context::Context &context) noexcept = 0; - - template ::value> * = nullptr> - void Add(T value, const U &attributes) noexcept - { - this->Add(value, common::KeyValueIterableView{attributes}); - } - - template ::value> * = nullptr> - void Add(T value, const U &attributes, const context::Context &context) noexcept - { - this->Add(value, common::KeyValueIterableView{attributes}, context); - } - - void Add(T value, - std::initializer_list> - attributes) noexcept - { - this->Add(value, nostd::span>{ - attributes.begin(), attributes.end()}); - } - - void Add(T value, - std::initializer_list> attributes, - const context::Context &context) noexcept - { - this->Add(value, - nostd::span>{ - attributes.begin(), attributes.end()}, - context); - } -}; - -#if OPENTELEMETRY_ABI_VERSION_NO >= 2 -/* A Gauge instrument that records values. */ -template -class Gauge : public SynchronousInstrument -{ - -public: - /** - * Record a value - * - * @param value The measurement value. May be positive, negative or zero. - */ - virtual void Record(T value) noexcept = 0; - - /** - * Record a value - * - * @param value The measurement value. May be positive, negative or zero. - * @param context The explicit context to associate with this measurement. - */ - virtual void Record(T value, const context::Context &context) noexcept = 0; - - /** - * Record a value with a set of attributes. - * - * @param value The measurement value. May be positive, negative or zero. - * @param attributes A set of attributes to associate with the value. - */ - - virtual void Record(T value, const common::KeyValueIterable &attributes) noexcept = 0; - - /** - * Record a value with a set of attributes. - * - * @param value The measurement value. May be positive, negative or zero. - * @param attributes A set of attributes to associate with the value. - * @param context The explicit context to associate with this measurement. - */ - virtual void Record(T value, - const common::KeyValueIterable &attributes, - const context::Context &context) noexcept = 0; - - template ::value> * = nullptr> - void Record(T value, const U &attributes) noexcept - { - this->Record(value, common::KeyValueIterableView{attributes}); - } - - template ::value> * = nullptr> - void Record(T value, const U &attributes, const context::Context &context) noexcept - { - this->Record(value, common::KeyValueIterableView{attributes}, context); - } - - void Record(T value, - std::initializer_list> - attributes) noexcept - { - this->Record(value, nostd::span>{ - attributes.begin(), attributes.end()}); - } - - void Record( - T value, - std::initializer_list> attributes, - const context::Context &context) noexcept - { - this->Record(value, - nostd::span>{ - attributes.begin(), attributes.end()}, - context); - } -}; -#endif - -} // namespace metrics -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/all.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/all.h deleted file mode 100644 index deaf3ac6f..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/all.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/nostd/utility.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -namespace detail -{ -template -using all = std::is_same, integer_sequence>; - -} // namespace detail -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/decay.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/decay.h deleted file mode 100644 index a6cb11124..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/decay.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -template -using decay_t = typename std::decay::type; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/dependent_type.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/dependent_type.h deleted file mode 100644 index 5bba09ff8..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/dependent_type.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -namespace detail -{ -template -struct dependent_type : T -{}; -} // namespace detail -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/functional.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/functional.h deleted file mode 100644 index 0da58dd18..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/functional.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/version.h" - -#define OPENTELEMETRY_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \ - { \ - return __VA_ARGS__; \ - } - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -namespace detail -{ -struct equal_to -{ - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - OPENTELEMETRY_RETURN(std::forward(lhs) == std::forward(rhs)) -}; - -struct not_equal_to -{ - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - OPENTELEMETRY_RETURN(std::forward(lhs) != std::forward(rhs)) -}; - -struct less -{ - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - OPENTELEMETRY_RETURN(std::forward(lhs) < std::forward(rhs)) -}; - -struct greater -{ - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - OPENTELEMETRY_RETURN(std::forward(lhs) > std::forward(rhs)) -}; - -struct less_equal -{ - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - OPENTELEMETRY_RETURN(std::forward(lhs) <= std::forward(rhs)) -}; - -struct greater_equal -{ - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - OPENTELEMETRY_RETURN(std::forward(lhs) >= std::forward(rhs)) -}; -} // namespace detail -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE - -#undef OPENTELEMETRY_RETURN diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/invoke.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/invoke.h deleted file mode 100644 index 55a943ed1..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/invoke.h +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/nostd/detail/decay.h" -#include "opentelemetry/nostd/detail/void.h" -#include "opentelemetry/version.h" - -#define OPENTELEMETRY_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \ - { \ - return __VA_ARGS__; \ - } - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -namespace detail -{ - -template -struct is_reference_wrapper : std::false_type -{}; - -template -struct is_reference_wrapper> : std::true_type -{}; - -template -struct Invoke; - -template <> -struct Invoke -{ - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args) - OPENTELEMETRY_RETURN((std::forward(arg).*pmf)(std::forward(args)...)) -}; - -template <> -struct Invoke -{ - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args) - OPENTELEMETRY_RETURN((std::forward(arg).get().*pmf)(std::forward(args)...)) -}; - -template <> -struct Invoke -{ - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args) - OPENTELEMETRY_RETURN(((*std::forward(arg)).*pmf)(std::forward(args)...)) -}; - -template <> -struct Invoke -{ - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - OPENTELEMETRY_RETURN(std::forward(arg).*pmo) -}; - -template <> -struct Invoke -{ - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - OPENTELEMETRY_RETURN(std::forward(arg).get().*pmo) -}; - -template <> -struct Invoke -{ - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - OPENTELEMETRY_RETURN((*std::forward(arg)).*pmo) -}; - -template -inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&...args) OPENTELEMETRY_RETURN( - Invoke::value, - (std::is_base_of>::value ? 0 - : is_reference_wrapper>::value ? 1 - : 2)>::invoke(f, - std::forward(arg), - std::forward(args)...)) - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4100) -#endif - template - inline constexpr auto invoke_impl(F &&f, Args &&...args) - OPENTELEMETRY_RETURN(std::forward(f)(std::forward(args)...)) -#ifdef _MSC_VER -# pragma warning(pop) -#endif -} // namespace detail - -/* clang-format off */ -template -inline constexpr auto invoke(F &&f, Args &&... args) - OPENTELEMETRY_RETURN(detail::invoke_impl(std::forward(f), std::forward(args)...)) - -namespace detail -/* clang-format on */ -{ - - template - struct invoke_result - {}; - - template - struct invoke_result(), std::declval()...))>, - F, Args...> - { - using type = decltype(nostd::invoke(std::declval(), std::declval()...)); - }; - -} // namespace detail - -template -using invoke_result = detail::invoke_result; - -template -using invoke_result_t = typename invoke_result::type; - -namespace detail -{ - -template -struct is_invocable : std::false_type -{}; - -template -struct is_invocable>, F, Args...> : std::true_type -{}; - -template -struct is_invocable_r : std::false_type -{}; - -template -struct is_invocable_r>, R, F, Args...> - : std::is_convertible, R> -{}; - -} // namespace detail - -template -using is_invocable = detail::is_invocable; - -template -using is_invocable_r = detail::is_invocable_r; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE - -#undef OPENTELEMETRY_RETURN diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/trait.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/trait.h deleted file mode 100644 index 8f76fdec8..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/trait.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/nostd/type_traits.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -namespace detail -{ -enum class Trait -{ - TriviallyAvailable, - Available, - Unavailable -}; - -template - class IsTriviallyAvailable, - template - class IsAvailable> -inline constexpr Trait trait() -{ - return IsTriviallyAvailable::value ? Trait::TriviallyAvailable - : IsAvailable::value ? Trait::Available - : Trait::Unavailable; -} - -inline constexpr Trait common_trait_impl(Trait result) -{ - return result; -} - -template -inline constexpr Trait common_trait_impl(Trait result, Trait t, Traits... ts) -{ - return static_cast(t) > static_cast(result) ? common_trait_impl(t, ts...) - : common_trait_impl(result, ts...); -} - -template -inline constexpr Trait common_trait(Traits... ts) -{ - return common_trait_impl(Trait::TriviallyAvailable, ts...); -} - -template -struct traits -{ - static constexpr Trait copy_constructible_trait = - common_trait(trait()...); - - static constexpr Trait move_constructible_trait = - common_trait(trait()...); - - static constexpr Trait copy_assignable_trait = - common_trait(copy_constructible_trait, - trait()...); - - static constexpr Trait move_assignable_trait = - common_trait(move_constructible_trait, - trait()...); - - static constexpr Trait destructible_trait = - common_trait(trait()...); -}; -} // namespace detail -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/type_pack_element.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/type_pack_element.h deleted file mode 100644 index 280d24e94..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/type_pack_element.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/nostd/utility.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -namespace detail -{ -template -using size_constant = std::integral_constant; - -template -struct indexed_type : size_constant -{ - using type = T; -}; - -template -struct type_pack_element_impl -{ -private: - template - struct set; - - template - struct set> : indexed_type... - {}; - - template - inline static std::enable_if impl(indexed_type); - - inline static std::enable_if impl(...); - -public: - using type = decltype(impl(set>{})); -}; - -template -using type_pack_element = typename type_pack_element_impl::type; - -template -using type_pack_element_t = typename type_pack_element::type; -} // namespace detail -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/valueless.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/valueless.h deleted file mode 100644 index 3b2ca7f7c..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/valueless.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -struct valueless_t -{}; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_alternative.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_alternative.h deleted file mode 100644 index cc0da9c8c..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_alternative.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/nostd/detail/type_pack_element.h" -#include "opentelemetry/nostd/detail/variant_fwd.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -template -struct variant_alternative; - -template -using variant_alternative_t = typename variant_alternative::type; - -template -struct variant_alternative : std::add_const> -{}; - -template -struct variant_alternative : std::add_volatile> -{}; - -template -struct variant_alternative : std::add_cv> -{}; - -template -struct variant_alternative> -{ - static_assert(I < sizeof...(Ts), "index out of bounds in `std::variant_alternative<>`"); - using type = detail::type_pack_element_t; -}; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_fwd.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_fwd.h deleted file mode 100644 index 6bae9659e..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_fwd.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -template -class variant; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_size.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_size.h deleted file mode 100644 index d8986a222..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/variant_size.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/nostd/detail/variant_fwd.h" -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -template -struct variant_size; - -template -struct variant_size : variant_size -{}; - -template -struct variant_size : variant_size -{}; - -template -struct variant_size : variant_size -{}; - -template -struct variant_size> : std::integral_constant -{}; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/void.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/void.h deleted file mode 100644 index 1b4c3b4f7..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/detail/void.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -namespace detail -{ -template -struct voider -{ - using type = void; -}; -} // namespace detail - -/** - * Back port of std::void_t - * - * Note: voider workaround is required for gcc-4.8 to make SFINAE work - */ -template -using void_t = typename detail::voider::type; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/function_ref.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/function_ref.h deleted file mode 100644 index 6f0c2dd33..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/function_ref.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include // IWYU pragma: keep -#include -#include - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ -template -class function_ref; // IWYU pragma: keep - -/** - * Non-owning function reference that can be used as a more performant - * replacement for std::function when ownership sematics aren't needed. - * - * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0792r0.html - * - * Based off of https://stackoverflow.com/a/39087660/4447365 - */ -template -class function_ref -{ - void *callable_ = nullptr; - R (*invoker_)(void *, Args...) = nullptr; - - template - using FunctionPointer = decltype(std::addressof(std::declval())); - - template - void BindTo(F &f) noexcept - { - callable_ = static_cast(std::addressof(f)); - invoker_ = [](void *callable, Args... args) -> R { - return (*static_cast>(callable))(std::forward(args)...); - }; - } - - template - void BindTo(R_in (*f)(Args_in...)) noexcept - { - using F = decltype(f); - if (f == nullptr) - { - return BindTo(nullptr); - } - callable_ = reinterpret_cast(f); - invoker_ = [](void *callable, Args... args) -> R { - return (F(callable))(std::forward(args)...); - }; - } - - void BindTo(std::nullptr_t) noexcept - { - callable_ = nullptr; - invoker_ = nullptr; - } - -public: - template < - class F, - typename std::enable_if::type>::value, - int>::type = 0, - typename std::enable_if< -#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402)) - // std::result_of deprecated in C++17, removed in C++20 - std::is_convertible::type, R>::value, -#else - // std::result_of since C++11 - std::is_convertible::type, R>::value, -#endif - int>::type = 0> - function_ref(F &&f) - { - BindTo(f); // not forward - } - - function_ref(std::nullptr_t) {} - - function_ref(const function_ref &) noexcept = default; - function_ref(function_ref &&) noexcept = default; - - R operator()(Args... args) const { return invoker_(callable_, std::forward(args)...); } - - explicit operator bool() const { return invoker_; } -}; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/.clang-format b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/.clang-format deleted file mode 100644 index 001170f7e..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/.clang-format +++ /dev/null @@ -1,3 +0,0 @@ -# Disable formatting for Google Abseil library snapshot -DisableFormat: true -SortIncludes: false diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/README.md b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/README.md deleted file mode 100644 index 5dd661971..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Notes on Abseil Variant implementation - -This is a snapshot of Abseil Variant -`absl::OTABSL_OPTION_NAMESPACE_NAME::variant` from Abseil `v2020-03-03#8`. diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/attributes.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/attributes.h deleted file mode 100644 index 72901a84c..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/attributes.h +++ /dev/null @@ -1,621 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// This header file defines macros for declaring attributes for functions, -// types, and variables. -// -// These macros are used within Abseil and allow the compiler to optimize, where -// applicable, certain function calls. -// -// This file is used for both C and C++! -// -// Most macros here are exposing GCC or Clang features, and are stubbed out for -// other compilers. -// -// GCC attributes documentation: -// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html -// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html -// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html -// -// Most attributes in this file are already supported by GCC 4.7. However, some -// of them are not supported in older version of Clang. Thus, we check -// `__has_attribute()` first. If the check fails, we check if we are on GCC and -// assume the attribute exists on GCC (which is verified on GCC 4.7). -// -// ----------------------------------------------------------------------------- -// Sanitizer Attributes -// ----------------------------------------------------------------------------- -// -// Sanitizer-related attributes are not "defined" in this file (and indeed -// are not defined as such in any file). To utilize the following -// sanitizer-related attributes within your builds, define the following macros -// within your build using a `-D` flag, along with the given value for -// `-fsanitize`: -// -// * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8) -// * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only) -// * `THREAD_SANITIZER + `-fsanitize=thread` (Clang, GCC 4.8+) -// * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+) -// * `CONTROL_FLOW_INTEGRITY` + -fsanitize=cfi (Clang-only) -// -// Example: -// -// // Enable branches in the Abseil code that are tagged for ASan: -// $ bazel build --copt=-DADDRESS_SANITIZER --copt=-fsanitize=address -// --linkopt=-fsanitize=address *target* -// -// Since these macro names are only supported by GCC and Clang, we only check -// for `__GNUC__` (GCC or Clang) and the above macros. -#ifndef OTABSL_BASE_ATTRIBUTES_H_ -#define OTABSL_BASE_ATTRIBUTES_H_ - -// OTABSL_HAVE_ATTRIBUTE -// -// A function-like feature checking macro that is a wrapper around -// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a -// nonzero constant integer if the attribute is supported or 0 if not. -// -// It evaluates to zero if `__has_attribute` is not defined by the compiler. -// -// GCC: https://gcc.gnu.org/gcc-5/changes.html -// Clang: https://clang.llvm.org/docs/LanguageExtensions.html -#ifdef __has_attribute -#define OTABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) -#else -#define OTABSL_HAVE_ATTRIBUTE(x) 0 -#endif - -// OTABSL_HAVE_CPP_ATTRIBUTE -// -// A function-like feature checking macro that accepts C++11 style attributes. -// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 -// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't -// find `__has_cpp_attribute`, will evaluate to 0. -#if defined(__cplusplus) && defined(__has_cpp_attribute) -// NOTE: requiring __cplusplus above should not be necessary, but -// works around https://bugs.llvm.org/show_bug.cgi?id=23435. -#define OTABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) -#else -#define OTABSL_HAVE_CPP_ATTRIBUTE(x) 0 -#endif - -// ----------------------------------------------------------------------------- -// Function Attributes -// ----------------------------------------------------------------------------- -// -// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -// Clang: https://clang.llvm.org/docs/AttributeReference.html - -// OTABSL_PRINTF_ATTRIBUTE -// OTABSL_SCANF_ATTRIBUTE -// -// Tells the compiler to perform `printf` format string checking if the -// compiler supports it; see the 'format' attribute in -// . -// -// Note: As the GCC manual states, "[s]ince non-static C++ methods -// have an implicit 'this' argument, the arguments of such methods -// should be counted from two, not one." -#if OTABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ - __attribute__((__format__(__printf__, string_index, first_to_check))) -#define OTABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ - __attribute__((__format__(__scanf__, string_index, first_to_check))) -#else -#define OTABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) -#define OTABSL_SCANF_ATTRIBUTE(string_index, first_to_check) -#endif - -// OTABSL_ATTRIBUTE_ALWAYS_INLINE -// OTABSL_ATTRIBUTE_NOINLINE -// -// Forces functions to either inline or not inline. Introduced in gcc 3.1. -#if OTABSL_HAVE_ATTRIBUTE(always_inline) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) -#define OTABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 -#else -#define OTABSL_ATTRIBUTE_ALWAYS_INLINE -#endif - -#if OTABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) -#define OTABSL_HAVE_ATTRIBUTE_NOINLINE 1 -#else -#define OTABSL_ATTRIBUTE_NOINLINE -#endif - -// OTABSL_ATTRIBUTE_NO_TAIL_CALL -// -// Prevents the compiler from optimizing away stack frames for functions which -// end in a call to another function. -#if OTABSL_HAVE_ATTRIBUTE(disable_tail_calls) -#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 -#define OTABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) -#elif defined(__GNUC__) && !defined(__clang__) -#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 -#define OTABSL_ATTRIBUTE_NO_TAIL_CALL \ - __attribute__((optimize("no-optimize-sibling-calls"))) -#else -#define OTABSL_ATTRIBUTE_NO_TAIL_CALL -#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 -#endif - -// OTABSL_ATTRIBUTE_WEAK -// -// Tags a function as weak for the purposes of compilation and linking. -// Weak attributes currently do not work properly in LLVM's Windows backend, -// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 -// for further information. -// The MinGW compiler doesn't complain about the weak attribute until the link -// step, presumably because Windows doesn't use ELF binaries. -#if (OTABSL_HAVE_ATTRIBUTE(weak) || \ - (defined(__GNUC__) && !defined(__clang__))) && \ - !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__) -#undef OTABSL_ATTRIBUTE_WEAK -#define OTABSL_ATTRIBUTE_WEAK __attribute__((weak)) -#define OTABSL_HAVE_ATTRIBUTE_WEAK 1 -#else -#define OTABSL_ATTRIBUTE_WEAK -#define OTABSL_HAVE_ATTRIBUTE_WEAK 0 -#endif - -// OTABSL_ATTRIBUTE_NONNULL -// -// Tells the compiler either (a) that a particular function parameter -// should be a non-null pointer, or (b) that all pointer arguments should -// be non-null. -// -// Note: As the GCC manual states, "[s]ince non-static C++ methods -// have an implicit 'this' argument, the arguments of such methods -// should be counted from two, not one." -// -// Args are indexed starting at 1. -// -// For non-static class member functions, the implicit `this` argument -// is arg 1, and the first explicit argument is arg 2. For static class member -// functions, there is no implicit `this`, and the first explicit argument is -// arg 1. -// -// Example: -// -// /* arg_a cannot be null, but arg_b can */ -// void Function(void* arg_a, void* arg_b) OTABSL_ATTRIBUTE_NONNULL(1); -// -// class C { -// /* arg_a cannot be null, but arg_b can */ -// void Method(void* arg_a, void* arg_b) OTABSL_ATTRIBUTE_NONNULL(2); -// -// /* arg_a cannot be null, but arg_b can */ -// static void StaticMethod(void* arg_a, void* arg_b) -// OTABSL_ATTRIBUTE_NONNULL(1); -// }; -// -// If no arguments are provided, then all pointer arguments should be non-null. -// -// /* No pointer arguments may be null. */ -// void Function(void* arg_a, void* arg_b, int arg_c) OTABSL_ATTRIBUTE_NONNULL(); -// -// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but -// OTABSL_ATTRIBUTE_NONNULL does not. -#if OTABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) -#else -#define OTABSL_ATTRIBUTE_NONNULL(...) -#endif - -// OTABSL_ATTRIBUTE_NORETURN -// -// Tells the compiler that a given function never returns. -#if OTABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) -#elif defined(_MSC_VER) -#define OTABSL_ATTRIBUTE_NORETURN __declspec(noreturn) -#else -#define OTABSL_ATTRIBUTE_NORETURN -#endif - -// OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS -// -// Tells the AddressSanitizer (or other memory testing tools) to ignore a given -// function. Useful for cases when a function reads random locations on stack, -// calls _exit from a cloned subprocess, deliberately accesses buffer -// out of bounds or does other scary things with memory. -// NOTE: GCC supports AddressSanitizer(asan) since 4.8. -// https://gcc.gnu.org/gcc-4.8/changes.html -#if defined(__GNUC__) -#define OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) -#else -#define OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS -#endif - -// OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY -// -// Tells the MemorySanitizer to relax the handling of a given function. All -// "Use of uninitialized value" warnings from such functions will be suppressed, -// and all values loaded from memory will be considered fully initialized. -// This attribute is similar to the ADDRESS_SANITIZER attribute above, but deals -// with initialized-ness rather than addressability issues. -// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. -#if defined(__clang__) -#define OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) -#else -#define OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY -#endif - -// OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD -// -// Tells the ThreadSanitizer to not instrument a given function. -// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. -// https://gcc.gnu.org/gcc-4.8/changes.html -#if defined(__GNUC__) -#define OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) -#else -#define OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD -#endif - -// OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED -// -// Tells the UndefinedSanitizer to ignore a given function. Useful for cases -// where certain behavior (eg. division by zero) is being used intentionally. -// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. -// https://gcc.gnu.org/gcc-4.9/changes.html -#if defined(__GNUC__) && \ - (defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER)) -#define OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ - __attribute__((no_sanitize("undefined"))) -#else -#define OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED -#endif - -// OTABSL_ATTRIBUTE_NO_SANITIZE_CFI -// -// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. -// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. -#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY) -#define OTABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) -#else -#define OTABSL_ATTRIBUTE_NO_SANITIZE_CFI -#endif - -// OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK -// -// Tells the SafeStack to not instrument a given function. -// See https://clang.llvm.org/docs/SafeStack.html for details. -#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER) -#define OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ - __attribute__((no_sanitize("safe-stack"))) -#else -#define OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK -#endif - -// OTABSL_ATTRIBUTE_RETURNS_NONNULL -// -// Tells the compiler that a particular function never returns a null pointer. -#if OTABSL_HAVE_ATTRIBUTE(returns_nonnull) || \ - (defined(__GNUC__) && \ - (__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \ - !defined(__clang__)) -#define OTABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) -#else -#define OTABSL_ATTRIBUTE_RETURNS_NONNULL -#endif - -// OTABSL_HAVE_ATTRIBUTE_SECTION -// -// Indicates whether labeled sections are supported. Weak symbol support is -// a prerequisite. Labeled sections are not supported on Darwin/iOS. -#ifdef OTABSL_HAVE_ATTRIBUTE_SECTION -#error OTABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set -#elif (OTABSL_HAVE_ATTRIBUTE(section) || \ - (defined(__GNUC__) && !defined(__clang__))) && \ - !defined(__APPLE__) && OTABSL_HAVE_ATTRIBUTE_WEAK -#define OTABSL_HAVE_ATTRIBUTE_SECTION 1 - -// OTABSL_ATTRIBUTE_SECTION -// -// Tells the compiler/linker to put a given function into a section and define -// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. -// This functionality is supported by GNU linker. Any function annotated with -// `OTABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into -// whatever section its caller is placed into. -// -#ifndef OTABSL_ATTRIBUTE_SECTION -#define OTABSL_ATTRIBUTE_SECTION(name) \ - __attribute__((section(#name))) __attribute__((noinline)) -#endif - - -// OTABSL_ATTRIBUTE_SECTION_VARIABLE -// -// Tells the compiler/linker to put a given variable into a section and define -// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. -// This functionality is supported by GNU linker. -#ifndef OTABSL_ATTRIBUTE_SECTION_VARIABLE -#define OTABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) -#endif - -// OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS -// -// A weak section declaration to be used as a global declaration -// for OTABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link -// even without functions with OTABSL_ATTRIBUTE_SECTION(name). -// OTABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's -// a no-op on ELF but not on Mach-O. -// -#ifndef OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS -#define OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ - extern char __start_##name[] OTABSL_ATTRIBUTE_WEAK; \ - extern char __stop_##name[] OTABSL_ATTRIBUTE_WEAK -#endif -#ifndef OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS -#define OTABSL_INIT_ATTRIBUTE_SECTION_VARS(name) -#define OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) -#endif - -// OTABSL_ATTRIBUTE_SECTION_START -// -// Returns `void*` pointers to start/end of a section of code with -// functions having OTABSL_ATTRIBUTE_SECTION(name). -// Returns 0 if no such functions exist. -// One must OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and -// link. -// -#define OTABSL_ATTRIBUTE_SECTION_START(name) \ - (reinterpret_cast(__start_##name)) -#define OTABSL_ATTRIBUTE_SECTION_STOP(name) \ - (reinterpret_cast(__stop_##name)) - -#else // !OTABSL_HAVE_ATTRIBUTE_SECTION - -#define OTABSL_HAVE_ATTRIBUTE_SECTION 0 - -// provide dummy definitions -#define OTABSL_ATTRIBUTE_SECTION(name) -#define OTABSL_ATTRIBUTE_SECTION_VARIABLE(name) -#define OTABSL_INIT_ATTRIBUTE_SECTION_VARS(name) -#define OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) -#define OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) -#define OTABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) -#define OTABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) - -#endif // OTABSL_ATTRIBUTE_SECTION - -// OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC -// -// Support for aligning the stack on 32-bit x86. -#if OTABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ - (defined(__GNUC__) && !defined(__clang__)) -#if defined(__i386__) -#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ - __attribute__((force_align_arg_pointer)) -#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) -#elif defined(__x86_64__) -#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) -#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC -#else // !__i386__ && !__x86_64 -#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) -#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC -#endif // __i386__ -#else -#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC -#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) -#endif - -// OTABSL_MUST_USE_RESULT -// -// Tells the compiler to warn about unused results. -// -// When annotating a function, it must appear as the first part of the -// declaration or definition. The compiler will warn if the return value from -// such a function is unused: -// -// OTABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); -// AllocateSprocket(); // Triggers a warning. -// -// When annotating a class, it is equivalent to annotating every function which -// returns an instance. -// -// class OTABSL_MUST_USE_RESULT Sprocket {}; -// Sprocket(); // Triggers a warning. -// -// Sprocket MakeSprocket(); -// MakeSprocket(); // Triggers a warning. -// -// Note that references and pointers are not instances: -// -// Sprocket* SprocketPointer(); -// SprocketPointer(); // Does *not* trigger a warning. -// -// OTABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result -// warning. For that, warn_unused_result is used only for clang but not for gcc. -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 -// -// Note: past advice was to place the macro after the argument list. -#if OTABSL_HAVE_ATTRIBUTE(nodiscard) -#define OTABSL_MUST_USE_RESULT [[nodiscard]] -#elif defined(__clang__) && OTABSL_HAVE_ATTRIBUTE(warn_unused_result) -#define OTABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) -#else -#define OTABSL_MUST_USE_RESULT -#endif - -// OTABSL_ATTRIBUTE_HOT, OTABSL_ATTRIBUTE_COLD -// -// Tells GCC that a function is hot or cold. GCC can use this information to -// improve static analysis, i.e. a conditional branch to a cold function -// is likely to be not-taken. -// This annotation is used for function declarations. -// -// Example: -// -// int foo() OTABSL_ATTRIBUTE_HOT; -#if OTABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_HOT __attribute__((hot)) -#else -#define OTABSL_ATTRIBUTE_HOT -#endif - -#if OTABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_COLD __attribute__((cold)) -#else -#define OTABSL_ATTRIBUTE_COLD -#endif - -// OTABSL_XRAY_ALWAYS_INSTRUMENT, OTABSL_XRAY_NEVER_INSTRUMENT, OTABSL_XRAY_LOG_ARGS -// -// We define the OTABSL_XRAY_ALWAYS_INSTRUMENT and OTABSL_XRAY_NEVER_INSTRUMENT -// macro used as an attribute to mark functions that must always or never be -// instrumented by XRay. Currently, this is only supported in Clang/LLVM. -// -// For reference on the LLVM XRay instrumentation, see -// http://llvm.org/docs/XRay.html. -// -// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration -// will always get the XRay instrumentation sleds. These sleds may introduce -// some binary size and runtime overhead and must be used sparingly. -// -// These attributes only take effect when the following conditions are met: -// -// * The file/target is built in at least C++11 mode, with a Clang compiler -// that supports XRay attributes. -// * The file/target is built with the -fxray-instrument flag set for the -// Clang/LLVM compiler. -// * The function is defined in the translation unit (the compiler honors the -// attribute in either the definition or the declaration, and must match). -// -// There are cases when, even when building with XRay instrumentation, users -// might want to control specifically which functions are instrumented for a -// particular build using special-case lists provided to the compiler. These -// special case lists are provided to Clang via the -// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The -// attributes in source take precedence over these special-case lists. -// -// To disable the XRay attributes at build-time, users may define -// OTABSL_NO_XRAY_ATTRIBUTES. Do NOT define OTABSL_NO_XRAY_ATTRIBUTES on specific -// packages/targets, as this may lead to conflicting definitions of functions at -// link-time. -// -#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ - !defined(OTABSL_NO_XRAY_ATTRIBUTES) -#define OTABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] -#define OTABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] -#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) -#define OTABSL_XRAY_LOG_ARGS(N) \ - [[clang::xray_always_instrument, clang::xray_log_args(N)]] -#else -#define OTABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] -#endif -#else -#define OTABSL_XRAY_ALWAYS_INSTRUMENT -#define OTABSL_XRAY_NEVER_INSTRUMENT -#define OTABSL_XRAY_LOG_ARGS(N) -#endif - -// OTABSL_ATTRIBUTE_REINITIALIZES -// -// Indicates that a member function reinitializes the entire object to a known -// state, independent of the previous state of the object. -// -// The clang-tidy check bugprone-use-after-move allows member functions marked -// with this attribute to be called on objects that have been moved from; -// without the attribute, this would result in a use-after-move warning. -#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) -#define OTABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] -#else -#define OTABSL_ATTRIBUTE_REINITIALIZES -#endif - -// ----------------------------------------------------------------------------- -// Variable Attributes -// ----------------------------------------------------------------------------- - -// OTABSL_ATTRIBUTE_UNUSED -// -// Prevents the compiler from complaining about variables that appear unused. -#if OTABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) -#undef OTABSL_ATTRIBUTE_UNUSED -#define OTABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) -#else -#define OTABSL_ATTRIBUTE_UNUSED -#endif - -// OTABSL_ATTRIBUTE_INITIAL_EXEC -// -// Tells the compiler to use "initial-exec" mode for a thread-local variable. -// See http://people.redhat.com/drepper/tls.pdf for the gory details. -#if OTABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) -#else -#define OTABSL_ATTRIBUTE_INITIAL_EXEC -#endif - -// OTABSL_ATTRIBUTE_PACKED -// -// Instructs the compiler not to use natural alignment for a tagged data -// structure, but instead to reduce its alignment to 1. This attribute can -// either be applied to members of a structure or to a structure in its -// entirety. Applying this attribute (judiciously) to a structure in its -// entirety to optimize the memory footprint of very commonly-used structs is -// fine. Do not apply this attribute to a structure in its entirety if the -// purpose is to control the offsets of the members in the structure. Instead, -// apply this attribute only to structure members that need it. -// -// When applying OTABSL_ATTRIBUTE_PACKED only to specific structure members the -// natural alignment of structure members not annotated is preserved. Aligned -// member accesses are faster than non-aligned member accesses even if the -// targeted microprocessor supports non-aligned accesses. -#if OTABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) -#else -#define OTABSL_ATTRIBUTE_PACKED -#endif - -// OTABSL_ATTRIBUTE_FUNC_ALIGN -// -// Tells the compiler to align the function start at least to certain -// alignment boundary -#if OTABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) -#else -#define OTABSL_ATTRIBUTE_FUNC_ALIGN(bytes) -#endif - -// OTABSL_CONST_INIT -// -// A variable declaration annotated with the `OTABSL_CONST_INIT` attribute will -// not compile (on supported platforms) unless the variable has a constant -// initializer. This is useful for variables with static and thread storage -// duration, because it guarantees that they will not suffer from the so-called -// "static init order fiasco". Prefer to put this attribute on the most visible -// declaration of the variable, if there's more than one, because code that -// accesses the variable can then use the attribute for optimization. -// -// Example: -// -// class MyClass { -// public: -// OTABSL_CONST_INIT static MyType my_var; -// }; -// -// MyType MyClass::my_var = MakeMyType(...); -// -// Note that this attribute is redundant if the variable is declared constexpr. -#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) -#define OTABSL_CONST_INIT [[clang::require_constant_initialization]] -#else -#define OTABSL_CONST_INIT -#endif // OTABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) - -#endif // OTABSL_BASE_ATTRIBUTES_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/config.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/config.h deleted file mode 100644 index e0836b9b3..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/config.h +++ /dev/null @@ -1,671 +0,0 @@ -// -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: config.h -// ----------------------------------------------------------------------------- -// -// This header file defines a set of macros for checking the presence of -// important compiler and platform features. Such macros can be used to -// produce portable code by parameterizing compilation based on the presence or -// lack of a given feature. -// -// We define a "feature" as some interface we wish to program to: for example, -// a library function or system call. A value of `1` indicates support for -// that feature; any other value indicates the feature support is undefined. -// -// Example: -// -// Suppose a programmer wants to write a program that uses the 'mmap()' system -// call. The Abseil macro for that feature (`OTABSL_HAVE_MMAP`) allows you to -// selectively include the `mmap.h` header and bracket code using that feature -// in the macro: -// -// #include "absl/base/config.h" -// -// #ifdef OTABSL_HAVE_MMAP -// #include "sys/mman.h" -// #endif //OTABSL_HAVE_MMAP -// -// ... -// #ifdef OTABSL_HAVE_MMAP -// void *ptr = mmap(...); -// ... -// #endif // OTABSL_HAVE_MMAP - -#ifndef OTABSL_BASE_CONFIG_H_ -#define OTABSL_BASE_CONFIG_H_ - -// Included for the __GLIBC__ macro (or similar macros on other systems). -#include - -#ifdef __cplusplus -// Included for __GLIBCXX__, _LIBCPP_VERSION -#include -#endif // __cplusplus - -#if defined(__APPLE__) -// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED, -// __IPHONE_8_0. -#include -#include -#endif - -#include "options.h" -#include "policy_checks.h" - -// Helper macro to convert a CPP variable to a string literal. -#define OTABSL_INTERNAL_DO_TOKEN_STR(x) #x -#define OTABSL_INTERNAL_TOKEN_STR(x) OTABSL_INTERNAL_DO_TOKEN_STR(x) - -// ----------------------------------------------------------------------------- -// Abseil namespace annotations -// ----------------------------------------------------------------------------- - -// OTABSL_NAMESPACE_BEGIN/OTABSL_NAMESPACE_END -// -// An annotation placed at the beginning/end of each `namespace absl` scope. -// This is used to inject an inline namespace. -// -// The proper way to write Abseil code in the `absl` namespace is: -// -// namespace absl { -// OTABSL_NAMESPACE_BEGIN -// -// void Foo(); // absl::OTABSL_OPTION_NAMESPACE_NAME::Foo(). -// -// OTABSL_NAMESPACE_END -// } // namespace absl -// -// Users of Abseil should not use these macros, because users of Abseil should -// not write `namespace absl {` in their own code for any reason. (Abseil does -// not support forward declarations of its own types, nor does it support -// user-provided specialization of Abseil templates. Code that violates these -// rules may be broken without warning.) -#if !defined(OTABSL_OPTION_NAMESPACE_NAME) -#error options.h is misconfigured. -#endif - -// Check that OTABSL_OPTION_NAMESPACE_NAME is neither "head" nor "" -#if defined(__cplusplus) - -#define OTABSL_INTERNAL_INLINE_NAMESPACE_STR \ - OTABSL_INTERNAL_TOKEN_STR(OTABSL_OPTION_NAMESPACE_NAME) - -static_assert(OTABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0', - "options.h misconfigured: OTABSL_OPTION_NAMESPACE_NAME must " - "not be empty."); -static_assert(OTABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || - OTABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' || - OTABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' || - OTABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' || - OTABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0', - "options.h misconfigured: OTABSL_OPTION_NAMESPACE_NAME must " - "be changed to a new, unique identifier name."); - -#endif - - -#define OTABSL_NAMESPACE_BEGIN namespace OTABSL_OPTION_NAMESPACE_NAME { -#define OTABSL_NAMESPACE_END } - -// ----------------------------------------------------------------------------- -// Compiler Feature Checks -// ----------------------------------------------------------------------------- - -// OTABSL_HAVE_BUILTIN() -// -// Checks whether the compiler supports a Clang Feature Checking Macro, and if -// so, checks whether it supports the provided builtin function "x" where x -// is one of the functions noted in -// https://clang.llvm.org/docs/LanguageExtensions.html -// -// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check. -// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html -#ifdef __has_builtin -#define OTABSL_HAVE_BUILTIN(x) __has_builtin(x) -#else -#define OTABSL_HAVE_BUILTIN(x) 0 -#endif - -#if defined(__is_identifier) -#define OTABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x)) -#else -#define OTABSL_INTERNAL_HAS_KEYWORD(x) 0 -#endif - -// OTABSL_HAVE_TLS is defined to 1 when __thread should be supported. -// We assume __thread is supported on Linux when compiled with Clang or compiled -// against libstdc++ with _GLIBCXX_HAVE_TLS defined. -#ifdef OTABSL_HAVE_TLS -#error OTABSL_HAVE_TLS cannot be directly set -#elif defined(__linux__) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS)) -#define OTABSL_HAVE_TLS 1 -#endif - -// OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE -// -// Checks whether `std::is_trivially_destructible` is supported. -// -// Notes: All supported compilers using libc++ support this feature, as does -// gcc >= 4.8.1 using libstdc++, and Visual Studio. -#ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE -#error OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set -#elif defined(_LIBCPP_VERSION) || \ - (defined(__clang__) && __clang_major__ >= 15) || \ - (!defined(__clang__) && defined(__GNUC__) && defined(__GLIBCXX__) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \ - defined(_MSC_VER) -#define OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1 -#endif - -// OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE -// -// Checks whether `std::is_trivially_default_constructible` and -// `std::is_trivially_copy_constructible` are supported. - -// OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE -// -// Checks whether `std::is_trivially_copy_assignable` is supported. - -// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with -// either libc++ or libstdc++, and Visual Studio (but not NVCC). -#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) -#error OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set -#elif defined(OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE) -#error OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set -#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \ - (defined(__clang__) && __clang_major__ >= 15) || \ - (!defined(__clang__) && defined(__GNUC__) && \ - (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 4)) && \ - (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) || \ - (defined(_MSC_VER) && !defined(__NVCC__)) -#define OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1 -#define OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1 -#endif - -// OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE -// -// Checks whether `std::is_trivially_copyable` is supported. -// -// Notes: Clang 15+ with libc++ supports these features, GCC hasn't been tested. -#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE) -#error OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE cannot be directly set -#elif defined(__clang__) && (__clang_major__ >= 15) -#define OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1 -#endif - -// OTABSL_HAVE_SOURCE_LOCATION_CURRENT -// -// Indicates whether `absl::OTABSL_OPTION_NAMESPACE_NAME::SourceLocation::current()` will return useful -// information in some contexts. -#ifndef OTABSL_HAVE_SOURCE_LOCATION_CURRENT -#if OTABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \ - OTABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE) -#define OTABSL_HAVE_SOURCE_LOCATION_CURRENT 1 -#endif -#endif - -// OTABSL_HAVE_THREAD_LOCAL -// -// Checks whether C++11's `thread_local` storage duration specifier is -// supported. -#ifdef OTABSL_HAVE_THREAD_LOCAL -#error OTABSL_HAVE_THREAD_LOCAL cannot be directly set -#elif defined(__APPLE__) -// Notes: -// * Xcode's clang did not support `thread_local` until version 8, and -// even then not for all iOS < 9.0. -// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator -// targeting iOS 9.x. -// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time -// making __has_feature unreliable there. -// -// Otherwise, `__has_feature` is only supported by Clang so it has be inside -// `defined(__APPLE__)` check. -#if __has_feature(cxx_thread_local) && \ - !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) -#define OTABSL_HAVE_THREAD_LOCAL 1 -#endif -#else // !defined(__APPLE__) -#define OTABSL_HAVE_THREAD_LOCAL 1 -#endif - -// There are platforms for which TLS should not be used even though the compiler -// makes it seem like it's supported (Android NDK < r12b for example). -// This is primarily because of linker problems and toolchain misconfiguration: -// Abseil does not intend to support this indefinitely. Currently, the newest -// toolchain that we intend to support that requires this behavior is the -// r11 NDK - allowing for a 5 year support window on that means this option -// is likely to be removed around June of 2021. -// TLS isn't supported until NDK r12b per -// https://developer.android.com/ndk/downloads/revision_history.html -// Since NDK r16, `__NDK_MAJOR__` and `__NDK_MINOR__` are defined in -// . For NDK < r16, users should define these macros, -// e.g. `-D__NDK_MAJOR__=11 -D__NKD_MINOR__=0` for NDK r11. -#if defined(__ANDROID__) && defined(__clang__) -#if __has_include() -#include -#endif // __has_include() -#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \ - defined(__NDK_MINOR__) && \ - ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1))) -#undef OTABSL_HAVE_TLS -#undef OTABSL_HAVE_THREAD_LOCAL -#endif -#endif // defined(__ANDROID__) && defined(__clang__) - -// Emscripten doesn't yet support `thread_local` or `__thread`. -// https://github.com/emscripten-core/emscripten/issues/3502 -#if defined(__EMSCRIPTEN__) -#undef OTABSL_HAVE_TLS -#undef OTABSL_HAVE_THREAD_LOCAL -#endif // defined(__EMSCRIPTEN__) - -// OTABSL_HAVE_INTRINSIC_INT128 -// -// Checks whether the __int128 compiler extension for a 128-bit integral type is -// supported. -// -// Note: __SIZEOF_INT128__ is defined by Clang and GCC when __int128 is -// supported, but we avoid using it in certain cases: -// * On Clang: -// * Building using Clang for Windows, where the Clang runtime library has -// 128-bit support only on LP64 architectures, but Windows is LLP64. -// * On Nvidia's nvcc: -// * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions -// actually support __int128. -#ifdef OTABSL_HAVE_INTRINSIC_INT128 -#error OTABSL_HAVE_INTRINSIC_INT128 cannot be directly set -#elif defined(__SIZEOF_INT128__) -#if (defined(__clang__) && !defined(_WIN32)) || \ - (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \ - (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__)) -#define OTABSL_HAVE_INTRINSIC_INT128 1 -#elif defined(__CUDACC__) -// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a -// string explaining that it has been removed starting with CUDA 9. We use -// nested #ifs because there is no short-circuiting in the preprocessor. -// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined. -#if __CUDACC_VER__ >= 70000 -#define OTABSL_HAVE_INTRINSIC_INT128 1 -#endif // __CUDACC_VER__ >= 70000 -#endif // defined(__CUDACC__) -#endif // OTABSL_HAVE_INTRINSIC_INT128 - -// OTABSL_HAVE_EXCEPTIONS -// -// Checks whether the compiler both supports and enables exceptions. Many -// compilers support a "no exceptions" mode that disables exceptions. -// -// Generally, when OTABSL_HAVE_EXCEPTIONS is not defined: -// -// * Code using `throw` and `try` may not compile. -// * The `noexcept` specifier will still compile and behave as normal. -// * The `noexcept` operator may still return `false`. -// -// For further details, consult the compiler's documentation. -#ifdef OTABSL_HAVE_EXCEPTIONS -#error OTABSL_HAVE_EXCEPTIONS cannot be directly set. - -#elif defined(__clang__) - -#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6) -// Clang >= 3.6 -#if __has_feature(cxx_exceptions) -#define OTABSL_HAVE_EXCEPTIONS 1 -#endif // __has_feature(cxx_exceptions) -#else -// Clang < 3.6 -// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro -#if defined(__EXCEPTIONS) && __has_feature(cxx_exceptions) -#define OTABSL_HAVE_EXCEPTIONS 1 -#endif // defined(__EXCEPTIONS) && __has_feature(cxx_exceptions) -#endif // __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6) - -// Handle remaining special cases and default to exceptions being supported. -#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \ - !(defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__cpp_exceptions)) && \ - !(defined(_MSC_VER) && !defined(_CPPUNWIND)) -#define OTABSL_HAVE_EXCEPTIONS 1 -#endif - -// ----------------------------------------------------------------------------- -// Platform Feature Checks -// ----------------------------------------------------------------------------- - -// Currently supported operating systems and associated preprocessor -// symbols: -// -// Linux and Linux-derived __linux__ -// Android __ANDROID__ (implies __linux__) -// Linux (non-Android) __linux__ && !__ANDROID__ -// Darwin (macOS and iOS) __APPLE__ -// Akaros (http://akaros.org) __ros__ -// Windows _WIN32 -// NaCL __native_client__ -// AsmJS __asmjs__ -// WebAssembly __wasm__ -// Fuchsia __Fuchsia__ -// -// Note that since Android defines both __ANDROID__ and __linux__, one -// may probe for either Linux or Android by simply testing for __linux__. - -// OTABSL_HAVE_MMAP -// -// Checks whether the platform has an mmap(2) implementation as defined in -// POSIX.1-2001. -#ifdef OTABSL_HAVE_MMAP -#error OTABSL_HAVE_MMAP cannot be directly set -#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \ - defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \ - defined(__ASYLO__) -#define OTABSL_HAVE_MMAP 1 -#endif - -// OTABSL_HAVE_PTHREAD_GETSCHEDPARAM -// -// Checks whether the platform implements the pthread_(get|set)schedparam(3) -// functions as defined in POSIX.1-2001. -#ifdef OTABSL_HAVE_PTHREAD_GETSCHEDPARAM -#error OTABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set -#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__ros__) -#define OTABSL_HAVE_PTHREAD_GETSCHEDPARAM 1 -#endif - -// OTABSL_HAVE_SCHED_YIELD -// -// Checks whether the platform implements sched_yield(2) as defined in -// POSIX.1-2001. -#ifdef OTABSL_HAVE_SCHED_YIELD -#error OTABSL_HAVE_SCHED_YIELD cannot be directly set -#elif defined(__linux__) || defined(__ros__) || defined(__native_client__) -#define OTABSL_HAVE_SCHED_YIELD 1 -#endif - -// OTABSL_HAVE_SEMAPHORE_H -// -// Checks whether the platform supports the header and sem_init(3) -// family of functions as standardized in POSIX.1-2001. -// -// Note: While Apple provides for both iOS and macOS, it is -// explicitly deprecated and will cause build failures if enabled for those -// platforms. We side-step the issue by not defining it here for Apple -// platforms. -#ifdef OTABSL_HAVE_SEMAPHORE_H -#error OTABSL_HAVE_SEMAPHORE_H cannot be directly set -#elif defined(__linux__) || defined(__ros__) -#define OTABSL_HAVE_SEMAPHORE_H 1 -#endif - -// OTABSL_HAVE_ALARM -// -// Checks whether the platform supports the header and alarm(2) -// function as standardized in POSIX.1-2001. -#ifdef OTABSL_HAVE_ALARM -#error OTABSL_HAVE_ALARM cannot be directly set -#elif defined(__GOOGLE_GRTE_VERSION__) -// feature tests for Google's GRTE -#define OTABSL_HAVE_ALARM 1 -#elif defined(__GLIBC__) -// feature test for glibc -#define OTABSL_HAVE_ALARM 1 -#elif defined(_MSC_VER) -// feature tests for Microsoft's library -#elif defined(__MINGW32__) -// mingw32 doesn't provide alarm(2): -// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h -// mingw-w64 provides a no-op implementation: -// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c -#elif defined(__EMSCRIPTEN__) -// emscripten doesn't support signals -#elif defined(__Fuchsia__) -// Signals don't exist on fuchsia. -#elif defined(__native_client__) -#else -// other standard libraries -#define OTABSL_HAVE_ALARM 1 -#endif - -// OTABSL_IS_LITTLE_ENDIAN -// OTABSL_IS_BIG_ENDIAN -// -// Checks the endianness of the platform. -// -// Notes: uses the built in endian macros provided by GCC (since 4.6) and -// Clang (since 3.2); see -// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html. -// Otherwise, if _WIN32, assume little endian. Otherwise, bail with an error. -#if defined(OTABSL_IS_BIG_ENDIAN) -#error "OTABSL_IS_BIG_ENDIAN cannot be directly set." -#endif -#if defined(OTABSL_IS_LITTLE_ENDIAN) -#error "OTABSL_IS_LITTLE_ENDIAN cannot be directly set." -#endif - -#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define OTABSL_IS_LITTLE_ENDIAN 1 -#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define OTABSL_IS_BIG_ENDIAN 1 -#elif defined(_WIN32) -#define OTABSL_IS_LITTLE_ENDIAN 1 -#else -#error "absl endian detection needs to be set up for your compiler" -#endif - -// macOS 10.13 and iOS 10.11 don't let you use , , or -// even though the headers exist and are publicly noted to work. See -// https://github.com/abseil/abseil-cpp/issues/207 and -// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes -// libc++ spells out the availability requirements in the file -// llvm-project/libcxx/include/__config via the #define -// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS. -#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \ - ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 120000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 50000)) -#define OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1 -#else -#define OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0 -#endif - -// OTABSL_HAVE_STD_ANY -// -// Checks whether C++17 std::any is available by checking whether exists. -#ifdef OTABSL_HAVE_STD_ANY -#error "OTABSL_HAVE_STD_ANY cannot be directly set." -#endif - -#ifdef __has_include -#if __has_include() && __cplusplus >= 201703L && \ - !OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE -#define OTABSL_HAVE_STD_ANY 1 -#endif -#endif - -// OTABSL_HAVE_STD_OPTIONAL -// -// Checks whether C++17 std::optional is available. -#ifdef OTABSL_HAVE_STD_OPTIONAL -#error "OTABSL_HAVE_STD_OPTIONAL cannot be directly set." -#endif - -#ifdef __has_include -#if __has_include() && __cplusplus >= 201703L && \ - !OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE -#define OTABSL_HAVE_STD_OPTIONAL 1 -#endif -#endif - -// OTABSL_HAVE_STD_VARIANT -// -// Checks whether C++17 std::variant is available. -#ifdef OTABSL_HAVE_STD_VARIANT -#error "OTABSL_HAVE_STD_VARIANT cannot be directly set." -#endif - -#ifdef __has_include -#if __has_include() && __cplusplus >= 201703L && \ - !OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE -#define OTABSL_HAVE_STD_VARIANT 1 -#endif -#endif - -// OTABSL_HAVE_STD_STRING_VIEW -// -// Checks whether C++17 std::string_view is available. -#ifdef OTABSL_HAVE_STD_STRING_VIEW -#error "OTABSL_HAVE_STD_STRING_VIEW cannot be directly set." -#endif - -#ifdef __has_include -#if __has_include() && __cplusplus >= 201703L -#define OTABSL_HAVE_STD_STRING_VIEW 1 -#endif -#endif - -// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than -// the support for , , , . So we use -// _MSC_VER to check whether we have VS 2017 RTM (when , , -// , is implemented) or higher. Also, `__cplusplus` is -// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language -// version. -// TODO(zhangxy): fix tests before enabling aliasing for `std::any`. -#if defined(_MSC_VER) && _MSC_VER >= 1910 && \ - ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402) -// #define OTABSL_HAVE_STD_ANY 1 -#define OTABSL_HAVE_STD_OPTIONAL 1 -#define OTABSL_HAVE_STD_VARIANT 1 -#define OTABSL_HAVE_STD_STRING_VIEW 1 -#endif - -// OTABSL_USES_STD_ANY -// -// Indicates whether absl::OTABSL_OPTION_NAMESPACE_NAME::any is an alias for std::any. -#if !defined(OTABSL_OPTION_USE_STD_ANY) -#error options.h is misconfigured. -#elif OTABSL_OPTION_USE_STD_ANY == 0 || \ - (OTABSL_OPTION_USE_STD_ANY == 2 && !defined(OTABSL_HAVE_STD_ANY)) -#undef OTABSL_USES_STD_ANY -#elif OTABSL_OPTION_USE_STD_ANY == 1 || \ - (OTABSL_OPTION_USE_STD_ANY == 2 && defined(OTABSL_HAVE_STD_ANY)) -#define OTABSL_USES_STD_ANY 1 -#else -#error options.h is misconfigured. -#endif - -// OTABSL_USES_STD_OPTIONAL -// -// Indicates whether absl::OTABSL_OPTION_NAMESPACE_NAME::optional is an alias for std::optional. -#if !defined(OTABSL_OPTION_USE_STD_OPTIONAL) -#error options.h is misconfigured. -#elif OTABSL_OPTION_USE_STD_OPTIONAL == 0 || \ - (OTABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(OTABSL_HAVE_STD_OPTIONAL)) -#undef OTABSL_USES_STD_OPTIONAL -#elif OTABSL_OPTION_USE_STD_OPTIONAL == 1 || \ - (OTABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(OTABSL_HAVE_STD_OPTIONAL)) -#define OTABSL_USES_STD_OPTIONAL 1 -#else -#error options.h is misconfigured. -#endif - -// OTABSL_USES_STD_VARIANT -// -// Indicates whether absl::OTABSL_OPTION_NAMESPACE_NAME::variant is an alias for std::variant. -#if !defined(OTABSL_OPTION_USE_STD_VARIANT) -#error options.h is misconfigured. -#elif OTABSL_OPTION_USE_STD_VARIANT == 0 || \ - (OTABSL_OPTION_USE_STD_VARIANT == 2 && !defined(OTABSL_HAVE_STD_VARIANT)) -#undef OTABSL_USES_STD_VARIANT -#elif OTABSL_OPTION_USE_STD_VARIANT == 1 || \ - (OTABSL_OPTION_USE_STD_VARIANT == 2 && defined(OTABSL_HAVE_STD_VARIANT)) -#define OTABSL_USES_STD_VARIANT 1 -#else -#error options.h is misconfigured. -#endif - -// OTABSL_USES_STD_STRING_VIEW -// -// Indicates whether absl::OTABSL_OPTION_NAMESPACE_NAME::string_view is an alias for std::string_view. -#if !defined(OTABSL_OPTION_USE_STD_STRING_VIEW) -#error options.h is misconfigured. -#elif OTABSL_OPTION_USE_STD_STRING_VIEW == 0 || \ - (OTABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ - !defined(OTABSL_HAVE_STD_STRING_VIEW)) -#undef OTABSL_USES_STD_STRING_VIEW -#elif OTABSL_OPTION_USE_STD_STRING_VIEW == 1 || \ - (OTABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ - defined(OTABSL_HAVE_STD_STRING_VIEW)) -#define OTABSL_USES_STD_STRING_VIEW 1 -#else -#error options.h is misconfigured. -#endif - -// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION -// SEH exception from emplace for variant when constructing the -// struct can throw. This defeats some of variant_test and -// variant_exception_safety_test. -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG) -#define OTABSL_INTERNAL_MSVC_2017_DBG_MODE -#endif - -// OTABSL_INTERNAL_MANGLED_NS -// OTABSL_INTERNAL_MANGLED_BACKREFERENCE -// -// Internal macros for building up mangled names in our internal fork of CCTZ. -// This implementation detail is only needed and provided for the MSVC build. -// -// These macros both expand to string literals. OTABSL_INTERNAL_MANGLED_NS is -// the mangled spelling of the `absl` namespace, and -// OTABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing -// the proper count to skip past the CCTZ fork namespace names. (This number -// is one larger when there is an inline namespace name to skip.) -#if defined(_MSC_VER) -#define OTABSL_INTERNAL_MANGLED_NS \ - OTABSL_INTERNAL_TOKEN_STR(OTABSL_OPTION_NAMESPACE_NAME) "@absl" -#define OTABSL_INTERNAL_MANGLED_BACKREFERENCE "6" -#endif - -#undef OTABSL_INTERNAL_HAS_KEYWORD - -// OTABSL_DLL -// -// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)` -// so we can annotate symbols appropriately as being exported. When used in -// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so -// that consumers know the symbol is defined inside the DLL. In all other cases, -// the macro expands to nothing. -#if defined(_MSC_VER) -#if defined(OTABSL_BUILD_DLL) -#define OTABSL_DLL __declspec(dllexport) -#elif 1 -#define OTABSL_DLL __declspec(dllimport) -#else -#define OTABSL_DLL -#endif -#else -#define OTABSL_DLL -#endif // defined(_MSC_VER) - -#endif // OTABSL_BASE_CONFIG_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/identity.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/identity.h deleted file mode 100644 index 4afba3179..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/identity.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#ifndef OTABSL_BASE_INTERNAL_IDENTITY_H_ -#define OTABSL_BASE_INTERNAL_IDENTITY_H_ - -#include "../config.h" - -namespace absl { -OTABSL_NAMESPACE_BEGIN -namespace internal { - -template -struct identity { - typedef T type; -}; - -template -using identity_t = typename identity::type; - -} // namespace internal -OTABSL_NAMESPACE_END -} // namespace absl - -#endif // OTABSL_BASE_INTERNAL_IDENTITY_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/inline_variable.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/inline_variable.h deleted file mode 100644 index dd66e9f22..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/inline_variable.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef OTABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ -#define OTABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ - -#include - -#include "identity.h" - -// File: -// This file define a macro that allows the creation of or emulation of C++17 -// inline variables based on whether or not the feature is supported. - -//////////////////////////////////////////////////////////////////////////////// -// Macro: OTABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) -// -// Description: -// Expands to the equivalent of an inline constexpr instance of the specified -// `type` and `name`, initialized to the value `init`. If the compiler being -// used is detected as supporting actual inline variables as a language -// feature, then the macro expands to an actual inline variable definition. -// -// Requires: -// `type` is a type that is usable in an extern variable declaration. -// -// Requires: `name` is a valid identifier -// -// Requires: -// `init` is an expression that can be used in the following definition: -// constexpr type name = init; -// -// Usage: -// -// // Equivalent to: `inline constexpr size_t variant_npos = -1;` -// OTABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1); -// -// Differences in implementation: -// For a direct, language-level inline variable, decltype(name) will be the -// type that was specified along with const qualification, whereas for -// emulated inline variables, decltype(name) may be different (in practice -// it will likely be a reference type). -//////////////////////////////////////////////////////////////////////////////// - -#ifdef __cpp_inline_variables - -// Clang's -Wmissing-variable-declarations option erroneously warned that -// inline constexpr objects need to be pre-declared. This has now been fixed, -// but we will need to support this workaround for people building with older -// versions of clang. -// -// Bug: https://bugs.llvm.org/show_bug.cgi?id=35862 -// -// Note: -// identity_t is used here so that the const and name are in the -// appropriate place for pointer types, reference types, function pointer -// types, etc.. -#if defined(__clang__) -#define OTABSL_INTERNAL_EXTERN_DECL(type, name) \ - extern const ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t name; -#else // Otherwise, just define the macro to do nothing. -#define OTABSL_INTERNAL_EXTERN_DECL(type, name) -#endif // defined(__clang__) - -// See above comment at top of file for details. -#define OTABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) \ - OTABSL_INTERNAL_EXTERN_DECL(type, name) \ - inline constexpr ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t name = init - -#else - -// See above comment at top of file for details. -// -// Note: -// identity_t is used here so that the const and name are in the -// appropriate place for pointer types, reference types, function pointer -// types, etc.. -#define OTABSL_INTERNAL_INLINE_CONSTEXPR(var_type, name, init) \ - template \ - struct AbslInternalInlineVariableHolder##name { \ - static constexpr ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t kInstance = init; \ - }; \ - \ - template \ - constexpr ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t \ - AbslInternalInlineVariableHolder##name::kInstance; \ - \ - static constexpr const ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t& \ - name = /* NOLINT */ \ - AbslInternalInlineVariableHolder##name<>::kInstance; \ - static_assert(sizeof(void (*)(decltype(name))) != 0, \ - "Silence unused variable warnings.") - -#endif // __cpp_inline_variables - -#endif // OTABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h deleted file mode 100644 index c37f43cfc..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::Invoke(f, args...) is an implementation of -// INVOKE(f, args...) from section [func.require] of the C++ standard. -// -// [func.require] -// Define INVOKE (f, t1, t2, ..., tN) as follows: -// 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T -// and t1 is an object of type T or a reference to an object of type T or a -// reference to an object of a type derived from T; -// 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a -// class T and t1 is not one of the types described in the previous item; -// 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is -// an object of type T or a reference to an object of type T or a reference -// to an object of a type derived from T; -// 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 -// is not one of the types described in the previous item; -// 5. f(t1, t2, ..., tN) in all other cases. -// -// The implementation is SFINAE-friendly: substitution failure within Invoke() -// isn't an error. - -#ifndef OTABSL_BASE_INTERNAL_INVOKE_H_ -#define OTABSL_BASE_INTERNAL_INVOKE_H_ - -#include -#include -#include - -#include "../../meta/type_traits.h" - -// The following code is internal implementation detail. See the comment at the -// top of this file for the API documentation. - -namespace absl { -OTABSL_NAMESPACE_BEGIN -namespace base_internal { - -// The five classes below each implement one of the clauses from the definition -// of INVOKE. The inner class template Accept checks whether the -// clause is applicable; static function template Invoke(f, args...) does the -// invocation. -// -// By separating the clause selection logic from invocation we make sure that -// Invoke() does exactly what the standard says. - -template -struct StrippedAccept { - template - struct Accept : Derived::template AcceptImpl::type>::type...> {}; -}; - -// (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T -// and t1 is an object of type T or a reference to an object of type T or a -// reference to an object of a type derived from T. -struct MemFunAndRef : StrippedAccept { - template - struct AcceptImpl : std::false_type {}; - - template - struct AcceptImpl - : std::integral_constant::value && - absl::OTABSL_OPTION_NAMESPACE_NAME::is_function::value> { - }; - - template - static decltype((std::declval().* - std::declval())(std::declval()...)) - Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) { - return (std::forward(obj).* - std::forward(mem_fun))(std::forward(args)...); - } -}; - -// ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a -// class T and t1 is not one of the types described in the previous item. -struct MemFunAndPtr : StrippedAccept { - template - struct AcceptImpl : std::false_type {}; - - template - struct AcceptImpl - : std::integral_constant::value && - absl::OTABSL_OPTION_NAMESPACE_NAME::is_function::value> { - }; - - template - static decltype(((*std::declval()).* - std::declval())(std::declval()...)) - Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) { - return ((*std::forward(ptr)).* - std::forward(mem_fun))(std::forward(args)...); - } -}; - -// t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is -// an object of type T or a reference to an object of type T or a reference -// to an object of a type derived from T. -struct DataMemAndRef : StrippedAccept { - template - struct AcceptImpl : std::false_type {}; - - template - struct AcceptImpl - : std::integral_constant::value && - !absl::OTABSL_OPTION_NAMESPACE_NAME::is_function::value> {}; - - template - static decltype(std::declval().*std::declval()) Invoke( - DataMem&& data_mem, Ref&& ref) { - return std::forward(ref).*std::forward(data_mem); - } -}; - -// (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 -// is not one of the types described in the previous item. -struct DataMemAndPtr : StrippedAccept { - template - struct AcceptImpl : std::false_type {}; - - template - struct AcceptImpl - : std::integral_constant::value && - !absl::OTABSL_OPTION_NAMESPACE_NAME::is_function::value> {}; - - template - static decltype((*std::declval()).*std::declval()) Invoke( - DataMem&& data_mem, Ptr&& ptr) { - return (*std::forward(ptr)).*std::forward(data_mem); - } -}; - -// f(t1, t2, ..., tN) in all other cases. -struct Callable { - // Callable doesn't have Accept because it's the last clause that gets picked - // when none of the previous clauses are applicable. - template - static decltype(std::declval()(std::declval()...)) Invoke( - F&& f, Args&&... args) { - return std::forward(f)(std::forward(args)...); - } -}; - -// Resolves to the first matching clause. -template -struct Invoker { - typedef typename std::conditional< - MemFunAndRef::Accept::value, MemFunAndRef, - typename std::conditional< - MemFunAndPtr::Accept::value, MemFunAndPtr, - typename std::conditional< - DataMemAndRef::Accept::value, DataMemAndRef, - typename std::conditional::value, - DataMemAndPtr, Callable>::type>::type>:: - type>::type type; -}; - -// The result type of Invoke. -template -using InvokeT = decltype(Invoker::type::Invoke( - std::declval(), std::declval()...)); - -// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section -// [func.require] of the C++ standard. -template -InvokeT Invoke(F&& f, Args&&... args) { - return Invoker::type::Invoke(std::forward(f), - std::forward(args)...); -} - -} // namespace base_internal -OTABSL_NAMESPACE_END -} // namespace absl - -#endif // OTABSL_BASE_INTERNAL_INVOKE_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/macros.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/macros.h deleted file mode 100644 index 707c375ed..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/macros.h +++ /dev/null @@ -1,220 +0,0 @@ -// -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: macros.h -// ----------------------------------------------------------------------------- -// -// This header file defines the set of language macros used within Abseil code. -// For the set of macros used to determine supported compilers and platforms, -// see absl/base/config.h instead. -// -// This code is compiled directly on many platforms, including client -// platforms like Windows, Mac, and embedded systems. Before making -// any changes here, make sure that you're not breaking any platforms. - -#ifndef OTABSL_BASE_MACROS_H_ -#define OTABSL_BASE_MACROS_H_ - -#include -#include - -#include "attributes.h" -#include "optimization.h" -#include "port.h" - -// OTABSL_ARRAYSIZE() -// -// Returns the number of elements in an array as a compile-time constant, which -// can be used in defining new arrays. If you use this macro on a pointer by -// mistake, you will get a compile-time error. -#define OTABSL_ARRAYSIZE(array) \ - (sizeof(::absl::OTABSL_OPTION_NAMESPACE_NAME::macros_internal::ArraySizeHelper(array))) - -namespace absl { -OTABSL_NAMESPACE_BEGIN -namespace macros_internal { -// Note: this internal template function declaration is used by OTABSL_ARRAYSIZE. -// The function doesn't need a definition, as we only use its type. -template -auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; -} // namespace macros_internal -OTABSL_NAMESPACE_END -} // namespace absl - -// kLinkerInitialized -// -// An enum used only as a constructor argument to indicate that a variable has -// static storage duration, and that the constructor should do nothing to its -// state. Use of this macro indicates to the reader that it is legal to -// declare a static instance of the class, provided the constructor is given -// the absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::kLinkerInitialized argument. -// -// Normally, it is unsafe to declare a static variable that has a constructor or -// a destructor because invocation order is undefined. However, if the type can -// be zero-initialized (which the loader does for static variables) into a valid -// state and the type's destructor does not affect storage, then a constructor -// for static initialization can be declared. -// -// Example: -// // Declaration -// explicit MyClass(absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal:LinkerInitialized x) {} -// -// // Invocation -// static MyClass my_global(absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::kLinkerInitialized); -namespace absl { -OTABSL_NAMESPACE_BEGIN -namespace base_internal { -enum LinkerInitialized { - kLinkerInitialized = 0, -}; -} // namespace base_internal -OTABSL_NAMESPACE_END -} // namespace absl - -// OTABSL_FALLTHROUGH_INTENDED -// -// Annotates implicit fall-through between switch labels, allowing a case to -// indicate intentional fallthrough and turn off warnings about any lack of a -// `break` statement. The OTABSL_FALLTHROUGH_INTENDED macro should be followed by -// a semicolon and can be used in most places where `break` can, provided that -// no statements exist between it and the next switch label. -// -// Example: -// -// switch (x) { -// case 40: -// case 41: -// if (truth_is_out_there) { -// ++x; -// OTABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations -// // in comments -// } else { -// return x; -// } -// case 42: -// ... -// -// Notes: when compiled with clang in C++11 mode, the OTABSL_FALLTHROUGH_INTENDED -// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed -// when performing switch labels fall-through diagnostic -// (`-Wimplicit-fallthrough`). See clang documentation on language extensions -// for details: -// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough -// -// When used with unsupported compilers, the OTABSL_FALLTHROUGH_INTENDED macro -// has no effect on diagnostics. In any case this macro has no effect on runtime -// behavior and performance of code. -#ifdef OTABSL_FALLTHROUGH_INTENDED -#error "OTABSL_FALLTHROUGH_INTENDED should not be defined." -#endif - -// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported. -#if defined(__clang__) && defined(__has_warning) -#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") -#define OTABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] -#endif -#elif defined(__GNUC__) && __GNUC__ >= 7 -#define OTABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] -#endif - -#ifndef OTABSL_FALLTHROUGH_INTENDED -#define OTABSL_FALLTHROUGH_INTENDED \ - do { \ - } while (0) -#endif - -// OTABSL_DEPRECATED() -// -// Marks a deprecated class, struct, enum, function, method and variable -// declarations. The macro argument is used as a custom diagnostic message (e.g. -// suggestion of a better alternative). -// -// Examples: -// -// class OTABSL_DEPRECATED("Use Bar instead") Foo {...}; -// -// OTABSL_DEPRECATED("Use Baz() instead") void Bar() {...} -// -// template -// OTABSL_DEPRECATED("Use DoThat() instead") -// void DoThis(); -// -// Every usage of a deprecated entity will trigger a warning when compiled with -// clang's `-Wdeprecated-declarations` option. This option is turned off by -// default, but the warnings will be reported by clang-tidy. -#if defined(__clang__) && __cplusplus >= 201103L -#define OTABSL_DEPRECATED(message) __attribute__((deprecated(message))) -#endif - -#ifndef OTABSL_DEPRECATED -#define OTABSL_DEPRECATED(message) -#endif - -// OTABSL_BAD_CALL_IF() -// -// Used on a function overload to trap bad calls: any call that matches the -// overload will cause a compile-time error. This macro uses a clang-specific -// "enable_if" attribute, as described at -// https://clang.llvm.org/docs/AttributeReference.html#enable-if -// -// Overloads which use this macro should be bracketed by -// `#ifdef OTABSL_BAD_CALL_IF`. -// -// Example: -// -// int isdigit(int c); -// #ifdef OTABSL_BAD_CALL_IF -// int isdigit(int c) -// OTABSL_BAD_CALL_IF(c <= -1 || c > 255, -// "'c' must have the value of an unsigned char or EOF"); -// #endif // OTABSL_BAD_CALL_IF -#if OTABSL_HAVE_ATTRIBUTE(enable_if) -#define OTABSL_BAD_CALL_IF(expr, msg) \ - __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg))) -#endif - -// OTABSL_ASSERT() -// -// In C++11, `assert` can't be used portably within constexpr functions. -// OTABSL_ASSERT functions as a runtime assert but works in C++11 constexpr -// functions. Example: -// -// constexpr double Divide(double a, double b) { -// return OTABSL_ASSERT(b != 0), a / b; -// } -// -// This macro is inspired by -// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ -#if defined(NDEBUG) -#define OTABSL_ASSERT(expr) \ - (false ? static_cast(expr) : static_cast(0)) -#else -#define OTABSL_ASSERT(expr) \ - (OTABSL_PREDICT_TRUE((expr)) ? static_cast(0) \ - : [] { assert(false && #expr); }()) // NOLINT -#endif - -#ifdef OTABSL_HAVE_EXCEPTIONS -#define OTABSL_INTERNAL_TRY try -#define OTABSL_INTERNAL_CATCH_ANY catch (...) -#define OTABSL_INTERNAL_RETHROW do { throw; } while (false) -#else // OTABSL_HAVE_EXCEPTIONS -#define OTABSL_INTERNAL_TRY if (true) -#define OTABSL_INTERNAL_CATCH_ANY else if (false) -#define OTABSL_INTERNAL_RETHROW do {} while (false) -#endif // OTABSL_HAVE_EXCEPTIONS - -#endif // OTABSL_BASE_MACROS_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/optimization.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/optimization.h deleted file mode 100644 index 69713654a..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/optimization.h +++ /dev/null @@ -1,181 +0,0 @@ -// -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: optimization.h -// ----------------------------------------------------------------------------- -// -// This header file defines portable macros for performance optimization. - -#ifndef OTABSL_BASE_OPTIMIZATION_H_ -#define OTABSL_BASE_OPTIMIZATION_H_ - -#include "config.h" - -// OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION -// -// Instructs the compiler to avoid optimizing tail-call recursion. Use of this -// macro is useful when you wish to preserve the existing function order within -// a stack trace for logging, debugging, or profiling purposes. -// -// Example: -// -// int f() { -// int result = g(); -// OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); -// return result; -// } -#if defined(__pnacl__) -#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } -#elif defined(__clang__) -// Clang will not tail call given inline volatile assembly. -#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") -#elif defined(__GNUC__) -// GCC will not tail call given inline volatile assembly. -#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") -#elif defined(_MSC_VER) -#include -// The __nop() intrinsic blocks the optimisation. -#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop() -#else -#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } -#endif - -// OTABSL_CACHELINE_SIZE -// -// Explicitly defines the size of the L1 cache for purposes of alignment. -// Setting the cacheline size allows you to specify that certain objects be -// aligned on a cacheline boundary with `OTABSL_CACHELINE_ALIGNED` declarations. -// (See below.) -// -// NOTE: this macro should be replaced with the following C++17 features, when -// those are generally available: -// -// * `std::hardware_constructive_interference_size` -// * `std::hardware_destructive_interference_size` -// -// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html -// for more information. -#if defined(__GNUC__) -// Cache line alignment -#if defined(__i386__) || defined(__x86_64__) -#define OTABSL_CACHELINE_SIZE 64 -#elif defined(__powerpc64__) -#define OTABSL_CACHELINE_SIZE 128 -#elif defined(__aarch64__) -// We would need to read special register ctr_el0 to find out L1 dcache size. -// This value is a good estimate based on a real aarch64 machine. -#define OTABSL_CACHELINE_SIZE 64 -#elif defined(__arm__) -// Cache line sizes for ARM: These values are not strictly correct since -// cache line sizes depend on implementations, not architectures. There -// are even implementations with cache line sizes configurable at boot -// time. -#if defined(__ARM_ARCH_5T__) -#define OTABSL_CACHELINE_SIZE 32 -#elif defined(__ARM_ARCH_7A__) -#define OTABSL_CACHELINE_SIZE 64 -#endif -#endif - -#ifndef OTABSL_CACHELINE_SIZE -// A reasonable default guess. Note that overestimates tend to waste more -// space, while underestimates tend to waste more time. -#define OTABSL_CACHELINE_SIZE 64 -#endif - -// OTABSL_CACHELINE_ALIGNED -// -// Indicates that the declared object be cache aligned using -// `OTABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to -// load a set of related objects in the L1 cache for performance improvements. -// Cacheline aligning objects properly allows constructive memory sharing and -// prevents destructive (or "false") memory sharing. -// -// NOTE: this macro should be replaced with usage of `alignas()` using -// `std::hardware_constructive_interference_size` and/or -// `std::hardware_destructive_interference_size` when available within C++17. -// -// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html -// for more information. -// -// On some compilers, `OTABSL_CACHELINE_ALIGNED` expands to an `__attribute__` -// or `__declspec` attribute. For compilers where this is not known to work, -// the macro expands to nothing. -// -// No further guarantees are made here. The result of applying the macro -// to variables and types is always implementation-defined. -// -// WARNING: It is easy to use this attribute incorrectly, even to the point -// of causing bugs that are difficult to diagnose, crash, etc. It does not -// of itself guarantee that objects are aligned to a cache line. -// -// NOTE: Some compilers are picky about the locations of annotations such as -// this attribute, so prefer to put it at the beginning of your declaration. -// For example, -// -// OTABSL_CACHELINE_ALIGNED static Foo* foo = ... -// -// class OTABSL_CACHELINE_ALIGNED Bar { ... -// -// Recommendations: -// -// 1) Consult compiler documentation; this comment is not kept in sync as -// toolchains evolve. -// 2) Verify your use has the intended effect. This often requires inspecting -// the generated machine code. -// 3) Prefer applying this attribute to individual variables. Avoid -// applying it to types. This tends to localize the effect. -#define OTABSL_CACHELINE_ALIGNED __attribute__((aligned(OTABSL_CACHELINE_SIZE))) -#elif defined(_MSC_VER) -#define OTABSL_CACHELINE_SIZE 64 -#define OTABSL_CACHELINE_ALIGNED __declspec(align(OTABSL_CACHELINE_SIZE)) -#else -#define OTABSL_CACHELINE_SIZE 64 -#define OTABSL_CACHELINE_ALIGNED -#endif - -// OTABSL_PREDICT_TRUE, OTABSL_PREDICT_FALSE -// -// Enables the compiler to prioritize compilation using static analysis for -// likely paths within a boolean branch. -// -// Example: -// -// if (OTABSL_PREDICT_TRUE(expression)) { -// return result; // Faster if more likely -// } else { -// return 0; -// } -// -// Compilers can use the information that a certain branch is not likely to be -// taken (for instance, a CHECK failure) to optimize for the common case in -// the absence of better information (ie. compiling gcc with `-fprofile-arcs`). -// -// Recommendation: Modern CPUs dynamically predict branch execution paths, -// typically with accuracy greater than 97%. As a result, annotating every -// branch in a codebase is likely counterproductive; however, annotating -// specific branches that are both hot and consistently mispredicted is likely -// to yield performance improvements. -#if OTABSL_HAVE_BUILTIN(__builtin_expect) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define OTABSL_PREDICT_FALSE(x) (__builtin_expect(x, 0)) -#define OTABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true)) -#else -#define OTABSL_PREDICT_FALSE(x) (x) -#define OTABSL_PREDICT_TRUE(x) (x) -#endif - -#endif // OTABSL_BASE_OPTIMIZATION_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/options.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/options.h deleted file mode 100644 index c4b00a3d3..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/options.h +++ /dev/null @@ -1,216 +0,0 @@ -#ifndef OTABSL_BASE_OPTIONS_H_ -#define OTABSL_BASE_OPTIONS_H_ - -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: options.h -// ----------------------------------------------------------------------------- -// -// This file contains Abseil configuration options for setting specific -// implementations instead of letting Abseil determine which implementation to -// use at compile-time. Setting these options may be useful for package or build -// managers who wish to guarantee ABI stability within binary builds (which are -// otherwise difficult to enforce). -// -// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS: It is important that -// maintainers of package managers who wish to package Abseil read and -// understand this file! *** -// -// Abseil contains a number of possible configuration endpoints, based on -// parameters such as the detected platform, language version, or command-line -// flags used to invoke the underlying binary. As is the case with all -// libraries, binaries which contain Abseil code must ensure that separate -// packages use the same compiled copy of Abseil to avoid a diamond dependency -// problem, which can occur if two packages built with different Abseil -// configuration settings are linked together. Diamond dependency problems in -// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in -// linker errors), or undefined behavior (resulting in crashes). -// -// Diamond dependency problems can be avoided if all packages utilize the same -// exact version of Abseil. Building from source code with the same compilation -// parameters is the easiest way to avoid such dependency problems. However, for -// package managers who cannot control such compilation parameters, we are -// providing the file to allow you to inject ABI (Application Binary Interface) -// stability across builds. Settings options in this file will neither change -// API nor ABI, providing a stable copy of Abseil between packages. -// -// Care must be taken to keep options within these configurations isolated -// from any other dynamic settings, such as command-line flags which could alter -// these options. This file is provided specifically to help build and package -// managers provide a stable copy of Abseil within their libraries and binaries; -// other developers should not have need to alter the contents of this file. -// -// ----------------------------------------------------------------------------- -// Usage -// ----------------------------------------------------------------------------- -// -// For any particular package release, set the appropriate definitions within -// this file to whatever value makes the most sense for your package(s). Note -// that, by default, most of these options, at the moment, affect the -// implementation of types; future options may affect other implementation -// details. -// -// NOTE: the defaults within this file all assume that Abseil can select the -// proper Abseil implementation at compile-time, which will not be sufficient -// to guarantee ABI stability to package managers. - -// Include a standard library header to allow configuration based on the -// standard library in use. -// Using C++20 feature-test macros when possible, otherwise fall back to -// ciso646/iso646.h.There are warnings when including ciso646 in C++17 mode -#ifdef __has_include -# if __has_include() -# include -# endif -#elif defined(_MSC_VER) && \ - ((defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) -# if _MSC_VER >= 1922 -# include -# endif -#else -# if defined(__GNUC__) && !defined(__clang__) && !defined(__apple_build_version__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wcpp" -# elif defined(__clang__) || defined(__apple_build_version__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wcpp" -# endif -# include -# if defined(__GNUC__) && !defined(__clang__) && !defined(__apple_build_version__) -# pragma GCC diagnostic pop -# elif defined(__clang__) || defined(__apple_build_version__) -# pragma clang diagnostic pop -# endif -#endif - -// ----------------------------------------------------------------------------- -// Type Compatibility Options -// ----------------------------------------------------------------------------- -// -// OTABSL_OPTION_USE_STD_ANY -// -// This option controls whether absl::OTABSL_OPTION_NAMESPACE_NAME::any is implemented as an alias to -// std::any, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::any. This requires that all code -// using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::any is available. This option is -// useful when you are building your entire program, including all of its -// dependencies, from source. It should not be used otherwise -- for example, -// if you are distributing Abseil in a binary package manager -- since in -// mode 2, absl::OTABSL_OPTION_NAMESPACE_NAME::any will name a different type, with a different mangled name -// and binary layout, depending on the compiler flags passed by the end user. -// For more info, see https://abseil.io/about/design/dropin-types. -// -// User code should not inspect this macro. To check in the preprocessor if -// absl::OTABSL_OPTION_NAMESPACE_NAME::any is a typedef of std::any, use the feature macro OTABSL_USES_STD_ANY. - -#define OTABSL_OPTION_USE_STD_ANY 0 - - -// OTABSL_OPTION_USE_STD_OPTIONAL -// -// This option controls whether absl::OTABSL_OPTION_NAMESPACE_NAME::optional is implemented as an alias to -// std::optional, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::optional. This requires that all -// code using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::optional is available. This option -// is useful when you are building your program from source. It should not be -// used otherwise -- for example, if you are distributing Abseil in a binary -// package manager -- since in mode 2, absl::OTABSL_OPTION_NAMESPACE_NAME::optional will name a different -// type, with a different mangled name and binary layout, depending on the -// compiler flags passed by the end user. For more info, see -// https://abseil.io/about/design/dropin-types. - -// User code should not inspect this macro. To check in the preprocessor if -// absl::OTABSL_OPTION_NAMESPACE_NAME::optional is a typedef of std::optional, use the feature macro -// OTABSL_USES_STD_OPTIONAL. - -#define OTABSL_OPTION_USE_STD_OPTIONAL 0 - - -// OTABSL_OPTION_USE_STD_STRING_VIEW -// -// This option controls whether absl::OTABSL_OPTION_NAMESPACE_NAME::string_view is implemented as an alias to -// std::string_view, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::string_view. This requires that -// all code using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::string_view is available. This -// option is useful when you are building your program from source. It should -// not be used otherwise -- for example, if you are distributing Abseil in a -// binary package manager -- since in mode 2, absl::OTABSL_OPTION_NAMESPACE_NAME::string_view will name a -// different type, with a different mangled name and binary layout, depending on -// the compiler flags passed by the end user. For more info, see -// https://abseil.io/about/design/dropin-types. -// -// User code should not inspect this macro. To check in the preprocessor if -// absl::OTABSL_OPTION_NAMESPACE_NAME::string_view is a typedef of std::string_view, use the feature macro -// OTABSL_USES_STD_STRING_VIEW. - -#define OTABSL_OPTION_USE_STD_STRING_VIEW 0 - -// OTABSL_OPTION_USE_STD_VARIANT -// -// This option controls whether absl::OTABSL_OPTION_NAMESPACE_NAME::variant is implemented as an alias to -// std::variant, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::variant. This requires that all -// code using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::variant is available. This option -// is useful when you are building your program from source. It should not be -// used otherwise -- for example, if you are distributing Abseil in a binary -// package manager -- since in mode 2, absl::OTABSL_OPTION_NAMESPACE_NAME::variant will name a different -// type, with a different mangled name and binary layout, depending on the -// compiler flags passed by the end user. For more info, see -// https://abseil.io/about/design/dropin-types. -// -// User code should not inspect this macro. To check in the preprocessor if -// absl::OTABSL_OPTION_NAMESPACE_NAME::variant is a typedef of std::variant, use the feature macro -// OTABSL_USES_STD_VARIANT. - -#define OTABSL_OPTION_USE_STD_VARIANT 0 - - -// OTABSL_OPTION_NAMESPACE_NAME -// -// All codes in otabsl are under OTABSL_OPTION_NAMESPACE_NAME, we do not use inline namespace to avoid -// conlict with external Abseil. - -#define OTABSL_OPTION_NAMESPACE_NAME otel_v1 - -#endif // OTABSL_BASE_OPTIONS_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/policy_checks.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/policy_checks.h deleted file mode 100644 index f86c264fc..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/policy_checks.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: policy_checks.h -// ----------------------------------------------------------------------------- -// -// This header enforces a minimum set of policies at build time, such as the -// supported compiler and library versions. Unsupported configurations are -// reported with `#error`. This enforcement is best effort, so successfully -// compiling this header does not guarantee a supported configuration. - -#ifndef OTABSL_BASE_POLICY_CHECKS_H_ -#define OTABSL_BASE_POLICY_CHECKS_H_ - -// Included for the __GLIBC_PREREQ macro used below. -#include - -// Included for the _STLPORT_VERSION macro used below. -#if defined(__cplusplus) -#include -#endif - -// ----------------------------------------------------------------------------- -// Operating System Check -// ----------------------------------------------------------------------------- - -#if defined(__CYGWIN__) -#error "Cygwin is not supported." -#endif - -// ----------------------------------------------------------------------------- -// Compiler Check -// ----------------------------------------------------------------------------- - -#if 0 /* FIXME: MG */ -// We support MSVC++ 14.0 update 2 and later. -// This minimum will go up. -#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__) -#error "This package requires Visual Studio 2015 Update 2 or higher." -#endif -#endif - -// We support gcc 4.7 and later. -// This minimum will go up. -#if defined(__GNUC__) && !defined(__clang__) -#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) -#error "This package requires gcc 4.7 or higher." -#endif -#endif - -// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later. -// This corresponds to Apple Xcode version 4.5. -// This minimum will go up. -#if defined(__apple_build_version__) && __apple_build_version__ < 4211165 -#error "This package requires __apple_build_version__ of 4211165 or higher." -#endif - -// ----------------------------------------------------------------------------- -// C++ Version Check -// ----------------------------------------------------------------------------- - -// Enforce C++11 as the minimum. -#if defined(_MSVC_LANG) -#if _MSVC_LANG < 201103L -#error "C++ versions less than C++11 are not supported." -#endif // _MSVC_LANG < 201103L -#elif defined(__cplusplus) -#if __cplusplus < 201103L -#error "C++ versions less than C++11 are not supported." -#endif // __cplusplus < 201103L -#endif - -// ----------------------------------------------------------------------------- -// Standard Library Check -// ----------------------------------------------------------------------------- - -#if defined(_STLPORT_VERSION) -#error "STLPort is not supported." -#endif - -// ----------------------------------------------------------------------------- -// `char` Size Check -// ----------------------------------------------------------------------------- - -// Abseil currently assumes CHAR_BIT == 8. If you would like to use Abseil on a -// platform where this is not the case, please provide us with the details about -// your platform so we can consider relaxing this requirement. -#if CHAR_BIT != 8 -#error "Abseil assumes CHAR_BIT == 8." -#endif - -// ----------------------------------------------------------------------------- -// `int` Size Check -// ----------------------------------------------------------------------------- - -// Abseil currently assumes that an int is 4 bytes. If you would like to use -// Abseil on a platform where this is not the case, please provide us with the -// details about your platform so we can consider relaxing this requirement. -#if INT_MAX < 2147483647 -#error "Abseil assumes that int is at least 4 bytes. " -#endif - -#endif // OTABSL_BASE_POLICY_CHECKS_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/port.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/port.h deleted file mode 100644 index aaba551b5..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/base/port.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// This files is a forwarding header for other headers containing various -// portability macros and functions. -// This file is used for both C and C++! - -#ifndef OTABSL_BASE_PORT_H_ -#define OTABSL_BASE_PORT_H_ - -#include "attributes.h" -#include "config.h" -#include "optimization.h" - -#endif // OTABSL_BASE_PORT_H_ diff --git a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/meta/type_traits.h b/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/meta/type_traits.h deleted file mode 100644 index dbd034887..000000000 --- a/ext/opentelemetry-cpp-1.21.0/api/include/opentelemetry/nostd/internal/absl/meta/type_traits.h +++ /dev/null @@ -1,779 +0,0 @@ -// -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// type_traits.h -// ----------------------------------------------------------------------------- -// -// This file contains C++11-compatible versions of standard API -// functions for determining the characteristics of types. Such traits can -// support type inference, classification, and transformation, as well as -// make it easier to write templates based on generic type behavior. -// -// See https://en.cppreference.com/w/cpp/header/type_traits -// -// WARNING: use of many of the constructs in this header will count as "complex -// template metaprogramming", so before proceeding, please carefully consider -// https://google.github.io/styleguide/cppguide.html#Template_metaprogramming -// -// WARNING: using template metaprogramming to detect or depend on API -// features is brittle and not guaranteed. Neither the standard library nor -// Abseil provides any guarantee that APIs are stable in the face of template -// metaprogramming. Use with caution. -#ifndef OTABSL_META_TYPE_TRAITS_H_ -#define OTABSL_META_TYPE_TRAITS_H_ - -#include -#include -#include - -#include "../base/config.h" - -// MSVC constructibility traits do not detect destructor properties and so our -// implementations should not use them as a source-of-truth. -#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__) -#define OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1 -#endif - -namespace absl { -OTABSL_NAMESPACE_BEGIN - -// Defined and documented later on in this file. -template -struct is_trivially_destructible; - -// Defined and documented later on in this file. -template -struct is_trivially_move_assignable; - -namespace type_traits_internal { - -// Silence MSVC warnings about the destructor being defined as deleted. -#if defined(_MSC_VER) && !defined(__GNUC__) -#pragma warning(push) -#pragma warning(disable : 4624) -#endif // defined(_MSC_VER) && !defined(__GNUC__) - -template -union SingleMemberUnion { - T t; -}; - -// Restore the state of the destructor warning that was silenced above. -#if defined(_MSC_VER) && !defined(__GNUC__) -#pragma warning(pop) -#endif // defined(_MSC_VER) && !defined(__GNUC__) - -template -struct IsTriviallyMoveConstructibleObject - : std::integral_constant< - bool, std::is_move_constructible< - type_traits_internal::SingleMemberUnion>::value && - absl::OTABSL_OPTION_NAMESPACE_NAME::is_trivially_destructible::value> {}; - -template -struct IsTriviallyCopyConstructibleObject - : std::integral_constant< - bool, std::is_copy_constructible< - type_traits_internal::SingleMemberUnion>::value && - absl::OTABSL_OPTION_NAMESPACE_NAME::is_trivially_destructible::value> {}; - -template -struct IsTriviallyMoveAssignableReference : std::false_type {}; - -template -struct IsTriviallyMoveAssignableReference - : absl::OTABSL_OPTION_NAMESPACE_NAME::is_trivially_move_assignable::type {}; - -template -struct IsTriviallyMoveAssignableReference - : absl::OTABSL_OPTION_NAMESPACE_NAME::is_trivially_move_assignable::type {}; - -template -struct VoidTImpl { - using type = void; -}; - -//////////////////////////////// -// Library Fundamentals V2 TS // -//////////////////////////////// - -// NOTE: The `is_detected` family of templates here differ from the library -// fundamentals specification in that for library fundamentals, `Op` is -// evaluated as soon as the type `is_detected` undergoes -// substitution, regardless of whether or not the `::value` is accessed. That -// is inconsistent with all other standard traits and prevents lazy evaluation -// in larger contexts (such as if the `is_detected` check is a trailing argument -// of a `conjunction`. This implementation opts to instead be lazy in the same -// way that the standard traits are (this "defect" of the detection idiom -// specifications has been reported). - -template class Op, class... Args> -struct is_detected_impl { - using type = std::false_type; -}; - -template